在ros2下使用ros1_bridge与ros1自定义消息桥接
示例环境
操作系统:ubuntu 20.04 amd64
ros版本:noetic
ros2版本:foxy
ros1示例代码
-
创建ros1的工作空间catkin_ws,功能包custom_msgs,并创建一个msg文件TestNoetic.msg
TestNoetic.msg文件内容如下:
string test_str1 int32 test_int1
编译功能包,由于大家对ros1很熟悉了,所以此处不在介绍ros1编译的细节;
-
创建ros2的工作空间colcon_ws,功能包custom_msgs,并创建一个msg文件TestFoxy.msg
ros2创建包指令:
ros2 pkg create --build-type ament_cmake custom_msgs
TestFoxy.msg文件内容如下:
string test_str2 int32 test_int2
注意事项:ros2的msg文件命名有正则表达式的规定,要以大写字母开头,文件内容中的每个变量不可以存在大写字母,更详细的规则请参考官方文档
-
由于示例中要桥接的消息的文件名和内部变量名不一样,所以需要定义映射文件mapping_rules.yaml
- ros1_package_name: 'custom_msgs' ros1_message_name: 'TestNoetic' ros2_package_name: 'custom_msgs' ros2_message_name: 'TestFoxy' fields_1_to_2: test_str1: 'test_str2' test_int1: 'test_int2'
此映射文件放在package.xml同级目录下即可,此文件中只需要在两个包名或msg名或者变量名不相同时给出,如果名称都相同可以省略,如果存在此文件,则CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.5) project(custom_msgs) # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() find_package(ament_cmake REQUIRED) find_package(builtin_interfaces REQUIRED) find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(custom_msgs msg/TestFoxy.msg DEPENDENCIES builtin_interfaces ) install(FILES mapping_rules.yaml DESTINATION share/${PROJECT_NAME} ) ament_export_dependencies(rosidl_default_runtime) ament_package()
package.xml如下:
<?xml version="1.0"?> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> <package format="3"> <name>custom_msgs</name> <version>0.0.0</version> <description>The custom_msgs package</description> <maintainer email="weibw@todo.todo">weibw</maintainer> <license>TODO</license> <depend>rclpy</depend> <depend>builtin_interfaces</depend> <depend>rosidl_default_generators</depend> <member_of_group>rosidl_interface_packages</member_of_group> <export> <build_type>ament_cmake</build_type> <ros1_bridge mapping_rules="mapping_rules.yaml"/> </export> </package>
-
编译ros2下的custom_msgs功能包
source /opt/ros/foxy/setup.bash cd colcon_ws colcon build --packages-select custom_msgs
-
下载ros1_bridge源码,由于我们要桥接自定义消息,所以ros1_bridge必须重新编译
源码到github自行下载,放到colcon_ws工作空间中
source /opt/ros/noetic/setup.bash source /opt/ros/foxy/setup.bash source catkin_ws/devel/setup.bash source colcon/install/setup.bash cd colcon_ws colcon build --packages-select ros1_bridge --cmake-force-configure
编译完成后命令行输入:
source colcon/install/setup.bash ros2 run ros1_bridge dynamic_bridge --print-pairs | grep custom_msgs
如果显示:
- 'custom_msgs/msg/TestFoxy' (ROS 2) <=> 'custom_msgs/TestNoetic' (ROS 1)
则代表桥接数据转换成功
-
编译通过后再创建一个测试用的ros2软件包bridge_test,编写一个简单的订阅器来监听话题,验证桥接是否成功
ros2 pkg create --build-type ament_cmake bridge_test --dependencies custom_msgs
创建test.cpp,内容如下
#include <memory> #include "rclcpp/rclcpp.hpp" #include "custom_msgs/msg/test_foxy.hpp" using std::placeholders::_1; class MinimalSubscriber : public rclcpp::Node { public: MinimalSubscriber() : Node("minimal_subscriber") { subscription_ = this->create_subscription<custom_msgs::msg::TestFoxy>( "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1)); } private: void topic_callback(const custom_msgs::msg::TestFoxy::SharedPtr msg) const { RCLCPP_INFO(this->get_logger(), "I heard custom_msgs::msg::TestFoxy : '%d'", msg->test_int); } rclcpp::Subscription<custom_msgs::msg::TestFoxy>::SharedPtr subscription_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<MinimalSubscriber>()); rclcpp::shutdown(); return 0; }
CMakelists.txt如下
cmake_minimum_required(VERSION 3.5) project(bridge_test) # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(custom_msgs REQUIRED) add_executable(subscriber src/test.cpp) ament_target_dependencies(subscriber rclcpp custom_msgs) install(TARGETS subscriber DESTINATION lib/${PROJECT_NAME}) ament_package()
package.xml如下
<?xml version="1.0"?> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> <package format="3"> <name>bridge_test</name> <version>0.0.0</version> <description>TODO: Package description</description> <maintainer email="weibw@todo.todo">weibw</maintainer> <license>TODO: License declaration</license> <buildtool_depend>ament_cmake</buildtool_depend> <depend>rclcpp</depend> <depend>custom_msgs</depend> <test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_common</test_depend> <export> <build_type>ament_cmake</build_type> </export> </package>
编译功能包
cd colcon_ws colcon build --packages-select bridge_test
-
验证桥接自定义消息是否成功
在ros1环境下使用命令行工具以固定频率向外广播话题数据
source /opt/ros/noetic/setup.bash source catkin_ws/devel/setup.bash roscore& rostopic pub topic custom_msgs/TestNoetic "test_str1: 'hello' test_int: 234" -r 2
在ros2环境下运行订阅节点
source /opt/ros/foxy/setup.bash source colcon_ws/install/setup.bash ros2 run bridge_test subscriber
运行ros1_bridge
source /opt/ros/noetic/setup.bash source /opt/ros/foxy/setup.bash source catkin_ws/devel/setup.bash source colcon/install/setup.bash ros2 run ros1_bridge dynamic_bridge
此时应该在ros2的订阅节点终端中看到如下打印:
[INFO] [1645162912.958789169] [minimal_subscriber]: I heard custom_msgs::msg::TestFoxy : '234'
至此,本文结束