ubuntu20.04下安装qt5.12
https://blog.csdn.net/lj19990824/article/details/121013721
Ubuntu 20.04在桌面左侧边栏添加QT creator快捷图标
https://blog.csdn.net/kavieen/article/details/118695038
Qt和ROS:https://github.com/chengyangkj?tab=repositories
官方ROS2教程:https://docs.ros.org/en/foxy/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Cpp-Publisher-And-Subscriber.html
目录
- 1.ROS的核心概念
- 2.ROS命令行工具的使用
- 3.ROS使用
- 4.ROS2的使用
- 5.ROS2中通过回调获取每一帧图像信息
- 6.对ROS2多个节点进行管理
- ps: 记录ROS2开发过程中遇到的问题和解决方法
- 1./opt/ros/foxy/include/rclcpp/subscription_factory.hpp:112: error: undefined reference to `rosidl_message_type_support_t const* rosidl_typesupport_cpp::get_message_type_support_handle<sensor_msgs::msg::Image_<std::allocator<void> > >()'
- 2.error: use of undeclared identifier 'cv_bridge'
- 3.error: no matching constructor for initialization of 'image_transport::ImageTransport'
1.ROS的核心概念
2.ROS命令行工具的使用
功能包+节点
3.ROS使用
catkin_make编译
https://blog.csdn.net/sinat_16643223/article/details/113935412
1.catkin_make编译流程
mkdir -p catkin_ws/src
将源码拷贝到 catkin_ws/src/目录下
cd catkin_ws/
catkin_make2.启动ros服务端
第一个窗口运行:
roscore
第二个窗口运行:
cd catkin_ws/
source devel/setup.bash
rosrun arm_socket_connect arm_socket_connect_noderosrun arm_socket_connect arm_connect_server
4.ROS2的使用
首先,您需要安装ROS2和C编译器。ROS2是一个机器人操作系统,它提供了一些工具和库,可以帮助您编写机器人应用程序。C是一种编程语言,它可以用来编写ROS2节点。
接下来,您需要创建一个ROS2工作区。这个工作区是一个文件夹,其中包含您的ROS2项目。您可以使用以下命令创建一个ROS2工作区:
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws
colcon build
然后,您需要创建一个ROS2节点。节点是ROS2中的一个基本概念,它是一个可以与其他节点通信的进程。您可以使用以下命令创建一个ROS2节点:
cd ~/ros2_ws/src
ros2 pkg create my_node --build-type ament_cmake --node-name my_node
这将创建一个名为“my_node”的ROS2节点,并在“~/ros2_ws/src/my_node”文件夹中生成一些文件。
接下来,您需要在my_node.cpp
文件中编写节点代码。这个文件位于~/ros2_ws/src/my_node/src
文件夹中。您可以使用以下代码作为起点:
#include "rclcpp/rclcpp.hpp"int main(int argc, char * argv[])
{rclcpp::init(argc, argv);auto node = rclcpp::Node::make_shared("my_node");RCLCPP_INFO(node->get_logger(), "Hello, world!");rclcpp::spin(node);rclcpp::shutdown();return 0;
}
这个代码创建了一个名为“my_node”的ROS2节点,并在控制台输出“Hello, world!”。您可以根据需要修改这个代码,以实现您的节点功能。
最后,您需要编译和运行您的节点。您可以使用以下命令编译您的节点:
cd ~/ros2_ws
colcon build --packages-select my_node
这将编译您的节点,并将可执行文件放在“~/ros2_ws/install/my_node/bin”文件夹中。
要运行您的节点,请使用以下命令:
cd ~/ros2_ws
source install/setup.bash
ros2 run my_node my_node
这将启动您的节点,并在控制台输出“Hello, world!”。您可以根据需要修改这个命令,以实现您的节点功能。
5.ROS2中通过回调获取每一帧图像信息
以下是在ROS2中通过topic回调获取一帧图像信息的C++实现:
#include <iostream>
#include <string>
#include <memory>#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp"class ImageSubscriber : public rclcpp::Node
{
public:ImageSubscriber(const std::string & topic_name): Node("image_subscriber_node"){// Create a subscriber to the image topicimage_subscriber_ = create_subscription<sensor_msgs::msg::Image>(topic_name, 10, std::bind(&ImageSubscriber::image_callback, this, std::placeholders::_1));}private:void image_callback(const sensor_msgs::msg::Image::SharedPtr msg){// Print the image width and heightstd::cout << "Image width: " << msg->width << std::endl;std::cout << "Image height: " << msg->height << std::endl;// Convert the image data to OpenCV formatcv::Mat image = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)->image;// Do some processing on the image// ...// Display the imagecv::imshow("Image", image);cv::waitKey(1);}rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr image_subscriber_;
};int main(int argc, char ** argv)
{// Initialize the ROS2 noderclcpp::init(argc, argv);// Create an image subscriberstd::string topic_name = "/camera/image_raw";auto image_subscriber = std::make_shared<ImageSubscriber>(topic_name);// Spin the noderclcpp::spin(image_subscriber);// Shutdown the ROS2 noderclcpp::shutdown();return 0;
}
在上述代码中,我们创建了一个ImageSubscriber类,该类继承自rclcpp::Node类,用于订阅图像topic并处理接收到的图像数据。在ImageSubscriber类的构造函数中,我们创建了一个subscriber来订阅指定的图像topic,并将回调函数image_callback绑定到该subscriber上。在image_callback函数中,我们首先打印了接收到的图像的宽度和高度,然后将图像数据转换为OpenCV格式,并进行一些图像处理操作。最后,我们将处理后的图像显示出来。
在main函数中,我们首先初始化ROS2节点,然后创建一个ImageSubscriber对象来订阅指定的图像topic。最后,我们调用rclcpp::spin函数来启动ROS2节点,并等待接收到图像数据。当接收到图像数据时,ROS2会自动调用image_callback函数来处理数据。当我们想要停止节点时,可以调用rclcpp::shutdown函数来关闭ROS2节点。
6.对ROS2多个节点进行管理
功能:可以对多个ROS2节点分别进行进行启动和关闭,通过调用相关函数可启动或关闭某个指定节点,不会阻塞主线程,且不需要用户操作来退出某个节点。
以下是一个C++代码示例,可以对多个ROS2节点分别进行启动和关闭,通过调用相关函数可启动或关闭某个指定节点,不会阻塞主线程,且不需要用户操作来退出某个节点。
#include <rclcpp/rclcpp.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>class NodeManager
{
public:NodeManager() {}void add_node(std::shared_ptr<rclcpp::Node> node){nodes_.push_back(node);}void start_all(){for (auto node : nodes_){std::thread t(&NodeManager::start_node, this, node);t.detach();}}void stop_all(){for (auto node : nodes_){std::thread t(&NodeManager::stop_node, this, node);t.detach();}}void start_node(std::shared_ptr<rclcpp::Node> node){std::unique_lock<std::mutex> lock(mutex_);cv_.wait(lock, [this] { return !paused_; });node->start();}void stop_node(std::shared_ptr<rclcpp::Node> node){node->stop();}void pause_all(){std::unique_lock<std::mutex> lock(mutex_);paused_ = true;}void resume_all(){std::unique_lock<std::mutex> lock(mutex_);paused_ = false;cv_.notify_all();}private:std::vector<std::shared_ptr<rclcpp::Node>> nodes_;std::mutex mutex_;std::condition_variable cv_;bool paused_ = false;
};int main(int argc, char * argv[])
{// 初始化ROS2节点rclcpp::init(argc, argv);// 创建节点管理器NodeManager node_manager;// 创建节点1auto node1 = std::make_shared<rclcpp::Node>("node1");node_manager.add_node(node1);// 创建节点2auto node2 = std::make_shared<rclcpp::Node>("node2");node_manager.add_node(node2);// 启动所有节点node_manager.start_all();// 暂停所有节点node_manager.pause_all();// 启动节点1node_manager.resume_all();// 等待一段时间std::this_thread::sleep_for(std::chrono::seconds(5));// 停止节点1node_manager.stop_node(node1);// 关闭ROS2节点rclcpp::shutdown();return 0;
}
在上面的代码中,我们使用了std::thread来启动和停止节点,这样可以避免阻塞主线程。在start_all函数和stop_all函数中,我们使用std::thread来启动和停止每个节点。我们使用t.detach()来分离线程,这样线程可以在后台运行,不会阻塞主线程。
在start_node函数中,我们使用了std::unique_lock和std::condition_variable来实现暂停和恢复节点的功能。当节点被暂停时,线程会等待条件变量cv_,直到被恢复时才会继续执行。
在main函数中,我们初始化ROS2节点,创建NodeManager对象,并向其添加两个节点。然后,我们启动所有节点,并暂停所有节点。接着,我们恢复节点1,并等待5秒钟。最后,我们停止节点1并关闭ROS2节点。
ps: 记录ROS2开发过程中遇到的问题和解决方法
1./opt/ros/foxy/include/rclcpp/subscription_factory.hpp:112: error: undefined reference to `rosidl_message_type_support_t const* rosidl_typesupport_cpp::get_message_type_support_handle<sensor_msgs::msg::Image_<std::allocator > >()’
解决方法:缺少头文件
#include "sensor_msgs/msg/image.hpp"
CMakeList.txt中增加sensor_msgs
库的依赖
find_package(sensor_msgs REQUIRED)ament_target_dependencies(yourprojectname sensor_msgs)
2.error: use of undeclared identifier ‘cv_bridge’
解决方法:缺少头文件
#include <cv_bridge/cv_bridge.h>
CMakeList.txt中增加sensor_msgs
库的依赖
find_package(cv_bridge REQUIRED)ament_target_dependencies(yourprojectname cv_bridge)
3.error: no matching constructor for initialization of ‘image_transport::ImageTransport’
解决方法:缺少头文件
#include <image_transport/image_transport.h>
CMakeList.txt中增加sensor_msgs
库的依赖
find_package(image_transport REQUIRED)ament_target_dependencies(yourprojectname image_transport)