ROS和ROS2使用

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和ROShttps://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使用

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_make

2.启动ros服务端
第一个窗口运行:
roscore
第二个窗口运行:
cd catkin_ws/
source devel/setup.bash 
rosrun  arm_socket_connect arm_socket_connect_node

rosrun 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 topic
    image_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 height
    std::cout << "Image width: " << msg->width << std::endl;
    std::cout << "Image height: " << msg->height << std::endl;

    // Convert the image data to OpenCV format
    cv::Mat image = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8)->image;

    // Do some processing on the image
    // ...

    // Display the image
    cv::imshow("Image", image);
    cv::waitKey(1);
  }

  rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr image_subscriber_;
};

int main(int argc, char ** argv)
{
  // Initialize the ROS2 node
  rclcpp::init(argc, argv);

  // Create an image subscriber
  std::string topic_name = "/camera/image_raw";
  auto image_subscriber = std::make_shared<ImageSubscriber>(topic_name);

  // Spin the node
  rclcpp::spin(image_subscriber);

  // Shutdown the ROS2 node
  rclcpp::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;

  // 创建节点1
  auto node1 = std::make_shared<rclcpp::Node>("node1");
  node_manager.add_node(node1);

  // 创建节点2
  auto node2 = std::make_shared<rclcpp::Node>("node2");
  node_manager.add_node(node2);

  // 启动所有节点
  node_manager.start_all();

  // 暂停所有节点
  node_manager.pause_all();

  // 启动节点1
  node_manager.resume_all();

  // 等待一段时间
  std::this_thread::sleep_for(std::chrono::seconds(5));

  // 停止节点1
  node_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节点。

7.解析sensor_msgs::PointCloud2 ROS点云数据

https://www.cnblogs.com/penuel/p/16396655.html

8.OpenCV使用Viz模块3D可视化显示

https://www.cnblogs.com/happyamyhope/p/12487096.html

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)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

boss-dog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值