——Franka机器人渠道、市场、销售负责
——学术背景来自于哈尔滨工业大学、多伦多大学
全国咨询热线:
400 188 3810
Franka机器人专线
18018175378(同微信)

PNP机器人ROS专题系列之4—ROS2开发实践:ROS核心(节点、话题、服务、DDS通信协议等)

发表时间:2025-08-17 21:20作者:herowuxu
PNP机器人专注具身智能方向, 是Franka战略合作伙伴。

德国慕尼黑—PNP机器人成为Franka Robotics卓越战略伙伴,推动具身智能机器人全球生态

具身智能方向:具身智能技术群

Franka机器人:具身智能方案/渠道/商务咨询


提要:ROS开源生态庞大,社区活跃,驱动、算法、可视化工具即装即用,大幅降低科研门槛;FRANKA机器人、KINOVA等主流机型原生支持ROS/ROS2,接口统一,实验成果可无缝迁移。PNP机器人更新ROS系列教程,从节点通信、MoveIt!到Gazebo仿真,全流程讲解,并附实验室级实例源码,助力机器人、AI、自动化等方向学者快速复现顶会算法,加速论文与原型落地,敬请关注后续深度篇章!
ROS2(Robot Operating System 2)是机器人操作系统(ROS)的第二版,是一个开源的机器人软件开发平台,提供工具、库和功能,帮助开发者构建机器人应用 。ROS2 是在 ROS 的基础上重新设计的,解决了 ROS 1 的局限性,如缺乏实时性支持、安全机制不足和跨平台兼容性差等问题 。ROS2 采用分布式架构,基于 DDS(Data Distribution Service)标准,支持高效、可靠的实时通信,并具备灵活的 QoS(服务质量)配置能力 。此外,ROS2 支持跨平台(如 Linux、Windows 和 macOS),并增加了对 Rust 等语言的支持。
ROS2 的核心组件包括节点(Nodes)、话题(Topics)、发布者(Publishers)、订阅者(Subscribers)、服务(Services)和客户端(Clients),这些组件通过 DDS 实现分布式通信,使机器人的感知、决策、控制等功能模块可以灵活地分布和协同工作。今天主要是分享一下ROS2的核心包括节点、话题、服务和DDS通信协议的内容,其中会对官方和本书的相关细节进行比对,本文章都以C++为例。原文链接:https://www.eeworld.com.cn/a44eHGC


节点


1、ROS2中的节点具有以下几个特点

  1. 每个节点是一个进程
  2. 每个节点都是一个可以独立运行的可执行文件
  3. 每个节点可使用不同的编程语言
  4. 每个节点可分布式运行在不同的主机中
  5. 每个节点需要唯一的名称

2、节点编程方法(C++)

a.C++程序编写

  1. #include "rclcpp/rclcpp.hpp"


  2. /***
  3. 创建一个HelloWorld节点, 初始化时输出“hello world”日志
  4. ***/
  5. class HelloWorldNode : public rclcpp::Node
  6. {
  7. public:
  8. HelloWorldNode()
  9.         : Node("node_helloworld_class")                          // ROS2节点父类初始化
  10.         {
  11. while(rclcpp::ok())                                  // ROS2系统是否正常运行
  12.             {
  13.                 RCLCPP_INFO(this->get_logger(), "Hello World");  // ROS2日志输出
  14.                 sleep(1);                                        // 休眠控制循环时间
  15.             }
  16.         }
  17. };

  18. // ROS2节点主入口main函数
  19. int main(int argc, char * argv[])                              
  20. {

  21. // ROS2 C++接口初始化
  22.     rclcpp::init(argc, argv);        

  23. // 创建ROS2节点对象并进行初始化                
  24.     rclcpp::spin(std::make_shared<HelloWorldNode>());

  25. // 关闭ROS2 C++接口
  26.     rclcpp::shutdown();                              

  27. return0;
  28. }

