1.rosrun package-name executable-name 比如 rosrun turtlesim turtlesim_node
2.一旦啟動roscore后,便可以運行ROS程序了。ROS程序的運行實例被稱為節點(node),roscore叫做節點管理器
3.查看節點列表rosnode list
4.需要注意節點名並不一定與對應可執行文件名稱相同
5.可以使用 rosrun 命令顯式設置節點的名稱rosrun package-name executable-name __name:=node-name這種方法將使用 node-name 參數給出的名稱覆蓋節點的默
認名。
6.查看節點信息rosnode info node-name 終止節點 rosnode kill node-name
7.用 Ctrl-C 命令終止節點。但使用這種方法時可能不會在節點管理器中注銷該節點,因此會導致已終止的節點仍然在 rosnode 列表中。這雖然沒有什么壞處,但可能會讓用戶對當前系統的行為感到困擾。此時可以使用下面的命令將節點從列表中刪除:rosnode cleanup
8.ROS節點之間進行通信所利用的最重要的機制就是消息傳遞。在ROS中,消息有組織地存放在話題里。消息傳遞的理念是:當一個節點想要分享信息時,它就會發布(publish)消息到對應的一個或者多個話題;當一個節點想要接收信息時,它就會訂閱(subscribe)它所需要的一個或者多個話題。ROS節點管理器負責確保發布節點和訂閱節點能找到對方;而且消息是直接地從發布節點傳遞到訂閱節點,中間並不經過節點管理器轉交
9.在 ROS 系統中查看節點之間的發布-訂閱關系的最簡單方式就是在終端輸入如下命令:rqt_graph
10.所有的節點發布都向話題/rosout 發布消息,該話題由同名的/rosout 節點訂閱。這個話題的作用是用來生成各個節點的文本日志消息。
11.ROS 節點通常設計成了只管發布它們有用的信息,而不需要擔心是否有其他節點來訂閱這些消息。這樣有助於減少各個節點之間的耦合度。
12.獲得話題列表 rostopic list這個列表列舉的話題和 rqt_graph 中展示的話題應該是一樣的。
13.打印消息內容 rostopic echo topic-name
14.測量發布頻率rostopic hz topic-name,帶寬rostopic bw topic-name
15.查看話題rostopic info topic-name,可以獲得消息類型等信息
16.查看消息類型rosmsg show message-type-name
17.用命令發布消息rostopic pub –r rate-in-hz topic-name message-type message-content,如rostopic pub –r 1 /turtle1/cmd_vel geometry_msgs/Twist ’[2,0,0]’ ’[0,0,0]’
18.問題檢查:roswtf
19.創建工作區caktin_ws並創建src子目錄用於存放功能包代碼,mkdir -p ~/catkin_ws/src
20.src目錄下創建功能包catkin_create_pkg package-name,會產生兩個文件package.xml和CMakeLists.txt
21.頭文件 ros/ros.h 包含了標准 ROS 類的聲明,你將會在每一個你寫的 ROS 程序中包含它。下面是一個ros helloworld程序
// This is a ROS version of the standard "hello , world"
// program.
// This header defines the standard ROS classes .
#include <ros / ros.h>
int main ( int argc , char ** argv ) {
// Initialize the ROS system .
ros::init ( argc , argv , " hello _ros " ) ;
// Establ ish this program as a ROS node .
ros::NodeHandle nh ;
// Send some output as a log message .
ROS_INFO_STREAM( " Hello , ␣ ROS! " ) ;
}
22.編譯hello程序
(1)聲明依賴庫
在CmakeList.txt中修改 find_package(catkin REQUIRED COMPONENTS package-names)
在package.xml中修改<build_depend>package-name</build_depend>,<run_depend>package-name</run_depend>例如這里的package-name應該是roscpp
(2)聲明可執行文件
在CmakeList.txt中add_executable(executable-name source-files),target_link_libraries(executable-name ${catkin_LIBRARIES})
(3)編譯工作區catkin_make
(4)Sourcing setup.bash source devel/setup.bash
23.執行hello程序,rosrun 包名 可執行文件名
編寫一個發布者程序
#include <ros/ros.h>
#include <geometry_msgs/Twist.h> // For geometry_msgs:: Twist
#include <stdlib.h> // For rand() and RAND_MAX
int main (int argc, char** argv) {
// Initialize the ROS system and become a node .
ros::init(argc, argv, "publish_velocity");
ros::NodeHandle nh;
// Create a publisher obj ect .
ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("turtle1/cmd_vel", 1000) ;
// Seed the random number generator .
srand(time(0));
// Loop at 2Hz until the node is shut down.
ros::Rate rate(2);
while(ros::ok()) {
// Create and fill in the message. The other four
// fields, which are ignored by turtlesim, default to 0.
geometry_msgs::Twist msg;
msg.linear.x = double(rand()) / double(RAND_MAX);
msg.angular.z = 2 * double(rand()) / double(RAND_MAX) - 1;
// Publish the message .
pub.publish(msg);
// Send a message to rosout with the details .
ROS_INFO_STREAM("Sending random velocity command : "<<" linear=" << msg.linear.x<< " angular=" << msg.angular.z);
// Wait untilit's time for another iteration .
rate.sleep();
}
}
上面程序用來給turtlesim仿真器中的海龜發布隨機生成的指令,在添加完依賴后,執行結果如下圖
編寫一個訂閱者程序
我們繼續使用 turtlesim 作為測試平台,訂閱 turtlesim_node發布的/turtle1/pose 話題。這一話題的消息描述了海龜的位姿(位置和朝向)。
這里有三點需要注意:
1)編寫回調函數
發布和訂閱消息的一個重要的區別是訂閱者節點無法知道消息什么時候到達。為了應對這一事實,我們必須把響應收到消息事件的代碼放到回調函數里,ROS 每接收到一個新的消息將調用一次這個函數。訂閱者的回調函數類似於:
void function_name(const package_name::type_name &msg)
{
}
其中參數 package_name 和 type_name 和發布消息時的相同,它們指明了我們想訂閱的話題的消息類。回調函數的主體有權限訪問接收到消息的所有域,並以它認為合適的方式存儲、使用或丟棄接收到的數據。與往常一樣,我們必須包含定義該類的頭文件。
2)創建訂閱者對象
為了訂閱一個話題,我們需要創建一個ros::Subscriber對象 :
ros::Subscriber sub = node_handle.subscribe(topic_name,queue_size, pointer_to_callback_function);
這個構造函數有三個形參,其中大部分與 ros::Publisher 聲明中的類似,最后一個參數是回調函數的指針
3)給ROS控制權
最后的復雜之處在於只有當我們明確給ROS許可時,它才會執行我們的回調函數 。實際上有兩個略微不同的方式來做到這一點,其中一個版本如下所示:
ros::spinOnce();
這個代碼要求 ROS 去執行所有掛起的回調函數,然后將控制權限返回給我們。另一個方法如下所示:
ros::spin();
這個方法要求 ROS 等待並且執行回調函數,直到這個節點關機。換句話說,ros::spin()大體等於這樣一個循環:
while(ros::ok( ))
{
ros::spinOnce();
}
使用 ros::spinOnce()還是使用 ros::spin()的建議如下:你的程序除了響應回調函數,還有其他重復性工作要做嗎?如果答案是“否”,那么使用 ros::spin();否則,合理的選擇是寫一個循環,做其他需要做的事情,並且周期性地調用 ros::spinOnce()來處理回調。
訂閱者代碼
// This program subscribes to turtle1/pose and shows its
// messages on the screen .
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <turtlesim/Pose.h>
#include <iomanip> // for std::setprecision and std::fixed
// A callback function . Executed each time a new pose
// message arrives .
void poseMessageReceived ( const turtlesim::Pose& msg ) {
ROS_INFO_STREAM( std::setprecision(2) << std::fixed
<< " position =(" << msg.x << " , " << msg.y << " ) "
<< " *direction=" << msg.theta) ;
}
int main(int argc, char** argv) {
// Initialize the ROS system and become a node .
ros::init(argc, argv,"subscribe_to_pose");
ros::NodeHandle nh;
// Create a subscri ber obj ect .
ros::Subscriber sub = nh.subscribe("turtle1/pose", 1000, &poseMessageReceived);
// Let ROS take over.
ros::spin();
}
注意在CmakeList.txt添加turtlesim依賴后還會出現找不到turtlesim/Pose.h的情況,這時看看CmakeList中build中的include_directories塊有沒有被注釋掉,如果注釋掉就要打開
試驗結果:

