当前位置: 首页 > news >正文

ros2 自定义消息、服务、动作接口详细范例

在ROS2中,自定义消息(.msg)、服务(.srv)和动作(.action)接口是扩展系统功能的核心。以下以完整工程结构为例,详细说明定义、编译和使用的全流程:

1. 项目结构

custom_interfaces/
├── CMakeLists.txt
├── package.xml
├── msg/
│   ├── MyMessage.msg
│   └── ...
├── srv/
│   ├── MyService.srv
│   └── ...
└── action/├── MyAction.action└── ...user_pkg/  # 使用自定义接口的包
├── CMakeLists.txt
├── package.xml
├── src/
│   ├── publisher_node.cpp
│   ├── subscriber_node.cpp
│   ├── service_server.cpp
│   ├── service_client.cpp
│   ├── action_server.cpp
│   └── action_client.cpp
└── ...

2. 自定义接口定义

消息(.msg)

custom_interfaces/msg/MyMessage.msg:

int32 id
string data
float64[3] values
服务(.srv)

custom_interfaces/srv/MyService.srv:

# 请求部分
string query
---
# 响应部分
bool success
string result
动作(.action)

custom_interfaces/action/MyAction.action:

# 目标(Goal)
int32 target_value
---
# 结果(Result)
bool achieved
float64 final_position
---
# 反馈(Feedback)
float64 progress

3. 编译配置(custom_interfaces包)

CMakeLists.txt关键部分:

cmake_minimum_required(VERSION 3.8)
project(custom_interfaces)find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)# 添加消息、服务、动作文件
rosidl_generate_interfaces(${PROJECT_NAME}"msg/MyMessage.msg""srv/MyService.srv""action/MyAction.action"DEPENDENCIES std_msgs
)ament_package()

package.xml关键依赖:

<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>

4. 使用自定义接口(user_pkg包)

消息发布/订阅示例

发布者节点(publisher_node.cpp):

#include "rclcpp/rclcpp.hpp"
#include "custom_interfaces/msg/my_message.hpp"int main(int argc, char **argv) {rclcpp::init(argc, argv);auto node = rclcpp::Node::make_shared("msg_publisher");auto pub = node->create_publisher<custom_interfaces::msg::MyMessage>("my_topic", 10);auto msg = custom_interfaces::msg::MyMessage();msg.id = 1;msg.data = "Hello ROS2";msg.values = {1.0, 2.0, 3.0};rclcpp::Rate loop_rate(1);while (rclcpp::ok()) {pub->publish(msg);loop_rate.sleep();}rclcpp::shutdown();return 0;
}

订阅者节点(subscriber_node.cpp):

#include "rclcpp/rclcpp.hpp"
#include "custom_interfaces/msg/my_message.hpp"void topic_callback(const custom_interfaces::msg::MyMessage &msg) {RCLCPP_INFO(rclcpp::get_logger("Subscriber"), "Received: ID=%d, Data=%s", msg.id, msg.data.c_str());
}int main(int argc, char **argv) {rclcpp::init(argc, argv);auto node = rclcpp::Node::make_shared("msg_subscriber");auto sub = node->create_subscription<custom_interfaces::msg::MyMessage>("my_topic", 10, topic_callback);rclcpp::spin(node);rclcpp::shutdown();return 0;
}
服务调用示例

服务端(service_server.cpp):

#include "rclcpp/rclcpp.hpp"
#include "custom_interfaces/srv/my_service.hpp"void handle_service(const std::shared_ptr<rmw_request_id_t> request_header,const std::shared_ptr<custom_interfaces::srv::MyService::Request> req,const std::shared_ptr<custom_interfaces::srv::MyService::Response> res
) {res->success = (req->query == "valid");res->result = "Processed: " + req->query;
}int main(int argc, char **argv) {rclcpp::init(argc, argv);auto node = rclcpp::Node::make_shared("srv_server");node->create_service<custom_interfaces::srv::MyService>("my_service", handle_service);rclcpp::spin(node);rclcpp::shutdown();return 0;
}

客户端(service_client.cpp):

#include "rclcpp/rclcpp.hpp"
#include "custom_interfaces/srv/my_service.hpp"int main(int argc, char **argv) {rclcpp::init(argc, argv);auto node = rclcpp::Node::make_shared("srv_client");auto client = node->create_client<custom_interfaces::srv::MyService>("my_service");auto request = std::make_shared<custom_interfaces::srv::MyService::Request>();request->query = "test_query";while (!client->wait_for_service(std::chrono::seconds(1))) {RCLCPP_WARN(node->get_logger(), "Service unavailable");}auto result = client->async_send_request(request);if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS) {RCLCPP_INFO(node->get_logger(), "Result: %s", result.get()->result.c_str());}rclcpp::shutdown();return 0;
}
动作调用示例

动作服务器(action_server.cpp):