** 可以看的出来ROS2对节点的编程推荐面向对象编程的编程方法**
同时ROS2的编程难度更大、C++的语法更新、所以使用python也不失为一种方法

b.设置编译选项(编译接口)

  1. find_package(rclcpp REQUIRED)

  2. add_executable(node_helloworld_class src/node_helloworld_class.cpp)

  3. ament_target_dependencies(node_helloworld_class rclcpp)

  4. install(TARGETS
  5.   node_helloworld_class
  6.   DESTINATION lib/${PROJECT_NAME})

前三行相对于ROS1没什么太大区别,主要是多了最后这个

将编译生成的可执行文件拷贝到install安装空间的lib文件夹下
我们知道ROS2相对于ROS1的工作空间构建方式变了,其中多了install文件夹 所以要注意最后一行

c.编译运行

  1. #进入工作空间后
  2. colcon build #编译工作空间
  3. ros2 run learning_node_cpp node_helloworld_class # (功能包 可执行文件)
  4. ros2 node list# 查看节点列表
  5. ros2 node info <node_name>   # 查看节点信息


话题




1.rqt_graph


  1. ros2 run turtlesim turtlesim_node

  2. ros2 run turtlesim turtle_teleop_key

  3. rqt_graph

我们将使用 rqt_graph 来可视化不断变化的节点和主题,以及它们之间的联系。


话题的特点:


  • 多对多通信
  • 异步通信
  • 消息接口

话题通信的一个特性,就是异步通信所谓异步,只要是指发布者发出数据后,并不知道订阅者什么时候可以收到。所以ROS2的后台会有一个轮询机制,当发现有数据进入消息队列时,就会触发回调函数

2.发布话题

  1. /***
  2. @作者: 古月居(www.guyuehome.com)
  3. @说明: ROS2话题示例-发布图像话题
  4. ***/

  5. #include <chrono>
  6. #include <functional>
  7. #include <memory>
  8. #include <string>

  9. #include "rclcpp/rclcpp.hpp"          // ROS2 C++接口库
  10. #include "std_msgs/msg/string.hpp"    // 字符串消息类型

  11. usingnamespacestd::chrono_literals;


  12. class PublisherNode : public rclcpp::Node
  13. {
  14. public:
  15.         PublisherNode()
  16.         : Node("topic_helloworld_pub") // ROS2节点父类初始化
  17.         {
  18. // 创建发布者对象(消息类型、话题名、队列长度)
  19.             publisher_ = this->create_publisher<std_msgs::msg::String>("chatter", 10);
  20. // 创建一个定时器,定时执行回调函数
  21.             timer_ = this->create_wall_timer(
  22. 500ms, std::bind(&PublisherNode::timer_callback, this));            
  23.         }

  24. private:
  25. // 创建定时器周期执行的回调函数
  26. void timer_callback()                                                      
  27.         {
  28. // 创建一个String类型的消息对象
  29. auto msg = std_msgs::msg::String();  
  30. // 填充消息对象中的消息数据                                    
  31.           msg.data = "Hello World";
  32. // 发布话题消息                                                
  33.           RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", msg.data.c_str());
  34. // 输出日志信息,提示已经完成话题发布  
  35.           publisher_->publish(msg);                                                
  36.         }

  37.         rclcpp::TimerBase::SharedPtr timer_;                             // 定时器指针
  38.         rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;  // 发布者指针
  39. };

  40. // ROS2节点主入口main函数
  41. int main(int argc, char * argv[])                      
  42. {
  43. // ROS2 C++接口初始化
  44.     rclcpp::init(argc, argv);                

  45. // 创建ROS2节点对象并进行初始化          
  46.     rclcpp::spin(std::make_shared<PublisherNode>());  

  47. // 关闭ROS2 C++接口
  48.     rclcpp::shutdown();                                

  49. return0;
  50. }

都是面向对象编程

