1. 程式人生 > >ROS/C++ 入門(Introduction to ROS/C++)

ROS/C++ 入門(Introduction to ROS/C++)

當我看到這一個教程的時候很興奮,因為這裡面的東西很實在,乾貨比較多。這個系列的教程有基於stage的模擬,有實物對照還是不錯的。所有的翻譯不一定完全遵照原文,摻雜有翻譯者的個人經驗和理解

主要內容:

1. ROS的入門介紹

3. 沿牆運動

1、ROS 入門介紹

ROS (Robot Operating System)

ROS是一個編寫機器人軟體很靈活的框架,它包含了工具集、庫和協議(conventions),這些包通過交叉不同的機器人平臺,可以簡化機器人的開發。
ROS支援多中作業系統,但是官方支援的是ubuntu,每一個版本ubuntu對應一個ROS版本,ROS indigo 版本對應的是ubuntu 14.04,kinetic對應ubuntu 16.04,本教程採用的是ros kinetic版本。
在ros下執行的可以理解為圖節點,通過ROS的通訊框架這些執行緒被鬆散耦合到一起。編寫ROS時候採用ROS的客戶端庫,ROS允許用不同程式編寫的節點進行通訊。節點既可以通過topic進行subscribe/publish,也可以服務(service)的方式進行通訊。ROS只有一個MASTER節點,它提供的是名稱檢索服務,幫助節點之間建立通訊。roscore的啟動命令:
roscore


節點啟動命令;
rosrun <package_name> <executable_name> <parameters>
如果有多個節點要啟動可以編寫launch檔案,通過roslaunch命令啟動。

建立包(packages)

編寫ROS程式時候需要首先建立一個package1,首先跳轉到路徑catkin_ws/src下面。執行下面的指令,
catkin_create_pkg <package_name> [dep1] ... [depN]
將package_name替換為自己的package名字,dep1 。。。 depN為依賴包,本教程中常用依賴項為:roscpp、std_msgs。編寫C++時候依賴包要包含roscpp,python程式需要rospy,用其他語言編寫ROS程式不推薦,因為支援的不是特別好。
新增依賴roscpp後,生成的包裡面會在目錄下面生成兩個新檔案(package.xml, CMakeLists.txt)和兩個新目錄(src/, include/),你可以在package.xml填寫這個package的相關資訊(作者,版本,名字、描述、、、) 。標頭檔案一般放在include目錄下面,原始檔放在src目錄下面。

準備 CMakeLists.txt

可以設定變數來包含所有必要的原始檔:
set (SRCS1 ${SRCS1} src/file_1.cpp)
set (SRCS1 ${SRCS1} src/file_2.cpp)
包含catkin檔案路徑:
include_directories(include ${catkin_INCLUDE_DIRS})
建立可執行檔案和catkin庫:
add_executable(executable_name ${SRCS1}) ## executable_name 節點的名字
target_link_libraries(executable_name ${catkin_LIBRARIES})

編譯程式

跳轉到catkin_ws目錄下面,執行下面的指令:
catkin_make

ROS and C++

如果是用C++編寫的ROS程式,必須新增roscpp依賴,ros.h裡面有常用的ros程式碼
#include "ros/ros.h"
ros程式正常執行必須得初始化
ros::init(argc, argv, "name_of_the_node");
初始化完成後需要一個Nodehandle進行ros的資源管理、通訊
ros::NodeHandle n;

Messages 和 topics

如上面提到的分立的節點之間是通過topic進行通訊的。每一個節點既可以publish 訊息到topic上面,也可以通過subscribe的方式獲得topic上的資訊。ROS裡面包含了很多種類的messages,也可以自己建立。基本的訊息型別包含在std_msgs包裡面。大多數的訊息裡面會包含:std_msgs::Header。你可以看到這個message的詳盡內容如下操作:
rosmsg show Header
輸出結果:
uint32 seq
time stamp
string frame_id

Header裡面包含了三個變數,seq序列號,保證傳送的多個訊息可以正確的排列,stamp是epoch格式的時間戳。frame_id為座標系名字,header的名字可以通過std_msgs::Header類在C++中訪問。
為了能夠釋出訊息,必須建立一個publisher物件:
ros::Publisher pub = n.advertise<std_msgs::Header>("topic_name", 1000);
1000為緩衝區的大小,通過pub函式進行傳送訊息:
pub.publish(message);
定於一個主題的時候需要建立一個callback函式,接收和處理訂閱的topic的訊息。
void callback(const std_msgs::Header::ConstPtr& msg);
建立一個subscriber,在訊息publish到topic上時候會呼叫這個callback函式。
ros::Subscriber sub = n.subscribe("topic_name", 1000, callback);
也可以把callback函式寫作類裡面:
ros::Subscriber sub = n.subscribe("topic_name", 1000, &SomeClass::callback, instanceOfThatClass);
最後呼叫spin,開始subscribe訊息:
ros::spin();

ROS常用除錯圖形化工具

rqt

這裡寫圖片描述

rviz

這裡寫圖片描述

機器人stage 模擬

下載模擬機器和環境:(右鍵另存為)
eci-arena.world
執行指令啟動模擬環境:
rosrun stage_ros stageros <path_to_the_world_file>/eci-arena.world

這裡寫圖片描述