ROS學習快速索引

基礎相關

創建工作空間(workspace)

ROS中整體代碼是在工作空間中運行,因此我們需要先創建工作空間。假定我們的工作空間爲test_ws,創建步驟如下:

  1. 創建文件夾test_ws/src,或者在某個路徑下(自己想要創建工作空間的路徑)輸入:mkdir -p test_ws/src
  2. 進入src目錄,打開終端輸入catkin_init_workspace命令對新空間初始化,完成後在src文件夾下會出現CMakeList.txt文件;
  3. 終端返回test_ws目錄(可以在第2步的前提下輸入cd ..),在該終端下輸入catkin_make對工作空間進行編譯,完成後會在test_ws中出現build和devel文件。

創建成功!在test_ws中:

  • bulid:是編譯的中間文件;
  • devel:(developing縮寫)是最終的一個目標文件(可執行文件、腳本等);
  • src:源代碼存放位置;
    src/package1/include:存放庫文件(*.hpp,*.cpp,*.h,*.c)
    src/package1/action:存放動作(*.action)文件;
    src/package1/msg:存放消息(*.msg)
    src/package1/srv:存放服務器相關信息文件(*.srv)
    src/package1/launch:存放啓動文件(*.launch)
    src/package1/scripts:存放python文件(*.py)
    src/package1/src:存放package的源文件(*.cpp,*.c)
    src/package1/CMakeList.txt:catkin_make文件
    src/package1/package.xml:package的描述文件

創建ROS package

ROS中的包,需要存放在src文件夾下,假設包名爲pack_test,則創建步驟爲:

  1. 進入test_ws/src文件夾下,打開終端;
  2. 輸入catkin_create_pkg pack_test std_msgs roscpp創建包pack_test,其依賴爲std_msgs和roscpp(ROS標準消息類型和C++編譯環境);

命令結構爲:catkin_create_pkg [package_name] [depend1] [depend2] [depend3]

關於ROS package的一些命令:

  • rospack profile:查看新添加包的信息;
  • rospack find [package_name]:查找指定包的位置;
  • rospack depends [package_name]:查看指定包的依賴;

消息傳輸機制

ROS的消息傳輸機制可以分爲Message、Action和Server

Publisher & Subcriber(Message)

Message通信雙方是Publisher和Subcriber,以下是C++程序示例:
Publisher:在pack_test包中的src文件下,創建Publisher.cpp文件,測試內容如下:

#include <ros/ros.h> // ros頭文件
#include <std_msgs/String.h> // 消息頭文件
#include <sstream> // stl字符串頭文件
int main(int argc, char **argv)
{
    // ROS初始化,名稱爲Publisher
    ros::init(argc, argv, "Publisher"); 
    // 創建節點句柄
    ros::NodeHandle n; 
    // 創建消息發佈變量,消息類型爲std_msgs::String,名稱爲message,緩存1000字節
    ros::Publisher pub = n.advertise<std_msgs::String>("message", 1000);
    // 創建發佈頻率變量,頻率爲10Hz
    ros::Rate loop_rate(10);
    // 如果ROS出於開啓狀態,則保持循環
    while (ros::ok()){
    //ros::ok()返回false,代表可能發生了以下事件
		//1.SIGINT被觸發(Ctrl-C)調用了ros::shutdown()
		//2.被另一同名節點踢出 ROS 網絡
		//3.ros::shutdown()被程序的另一部分調用
		//4.節點中的所有ros::NodeHandles 都已經被銷
     // 創建消息變量並,輸入信息: I am the publish node 
        std_msgs::String msg;
        std::stringstream ss;
        ss << " I am the publish node ";
        msg.data = ss.str();
        // 發佈消息
        pub.publish(msg);
        // 啓動ROS消息回調處理函數
        ros::spinOnce();
        // 等待
        loop_rate.sleep();
    }
    return 0;
}

Subcriber:在pack_test包中的src文件下,創建Subcriber.cpp文件,測試內容爲:

#include <ros/ros.h>
#include <std_msgs/String.h>
// 消息回調處理函數
void Callback(const std_msgs::String::ConstPtr& msg)
{
    // 將收到的消息打印出來
    ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
    ros::init(argc, argv, "Subscriber");
    ros::NodeHandle n;
    // 創建消息訂閱變量,消息名稱爲message,緩存1000字節,回調函數爲CallBack
    ros::Subscriber sub = n.subscribe("message", 1000, Callback);
    // 啓動ROS消息回調處理函數
    ros::spin();
    return 0;
}

之後,我們要在pack_test/CMakeList.txt中(最下面)添加如下內容:

# 添加路徑搜索目錄
include_directories(
include
${catkin_INCLUDE_DIRS}
)
# 添加節點的可執行文件
add_executable(subscirber_node src/Subscriber_node.cpp)
add_executable(publisher_node   src/Publisher_node.cpp)

