2018年7月3日 星期二

ROS 2 create node - publisher / subscriber

紀錄ROS 2 ardent 版本下
如何建立workspace 及自定義msg type 並建立publisher 及 subscriber 程式

因為目前ROS 2 ardent 不支援catkin ,所以很多步驟還是得手動進行
如果沒將 source /opt/ros/ardent/setup.bash 放到bashrc,記得先進行一次source

在Windows 10建立ROS 2 node的方式跟Linux 一樣
package.xml 及cmake file 幾乎不用改 (只要改include path . link path )
使用VS2015 x64 Native Tools Command Prompt 設置ROS 2 環境變數後,進到workspace 輸入ament build

程式碼可以到以下github 查看部分sample
建立worksapce 及package
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
mkdir -p karl_demo/src
建立一個自定義的msg file  (ROS data format),ROS 2 可以在build 時自動gen 出idl file (DDS data format),再連鎖gen 出header 檔案開發用
注意msg 檔名要大寫開頭
cd ~/ros2_ws/src/karl_demo
mkdir msg
cd msg
vim Custom.msg
資料結構先定為一個uint32 的data
Custom.msg
uint32 data
建立cmake file 及package.xml 寫入所需的內容
並用ament gen 出 header
cd ~/ros2_ws/src/karl_demo
vim CMakeLists.txt
vim package.xml
cd ~/ros2_ws
ament build
ls install/include/karl_demo/msg/
#custom__functions.h
#custom.h
#custom.hpp
#custom__rosidl_typesupport_introspection_c.h
#custom__rosidl_typesupport_introspection_cpp.hpp
#custom__rosidl_typesupport_opensplice_c.h
#custom__rosidl_typesupport_opensplice_cpp.hpp
#custom__struct.h
#custom__struct.hpp
#custom__traits.hpp
#custom__type_support.h
#dds_opensplice
#dds_opensplice_c
#rosidl_generator_c__visibility_control.h
#rosidl_typesupport_introspection_c__visibility_control.h
#rosidl_typesupport_opensplice_cpp__visibility_control.h
#rosidl_typesupport_opensplice_c__visibility_control.h
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(karl_demo)
# 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(rclcpp REQUIRED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/Custom.msg"
)
ament_export_dependencies(rosidl_default_runtime)
ament_package()
package.xml
<?xml version="1.0"?>
<package format="3">
  <name>karl_demo</name>
  <version>0.0.3</version>
  <description>
    C++ nodes which were previously in the ros2/examples repository but are now just used for demo purposes.
  </description>
  <maintainer email="william@osrfoundation.org">William Woodall</maintainer>
  <license>Apache License 2.0</license>
  <buildtool_depend>ament_cmake</buildtool_depend>
  <buildtool_depend>rosidl_default_generators</buildtool_depend>
  <build_depend>rclcpp</build_depend>
  <exec_depend>rclcpp</exec_depend>
  <exec_depend>rosidl_default_runtime</exec_depend>
  <member_of_group>rosidl_interface_packages</member_of_group>
  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

接著先建立一個publisher 程式
並修改CMakeLists.txt
cd ~/ros2_ws/src/karl_demo/src
vim talker.cpp

talker.cpp
#include <iostream>
#include <memory>
#include <string>
#include "rclcpp/rclcpp.hpp"
#include "karl_demo/msg/custom.hpp"
int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  auto node = rclcpp::Node::make_shared("talker");//node name = talker
  rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
  custom_qos_profile.depth = 7;
  auto chatter_pub = node->create_publisher<karl_demo::msg::Custom>("chatter", custom_qos_profile);//topic name = chatter
  rclcpp::WallRate loop_rate(2);
  auto msg = karl_demo::msg::Custom();
  auto i = 1;
  while (rclcpp::ok()) {
    msg.data = i;
    std::cout << "Publishing: '" << msg.data << "'" << std::endl;
    chatter_pub->publish(msg);
    rclcpp::spin_some(node);
    loop_rate.sleep();
    i++;
  }
  return 0;
}
修改cmake file 並回到workspace build
cd ~/ros2_ws/src/karl_demo
vim CMakeLists.txt
cd ~/ros2_ws
ament build

CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(karl_demo)
# 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(rclcpp REQUIRED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/Custom.msg"
)
ament_export_dependencies(rosidl_default_runtime)
#########
find_package(karl_demo REQUIRED)
include_directories(include /home/karlkwchen/ros2_overlay_ws/install/include)
add_executable(talker src/talker.cpp)
ament_target_dependencies(talker rclcpp karl_demo)
install(TARGETS talker DESTINATION lib/${PROJECT_NAME})
ament_package()
執行talker
source ~/ros2_ws/install/local_setup.bash
ros2 run karl_demo talker
#Publishing: '1'
#Publishing: '2'
#Publishing: '3'
#Publishing: '4'
#Publishing: '5'
#Publishing: '6'
#Publishing: '7'
#Publishing: '8'
再開一個terminal,可以先用ros2 指令測試接收topic
注意topic 要加斜線
source ~/ros2_ws/install/local_setup.bash
ros2 topic echo /chatter karl_demo/Custom
#data: 2
#
#data: 3
#
#data: 4
#
#data: 5
#
#data: 6
#
#data: 7
#
#data: 8
如果要換成Opensplice 傳輸,先設變數再去啟動程式即可
export RMW_IMPLEMENTATION=rmw_opensplice_cpp
目前確定Opensplice 及 FastRTPS 在ROS 2b3 arch下可以互通

建立subscriber,範例如下
回去修改cmake 再重新ament build 即可
#include <iostream>
#include "rclcpp/rclcpp.hpp"
#include "karl_demo/msg/custom.hpp"
void callback(const karl_demo::msg::Custom::SharedPtr msg)
{
    printf("I heard [%d]\n", msg->data);
}
int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    auto node = rclcpp::Node::make_shared("listener");
    auto chatter_sub = node->create_subscription<karl_demo::msg::Custom>("chatter", callback);
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

沒有留言:

張貼留言

NoSQL Redis intro

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