3.订阅话题

  1. /***
  2. @作者: 古月居(www.guyuehome.com)
  3. @说明: ROS2话题示例-订阅“Hello World”话题消息
  4. ***/

  5. #include <memory>

  6. #include "rclcpp/rclcpp.hpp"// ROS2 C++接口库
  7. #include "std_msgs/msg/string.hpp"// 字符串消息类型
  8. usingstd::placeholders::_1;

  9. class SubscriberNode : public rclcpp::Node
  10. {
  11. public:
  12. SubscriberNode()
  13.         : Node("topic_helloworld_sub")        // ROS2节点父类初始化
  14.         {
  15.             subscription_ = this->create_subscription<std_msgs::msg::String>(      
  16. "chatter", 10, std::bind(&SubscriberNode::topic_callback, this, _1));   // 创建订阅者对象(消息类型、话题名、订阅者回调函数、队列长度)
  17.         }

  18. private:
  19. voidtopic_callback(const std_msgs::msg::String & msg) const// 创建回调函数,执行收到话题消息后对数据的处理
  20.         {
  21.             RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg.data.c_str());       // 输出日志信息,提示订阅收到的话题消息
  22.         }

  23.         rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;         // 订阅者指针
  24. };

  25. // ROS2节点主入口main函数
  26. int main(int argc, char * argv[])                        
  27. {
  28. // ROS2 C++接口初始化
  29.     rclcpp::init(argc, argv);                

  30. // 创建ROS2节点对象并进行初始化            
  31.     rclcpp::spin(std::make_shared<SubscriberNode>());    

  32. // 关闭ROS2 C++接口
  33.     rclcpp::shutdown();                                  

  34. return0;
  35. }


服务





服务可以实现类似你问我答的同步通信效果

a.服务的特点

服务的特点:
  • 同步通信
  • 一对多通信(服务端唯一)
  • 服务接口

b.客户端

  1. /***
  2. @作者: 古月居(www.guyuehome.com)
  3. @说明: ROS2服务示例-发送两个加数,请求加法器计算
  4. ***/

  5. #include "rclcpp/rclcpp.hpp"                          // ROS2 C++接口库
  6. #include "learning_interface/srv/add_two_ints.hpp"    // 自定义的服务接口

  7. #include <chrono>
  8. #include <cstdlib>
  9. #include <memory>

  10. usingnamespacestd::chrono_literals;

  11. int main(int argc, char **argv)
  12. {
  13. // ROS2 C++接口初始化
  14.     rclcpp::init(argc, argv);                      

  15. if (argc != 3) {
  16.         RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "usage: service_adder_client X Y");
  17. return1;
  18.     }

  19. // 创建ROS2节点对象并进行初始化
  20. std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("service_adder_client");  
  21. // 创建服务客户端对象(服务接口类型,服务名)
  22.     rclcpp::Client<learning_interface::srv::AddTwoInts>::SharedPtr client =
  23.         node->create_client<learning_interface::srv::AddTwoInts>("add_two_ints");            

  24. // 创建服务接口数据
  25. auto request = std::make_shared<learning_interface::srv::AddTwoInts::Request>();          
  26.     request->a = atoll(argv[1]);
  27.     request->b = atoll(argv[2]);

  28. // 循环等待服务器端成功启动
  29. while (!client->wait_for_service(1s)) {                                                  
  30. if (!rclcpp::ok()) {
  31.             RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");
  32. return0;
  33.         }
  34.         RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");
  35.     }

  36. // 异步方式发送服务请求
  37. auto result = client->async_send_request(request);                                        

  38. // 接收服务器端的反馈数据
  39. if (rclcpp::spin_until_future_complete(node, result) ==
  40.         rclcpp::FutureReturnCode::SUCCESS)                                                    
  41.     {
  42. // 将收到的反馈信息打印输出
  43.         RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Sum: %ld", result.get()->sum);            
  44.     } else {
  45.         RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service add_two_ints");
  46.     }

  47. // 关闭ROS2 C++接口
  48.     rclcpp::shutdown();  
  49. return0;
  50. }