左邊是訂閱者收到的消息,右邊是隨機發送的指令
24.通過 rosparam get /run_id 查看 run_id通過runid來查看日志消息
25.清除日志rosclean check ,rosclean purge
26.roslanch啟動多個節點的。其基本思想是在一個XML格式的文件內將需要同時啟動的一組節點羅列出來
一個launch文件例子
<launch>
<node name="turtlesim_node" pkg="turtlesim" type="turtlesim_node" ns="sim1" respawn="true" />
<node pkg="learn_ros" type="sub" name="sub_pose" output="screen" />
<node pkg="learn_ros" type="pub" required="true" launch-prefix="xterm -e" ns="sim1" name="pub"/>
<node name="turtlesim_node" pkg="turtlesim" type="turtlesim_node" ns="sim2" respawn="true" />
<node pkg="turtlesim" type="turtle_teleop_key" required="true" launch-prefix="xterm -e" ns="sim2" name="pub2"/>
</launch>
說明:respawn參數為真代表如果節點崩了過一會會自動重啟節點
output="screen"將結果輸出到屏幕
type的參數是可執行的文件名
pkg的參數是功能包名
required為真代表如果這個節點崩了,那么整個launch結束
launch-prefix="xterm -e"表示新開個終端顯示數據
ns是命名空間,用於分開控制兩只烏龜
上面launch執行后的結果如下:
launch中的重映射
重映射是基於替換的思想:每個重映射包含一個原始名稱和一個新名稱。每當節點使用重映射中的原始名稱時,ROS客戶端庫就會將它默默地替換成其對應的新名稱。
<remap from="turtle1 /cmd_vel" to="turtle1 /cmd_vel_reversed" />
這樣原來訂閱turtle1 /cmd_vel的節點就會訂閱turtle1 /cmd_vel_reversed的消息了
下面是一個包含其他launch文件的示例
<launch>
<include file ="$(find learn_ros)/doublesim.launch" />
<arg name="use_sim3" default="0" />
<group ns="sim3" if="$(arg use_sim3)" >
<node name="turtlesim_node" pkg="turtlesim " type="turtlesim_node" />
<node pkg="turtlesim " type="turtle_teleop_key" name="teleop_key" required="true " launch-prefix="xterm -e"/>
</group>
</launch>
其中use_sim3是參數,可以通過roslaunch learn_ros example.launch use_sim3:=1 來賦值
group可以將一些節點分組到同一個命名空間 sim3