程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

[ROS](09)ROS通信 —— 話題(Topic)通信編程之msg(C++)(Python)

編輯:Python

文章只是個人學習過程中學習筆記,主要參考ROS教程123


[ROS](01)創建ROS工作空間

[ROS](02)創建&編譯ROS軟件包Package

目錄

  • 1、概述
  • 2、msg結構和類型
    • 2.1 類型
    • 2.2 舉例
  • 3、msg命令rosmsg
  • 4、msg的用法
    • 4.1 創建msg
    • 4.2 配置CMakeLists.txt
    • 4.3 配置package.xml
    • 4.4 編譯package
  • 5、msg命令實操
    • 5.1 rosmsg list
    • 5.2 rosmsg packages
    • 5.3 rosmsg package
    • 5.4 rosmsg show / rosmsg info
    • 5.5 rosmsg md5
  • 6、實操編程 -- 話題通信發送自定義消息
    • 6.1 編寫程序(C++)
      • 6.1.1 發布者程序(talker.cpp)
      • 6.1.2 訂閱者程序(listener.cpp)
      • 6.1.3 配置CMakeLists.txt
      • 6.1.4 編譯、運行
    • 6.2 編寫程序(python)
      • 6.2.1 發布者程序(talker.py)
      • 6.2.2 訂閱者程序(listener.py)
      • 6.2.3 配置CMakeLists.txt
      • 6.1.4 編譯、運行

1、概述

msg(消息)文件就是文本文件,用於描述ROS消息的字段。它們用於為不同編程語言編寫的消息生成源代碼。
msg文件存放在軟件包的msg目錄下。

2、msg結構和類型

msg4文件就是簡單的文本文件,每行都有一個字段類型和字段名稱。它的結構為:
fieldtype + fieldname

2.1 類型

可以使用的類型為:

  • int8, int16, int32, int64 (以及 uint*)
  • float32, float64
  • string
  • time, duration
  • 其他msg文件
  • variable-length array[] 和 fixed-length array[C]

2.2 舉例

# 特殊的Header類型,它含有時間戳和ROS中廣泛使用的坐標幀信息
# 在msg文件的第一行經常可以看到Header header。
std_msgs/Header header
uint8 is_true
uint32 height
uint32 width
string child_frame_id
time stamp
geometry_msgs/PoseWithCovariance pose
geometry_msgs/TwistWithCovariance twist
uint8[] data

3、msg命令rosmsg

rosmsg顯示有關ROS消息類型的信息。

命令功能rosmsg show顯示消息的描述(詳細信息)rosmsg inforosmsg show的別名,功能一樣rosmsg list列出所有消息rosmsg md5顯示md5加密的消息rosmsg package列出某個軟件包(package)的消息rosmsg packages列出包含消息的軟件包(packages)

4、msg的用法

4.1 創建msg

還是在原來創建的軟件包 beginner_tutorials 中定義一個新的消息。

# 切換到軟件包的目錄路徑
roscd beginner_tutorials
# 創建msg文件夾目錄
mkdir msg
# 創建名為Num.msg的文件,並添加一個消息字段
echo "int64 num" > msg/Num.msg

4.2 配置CMakeLists.txt

1. 為已經存在裡面的find_package調用添加message_generation依賴項(),這樣就能生成消息了。(添加 message_generation 依賴項,必須有 std_msgs 。)

find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
message_generation
)

2. 添加自定義的消息文件。將你msg文件夾中自定義的*.msg文件添加在這裡。

add_message_files(
FILES
Num.msg
)

3. 用於生成所有定義的message文件,需要添加本文件需要依賴的packages。其實就是告訴編譯器,編譯 *.msg 文件時,需要依賴的庫或package。

generate_messages(
DEPENDENCIES
std_msgs
)

4. 導出消息的運行時依賴關系。

catkin_package(
...
CATKIN_DEPENDS message_runtime ...
...)

4.3 配置package.xml

添加編譯依賴與執行依賴。

 <build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

Node :在構建時,其實只需要message_generation,而在運行時,我們只需要message_runtime

4.4 編譯package

已經創建了一些新消息,所以需要重新make一下軟件包:

cd
cd catkin_ws
catkin_make


msg目錄中的任何.msg文件都將生成所有支持語言的代碼。

  • C++消息的頭文件將生成在~/catkin_ws/devel/include/beginner_tutorials/

  • python腳本將創建在~/catkin_ws/devel/lib/python2.7/dist-packages/beginner_tutorials/msg

5、msg命令實操

5.1 rosmsg list

rosmsg list 列出ROS中的所有消息(msg)。

5.2 rosmsg packages

rosmsg packages [options] 列出包含消息的軟件包。

# 列出包含消息的軟件包,每行顯示一個軟件包名
rosmsg packages
# 在一行中列出包含消息的軟件包
rosmsg packages -s

5.3 rosmsg package

rosmsg package [package-name] 列出某個軟件包(package)的消息。

5.4 rosmsg show / rosmsg info

rosmsg show [message type] 顯示消息的詳細信息。

5.5 rosmsg md5

rosmsg md5[message type] 顯示md5加密的消息。如果編譯的版本不匹配,這也會發出警告。

Node:md5 命令僅供專家用戶使用。(??)

6、實操編程 – 話題通信發送自定義消息