c. 服务端

  1. /***
  2. @作者: 古月居(www.guyuehome.com)
  3. @说明: ROS2服务示例-提供加法器的服务器处理功能
  4. ***/

  5. #include "rclcpp/rclcpp.hpp"// ROS2 C++接口库
  6. #include "learning_interface/srv/add_two_ints.hpp"// 自定义的服务接口

  7. #include <memory>

  8. // 创建回调函数,执行收到请求后对数据的处理
  9. void adderServer(conststd::shared_ptr<learning_interface::srv::AddTwoInts::Request> request,
  10. std::shared_ptr<learning_interface::srv::AddTwoInts::Response>      response)
  11. {
  12. // 完成加法求和计算,将结果放到反馈的数据中
  13.     response->sum = request->a + request->b;
  14. // 输出日志信息,提示已经完成加法求和计算                                                    
  15.     RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming request\na: %ld"" b: %ld",            
  16.                 request->a, request->b);
  17.     RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "sending back response: [%ld]", (longint)response->sum);
  18. }

  19. // ROS2节点主入口main函数
  20. int main(int argc, char **argv)                                                                
  21. {
  22. // ROS2 C++接口初始化
  23.     rclcpp::init(argc, argv);
  24. // 创建ROS2节点对象并进行初始化                                                                  
  25. std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("service_adder_server");  
  26. // 创建服务器对象(接口类型、服务名、服务器回调函数)  
  27.     rclcpp::Service<learning_interface::srv::AddTwoInts>::SharedPtr service =
  28.         node->create_service<learning_interface::srv::AddTwoInts>("add_two_ints", &adderServer);  

  29.     RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Ready to add two ints.");

  30. // 循环等待ROS2退出
  31.     rclcpp::spin(node);    
  32. // 关闭ROS2 C++接口                                                                    
  33.     rclcpp::shutdown();                                                                        
  34. }

d.命令行操作

  1. ros2 service list# 查看服务列表
  2. ros2 service type <service_name>   # 查看服务数据类型
  3. ros2 service call <service_name><service_type><service_data># 发送服务请求


通信接口




同ROS1一样ROS2同样有的可自定义的通信接口,这些通信接口大大拓展了ROS的应用场景
具体的自定义接口的方法可以看官方文档或者


动作


动作是一种应用层的通信机制,其底层是基于话题和服务实现的