#include "rclcpp/rclcpp.hpp"
#include "custom_interfaces/action/my_action.hpp"
#include "rclcpp_action/rclcpp_action.hpp"class ActionServer : public rclcpp::Node {
public:using MyAction = custom_interfaces::action::MyAction;explicit ActionServer() : Node("action_server") {action_server_ = rclcpp_action::create_server<MyAction>(this, "my_action",[this](const std::shared_ptr<Goal> goal) {RCLCPP_INFO(this->get_logger(), "Received goal: %d", goal->target_value);return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;},[this](const std::shared_ptr<Goal> goal) {// 取消逻辑return rclcpp_action::CancelResponse::ACCEPT;},[this](const std::shared_ptr<Goal> goal, const std::shared_ptr<Feedback> feedback) {feedback->progress = 0.5; // 更新反馈},[this](const std::shared_ptr<Goal> goal, const std::shared_ptr<Result> result) {result->achieved = true;result->final_position = 10.0;return rclcpp_action::ResultCode::SUCCEEDED;});}
private:rclcpp_action::Server<MyAction>::SharedPtr action_server_;
};

动作客户端(action_client.cpp):

#include "rclcpp/rclcpp.hpp"
#include "custom_interfaces/action/my_action.hpp"
#include "rclcpp_action/rclcpp_action.hpp"class ActionClient : public rclcpp::Node {
public:using MyAction = custom_interfaces::action::MyAction;explicit ActionClient() : Node("action_client") {action_client_ = rclcpp_action::create_client<MyAction>(this, "my_action");auto goal = MyAction::Goal();goal.target_value = 100;action_client_->async_send_goal(goal, [this](auto future) {auto result = future.get();if (!result) {RCLCPP_ERROR(this->get_logger(), "Goal failed");} else if (result->code == rclcpp_action::ResultCode::SUCCEEDED) {RCLCPP_INFO(this->get_logger(), "Success! Final position: %f", result->result->final_position);}});}
private:rclcpp_action::Client<MyAction>::SharedPtr action_client_;
};

5. 编译与运行

编译自定义接口包:

cd ~/ros2_ws
colcon build --packages-select custom_interfaces
source install/setup.bash

编译用户包:

colcon build --packages-select user_pkg
source install/setup.bash

运行示例:

# 消息测试
ros2 run user_pkg publisher_node
ros2 run user_pkg subscriber_node# 服务测试
ros2 run user_pkg service_server
ros2 run user_pkg service_client# 动作测试
ros2 run user_pkg action_server
ros2 run user_pkg action_client

6. 验证接口生成

# 检查消息类型
ros2 interface show custom_interfaces/msg/MyMessage# 检查服务类型
ros2 interface show custom_interfaces/srv/MyService# 检查动作类型
ros2 interface show custom_interfaces/action/MyAction

关键注意事项

  1. 依赖管理:确保package.xml中声明<build_depend><exec_depend>,并在CMakeLists.txt中链接rosidl_default_runtime
  2. 命名规范:接口名称需使用小写+下划线(如my_message),避免大写开头。
  3. 编译顺序:先编译custom_interfaces包,再编译使用它的包。
  4. 调试工具:使用rqt_graph查看节点/话题连接,ros2 topic echo验证数据。

通过以上步骤,您可完整实现ROS2中自定义消息、服务和动作接口的定义、编译与使用。实际开发中,可根据需求扩展接口字段和业务逻辑。

http://www.dtcms.com/a/462581.html

相关文章:

  • 企业网站托管后果html5和h5的区别
  • 做网站营业执照经营范围怎么填写如何修改asp网站栏目
  • css里的where选择器的用法
  • 网站人多怎么优化全网引擎搜索
  • 10-七麦js扣代码
  • 做一婚恋网站多少钱医疗网络营销方式
  • golang面经——sync相关
  • wordpress 财经插件wordpress mysql优化
  • 软考中级习题与解答——第十四章_UML建模(5)
  • 万网怎样做网站调试字体怎么装到wordpress
  • 【Open3D】Ch.2:点云体素下采样 | Python
  • 奉贤区做网站wordpress五分钟安装
  • 复杂网络仿真从入门到精通:0 学习路线
  • 怎样创建网站数据库服装租赁 网站 php
  • 礼品工艺品网站建设首页网站模板
  • 福州推广企业网站网站优化助手
  • Playwright MCP 使用归档:让 AI IDE 看懂 API 文档与流程图
  • 网站优化 情况公司注册地址在哪里查询
  • (二)Kafka学习笔记(p13-p23)
  • .net 微信网站开发wordpress 安装 此网页包含重定向循环
  • 【开题答辩过程】以《基于SpringBoot的消防安全应急培训管理平台》为例,不会开题答辩的可以进来看看
  • iis 创建网站o2o有哪些电商平台
  • 南京市环保局官方南京做网站wordpress制作404页面模板
  • python入门到入土---装饰器
  • 自己做网站不推广东莞网站建设哪家专业
  • ubuntu 安装应用
  • 重庆媒体网站建设单价做网站需要登录什么软件
  • 学生管理系统2.0(面向对象)
  • 桐庐建设局网站网络营销方案500字
  • 线段树上二分模板