# 添加節點可指定文件作需要鏈接的庫文件
target_link_libraries(subscriber_node ${catkin_LIBRARIES})
target_link_libraries(publisher_node   ${catkin_LIBRARIES})

最後,在test_ws中輸入catkin_make,編譯成功後,分別在test_ws中打開三個終端運行:

  1. roscore
  2. rosrun pack_test publisher_node
  3. rosrun pack_test subcriber_node

如果出現某個終端找不到pack_test,就在該終端輸入source devel/setup.bash

Publisher & Subcriber(Message Python版本)

ROS中可以使用Python作爲編程語言,其好處是不用編譯,不用寫CMakeLists.txt(只需要在CMakeList.txt中find_package內添加rospy,然後重新對包進行編譯,以獲得對python的支持),獲得腳本語言快速的編寫能力。我們將python腳本放入test_ws/src/pack_test/scripts,下面則是python對以上兩個節點進行重寫:
Publisher.py

#!/usr/bin/env python
# 添加ros函數庫
import rospy
# 添加std_msgs中String類型
from std_msgs.msg import String
# 初始化節點
rospy.init_node('publisher_node')
# 初始化發佈者,話題名稱messaage,類型String,緩存1000字節
pub = rospy.Publisher('message', String, queue_size = 1000)
# 發佈頻率10Hz
rate = rospy.Rate(10)
# 定義發佈的信息
msg = String()
msg = ' I am the talker node '
# 循環發佈
while not rospy.is_shutdown():
	pub.publish(msg)
	rate.sleep()

subscriber.py

#!/usr/bin/env python
import rospy
from std_msgs.msg import String
# 話題回調函數
def CallBack(msg):
	rospy.info('I heard %s"', msg.data)

rospy.init_node('subscriber_node')
# 初始化訂閱者,訂閱話題爲message,類型String,回調函數CallBack
sub = rospy.Subscriber('message', String, CallBack)
rospy.spin()

最後,我們在三個終端中依次運行:

  1. roscore
  2. rosrun pack_test publisher.py
  3. rosrun pack_test subscriber.py

launch文件初探

在終端中運行任何一個節點,我們都需要添加roscore的額外終端,不是很方便。ROS中提供了roslaunch命令,目的是實現同一個終端運行多個節點的目的,此命令會自動運行roscore節點,具體步驟爲:

  1. 在包(比如pack_test)中新建launch文件夾,並在其中創建node.launch文件(文件名自擬)。
  2. 在node.launch中添加以下內容:
<?xml version="1.0"  encoding="UTF-8" standalone="no"?>
<launch>
    <!-- Subscriber node, 節點名稱,包名,節點。output=“screen“將輸出打印到終端,如果是python的話,要在type中輸入python腳本名稱 -->
    <node name="subscirber_node" pkg="test" type="subscriber_node" output="screen"/>
    <!-- Publisher node -->
    <node name="publisher_node" pkg="test" type="publisher_node"/>
</launch>
  1. 在test_ws中新建終端運行roslaunch pack_test node.launch

通過在新的終端中鍵入rosnode list可以查看當前運行的節點,rostopic list可查看已發佈消息的名稱。

自定義message

test_ws/src/pack_test/msg中新建Pose.msg文件,寫入如下內容

float64 x
float64 y
float64 z

std_msgs文件中的變量類型與C++中的變量類型有如下的對應關係:

msg type c++ msg type C++
bool bool int64 long long
int8 char unit64 unsigned long
int8 unsigned char float32 float
int16 short float64 double
uint16 unsigned short string std::string
int32 int time ros::Time
uint32 unsigned int duration ros::Duration

此外msg還可以使用其他包中的消息類型,比如senor_msgs中的Image.msg等等,或者用戶自定義的消息類型,此時需要在generate_message中添加對這些包的依賴,並且在去掉add_dependencies註釋。
注意:如果當前包中使用了其他包中所定義的消息,服務和動作類型,需要添加add_dependencies項。
比如,在以上我們的自定消息Pose.msg文件,我們需要修改CMakeList.txt文件:

  1. 在find_package中加入message_generation的依賴;
  2. 在add_message_files中添加Pose.msg
  3. generate_messages中添加自定義消息的依賴

比如:

find_package(catkin REQUIRED COMPONENTS
std_msgs
roscpp
rospy
...
message_generation
)

add_message_files(
FILES
Pose.msg
)

generate_messages(
DEPENDENCIES
std_msgs
)

修改package.xml文件,去掉註釋:

<!--   <build_depend>message_generation</build_depend> -->
<!--   <exec_depend>message_runtime</exec_depend> -->
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章