功能:基於話題通信,發布者以一定頻率發布自定義消息並打印輸出消息,訂閱者訂閱自定義消息並打印輸出消息。
實現
1. 創建發布者(talker)節點,該節點不斷廣播自定義消息。
2. 創建訂閱者(listener)節點,該節點持續接收自定義消息。
3. 創建自定義消息(Num.msg),(見4.1小節 創建msg
4. 發布訂閱話題chatter

Num.msgNum.msg talker chatter listener

6.1 編寫程序(C++)

beginner_tutorials軟件包的src目錄下創建發布者和訂閱者源文件:

roscd beginner_tutorials
cd src
touch talker.cpp listener.cpp

6.1.1 發布者程序(talker.cpp)

#include "ros/ros.h"
#include "beginner_tutorials/Num.h" // 在 /devel/include 目錄下
int main(int argc, char **argv)
{

/* 防止中文亂碼 */
setlocale(LC_ALL,"");
/* 初始化ROS節點 */
ros::init(argc, argv, "talker");
/* 為這個進程節點創建句柄 */
ros::NodeHandle nh;
/* 創建發布者對象 */
ros::Publisher pub = nh.advertise<beginner_tutorials::Num>("chatter", 1000);
/* 設定循環發布的頻率為1Hz */
ros::Rate loop_rate(1);
/* 要發布的消息 */
beginner_tutorials::Num msg;
msg.num = 0;
while(ros::ok())
{

ROS_INFO("當前num值為: %d",msg.num);
/* 發布消息 */
pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
msg.num += 1;
}
return 0;
}

對上邊的內容進行一下總結:

  • 初始化ROS系統
  • 向主節點宣告我們將要在chatter話題上發布beginner_tutorials/Num類型的消息
  • 以每秒1次的速率向chatter話題循環發布消息

6.1.2 訂閱者程序(listener.cpp)

#include "ros/ros.h"
#include "beginner_tutorials/Num.h" // 在 /devel/include 目錄下
/* 回調函數,當有新消息到達chatter話題時就會調用 */
void chatterCallback(const beginner_tutorials::Num::ConstPtr& msg)
{

ROS_INFO("已收到的Num的值: %d",msg->num);
}
int main(int argc, char **argv)
{

/* 防止中文亂碼 */
setlocale(LC_ALL,"");
/* 初始化ROS節點 */
ros::init(argc, argv, "listener");
/* 為這個進程節點創建句柄 */
ros::NodeHandle nh;
/* 創建訂閱者對象 * 通過節點管理器訂閱chatter話題。收到消息,調用回調函數chatterCallback。 * 第2個參數是隊列大小,>1000時,丟棄舊消息。 */
ros::Subscriber sub = nh.subscribe("chatter",1000, chatterCallback);
/* 啟動自循環 回調函數處理, 不占用太多CPU */
ros::spin();
return 0;
}

同樣地,我們來總結一下:

  • 初始化ROS系統
  • 訂閱chatter話題
  • 開始spin自循環,等待消息的到達
  • 當消息到達後,調用chatterCallback()函數

6.1.3 配置CMakeLists.txt

只需將這幾行添加到CMakeLists.txt文件的底部:

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener ${PROJECT_NAME}_generate_messages_cpp)

6.1.4 編譯、運行

編譯後,在終端中執行過程如下所示。

6.2 編寫程序(python)

beginner_tutorials軟件包的scripts目錄下創建發布者和訂閱者源文件:

roscd beginner_tutorials
cd scripts
touch talker.py listener.py
chmod +x talker.py listener.py

6.2.1 發布者程序(talker.py)

#!/usr/bin/env python
# encoding: utf-8
import rospy
from beginner_tutorials.msg import Num
def talker():
# 初始化ROS節點
rospy.init_node("talker",anonymous=True)
# 創建發布者對象
pub = rospy.Publisher('chatter', Num, queue_size=1000)
# 創建一個Rate對象rate,1Hz
rate = rospy.Rate(1)
# 要發布的消息
msg = Num()
msg.num = 0
# 循環
while not rospy.is_shutdown():
rospy.loginfo("當前num值為: %d",msg.num)
pub.publish(msg)
rate.sleep()
msg.num += 1
if __name__ == '__main__':
try:
talker()
except rospy.ROSInterruptException:
pass

6.2.2 訂閱者程序(listener.py)

#!/usr/bin/env python
# encoding: utf-8
import rospy
from beginner_tutorials.msg import Num
def callback(msg):
rospy.loginfo("已收到的Num的值: %d",msg.num)
def listener():
# 初始化ROS節點
rospy.init_node("listener",anonymous=True)
# 創建發布者對象
pub = rospy.Subscriber('chatter', Num, callback, queue_size=1000)
rospy.spin()
if __name__ == '__main__':
listener()

6.2.3 配置CMakeLists.txt

# 安裝python可執行腳本
catkin_install_python(PROGRAMS
scripts/turtle_publisher.py
scripts/talker.py
scripts/listener.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

6.1.4 編譯、運行

編譯後,在終端中執行過程如下所示。


  1. ROS.otg. ROS教程[EB/OL]. 2020-12-22[2022-7-5].
    http://wiki.ros.org/cn/ROS/Tutorials. ︎

  2. .ROS.org. 編寫簡單的發布者和訂閱者(C++)[EB/OL]. 2020-12-25[2022-07-30]. https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29. ︎

  3. .ROS.org. 編寫簡單的發布者和訂閱者(Python)[EB/OL]. 2020-12-25[2022-07-30]. https://wiki.ros.org/cn/ROS/Tutorials/WritingPublisherSubscriber%28python%29. ︎

  4. ROS.org. msg[EB/OL]. https://wiki.ros.org/msg[2022-07-30]. https://wiki.ros.org/msg.︎


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved