前言
- 已安裝ros,.bashrc配置完成
- 已建立catkin工作空間
- 已安裝rospy
生成一個新的catkin包
- 連結:
http://wiki.ros.org/ROS/Tutorials/CreatingPackage
- 打開一個terminal:
$ cd ~/catkin_ws/src
$ catkin_create_pkg beginner_tutorials std_msgs rospy roscpp
$ cd ..
$ catkin_make
上述指令完成後,
~/catkin_ws/src/beginner_tutorials/
下會自動生成
CMakeLists.txt
和
package.xml
對于非新打開的terminal,需要:
source ~/.bashrc
自定義話題消息
- 定義msg消息
$ cd ~/catkin_ws/src/beginner_tutorials/
$ mkdir msg
$ cd msg
$ touch Num.msg
$ rosed beginner_tutorials Num.msg (也可使用vim編輯:vim Num.msg)
在打開的視窗中,輸入資料格式,例如:
int64 num
。儲存退出
- 在package.xml中添加功能包依賴
$ rosed beginner_tutorials package.xml
- 找到
的位置(一般在文檔末尾)添加以下兩行:<build_xxx>
<build_export_depend>std_msgs</build_export_depend>
<build_depend>message_generation</build_depend>
- 檢視檔案添加結果:
$ tail -n +58 package.xml | head -n 2 (+58是行數,可根據實際情況調整)
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
添加完成後如圖:
3. 在CMakeLists.txt中添加編譯選項
- 增加對message_generation的依賴
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation # 在此處添加新的依賴
)
-
增加消息檔案
找到
的位置:首次打開CMakeLists.txt,add_message_files
是注釋的狀态,解開注釋即可。add_message_files
## Generate messages in the 'msg' folder
add_message_files(
FILES
Num.msg # 在此處添加新定義的消息
# Message1.msg
# Message2.msg
)
-
增加消息生成包
找到
的位置:首次打開CMakeLists.txt,catkin_package
是注釋的狀态,解開注釋即可。catkin_package
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES beginner_tutorials
CATKIN_DEPENDS roscpp rospy std_msgs message_runtime
# DEPENDS system_lib
)
-
添加msgs的軟體包依賴
找到
的位置:首次打開CMakeLists.txt,generate_messages
是注釋的狀态,解開注釋即可。generate_messages
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
std_msgs
)
- 編譯
$ cd ~/catkin_ws
$ catkin_make
- 檢查服務
$ rosmsg show beginner_tutorials/Num
int64 num
rospy話題通信
建立scripts:
$ roscd beginner_tutorials/
$ mkdir scripts
$ cd scripts/
$ touch publisher.py # 建立釋出者
$ touch listener.py # 建立訂閱者
python檔案中代碼的編寫,可以使用IDE,也可以使用rosed、vim等編輯器
建立釋出者:publisher.py
#!/usr/bin/python3 //指定python路徑,必需
# coding=utf-8
import rospy
from beginner_tutorials.msg import Num
def talker():
pub = rospy.Publisher('chatter', Num, queue_size = 10)
rate = rospy.Rate(10)
while not rospy.is_shutdown():
mynum = int(rospy.get_time())
msg = Num()
msg.num = mynum
rospy.loginfo(mynum)
pub.publish(msg)
rate.sleep()
if __name__ == '__main__':
rospy.init_node('msg_pub', anonymous=True)
try:
talker()
except rospy.ROSInterruptException:
pass
-
init_node注意事項
在主線程/主程序中聲明
-
anonymous傳參:
1)
True
:node名稱後會跟随時間戳,用以避免node重名
2)
:node唯一,ros意外中斷時,該節點需等待系統釋放False
建立訂閱者:listener.py
#!/usr/bin/python3 //指定python路徑,必需
#coding=utf-8
import rospy
from beginner_tutorials.msg import Num
def callback(data):
rospy.loginfo(rospy.get_caller_id() + ' I heard %d', data.num)
def listener():
rospy.Subscriber('chatter', Num, callback)
# spin() simply keeps python from exiting until this node is stopped
rospy.spin()
if __name__ == '__main__':
# In ROS, nodes are uniquely named. If two nodes with the same
# name are launched, the previous one is kicked off. The
# anonymous=True flag means that rospy will choose a unique
# name for our 'listener' node so that multiple listeners can
# run simultaneously.
rospy.init_node('msg_sub', anonymous=True)
listener()
運作
- 打開一個terminal,啟動ros master
$ roscore
- 新打開一個terminal,啟動釋出者
$ rosrun beginner_tutorials publisher.py
[INFO] [1656042406.758045]: 1656042406
[INFO] [1656042406.857847]: 1656042406
[INFO] [1656042406.957995]: 1656042406
[INFO] [1656042407.057947]: 1656042407
- 新打開一個terminal,啟動訂閱者
$ rosrun beginner_tutorials listener.py
[INFO] [1656042406.762065]: /msg_sub I heard 1656042406
[INFO] [1656042406.858974]: /msg_sub I heard 1656042406
[INFO] [1656042406.962152]: /msg_sub I heard 1656042406
[INFO] [1656042407.060434]: /msg_sub I heard 1656042407
檢視已開啟的node
$ rosnode list
/msg_pub
/msg_sub
/rosout
建立Launch
在beginner_tutorials目錄下,建立launch目錄:
$ cd ~/catkin_ws/src/beginner_tutorials
$ mkdir launch
$ cd launch
$ vim msg_pub_sub.launch
輸入:
<launch>
<node name="publisher" pkg="beginner_tutorials" type="publisher.py" />
<node name="listener" pkg="beginner_tutorials" type="listener.py" />
</launch>
儲存退出
附:
<node>
參數簡要說明:
參考連結:https://www.jianshu.com/p/e55850b87c7d
<launch>
<node
pkg=""
type=""
name=""
respawn="true"
required="true"
launch-prefix="xterm -e"
output="screen"
ns="some_namespace"
/>
</launch>
-
:node所在的 package 名稱pkg
-
: package 中的可執行檔案,如果是 python 或者 Julia 編寫的,就可能是type
或者.py
檔案,如果是 c++ 編寫的,就是源檔案編譯之後的可執行檔案的名字。.jl
-
:node啟動之後的名字, 每一個節點都要有自己獨一無二的名字。name
-
:若該node關閉,是否自動重新啟動respawn
-
:若該node關閉,是否關閉其他所有noderequired
-
: 是否新開一個視窗執行。例如,需要通過視窗進行機器人移動控制的時候,應該為控制 node 新開一個視窗;或者當 node 有些資訊輸出,不希望與其他 node 資訊混雜在一起的時候。launch-prefix
-
:預設情況下,launch 啟動 node 的資訊會存入下面的 log 檔案中output
/.ros/log/{$run_id}/node_name-number.log
可以通過此處參數設定,令資訊顯示在螢幕上
8.
ns
:将 node 歸入不同的 namespace,即在 node name 前邊加
ns
指定的字首。為了實作這類操作,在 node 源檔案中定義 node name 和 topic name 時要采用 relative name, 即不加slash符号
/
.
運作launch
- 打開一個terminal,啟動ros master(若已啟動roscore,該步驟省略)
$ roscore
-
新打開一個terminal,啟動launch
指令為:
roslaunch {$pkg_name} {$launchfile_name}.launch
$ roslaunch beginner_tutorials msg_pub_sub.launch
注:roslaunch 不能保證 node 的啟動順序,是以 launch 檔案中所有的 node 都應該對啟動順序有魯棒性。
- 日志檢視
- 使用指令:
$ rqt_console
-
檢視log檔案
檢視目前roscore運作的run_id:
$ rosparam get /run_id
e04b3b26-f386-11ec-b422-2cf05d2c73c1
# 注:這個數字是根據本機mac位址、運作時間等資訊生成的唯一UUID
檢視目前run_id的log:
$ cd ~/.ros/log/e04b3b26-f386-11ec-b422-2cf05d2c73c1
$ tail -f node_name-number.log 或者 vim node_name-number.log
參考連結:https://blog.csdn.net/betterzl/article/details/105835403