a. 服务端

  1. /***
  2. @作者: 古月居(www.guyuehome.com)
  3. @说明: ROS2动作示例-负责执行圆周运动动作的服务端
  4. ***/

  5. #include <iostream>

  6. #include "rclcpp/rclcpp.hpp"                          // ROS2 C++接口库
  7. #include "rclcpp_action/rclcpp_action.hpp"            // ROS2 动作类
  8. #include "learning_interface/action/move_circle.hpp"  // 自定义的圆周运动接口

  9. usingnamespacestd;

  10. class MoveCircleActionServer : public rclcpp::Node
  11. {
  12. public:
  13. // 定义一个自定义的动作接口类,便于后续使用
  14. using CustomAction = learning_interface::action::MoveCircle;
  15. // 定义一个处理动作请求、取消、执行的服务器端
  16. using GoalHandle = rclcpp_action::ServerGoalHandle<CustomAction>;

  17. explicit MoveCircleActionServer(const rclcpp::NodeOptions & action_server_options = rclcpp::NodeOptions())
  18.         : Node("action_move_server", action_server_options)                                     // ROS2节点父类初始化
  19.         {
  20. usingnamespacestd::placeholders;

  21. this->action_server_ = rclcpp_action::create_server<CustomAction>(                  // 创建动作服务器(接口类型、动作名、回调函数)
  22. this->get_node_base_interface(),
  23. this->get_node_clock_interface(),
  24. this->get_node_logging_interface(),
  25. this->get_node_waitables_interface(),
  26. "move_circle",
  27. std::bind(&MoveCircleActionServer::handle_goal, this, _1, _2),
  28. std::bind(&MoveCircleActionServer::handle_cancel, this, _1),
  29. std::bind(&MoveCircleActionServer::handle_accepted, this, _1));
  30.         }

  31. private:
  32.         rclcpp_action::Server<CustomAction>::SharedPtr action_server_;  // 动作服务器

  33. // 响应动作目标的请求
  34.         rclcpp_action::GoalResponse handle_goal(
  35. const rclcpp_action::GoalUUID & uuid,
  36. std::shared_ptr<const CustomAction::Goal> goal_request)                            
  37.         {
  38.             RCLCPP_INFO(this->get_logger(), "Server: Received goal request: %d", goal_request->enable);
  39.             (void)uuid;

  40. // 如请求为enable则接受运动请求,否则就拒绝
  41. if (goal_request->enable)                                                          
  42.             {
  43. return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
  44.             }
  45. else
  46.             {
  47. return rclcpp_action::GoalResponse::REJECT;
  48.             }
  49.         }

  50. // 响应动作取消的请求
  51.         rclcpp_action::CancelResponse handle_cancel(
  52. conststd::shared_ptr<GoalHandle> goal_handle_canceled_)                            
  53.         {
  54.             RCLCPP_INFO(this->get_logger(), "Server: Received request to cancel action");
  55.             (void) goal_handle_canceled_;
  56. return rclcpp_action::CancelResponse::ACCEPT;
  57.         }

  58. // 处理动作接受后具体执行的过程
  59. void handle_accepted(conststd::shared_ptr<GoalHandle> goal_handle_accepted_)          
  60.         {
  61. usingnamespacestd::placeholders;
  62. // 在线程中执行动作过程
  63. std::thread{std::bind(&MoveCircleActionServer::execute, this, _1), goal_handle_accepted_}.detach();
  64.         }


  65. void execute(conststd::shared_ptr<GoalHandle> goal_handle_)
  66.         {
  67. constauto requested_goal = goal_handle_->get_goal();       // 动作目标
  68. auto feedback = std::make_shared<CustomAction::Feedback>(); // 动作反馈
  69. auto result = std::make_shared<CustomAction::Result>();     // 动作结果

  70.             RCLCPP_INFO(this->get_logger(), "Server: Executing goal");
  71.             rclcpp::Rate loop_rate(1);

  72. // 动作执行的过程
  73. for (int i = 0; (i < 361) && rclcpp::ok(); i=i+30)
  74.             {
  75. // 检查是否取消动作
  76. if (goal_handle_->is_canceling())
  77.                 {
  78.                     result->finish = false;
  79.                     goal_handle_->canceled(result);
  80.                     RCLCPP_INFO(this->get_logger(), "Server: Goal canceled");
  81. return;
  82.                 }

  83. // 更新反馈状态
  84.                 feedback->state = i;
  85. // 发布反馈状态
  86.                 goal_handle_->publish_feedback(feedback);
  87.                 RCLCPP_INFO(this->get_logger(), "Server: Publish feedback");

  88.                 loop_rate.sleep();
  89.             }

  90. // 动作执行完成
  91. if (rclcpp::ok())
  92.             {
  93.                 result->finish = true;
  94.                 goal_handle_->succeed(result);
  95.                 RCLCPP_INFO(this->get_logger(), "Server: Goal succeeded");
  96.             }
  97.         }
  98. };

  99. // ROS2节点主入口main函数
  100. int main(int argc, char * argv[])                                
  101. {
  102. // ROS2 C++接口初始化
  103.     rclcpp::init(argc, argv);                        

  104. // 创建ROS2节点对象并进行初始化            
  105.     rclcpp::spin(std::make_shared<MoveCircleActionServer>());  

  106. // 关闭ROS2 C++接口  
  107.     rclcpp::shutdown();                                          

  108. return0;
  109. }

