控制無人機需要寫 ROS 節點,但是 Gazebo 和 ROS 畢竟還是兩個獨立的系統,並不能直接通訊。因此還需要在我們的模型中加入插件(plugins)才行。
Gazebo 的插件(plugin) 是官方提供的函式庫,透過匯入插件到模型的 SDF 檔或 URDF 檔中,可以讓開發者為模擬環境中的模型加入感測器的功能,或是讓 Gazebo 與 ROS 互相通訊藉此控制模型。
Gazebo 插件使用的是 C++ 來寫的,而開發者也可以根據原始碼調整,建立預設類型之外的感測器插件。由於這個系列主要還是使用 Python 來寫程式,因此這一篇會直接使用現有插件,就不重新寫一個新的插件了。
Gazebo 插件分為幾種主要類型,我們會用到的有以下這兩種:
模型插件(Model Plugins):
模型插件可以改變模型的運動狀態和行為,例如施加外力和扭力、設定速度和位置,或是讓它們根據指令進行移動、旋轉等動作。
感測器插件(Sensor Plugins):
感測器插件能模擬多種不同感測器的數值輸出,如相機、IMU、LiDAR 等,這些感測器插件能夠幫助機器人從模擬環境中收集數據,並傳遞到 ROS 處理和進行決策。
這次使用 ardrone_gazebo
這個專案來當做範例,這是 GitHub 上找到內建感測器的無人機模型。我會快速帶過 Gazebo 插件是如何在這個專案裡使用,並且在之後直接透過這個專案裡的無人機模型來寫控制節點。
按照 Day 5 安裝套件的步驟進行。
$ cd catkin_ws/src
$ git clone https://github.com/PXLRoboticsLab/ardrone_autonomy # 這是 ardrone_gazebo 的相依套件
$ git clone https://github.com/PXLRoboticsLab/ardrone_gazebo
$ cd ..
$ rosdep install --from-paths src --ignore-src -r
$ catkin_make
$ source devel/setup.bash
啟動模擬看看是否安裝成功,應該可以看到開啟類似下圖的模擬視窗。
$ roslaunch ardrone_gazebo single_ardrone.launch
安裝完成後就來看看這個套件的內容。
前面提到 Gazebo 的插件原始碼使用 C++ 程式碼(.cc
或 .cpp
)撰寫,而我們會需要在模型 SDF 檔中匯入編譯後產生的共享物件檔(.so
),才能供 Gazebo 使用。前者放在這個專案的 src
目錄中,後者則是在 catkin 編譯後放在 plugins
目錄中。
無人機的模型插件:
在 src
中,ardrone_plugin.cc
這支程式是控制無人機的模型插件,包含了無人機的運動控制指令、狀態管理和與 ROS 、其他感測器插件通訊。
無人機的感測器插件:
其餘名稱包含 plugin
的程式則是定義了無人機上搭載的感測器。例如 plugin_ros_cam.cpp
定義了一個相機插件,用於模擬機載相機看到的畫面,並將其影像資料發佈到 ROS 中。
編譯專案後,插件原始碼會在 plugins
目錄生成對應的 .so
檔,在 Gazebo 中 .so
是代表共享物件檔案(Shared Object File),一旦設定好就可以讓多個專案共享使用。例如 libardrone_plugub.so
是控制無人機的模型插件,而 libplugin_ros_cam.so
便對應相機插件。
首先需要在模型的 SDF 或 URDF 文件中定義要加入的模型插件,在 ardrone_gazebo
專案裡是兩種文件都寫。這次選擇來看 urdf
目錄中的 URDF 檔,URDF 檔和 SDF 檔的差異只差在前者使用 <robot>
標籤,後者則是 <model>
標籤,其餘都大同小異。
URDF 檔案可以更詳細設定機器人的部件,將模型分成連結(Link)和關節(Joint)兩個部份:
連結(Link):每個連結代表機器人的一個部件,可以是靜態的或可移動的。每個連結可以包含其幾何形狀、慣性、材質、碰撞和視覺屬性。
關節(Joint):關節負責連接兩個連結,定義了這兩個連結之間的運動關係。常見的關節類型包括:固定關節(
type="fixed"
)、旋轉關節(type="revolute"
)和滑動關節(type="prismatic"
)。
找到 ardrone_gazebo.urdf
中用 <gazebo>
標籤包住的部份如下:
<gazebo>
<plugin name='ardrone_gazebo' filename='libardrone_plugin.so'>
<bodyName>base_link</bodyName>
<imuTopic>/ardrone/imu</imuTopic>
<!-- 模型控制靈敏度設置 -->
<rollpitchProportionalGain>10.0</rollpitchProportionalGain>
<rollpitchDifferentialGain>5.0</rollpitchDifferentialGain>
<rollpitchLimit>0.5</rollpitchLimit>
<yawProportionalGain>2.0</yawProportionalGain>
<yawDifferentialGain>1.0</yawDifferentialGain>
<yawLimit>1.5</yawLimit>
<velocityXYProportionalGain>5.0</velocityXYProportionalGain>
<velocityXYDifferentialGain>2.3</velocityXYDifferentialGain>
<velocityXYLimit>2</velocityXYLimit>
<velocityZProportionalGain>5.0</velocityZProportionalGain>
<velocityZDifferentialGain>1.0</velocityZDifferentialGain>
<velocityZLimit>-1</velocityZLimit>
<positionXYProportionalGain>1.1</positionXYProportionalGain>
<positionXYDifferentialGain>0.0</positionXYDifferentialGain>
<positionXYIntegralGain>0.0</positionXYIntegralGain>
<positionXYLimit>5</positionXYLimit>
<positionZProportionalGain>1.0</positionZProportionalGain>
<positionZDifferentialGain>0.2</positionZDifferentialGain>
<positionZLimit>-1</positionZLimit>
<!-- 無人機能產生的最大動力 -->
<maxForce>30</maxForce>
<!-- 運動雜訊 -->
<motionSmallNoise>0.05</motionSmallNoise>
<motionDriftNoise>0.03</motionDriftNoise>
<motionDriftNoiseTime>5.0</motionDriftNoiseTime>
</plugin>
</gazebo>
Gazebo 和插件標籤:
不管是模型插件還是感測器插件,都會需要先用定義在 <gazebo>
標籤中。接著使用 <plugin>
標籤定義插件名稱和使用的共享庫(.so
檔)。
模型控制靈敏度設置:
中間的標籤是在定義模型對於各個軸運動的靈敏度,這些設定是基於 PID 控制器(Proportional-Integral-Derivative Controller)演算法設定的,用於調節系統狀態如位置、速度、角度等。
比例增益(Proportional Gain):數值越大,控制反應越靈敏。
微分增益(Differential Gain):控制運動的速度變化率,使控制過程更加平穩。
積分增益(Integral Gain):處理機器人長期運作的累積誤差,確保最終可以精準完成動作。
限制(Limit):定義速度與角速度的上限,避免模型做出超出現實的行為。
雜訊(Noise):
這部份定義了無人機運動中的小雜訊,用來模擬真實環境中的微小擾動,包含長時間飛行的微小漂移現象。
因為.so
檔的內容是從 C++ 原始碼生成的,所以不建議直接在這裡修改,加上調整模型的 PID 控制參數通常需要一些經驗和不斷的試錯與調整,所以我們就直接沿用這個專案的設定吧。