Cyberbotics 機器人課程/初級程式設計練習
本章由一系列針對初學者的練習組成。我們假設已經掌握了之前的練習。前幾個練習仍然使用 BotStudio。我們將使用此模組建立更復雜的自動機。然後,我們將介紹 C 語言程式設計。您將詳細瞭解 e-puck 裝置。
本練習的目的是建立一個更復雜的自動機。此外,您將同時操作多個虛擬 e-puck。此模擬使用了更多 e-puck,您的計算機必須是近期的,以避免延遲和故障。
開啟以下世界檔案
.../worlds/novice_train.wbt
最靠近模擬攝像頭的 e-puck 是佇列的最後一個。每個 e-puck 都有自己的 BotStudio 視窗。BotStudio 視窗的順序與 e-puck 的順序相同,即佇列中的第一個 e-puck 與最上面的 BotStudio 視窗相關聯。
建議在上傳之前停止模擬。選擇一個 BotStudio 視窗(比如最下面的那個)。您可以像往常一樣修改其自動機。您可以為每個 e-puck 使用相同的機器人控制器,也可以為每個 e-puck 使用不同的機器人控制器。如果您想為每個 e-puck 使用相同的控制器,請儲存所需的自動機並將儲存的檔案載入到其他 e-puck 上。這種方法是推薦的。
[P.1] 建立一個自動機,使 e-puck 形成一條鏈,即第一個 e-puck 行駛到某處,第二個 e-puck 跟隨第一個,第三個跟隨第二個,等等。(提示:建立兩個自動機;一個用於鏈中的第一個 e-puck(“火車頭”)和一個用於其他 e-puck(“車廂”)。火車頭應該比車廂行駛得慢得多。)
如果您沒有成功,您可以開啟以下自動機並嘗試改進它
.../novice_train/novice_train_corr.bsg
請注意,在一個檔案中有兩個自動機。車廂必須以“車廂初始化”狀態作為初始狀態,而火車頭必須以“火車頭初始化”狀態作為初始狀態。
本練習的目的是建立一個循壁自動機。您將看到這並不容易。本練習仍然使用 BotStudio,但比之前的練習更難。
開啟以下世界檔案
.../worlds/novice_remain_in_shadow.wbt
您會觀察到世界已經改變。板子更大,有更多障礙物,還有一堵雙層牆。雙層牆的目的是執行內壁或外壁循壁,障礙物的目的是繞過它們。因此,不要猶豫,透過 Shift 鍵加單擊移動 e-puck 或障礙物。
讓我們思考一下循壁演算法。有很多不同的方法可以解決這個問題。建議的解決方案可以使用有限狀態機來實現。首先,e-puck 必須向前行駛,直到遇到障礙物,然後它向左或向右旋轉(比如向右),使其垂直於牆壁。然後,它必須沿著牆壁行駛。當然,它不知道牆壁的形狀。因此,如果它離牆壁太近,它必須向左校正其軌跡。相反,如果它離牆壁太遠,它必須向右校正。
[P.1] 建立一個自動機,對應於前面的描述。僅在虛擬 e-puck 上進行測試。(提示:設定條件的引數是一項艱鉅的任務。如果您沒有找到解決方案,請將您的 e-puck 執行到牆壁附近,觀察感測器的值並思考條件。不要猶豫,新增更多狀態(如“簡單校正 - 左”和“困難校正 - 左”。)
如果您沒有找到解決方案,請在 BotStudio 中開啟以下自動機(這是一個良好的開端,但不是完美的解決方案)
.../controllers/novice_remain_in_shadow/novice_remain_in_shadow_corr.bsg
[P.2] 如果您在內壁上測試了您的自動機,請將其修改為在外壁上工作,反之亦然。
[P.3] 到目前為止,環境沒有改變。新增一個轉換,以便在您失去與障礙物的接觸時重新找到牆壁。如果 e-puck 繞過一個被移除的障礙物,它應該找到另一個牆壁。
[P.4] 修改自動機的引數,以便在真實的 e-puck 上覆制相同的行為。
你的進度
[edit | edit source]透過前兩個練習,您已經瞭解了
- 如何使用 BotStudio 構建複雜的 FSM
- BotStudio 的侷限性是什麼
以下練習將教您另一種程式設計 e-puck 的方法:C 語言。
C 程式設計簡介
[edit | edit source]到目前為止,您一直使用 BotStudio 來程式設計機器人行為。該工具使您可以快速直觀地程式設計簡單的行為。您可能也注意到了該工具的侷限性,特別是表示式自由度有限,並且一些複雜的程式很快變得難以閱讀。出於這個原因,需要更強大的程式設計工具:C 程式語言。這種程式語言具有重要的表示式自由度。藉助它和 Webots 庫,您可以透過編寫程式來程式設計機器人控制器。問題是您必須瞭解其語法。學習 C 語言超出了本文件的範圍。因此,請參考有關 C 程式設計的書籍。網路上也有一些關於此主題非常有用的教程,例如 C 程式設計的華夏公益教科書
您不必瞭解這種語言的每一個細節就能成功完成以下練習。如果您是完全的初學者,請首先關注:變數、陣列、函式、控制結構(布林測試、if ... else ...、switch、for、while 等)。
在接下來的四個練習中,您將獨立探索 e-puck 裝置。關於裝置的練習按難度排序,即分別為:LED、步進電機、紅外感測器、加速度計和攝像頭。
Webots 模擬的結構
[edit | edit source]要在 Webots 中建立模擬,需要兩種型別的檔案
- 世界檔案:它定義了虛擬環境,即每個物件的形狀、物理邊界、位置和方向(包括機器人),以及一些其他全域性引數,例如視窗的位置、模擬攝像頭的引數、光源的引數、重力向量等。此檔案是用 VRML[1] 語言編寫的。
- 控制器檔案:它是機器人使用的程式。它定義了機器人的行為。您已經看到控制器檔案可以是 BotStudio 自動機,您還將看到它也可以是使用 Webots 庫的 C 程式。
請注意,本文件中幾乎所有世界檔案都使用位於
webots_root/project/default/protos/EPuck.proto
此檔案包含標準 e-puck 的描述,尤其包括裝置名稱。這將有助於獲取裝置標籤。
最簡單的程式
[edit | edit source]這裡編寫了最簡單的 Webots 程式。此指令碼使用 Webots 庫(參考第一行)來獲得基本的機器人功能。
// included libraries
#include <webots/robot.h>
// global defines
#define TIME_STEP 64 // [ms]
// global variables...
int main() {
// Webots init
wb_robot_init();
// put here your initialization code
// main loop
while(wb_robot_step(TIME_STEP) != -1) {
}
// put here your cleanup code
// Webots cleanup
wb_robot_cleanup();
return 0;
}
K-2000 [新手]
[edit | edit source]這是第一次使用 C 程式設計。您將建立一個圍繞機器人的 LED 迴圈,就像您之前在練習 閃爍的 e-puck 中所做的那樣。
開啟世界檔案和文字編輯器視窗
[edit | edit source]開啟以下世界檔案
.../worlds/curriculum_novice_k2000.wbt
這將開啟一個小型面板。實際上,當使用 LED 時,我們不需要太多空間。您還會看到一個新視窗:文字編輯器視窗(您可以在圖片中看到它)。在這個視窗中,您可以編寫 C 程式,載入、儲存和編譯[2] 它們(要編譯,請點選編譯按鈕)。

[P.1] 在虛擬 e-puck 上執行程式(通常,它應該在開啟世界檔案後自動執行。如果不是這樣,您需要編譯控制器並恢復模擬)。觀察 e-puck 的行為。
[P.2] 仔細觀察此練習的 C 程式設計程式碼。注意第二個包含語句。
[Q.1] 使用哪個函式更改 LED 的狀態?您可以在哪個庫中找到此函式?解釋全域性變數 i 在主函式中的作用。
模擬、遠端控制會話和交叉編譯
[edit | edit source]e-puck 有三種使用模式
- 模擬:使用 Webots 庫,您可以編寫機器人控制器,編譯它並在虛擬 3D 環境中執行它。這是您在上一節中所做的。
- 遠端控制會話:您可以編寫相同的程式,像以前一樣編譯它,並透過藍牙連線在真實的 e-puck 上執行它。
- 交叉編譯:您可以編寫相同的程式,為 e-puck 處理器交叉編譯它,並將其上傳到真實的機器人。在這種情況下,舊的 e-puck 程式(韌體)將被您的程式替換。在這種情況下,您的程式不依賴於 Webots,並且可以在 e-puck 重啟後繼續執行。
如果您想建立遠端控制會話,您只需在機器人視窗中選擇您的藍牙而不是模擬。您的機器人必須具有正確的韌體,如部分 E-puck 先決條件 中所述。
對於交叉編譯,請先在文字編輯器視窗中選擇構建 | 交叉編譯...選單(或點選工具欄中的對應圖示)。此操作將建立一個.hex檔案,該檔案可以在e-puck上執行。執行交叉編譯後,Webots會要求您上傳生成的檔案(位於e-puck的目錄中)。點選“是”按鈕,然後選擇要使用的藍牙連線。檔案應該上傳到e-puck上。您也可以透過在模擬視窗中選擇工具 | 上傳到e-puck機器人...選單來上傳檔案。
要了解機器人處於哪種模式,您可以呼叫wb_robot_get_mode()函式。在模擬中返回0,在交叉編譯中返回1,在遠端控制會話中返回2。
[P.4] 將韌體上傳到e-puck(參見E-puck 先決條件部分)。編譯程式並啟動遠端控制會話。
修改
[edit | edit source]
[P.6] 修改給定的程式設計程式碼以使所有LED以同步方式閃爍。
[P.7] 透過測試確定每個裝置名稱對應的LED。例如,“led0”裝置名稱對應於e-puck最前面的LED。
電機 [新手]
[edit | edit source]本練習的目的是使用一些其他的e-puck裝置:兩個步進電機。
開啟世界檔案
[edit | edit source]開啟以下世界檔案
.../worlds/novice_motors.wbt
迴旋鏢
[edit | edit source]“步進電機是一種機電裝置,它將電脈衝轉換為離散機械運動”[3]。它可以將一個完整的旋轉分成大量的步驟。一個e-puck步進電機有1000步。這種型別的電機具有±1步的精度。它與數字技術直接相容。您可以使用wb_differential_wheels_set_speed(...)函式設定電機速度。該函式接收兩個引數:左電機速度和右電機速度。e-puck接受-1000到1000之間的速度值。最大速度對應於大約每秒旋轉一次。
要了解車輪的位置,可以使用編碼器裝置。請注意,e-puck沒有像其他一些機器人那樣測量車輪位置的物理編碼器裝置。但是,當執行電機步驟時,計數器會遞增,如果車輪轉到另一側,則會遞減。這是車輪位置的良好近似值。不幸的是,如果e-puck被阻塞並且車輪沒有滑動,即使車輪沒有轉動,編碼器計數器也可能被遞增。
編碼器在遠端控制模式下尚未實現。因此,如果您想在真實的e-puck上使用它,請使用交叉編譯。
[Q.1] 在不執行模擬情況下,描述e-puck的行為將是什麼。
修改
[edit | edit source]
[P.2] 修改給定的程式設計程式碼以獲得以下行為:e-puck向前移動,並在其車輪完全旋轉一圈後停止。嘗試在真實和虛擬e-puck上執行您的程式。
[P.3] 修改給定的程式設計程式碼以獲得以下行為:e-puck向前移動,並在精確移動10釐米後停止。(提示:e-puck車輪半徑為2.1釐米)
[P.4] [挑戰] 修改給定的程式設計程式碼以獲得以下行為:e-puck移動到特定的XZ座標(相對於e-puck的初始位置)。
紅外感測器 [新手]
[edit | edit source]在本練習中,您將操作紅外感測器。這個裝置不像前面的裝置那樣直觀。實際上,紅外感測器可以有多種用途。在本練習中,您將瞭解該裝置提供的哪些資訊以及如何使用它。日誌視窗也會被介紹。
紅外感測器
[edit | edit source]八個紅外感測器以非規則的方式放置在e-puck周圍。e-puck的前部比後部有更多感測器。紅外感測器由兩部分組成:紅外發射器和光電感測器。這種配置使紅外感測器能夠發揮兩種作用。
首先,它們可以測量自身與障礙物之間的距離。紅外發射器發射紅外光,紅外光照射到潛在的障礙物上並反射回來。接收到的光線由光電感測器測量。光線的強度直接反映了物體的距離。第一個應用可能是最有趣的,因為它可以讓 e-puck 瞭解其周圍環境。在 Webots 中,這種模式下的紅外感測器透過使用 *距離感測器* 來建模。需要注意的是,紅外感測器的測量值是非線性的。為了說明這一點,我們進行了以下實驗。將一個 e-puck 放在一面牆前。當實驗開始時,e-puck 向後移動。前右紅外感測器的值儲存在一個檔案中。這些值在圖中繪製出來。請注意,兩條曲線的步長並不相同。e-puck 與牆壁之間的距離呈線性增長,但紅外感測器的測量值是非線性的。然後,觀察偏移值。該值主要取決於光照環境。因此,這個偏移值通常是沒有意義的。還要注意,距離估計取決於障礙物(顏色、方向、形狀、材料)和紅外感測器(特性和校準)。

其次,光電感測器可以單獨使用。在這種情況下,紅外感測器量化接收到的紅外光的量。一個典型的應用是趨光性,即機器人跟隨或避免光刺激。這種行為是受生物學啟發的(特別是昆蟲)。在 Webots 中,在這種模式下的紅外感測器透過使用光感測器來建模。請注意,在本練習中,只操作距離感測器。但是,光感測器也可以使用。
開啟以下世界檔案
.../worlds/novice_ir_sensors.wbt
你應該看到一個小板,上面只有一個障礙物。為了測試紅外感測器,你可以移動 e-puck 或障礙物。請注意圖中所示的視窗。這個視窗稱為 *日誌視窗*。它顯示文字。兩個實體可以在此視窗中寫入內容:機器人控制器或 Webots。

[P.1] 在不執行模擬的情況下,仔細觀察本練習的程式設計程式碼。
[Q.1] 為什麼距離感測器值要減去一個偏移值?描述一種計算此偏移值的方法。
[Q.3] 在不執行模擬的情況下,描述 e-puck 的行為將是什麼。
[P.2] 在虛擬和真實 e-puck 上執行模擬,觀察當物體靠近 e-puck 時 e-puck 的行為。
[P.3] 到目前為止,偏移值是任意定義的。本部分的目標是使用 calibrate 函式來校準你真實 e-puck 的紅外感測器偏移值。首先,在主函式中,取消對 calibrate 函式呼叫的註釋,並編譯程式。你的真實 e-puck 必須放在通風的地方。在你的真實 e-puck 上執行程式。校準函式的執行時間取決於 n 的值。將校準函式的執行結果從日誌視窗複製貼上到程式中的ps_offset_real陣列中。再次編譯。你的紅外感測器偏移值已校準到你的環境。
[P.4] 透過測試確定每個裝置名稱對應哪個紅外感測器。例如,裝置名稱“ps2”對應於 e-puck 的右側紅外感測器。
幸運的是,紅外感測器可以更簡單地使用。為了繞過紅外感測器的校準和對其返回值的處理,可以使用 e-puck 的對稱性。如果你想建立一個簡單的避碰演算法,左右兩側之間的差異(示例中的 delta 變數)比紅外感測器的值更重要。
[P.5] 取消 run 函式最後部分的註釋並編譯程式。觀察程式碼和 e-puck 的行為。請注意,只使用了紅外感測器返回的值。也可以在遠端控制模式或交叉編譯中嘗試這部分程式碼在真實機器人上的效果。
[P.6] 獲得與之前相同的行為,但向後移動而不是向前移動。
在本練習中,我們將首次使用 e-puck 的加速度計。你將學習這個裝置的作用以及如何使用它。對這個裝置的解釋涉及到一些超出本文件範圍的概念,例如加速度和向量。如果你想了解更多關於這些主題的資訊,請分別查閱物理書籍和數學書籍。
開啟以下世界檔案
.../worlds/novice_accelerometer.wbt
這將開啟一個包含彈簧板的世界。這個物體的作用是在斜坡上以及 e-puck 墜落時觀察加速度計的行為。在測試時,不要猶豫,移動你的 e-puck(SHIFT + 滑鼠按鈕)並使用“步進”按鈕。為了垂直移動 e-puck,請使用 SHIFT + 滑鼠滾輪。
加速度可以定義為瞬時速度的變化。它的 SI 單位是 。加速度計是一種測量自身加速度(以及 e-puck 的加速度)的裝置,它以 3D 向量的形式測量。加速度計的軸線如圖形所示。在靜止狀態下,加速度計至少會測量重力加速度。電機速度的改變、機器人的旋轉以及外力的影響也會影響加速度向量。e-puck 加速度計主要用於
- 測量機器人靜止時地面傾斜度和方向。這些值可以透過使用重力加速度向量 3 個分量的三角函式來計算。在本練習的控制器程式碼中,請觀察getInclination(float x,float y, float z)和getOrientation(float x,float y, float z)函式。
- 檢測與障礙物的碰撞。事實上,如果加速度的模數(觀察本練習的getAcceleration(float x,float y, float z)函式)在沒有改變電機速度的情況下發生了劇烈變化,則可以假設發生了碰撞。
- 檢測機器人的墜落。事實上,如果加速度的模數變得過低,則可以假設機器人墜落。

[Q.1] 重力加速度的方向應該是什麼?加速度計測量的向量方向是什麼?
[P.1] 驗證您的先前答案,即在模擬中,當 e-puck 靜止時,透過觀察日誌視窗觀察重力加速度的方向。(提示:使用“步進”按鈕。)
練習
[edit | edit source]
[P.2] 獲取以下行為:當 e-puck 墜落時,身體上的 LED 會亮起。如果您想在現實中嘗試,請記住 e-puck 是易碎的。
[P.3] 獲取以下行為:只有最下面的 LED 亮起(根據垂直方向)。
相機 [初學者]
[edit | edit source]在 [sec:Line-following] 部分中,您已經學習了 e-puck 相機的基本知識。您透過處理 BotStudio 介面將 e-puck 相機用作線性相機。透過使用此介面,您或多或少地侷限於跟隨黑線。在本練習中,您將觀察到,透過使用 C 程式設計,您可以以不同的方式使用相機。首先,您的 e-puck 將使用線性相機。它將能夠跟隨特定顏色的線。其次,您的 e-puck 將使用相機的整個視野跟隨光源,光源以光點的形式表示。
開啟世界檔案
[edit | edit source]開啟以下世界檔案
.../worlds/novice_linear_camera.wbt
這將開啟一塊長木板,上面繪製了三條彩色線。
線性相機 - 跟蹤彩色線
[edit | edit source]在木板上,有一條青色線、一條黃色線和一條洋紅色線。這三種顏色(原色)不是隨機選擇的。它們具有可以使用紅色、綠色或藍色濾鏡(原色)獨立檢視的特性。這四張圖顯示了模擬首先以彩色模式 (RGB) 進行,然後透過應用紅色、綠色或藍色濾鏡進行。如表格所示,如果使用紅色濾鏡,則青色在紅色通道中沒有分量,因此看起來是黑色的,而洋紅色有分量,因此看起來像地面一樣是白色的。

| 顏色 | 紅色通道 | 綠色通道 | 藍色通道 |
|---|---|---|---|
| 青色 | 0 | 1 | 1 |
| 洋紅色 | 1 | 0 | 1 |
| 黃色 | 1 | 1 | 0 |
| 黑色 | 0 | 0 | 0 |
| 白色 | 1 | 1 | 1 |
在實際配置中,e-puck 相機以 RGB 模式獲取影像。Webots 軟體也使用這種渲染模式。因此,很容易分離這三個通道,只看到其中的一條線。在程式碼中,這將透過使用wb_camera_image_get_red(...), wb_camera_image_get_green(...)和wb_camera_image_get_blue(...)函式來完成,這些函式來自webots/camera.h庫。
[Q.1] 根據當前的機器人控制器,e-puck 跟蹤的是黃色線。您需要在控制器程式碼中更改什麼才能跟蹤藍色線?
[Q.2]find_middle(...)函式的作用是什麼?(注意:與 BotStudio 中使用的find_middle(...)函式相同)
[Q.4] 解釋宏變數TIME_STEP和TIME_STEP_CAM.
[P.1] 在您的真實 e-puck 上嘗試此機器人控制器。要建立真實環境,請使用一張大紙,並用熒光筆在上面描繪線條。(提示:結果很大程度上取決於您房間的光線)
開啟另一個世界檔案
[edit | edit source]開啟以下世界檔案
.../worlds/novice_camera.wbt
這將開啟一塊黑色的木板,上面有一個白色的球。要移動球,請使用箭頭鍵。透過按 M 鍵,此球也可以隨機移動。
跟蹤白色物體 - 更改相機解析度
[edit | edit source]本節的其餘部分將教您如何配置 e-puck 相機。事實上,根據您的目標,您不需要使用相同的解析度。您必須根據您的問題將解析度降至最低。從 e-puck 傳輸影像到 Webots 需要時間。影像越大,傳輸時間越長。e-puck 的相機解析度為 480x640 畫素。但是藍牙連線僅支援傳輸 2028 個彩色畫素。因此,52x39 畫素的解析度可以最大限度地利用藍牙連線並保持 4:3 的比例。
帶有 e-puck 視野的圖顯示了 e-puck 相機的物理引數在哪裡。它們對應於以下值:
- a:約 6 釐米
- b:約 4.5 釐米
- c:約 5.5 釐米
- :約 0.47 弧度
- :約 0.7 弧度
在文字編輯器視窗中,開啟 world 檔案。
.../worlds/novice_camera.wbt
這將開啟本練習世界的解密。在檔案末尾,您將找到以下節點:
EPuck {
translation -0.03 0 0.7
rotation 0 1 0 0
controller "curriculum_novice_camera"
camera_fieldOfView 0.7
camera_width 52
camera_height 39
}
這部分定義了虛擬的 e-puck。e-puck 的原型[4]儲存在外部檔案中(參見 Webots 模擬的結構)。只有一部分欄位可以修改。特別是,e-puck 的位置、方向和機器人控制器將是什麼。您還將在那裡找到相機的屬性。首先,您可以修改視野。此欄位接受大於 0 且不超過 0.7 的值,因為這是您真實 e-puck 相機的範圍。此欄位還將定義真實 e-puck 相機的縮放屬性。其次,您還可以修改虛擬相機的寬度和高度。您可以將它們設定為 1 到 127 之間的任何值。但它們的乘積不能超過 2028。當 world 檔案修改完成後,儲存 world 檔案並恢復模擬。
當前版本的 e-puck 韌體[5]只允許獲得居中的影像。為了獲得真實相機最後一行以模擬線性相機,需要一個技巧。如果虛擬 e-puck 相機傾斜且高度為 1,Webots 會呼叫 e-puck 韌體的另一個例程來獲取最後一行。因此,如果您想使用線性相機,您必須使用另一個虛擬相機傾斜的 e-puck 原型。
epuck_linear_camera {
translation -0.03 0 0.7
rotation 0 1 0 0
controller "curriculum_novice_camera"
camera_fieldOfView 0.7
camera_width 60
}
請注意,相機的 height 未定義。此欄位隱式設定為 1。
該表比較了 world 檔案的值與真實 e-puck 相機產生的值。請注意,視野(β)會影響縮放屬性。縮放值為 8 表示欠取樣(每 8 個畫素取一個畫素)。X 和 Y 顯示真實相機視窗的相對位置(參見圖 [fig:utilisation-camera])。


| 寬度(模擬) | 高度(模擬) | 角度[6] | 寬度 | 高度 | 縮放 | x | y | |
|---|---|---|---|---|---|---|---|---|
| 52 | 39 | 0.7 | false | 416 | 312 | 8 | 32 | 164 |
| 39 | 52 | 0.7 | false | 468 | 624 | 12 | 6 | 8 |
| 52 | 39 | 0.08 | false | 52 | 39 | 1 | 214 | 300 |
| 39 | 52 | 0.08 | false | 39 | 52 | 1 | 222 | 294 |
| 120 | 1 | 0.7 | true | 480 | 1 | 4 | 0 | 639 |
| 60 | 1 | 0.7 | true | 480 | 1 | 8 | 0 | 639 |
| 40 | 1 | 0.35 | false | 240 | 1 | 6 | 120 | 320 |
[P.3] 嘗試表格中的每種配置。觀察您虛擬 e-puck 和真實 e-puck 上的結果。(提示:將表格左側的值放到 world 檔案中)
你的進度
[edit | edit source]在前五個練習中,您詳細瞭解了 e-puck 的五個裝置:LED、步進電機、紅外感測器、加速度計和相機。您瞭解了它們的用途以及如何使用 C 程式語言使用它們。現在,您擁有了開始程式設計 e-puck 行為所需的所有技術知識。這是本課程其餘部分的主要主題。