b. 客户端

  1. /***
  2. @作者: 古月居(www.guyuehome.com)
  3. @说明: ROS2动作示例-请求执行圆周运动动作的客户端
  4. ***/

  5. #include <iostream>

  6. #include "rclcpp/rclcpp.hpp"                          // ROS2 C++接口库
  7. #include "rclcpp_action/rclcpp_action.hpp"            // ROS2 动作类
  8. #include "learning_interface/action/move_circle.hpp"  // 自定义的圆周运动接口

  9. usingnamespacestd;

  10. class MoveCircleActionClient : public rclcpp::Node
  11. {
  12. public:
  13. // 定义一个自定义的动作接口类,便于后续使用
  14. using CustomAction = learning_interface::action::MoveCircle;
  15. // 定义一个处理动作请求、取消、执行的客户端类
  16. using GoalHandle = rclcpp_action::ClientGoalHandle<CustomAction>;

  17. explicit MoveCircleActionClient(const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions())
  18.         : Node("action_move_client", node_options)                            // ROS2节点父类初始化
  19.         {
  20. this->client_ptr_ = rclcpp_action::create_client<CustomAction>(   // 创建动作客户端(接口类型、动作名)
  21. this->get_node_base_interface(),
  22. this->get_node_graph_interface(),
  23. this->get_node_logging_interface(),
  24. this->get_node_waitables_interface(),
  25. "move_circle");
  26.         }

  27. // 创建一个发送动作目标的函数
  28. void send_goal(bool enable)
  29.         {
  30. // 检查动作服务器是否可以使用
  31. if (!this->client_ptr_->wait_for_action_server(std::chrono::seconds(10)))
  32.             {
  33.                 RCLCPP_ERROR(this->get_logger(), "Client: Action server not available after waiting");
  34.                 rclcpp::shutdown();
  35. return;
  36.             }

  37. // 绑定动作请求、取消、执行的回调函数
  38. auto send_goal_options = rclcpp_action::Client<CustomAction>::SendGoalOptions();
  39. usingnamespacestd::placeholders;
  40.             send_goal_options.goal_response_callback =
  41. std::bind(&MoveCircleActionClient::goal_response_callback, this, _1);
  42.             send_goal_options.feedback_callback =
  43. std::bind(&MoveCircleActionClient::feedback_callback, this, _1, _2);
  44.             send_goal_options.result_callback =
  45. std::bind(&MoveCircleActionClient::result_callback, this, _1);

  46. // 创建一个动作目标的消息
  47. auto goal_msg = CustomAction::Goal();
  48.             goal_msg.enable = enable;
  49. // 异步方式发送动作的目标
  50.             RCLCPP_INFO(this->get_logger(), "Client: Sending goal");
  51. this->client_ptr_->async_send_goal(goal_msg, send_goal_options);
  52.         }

  53. private:
  54.         rclcpp_action::Client<CustomAction>::SharedPtr client_ptr_;

  55. // 创建一个服务器收到目标之后反馈时的回调函数
  56. void goal_response_callback(GoalHandle::SharedPtr goal_message)
  57.         {
  58. if (!goal_message)
  59.             {
  60.                 RCLCPP_ERROR(this->get_logger(), "Client: Goal was rejected by server");
  61.                 rclcpp::shutdown(); // Shut down client node
  62.             }
  63. else
  64.             {
  65.                 RCLCPP_INFO(this->get_logger(), "Client: Goal accepted by server, waiting for result");
  66.             }
  67.         }

  68. // 创建处理周期反馈消息的回调函数
  69. void feedback_callback(
  70.             GoalHandle::SharedPtr,
  71. conststd::shared_ptr<const CustomAction::Feedback> feedback_message)
  72.         {
  73. std::stringstream ss;
  74.             ss << "Client: Received feedback: "<< feedback_message->state;
  75.             RCLCPP_INFO(this->get_logger(), "%s", ss.str().c_str());
  76.         }

  77. // 创建一个收到最终结果的回调函数
  78. void result_callback(const GoalHandle::WrappedResult & result_message)
  79.         {
  80. switch (result_message.code)
  81.             {
  82. case rclcpp_action::ResultCode::SUCCEEDED:
  83. break;
  84. case rclcpp_action::ResultCode::ABORTED:
  85.                     RCLCPP_ERROR(this->get_logger(), "Client: Goal was aborted");
  86.                     rclcpp::shutdown(); // 关闭客户端节点
  87. return;
  88. case rclcpp_action::ResultCode::CANCELED:
  89.                     RCLCPP_ERROR(this->get_logger(), "Client: Goal was canceled");
  90.                     rclcpp::shutdown(); // 关闭客户端节点
  91. return;
  92. default:
  93.                     RCLCPP_ERROR(this->get_logger(), "Client: Unknown result code");
  94.                     rclcpp::shutdown(); // 关闭客户端节点
  95. return;
  96.             }
  97.             RCLCPP_INFO(this->get_logger(), "Client: Result received: %s", (result_message.result->finish ? "true" : "false"));
  98.             rclcpp::shutdown();         // 关闭客户端节点
  99.         }
  100. };

  101. // ROS2节点主入口main函数
  102. int main(int argc, char * argv[])                                    
  103. {
  104. // ROS2 C++接口初始化
  105.     rclcpp::init(argc, argv);  

  106. // 创建一个客户端指针                                    
  107. auto action_client = std::make_shared<MoveCircleActionClient>();

  108. // 发送动作目标
  109.     action_client->send_goal(true);    

  110. // 创建ROS2节点对象并进行初始化                            
  111.     rclcpp::spin(action_client);  

  112. // 关闭ROS2 C++接口                                  
  113.     rclcpp::shutdown();                                              

  114. return0;
  115. }

