<source : gazebo中的模擬截圖>

一、前言

開始進行ROS應用開發前,最重要的就是建立開發環境,常見的工作環境名稱為 "catkin_ws",也可以依據你的實際需求做其他命名。

在 "catkin_ws"中,通常會有 "src"、"build"、"devel"等3個資料夾。我們所撰寫或下載的程式碼都會放在"src"。"build" 是放置編譯過程中的暫存資料 ; "devel" 則是存放編譯完的資料。因此,在開發過程中,開發者僅會使用到 "src" 資料夾,而不會碰觸到 "build" 和 "devel" 資料夾。

本次實作將透過創建工作空間和撰寫讓 Husky Car 隨機駕駛的 Publisher Node,更進一步熟悉關於ROS應用的基本觀念。

順帶一提,實作的系統為 Ubuntu 16.04 和 ROS Kinetic。

二、實作解說

(一)、創建工作空間

工作空間其實就是一個存儲 Package (套件包)的 directories(路徑)。 創建工作空間的步驟如下 :

1.創建工作空間

$ mkdir ~/catkin_ws

2.建立 "src" 資料夾

$ mkdir ~/catkin_ws/src

如同先前所提, "src" 為我們放置開發程式碼的路徑,因此在建立完工作空間後,接這就是建立 "src"。

3.進到 "src",並對工作空間初始化
$ cd ~/catkin_ws/src
$ catkin_init_workspace


(二)、創建Package 和 Publisher Node

建立工作空間後,未來要創建新的套件或撰寫任何程式碼,都記得要先進到 "src"中。我們希望讓 Husky Car 能隨機移動,實現的過程將會藉由建立名為 "random_husky_driver" 套件包,在套件包底下建立一個Publisher Node,再發布移動的資料到 "/husky_velocity_controller/cmd_vel" 的Topic,順利實現讓Husky Car 隨機移動的目的。

接下來,我們從創建套件包開始。

1.進入 "src"

cd ~/catkin_ws/src 

2.創建package(套件包)

$ catkin_create_pkg <套件包名稱> <相依套件1> <相依套件2> <相依套件3> ...
此處範例為 $ catkin_create_pkg random_husky_driver roscpp std_msgs
如下圖所示 :


套件建立完後,將會在 "random_husky_driver"那層路徑看到屬於該套件的 "src",關於此套件的程式碼將會存放於此 "src" 中,詳細的路徑如下圖所示。


3.編輯名為 random_driver.cpp 的程式文件檔

$ gedit random_driver.cpp

關於程式碼,請見本文第三部份。

4.編譯程式碼

設定 package.xml 和 CMakeLists.txt 內容。

package.xml >>



CMakeLists.txt >>

1.查找相關的CMake套件



2.設定catkin_package


3.設定可執行目標 和 指定連接可執行目標之套件



完成上述檔案編輯後,存檔關閉,回到 catkin_ws,執行編譯。

$ cd ~/catkin_ws
$ catkin_make



5.更新環境變數,執行 Launch 檔,開啟gazebo等相關設定

$ source ~/catkin_ws/devel/setup.bash

roslaunch husky_gazebo husky_empty_world.launch



6.執行新建的Publisher node 程式


$ rosrun random_husky_driver random_driver


(如果 terminal 顯示找不到套件,則在下一次更新環境變數的指令,再重新執行)

source ~/catkin_ws/devel/setup.bash

正常執行後,husky_car將在gazebo中自主移動,如下圖所示。



7.查看message內容

透過以下指令,將可以看到發佈的message,線性的x值和角度的z值呈隨機變化。

rostopic echo /husky_velocity_controller/cmd_vel


(三)、程式碼解說


---
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <stdlib.h>

int main(int argc, char **argv){

//initializes ROS, and sets up a node
ros::init(argc, argv, "random_husky_commands");
ros::NodeHandle bh;

//create the publisher, and tells it to publish
//to the husky_velocity_controller/cmd_vel topic, with a queue size of 100
ros::Publisher pub=nh.advertise<geometry_msgs::Twist>("husky_velocity_controller/cmd_vel", 100);

//Sets up the random number generator
srand(time(0));

//sets the loop to publish at a rate of 10Hz
ros::Rate rate(10);

  while (ros::ok())
  {
    //declares the message to be sent
    geometry_msgs::Twist msg;

    //random x value between -2 and 2
    msg.linear.x = 4*double(rand())/double(RAND_MAX)-2; 

    //random y value between -3 and 3
    msg.angular.z = 6*double(rand())/double(RAND_MAX)-3;

    //publish the message
    pub.publish(msg);

    //delays until it is time to send another message
    rate.sleep();

  }

}
---
1.
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
載入必要的標頭檔
<ros/ros.h>定義了ROS運行的基本功能。<geometry_msgs/Twist.h>定義了所需的訊息型式。

2.
ros::init(argc, argv, "random_husky_commands");
ros::NodeHandle nh;
第一行為初始化這個名為 "random_husky_commands"的節點。第二行的宣告,方便對節點資源的使用與管理。

3.
ros::Publisher pub=nh.advertise<geometry_msgs::Twist>("husky_velocity_controller/cmd_vel", 100);
該行定義發布message的動作,發布的訊息為 "geometry_msga::Twist",Topic為 "husky_velocity_controller/cmd_vel"。

100表示message的佇列大小為100,也就是可存放100單位的message。值越大,訊息的緩存空間越大。

在實際的移動狀況中,我們會設定的較小的值,因為過大的值會增加機器人的移動風險。而對於感測器而言,會使用較大的設定值來降地資料丟失的機率。

4.
ros::Rate rate(10)
...
rate.sleep()
ros::Rate rate(10),控制迴圈執行的頻率,頻率是10Hz。rate.sleep則表示讓節點在一個週期工作後,休息一段時間,10Hz (100 ms)後,再進行下一段循環工作。

5.
while(ros::ok())
該指令表示,除非接收到停止指令,否則程式會繼續執行。


6.
msg.linear.x=4*double(rand())/double(RAND_MAX)-2;
msg.angular.z=6*double(rand())/double(RAND_MAX)-3;
定義發送的訊息資料。

7.
pub.publish(msg)
定義將訊息加入發佈佇列中,進行發佈。


---
參考資料 :

#WORKSPACE  #catkin #publisher # node #husky #launch #CMakeList #package

0 留言