2019年7月1日 星期一

ROS 2 Bridge to ROS

demo 如何讓ROS 及ROS 2 互通,至於動機是甚麼呢,因為還有很多功能或者用戶還是在ROS
注意需要先安裝ROS 及ROS 2
下載安裝官方的ros1_bridge package
文件顯示從source code 自己build 需要系統有4 GB 的RAM
sudo apt-get update
sudo apt-get install ros-ardent-ros1-bridge
# if you use beta 3 version , use below instead
# sudo apt-get install ros-r2b3-ros1-bridge
先開一個terminal 啟動roscore 
再開第二個terminal 啟動bridge,讓他連到roscore
export ROS_MASTER_URI=http://localhost:11311
ros2 run ros1_bridge dynamic_bridge
 
 
#created 2to1 bridge for topic '/chatter' with ROS 2 type 'std_msgs/String' and ROS 1 type ''
#[INFO] [ros1_bridge]: Passing message from ROS 2 ROS2_T to ROS 1 ROS1_T (showing msg only once per type) (ros2_callback() at /tmp/binarydeb/ros-r2b3-ros1-bridge-0.0.3/include/ros1_bridge/factory.hpp:144)
#removed 2to1 bridge for topic '/chatter'
再開兩個terminal 分別啟動ROS 及ROS 2 的node,就可以測試連通性了
ros2 run demo_nodes_cpp talker
#Publishing: 'Hello World: 1'
#Publishing: 'Hello World: 2'
#Publishing: 'Hello World: 3'
#Publishing: 'Hello World: 4'
#Publishing: 'Hello World: 5'
#Publishing: 'Hello World: 6'
#Publishing: 'Hello World: 7'
#Publishing: 'Hello World: 8'
#Publishing: 'Hello World: 9'
#Publishing: 'Hello World: 10'
#Publishing: 'Hello World: 11'
#Publishing: 'Hello World: 12'
#Publishing: 'Hello World: 13'
#Publishing: 'Hello World: 14'
#Publishing: 'Hello World: 15'
 
 
 
 
rosrun roscpp_tutorials listener
#[ INFO] [1513059523.468086510]: I heard: [Hello World: 3]
#[ INFO] [1513059523.967160215]: I heard: [Hello World: 4]
#[ INFO] [1513059524.467541429]: I heard: [Hello World: 5]
#[ INFO] [1513059524.967622988]: I heard: [Hello World: 6]
#[ INFO] [1513059525.467242192]: I heard: [Hello World: 7]
#[ INFO] [1513059525.967151196]: I heard: [Hello World: 8]
#[ INFO] [1513059526.467345780]: I heard: [Hello World: 9]
#[ INFO] [1513059526.967592714]: I heard: [Hello World: 10]
#[ INFO] [1513059527.467160224]: I heard: [Hello World: 11]
#[ INFO] [1513059527.967049629]: I heard: [Hello World: 12]
#[ INFO] [1513059528.467056936]: I heard: [Hello World: 13]
#[ INFO] [1513059528.967666693]: I heard: [Hello World: 14]
#[ INFO] [1513059529.467657316]: I heard: [Hello World: 15]


如果自己建立msg type,ROS 2 提供的ros1_bridge package 無法支援( 需要從source code 重新build ,目前還沒嘗試)
但也可以選擇自己寫一個bridge

其實原理就是一支程式同時使用ROS 及ROS 2 的API 來建構,如果只是要轉換自己的msg 不難(官方的ros1_bridge 用良好的架構處理多種的msg 轉換)
難的地方反而是在link library !? (一開始想抄官方的cmake 寫,但因為他的模組化還需要時間消化修改才能用,最後是直接寫cmake 語法較簡單)
底下的source code,示範將ROS 的msg 轉丟到ROS 2 上( ROS 2 sub 可以收到ROS pub 的topic )
處理方式是在callback function 內將ROS 的msg sample copy 塞到ROS 2 的msg sample
此處的package name 在ROS 及ROS 2 剛好都叫 beginner_tutorials ,可以不一樣
bridge.cpp
#include <iostream>
#include <memory>
 
#ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-parameter"
#endif
#include "ros/ros.h"
//your custom msg header in ROS
#include "beginner_tutorials/Daq.h"
#ifdef __clang__
# pragma clang diagnostic pop
#endif
 
#include "rclcpp/rclcpp.hpp"
//your custom msg header in ROS 2
#include "beginner_tutorials/msg/daq.hpp"
 
rclcpp::Publisher<beginner_tutorials::msg::Daq>::SharedPtr pub;
 
void callback(const beginner_tutorials::Daq::ConstPtr & ros1_msg)
{
  std::cout << "I heard: [" << ros1_msg->length << "]" << std::endl;
 
  auto ros2_msg = std::make_shared<beginner_tutorials::msg::Daq>();
  ros2_msg->length = ros1_msg->length;
  for(int i=0;i<ros1_msg->length;i++)
    ros2_msg->data.push_back(ros1_msg->data[i]);
  pub->publish(ros2_msg);
}
 
int main(int argc, char * argv[])
{
  // ROS 2 node and publisher
  rclcpp::init(argc, argv);
  auto node = rclcpp::Node::make_shared("bridger2");
  pub = node->create_publisher<beginner_tutorials::msg::Daq>("test");
 
  // ROS 1 node and subscriber
  ros::init(argc, argv, "bridger1");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("test", 10, callback);
 
  ros::spin();
 
  return 0;
}
建置步驟
我是用ROS 2的ament 建置,所以檔案要放到ROS 2 的workspace 內
需要先gen 出ROS 2 的msg header file
修改cmake file,再底下加入如下內容

CMakeLists.txt
include_directories(include /opt/ros/kinetic/include)
 
add_executable(bridge src/bridge.cpp)
target_link_libraries(bridge /opt/ros/kinetic/lib/libroscpp.so)
target_link_libraries(bridge /opt/ros/kinetic/lib/librosconsole.so)
target_link_libraries(bridge /opt/ros/kinetic/lib/libroscpp_serialization.so)
ament_target_dependencies(bridge rclcpp beginner_tutorials )
 
install(TARGETS bridge DESTINATION lib/${PROJECT_NAME})
要做到以下三件事情
  • include ROS header
  • link ROS library
  • include ROS msg header ( 程式碼的這行#include "beginner_tutorials/Daq.h" )
    • 因為我將Daq.h 放到ROS 2 的workspace 所以不用寫到cmake file 內了
cd ~/ros2_ws
ament build
啟動步驟跟用官方的一樣

沒有留言:

張貼留言

NoSQL Redis intro

Redis是一個使用ANSI C編寫的開源、支援網路、基於記憶體、可選永續性的鍵值對儲存資料庫。 支援rdb 及aof 兩種儲存方式 From  https://zh.wikipedia.org/wiki/Redis Redis 目前擁有兩種資料...