c. 命令行操作

  1. $ ros2 action list                  # 查看服务列表
  2. $ ros2 action info <action_name>    # 查看服务数据类型
  3. $ ros2 action send_goal <action_name><action_type><action_data># 发送服务请求


参数



参数是ROS2模块化封装的重要功能,可以利用全局参数可视化显示以及动态调整
默认情况下,某一个参数被修改后,使用它的节点并不会立刻被同步,ROS2提供了动态配置的机制,需要在程序中进行设置,通过回调函数的方法,动态调整参数

关于参数,具体可以看https://docs.ros.org/en/jazzy/Concepts/Basic/About-Parameters.html#parameters


DDS



DS的全称是Data Distribution Service,也就是数据分发服务,2004年由对象管理组织OMG发布和维护,是一套专门为实时系统设计的数据分发/订阅标准,最早应用于美国海军, 解决舰船复杂网络环境中大量软件升级的兼容性问题,现在已经成为强制标准。

DDS强调以数据为中心,可以提供丰富的服务质量策略,以保障数据进行实时、高效、灵活地分发,可满足各种分布式实时通信应用需求。

在命令行中配置DDS

  1. $ ros2 topic pub /chatter std_msgs/msg/Int32"data: 42" --qos-reliability best_effort
  2. $ ros2 topic echo /chatter --qos-reliability reliable
  3. $ ros2 topic echo /chatter --qos-reliability best_effort
  4. $ ros2 topic info /chatter --verbose #查看节点的Qos策略


分布式通信



分布式通信是解决使用一台计算机算力不足的情况
有几个实用的例子,也是我自己在使用的:
一台电脑运行执行器节点 另一台电脑读取数据并使用QT可视化数据
一台电脑运行节点 另一台使用rviz等等



转载请申请。


FRANKA机器人因其高精度力控与开放式架构,在学术界广泛应用,成为具身智能与操作研究的主流平台。斯坦福、伯克利、CMU等顶尖实验室构建了丰富的软件生态,ROS、MoveIt 等工具无缝集成,使其在 ICRA、IROS、RSS 等顶会中成为最佳论文常用的验证平台。PNP机器人作为 FRANKA 在国内的官方合作伙伴,负责其技术支持、渠道建设与销售,并基于 FRANKA 开发了一系列生态工具,如遥操作、视觉、移动平台等,具身智能方向如有部署需求,可联系 PNP机器人获取支持。
图片

热点文章参考:

PNP&Franka机器人活动

WRC具身觉醒:当机器人初步长出“人类”的直觉——2025世界机器人大会热点讨论纪实

在具身智能火热加持下,看 2025 年机器人学术年会中的热点主题。PNP机器人展示力控、灵巧手捕捉等案例

具身智能在线活动总结:Franka Robotics与PNP机器人在具身智能领域的技术分享

具身直播活动:机器人大讲堂联合PNP机器人关于Franka机器人具身智能专题直播讨论

具身活动总结:PNP机器人在FAIR plus 2025机器人链接会中呈现具身智能机器人数据集和操作等多项技术

中国具身智能大会:具身智能发展迅速,PNP机器人展出和分享感悟全力控感知特点、操作策略局限以及数据采集等

PNP具身智能数据集总结

双臂类人形具身智能方向:一文汇总Franka机器人在科研、医疗等双臂机器人研究案例和双臂方案参考

机器人数据集:一文汇总机器人数据集RoboDataset的意义与机器人数据采集方法

机器人数据集:数据集越来越成为重要具身智能方向的基础设施—PNP机器人近期活动总结

PNP&FRANKA机器人发展

Franka机器人中国业务全新启航——Franka机器人的10个基本问题,一文掌握归来的力控机器人最新产品和趋势

技术要点分享:Franka机器人常见的10个问题——硬件篇,一文干货汇总。

中国具身智能大会:具身智能发展迅速,PNP机器人展出和分享感悟全力控感知特点、操作策略局限以及数据采集等

机器人操作策略

斯坦福大学李飞飞携Franka机器人创业空间智能提ReKep

具身方案和配置:基于“扩散策略”模仿学习训练机器人以及常用配置方案

OpenVLA:7B 参数开源 VLA模型,可以 HuggingFace下载和微调,支持 Open X-Embodiment


<<<  END >>>


关于集智联机器/PNP机器人

集智联机器人(Plug & Play Robotics),简称PNP机器人。PNP机器人团队成员均来自于ABB、Uninversal Robots(优傲机器人)等国内外机器人行业知名企业,学术背景来自于哈尔滨工业大学、多伦多大学、滑铁卢大学等,具有较强的学术背景。PNP机器人致力于为客户提供从硬件到软件的全方位支持,帮助客户快速实现机器人的部署与应用,提升生产效率和智能化水平


PNP机器人成立以来,先后获得“江苏省双创人才”、“姑苏领军”、“崇本领军、“吴江领军”等人才领军企业称号,公司具有较强科研能力,公司持续研发投入拥有技术发明等多项专利,是高新技术企业,科技中小企业;得益于推动在具身智能领域的最新技术和落地,PNP机器人获得”2024年中国科研贡献奖“

PNP机器人在具身智能方向和思灵机器人以及旗下Franka机器人金牌合作,聚焦面向生活和工业场景的单臂/双臂数据采集场景,致力于机器人即插即用(Plug & Play)技术和具身智能通用解决方案。

www.pnprobotics.com   (PNP机器人官方网站)

sales@pnprobotics.com (官方邮箱/Email Add.)

180 1817 5378(微信同号)


关注具身智能,关注PNP公众号

图片

具身智能技术对接/具身群

180 1817 5378(微信同号)

图片





Plug & Play Robotics
集智联机器人(苏州)有限公司

联系信息                            联系电话:86 138 1609 4093         联系邮箱:sales@plugplayrobotics.com            联系地址:江苏省苏州市吴江智能制造产业园C1栋