CoppeliaSim <<
Previous Next >> Line following BubbleRob
BubbleRob tutorial
由40723210提供
個人操作影片連結:https://youtu.be/BStp8J-KXuY
本教程將在設計簡單的移動機器人BubbleRob時嘗試介紹很多CoppeliaSim功能。與本教程相關的CoppeliaSim場景文件位於CoppeliaSim的安裝文件夾的tutorials / BubbleRob文件夾中。下圖說明了我們將設計的仿真場景:

由於本教程將跨越許多不同的方面,因此請確保也看看其他教程,主要是有關構建仿真模型的教程。首先,重新啟動CoppeliaSim。模擬器顯示默認場景。我們將從BubbleRob的主體開始。
我們使用[菜單欄->添加->基本形狀->球體]將直徑為0.2的基本球體添加到場景中。我們將X尺寸項目調整為0.2,然後點擊確定。默認情況下,創建的球體將顯示在可見性層 1中,並且是動態且可響應的(因為我們已啟用“ 創建動態且可響應的形狀 ”項)。這意味著BubbleRob的身體將掉落,並且能夠對與其他可響應形狀的碰撞做出反應(即,由物理引擎模擬)。我們可以看到這是形狀動力學屬性:項目身體是可響應的,身體是動態的已啟用。我們開始模擬(通過工具欄按鈕,或在場景窗口中按<control-space>),然後復制並粘貼創建的球體(使用[菜單欄->編輯->複製所選對象],然後[菜單欄->編輯->粘貼緩衝區],或者先按<control-c>,再按<control-v>):這兩個球將對碰撞做出反應並滾動。我們停止模擬:重複的球體將自動刪除。可以在模擬對話框中修改此默認行為。
我們還希望BubbleRob的主體可以被其他計算模塊(例如最小距離計算模塊)使用。因此,如果尚未啟用,則在該形狀的對象公共屬性中啟用Collidable,Measurable,Renderable和Detectable。如果需要,我們現在還可以在形狀屬性中更改球體的視覺外觀。
現在,我們在“ 平移”選項卡上打開“ 位置”對話框,選擇表示BubbleRob身體的球體,然後為“ 沿著Z”輸入0.02 。我們確保將相對項設置為World。然後,單擊翻譯選擇。這會將所有選定對象沿絕對Z軸平移2 cm,並有效地將我們的球體抬高了一點。在場景層次結構中,我們雙擊球體的名稱,以便我們可以編輯其名稱。我們輸入bubbleRob,然後按Enter。
接下來,我們將添加一個接近傳感器,以便BubbleRob知道它何時接近障礙物:我們選擇[菜單欄->添加->接近傳感器->圓錐類型]。在方向選項卡上的方向對話框中,我們為Y周圍和Z 周圍輸入90 ,然後單擊旋轉選擇。在位置對話框的“ 位置”選項卡上,為X坐標輸入0.1 。Z坐標為0.12 。現在,接近傳感器已相對於BubbleRob的身體正確定位。我們在場景層次中雙擊接近傳感器的圖標打開其屬性對話框。我們單擊顯示體積參數以打開接近傳感器體積對話框。我們將偏移量調整為0.005,角度調整為30,範圍調整為0.15。然後,在接近傳感器屬性中,單擊顯示檢測參數。這將打開接近傳感器檢測參數對話框。如果距離小於則取消選中“不允許檢測”項,然後再次關閉該對話框。在場景層次結構中,我們雙擊接近傳感器的名稱,以便我們可以編輯其名稱。我們輸入bubbleRob_sensingNose並按回車鍵。
我們選擇bubbleRob_sensingNose,然後按住 Control鍵選擇bubbleRob,然後單擊[菜單欄->編輯->將最後選擇的對象設為父對象]。這會將傳感器連接到機器人的身體。我們也可以拖bubbleRob_sensingNose到bubbleRob在場景層次。這就是我們現在擁有的:

[接近傳感器連接到bubbleRob的身體]
接下來,我們將照顧BubbleRob的車輪。我們使用[菜單欄->文件->新場景]創建一個新場景。跨多個場景工作通常非常方便,以便可視化並僅對特定元素進行工作。我們添加一個尺寸為(0.08,0.08,0.02)的純原始圓柱體。至於BubbleRob的主體,如果尚未啟用,則在該圓柱的對象通用屬性中啟用 Collidable,Measurable,Renderable和Detectable。然後,將圓柱的絕對位置設置為(0.05,0.1,0.04),並將其絕對方向設置為(-90,0,0)。我們將名稱更改為bubbleRob_leftWheel。我們複製並粘貼滾輪,然後將復制的絕對Y坐標設置為-0.1。我們將副本重命名為bubbleRob_rightWheel。我們選擇兩個輪子,複製它們,然後切換回場景1,然後粘貼輪子。
現在,我們需要為車輪添加接頭(或電動機)。我們單擊[菜單欄->添加->關節->旋轉]將旋轉關節添加到場景。在大多數情況下,將新對象添加到場景時,該對象將出現在世界的起源處。我們保持關節處於選中狀態,然後控制選擇bubbleRob_leftWheel。在“ 位置”對話框的“ 位置”選項卡上,單擊“ 應用到選擇”按鈕:這將關節定位在左輪的中心。然後,在“ 方向”對話框的“ 方向”選項卡上,執行相同的操作:這將關節與左輪定向的方向相同。我們將關節重命名為bubbleRob_leftMotor。現在,我們在場景層次中雙擊關節的圖標以打開關節屬性對話框。然後,單擊“ 顯示動態參數”以打開關節動力學屬性對話框。我們啟用電動機,並檢查項目“ 目標速度為零時鎖定電動機”。現在,我們對右馬達重複相同的過程,並將其重命名為bubbleRob_rightMotor。現在,我們將左輪連接到左馬達,將右輪連接到右馬達,然後將兩個馬達連接到bubbleRob。這就是我們所擁有的:

[接近傳感器,電動機和車輪]
我們運行模擬,並註意到機器人向後倒下。我們仍然缺少與地板的第三個聯繫點。現在,我們添加一個小的滑塊(或腳輪)。在一個新的場景,我們並添加純原始球體直徑為0.05,讓球可碰撞,可衡量的,可渲染和檢測的(如果尚未啟用),然後將其重命名為bubbleRob_slider。我們在形狀動力學屬性中將Material設置為noFrictionMaterial。為了將滑塊與機器人的其餘部分牢固地鏈接在一起,我們使用[菜單欄->添加->力傳感器] 添加了力傳感器對象。我們將其重命名為bubbleRob_connection並將其上移0.05。我們將滑塊連接到力傳感器,然後復制兩個對象,切換回場景1並粘貼它們。然後,我們將力傳感器沿絕對X軸移動-0.07,然後將其安裝到機器人主體上。如果現在運行模擬,我們會注意到滑塊相對於機器人主體略微移動:這是因為兩個對象(即bubbleRob_slider和bubbleRob)都相互碰撞。為了避免在動力學模擬過程中產生奇怪的影響,我們必須通知CoppeliaSim兩個對像不會相互碰撞,我們可以通過以下方式進行此操作:在shape dynamics屬性中,為bubbleRob_slider設置了本地可響應蒙版設置為00001111,對於bubbleRob,我們將本地可響應掩碼設置為11110000。如果再次運行仿真,我們會注意到兩個對像不再乾涉。這就是我們現在擁有的:

[接近傳感器,電機,車輪和滑塊]
我們再次運行仿真,發現即使在電機鎖定的情況下,BubbleRob也會輕微移動。我們還嘗試使用不同的物理引擎運行仿真:結果將有所不同。動態仿真的穩定性與所涉及的非靜態形狀的質量和慣性緊密相關。有關此效果的說明,請務必仔細閱讀本節和該節。現在,我們嘗試糾正這種不良影響。我們選擇兩個輪子和滑塊,然後在“形狀動力學”對話框中單擊3次M = M * 2(用於選擇)。效果是所有選定形狀的質量都將乘以8。我們對3個選定形狀的慣性進行相同的操作,然後再次運行仿真:穩定性得到了改善。在關節動力學對話框中,我們將兩個電機的目標速度都設置為50。我們運行模擬:BubbleRob現在向前移動並最終掉落在地板上。我們將兩個電機的目標速度項都重置為零。
對象bubbleRob是所有以後將形成BubbleRob 模型的對象的基礎。我們將在稍後定義模型。同時,我們要定義代表BubbleRob的對象的集合。為此,我們定義了一個集合對象。我們單擊[菜單欄->工具->集合]以打開集合對話框。或者,我們也可以通過單擊相應的工具欄按鈕來打開對話框:

在集合對話框中,點擊添加新集合。一個新的集合對像出現在下面的列表中。目前,新添加的集合仍為空(未定義)。在列表中選擇新的收藏項時,在場景層次中選擇bubbleRob,然後在收藏對話框中單擊“ 添加 ”。現在,我們的集合被定義為包含層次結構樹的所有對象(從bubbleRob對像開始)(集合的組成顯示在“ 組成元素和屬性”部分中)。要編輯集合名稱,請雙擊它,然後將其重命名為bubbleRob_collection。我們關閉收集對話框。
在此階段,我們希望能夠跟踪BubbleRob與任何其他對象之間的最小距離。為此,我們使用[菜單欄->工具->計算模塊屬性] 打開距離對話框。或者,我們也可以使用相應的工具欄按鈕打開計算模塊屬性對話框:

在距離對話框中,單擊添加新的距離對象,然後選擇一個距離對:[collection] bubbleRob_collection-場景中的所有其他可測量對象。這只是添加了一個距離對象,該距離對象將測量集合bubbleRob_collection(即該集合中的任何可測量對象)與場景中任何其他可測量對象之間的最小距離。我們通過雙擊其名稱將距離對象重命名為bubbleRob_distance。我們關閉距離對話框。現在運行模擬時,我們看不到任何區別,因為距離對象將嘗試測量(並顯示)BubbleRob之間的最小距離段以及場景中的其他任何可測量對象。問題在於,在此階段,場景中沒有其他可測量的對象(定義地板的形狀默認情況下已禁用其可測量的屬性)。在本教程的後續階段,我們將為場景添加障礙。
接下來,我們將向BubbleRob添加一個圖形對象,以顯示最小距離以上的距離,同時還顯示BubbleRob隨時間的軌跡。我們單擊[菜單欄->添加->圖]並將其重命名為bubbleRob_graph。我們將圖形附加到bubbleRob,並將圖形的絕對坐標設置為(0,0,0.005)。現在,通過在場景層次結構中雙擊其圖標來打開圖形屬性對話框。我們取消選中“ 顯示XYZ平面”,然後單擊“ 添加新數據流”以進行記錄,然後選擇“ 對象:數據流類型的絕對x位置 ” 和bubbleRob_graph用於記錄的對象/項目。數據流記錄列表中出現了一個項目。該項目是bubbleRob_graph的絕對X坐標的數據流(即,將記錄bubbleRobGraph的對象的絕對X位置)。現在,我們還想記錄y和z位置:我們以與上述類似的方式添加這些數據流。現在,我們有3個數據流,分別表示BubbleRob的x,y和z軌跡。我們將添加更多的數據流,使我們能夠跟踪我們的機器人與環境之間的最小距離:我們點擊添加新的數據流記錄,並選擇距離:段長度的數據流類型,並bubbleRob_distance用於記錄的對象/項目。在數據流記錄列表中,我們現在將Data重命名為bubbleRob_x_pos,將Data0重命名為bubbleRob_y_pos,將Data1重命名為bubbleRob_z_pos,將Data2重命名為bubbleRob_obstacle_dist。
我們在“ 數據流”記錄列表中和“ 時間圖屬性”部分中選擇bubbleRob_x_pos,取消選中“ 可見”。我們對bubbleRob_y_pos和bubbleRob_z_pos都執行相同的操作。這樣,在時間圖中只能看到bubbleRob_obstacle_dist數據流。以下是我們應該擁有的:

[圖形屬性]
接下來,我們將建立一個顯示BubbleRob軌蹟的3D曲線:單擊編輯3D曲線打開XY圖和3D曲線對話框,然後單擊添加新曲線。在對話框彈出打開,我們選擇bubbleRob_x_pos為X-值項,bubbleRob_y_pos為Y值項,bubbleRob_z_pos的Z值項目。我們將新添加的曲線從Curve重命名為bubbleRob_path。最後,我們檢查“ 相對於世界”項目並將“ 曲線寬度”設置為4:

[3D曲線屬性]
我們關閉與圖有關的所有對話框。現在我們將一個電機目標速度設置為50,運行模擬,然後將看到BubbleRob的軌跡顯示在場景中。然後,我們停止仿真並將電動機目標速度重置為零。
我們添加具有以下尺寸的純原始圓柱體:(0.1,0.1,0.2)。我們希望此圓柱體是靜態的(即不受重力或碰撞的影響),但仍會對非靜態的可響應形狀施加一些碰撞響應。為此,我們在形狀動力學屬性中禁用“ 主體是動態的” 。我們也希望我們的汽缸是 可碰撞,可衡量的,可渲染和檢測的。我們在對象的通用屬性中執行此操作。現在,在仍選擇圓柱體的情況下,我們單擊對象平移工具欄按鈕:

現在我們可以拖動場景中的任何點:圓柱體將跟隨運動,同時始終受約束以保持相同的Z坐標。我們複製並粘貼圓柱幾次,然後將它們移動到BubbleRob周圍的位置(從頂部查看場景時執行該操作最方便)。在對象移動期間,按住Shift鍵可以執行較小的移動步驟。按住ctrl鍵可以在與常規方向正交的方向上移動。完成後,再次選擇相機平移工具欄按鈕:

我們將左馬達的目標速度設置為50並運行模擬:現在,圖形視圖顯示了到最近障礙物的距離,並且該距離段在場景中也可見。我們停止模擬並將目標速度重置為零。
現在,我們需要完成BubbleRob作為模型定義。我們選擇模型庫(即對象bubbleRob),然後檢查項目Object是模型庫,並且Object / model可以轉移或接受對象共有屬性中的DNA:現在有一個點畫框,它包圍了模型層次結構中的所有對象。我們選擇兩個關節,即接近傳感器和圖形,然後啟用項目“不顯示為內部模型選擇”,然後在同一對話框中單擊“ 應用於選擇”:模型邊界框現在忽略了兩個關節和接近傳感器。仍在同一對話框中,我們禁用相機可見性圖層2,並為兩個關節和力傳感器啟用攝像機可見性層 10:這有效地隱藏了兩個關節和力傳感器,因為默認情況下禁用9-16層。任何時候我們都可以修改整個場景的可見性層。要完成模型定義,我們選擇視覺傳感器,兩個輪子,滑塊和圖形,然後啟用“ 選擇模型基礎”項:如果現在嘗試在場景中的模型中選擇一個對象,則將選擇整個模型,這是一種將整個模型作為單個對象進行處理和操作的便捷方法。此外,這可以防止模型受到意外修改。仍然可以通過在按住Shift的同時單擊選擇對像或在場景層次結構中正常選擇它們,來在場景中選擇模型中的單個對象。最後,我們將模型樹折疊到場景層次中。這就是我們所擁有的:

[ BubbleRob模型定義]
接下來,我們將在與BubbleRob接近傳感器相同的位置和方向上添加視覺傳感器。我們再次打開模型層次結構,然後單擊[菜單欄->添加->視覺傳感器->透視類型],然後將視覺傳感器連接到接近傳感器,並將視覺傳感器的本地位置和方向設置為(0,0,0)。我們還確保視覺傳感器不可見,不是模型邊界框的一部分,並且如果單擊該模型,則會選擇模型。為了自定義視覺傳感器,我們打開其屬性對話框。我們將遠裁剪平面項設置為1,將分辨率x和分辨率y設置為 項目分別為256和256。我們向場景中添加了一個浮動視圖,然後在新添加的浮動視圖上,右鍵單擊[彈出菜單->視圖->將視圖與選定的視覺傳感器關聯](我們確保視覺傳感器在該過程中被選中)。
通過單擊[菜單欄->添加->關聯的子腳本->非線程],將非線程子腳本附加到視覺傳感器。我們雙擊場景層次結構中視覺傳感器旁邊出現的小圖標:這將打開我們剛剛添加的子腳本。我們將以下代碼複製並粘貼到腳本編輯器中,然後將其關閉:
function sysCall_vision(inData)
simVision.sensorImgToWorkImg(inData.handle) -- copy the vision sensor image to the work image
simVision.edgeDetectionOnWorkImg(inData.handle,0.2) -- perform edge detection on the work image
simVision.workImgToSensorImg(inData.handle) -- copy the work image to the vision sensor image buffer
end
function sysCall_init()
end
為了能夠看到視覺傳感器的圖像,我們開始模擬,然後再次停止。
我們場景所需的最後一件事是一個小的子腳本,它將控制BubbleRob的行為。我們選擇bubbleRob並單擊[菜單欄->添加->關聯的子腳本->非線程]。我們雙擊場景層次結構中bubbleRob名稱旁邊顯示的腳本圖標,然後將以下代碼複製並粘貼到腳本編輯器中,然後將其關閉:
function speedChange_callback(ui,id,newVal)
speed=minMaxSpeed[1]+(minMaxSpeed[2]-minMaxSpeed[1])*newVal/100
end
function sysCall_init()
-- This is executed exactly once, the first time this script is executed
bubbleRobBase=sim.getObjectAssociatedWithScript(sim.handle_self) -- this is bubbleRob's handle
leftMotor=sim.getObjectHandle("bubbleRob_leftMotor") -- Handle of the left motor
rightMotor=sim.getObjectHandle("bubbleRob_rightMotor") -- Handle of the right motor
noseSensor=sim.getObjectHandle("bubbleRob_sensingNose") -- Handle of the proximity sensor
minMaxSpeed={50*math.pi/180,300*math.pi/180} -- Min and max speeds for each motor
backUntilTime=-1 -- Tells whether bubbleRob is in forward or backward mode
-- Create the custom UI:
xml = '<ui title="'..sim.getObjectName(bubbleRobBase)..' speed" closeable="false" resizeable="false" activate="false">'..[[
<hslider minimum="0" maximum="100" onchange="speedChange_callback" id="1"/>
<label text="" style="* {margin-left: 300px;}"/>
</ui>
]]
ui=simUI.create(xml)
speed=(minMaxSpeed[1]+minMaxSpeed[2])*0.5
simUI.setSliderValue(ui,1,100*(speed-minMaxSpeed[1])/(minMaxSpeed[2]-minMaxSpeed[1]))
end
function sysCall_actuation()
result=sim.readProximitySensor(noseSensor) -- Read the proximity sensor
-- If we detected something, we set the backward mode:
if (result>0) then backUntilTime=sim.getSimulationTime()+4 end
if (backUntilTime<sim.getSimulationTime()) then
-- When in forward mode, we simply move forward at the desired speed
sim.setJointTargetVelocity(leftMotor,speed)
sim.setJointTargetVelocity(rightMotor,speed)
else
-- When in backward mode, we simply backup in a curve at reduced speed
sim.setJointTargetVelocity(leftMotor,-speed/2)
sim.setJointTargetVelocity(rightMotor,-speed/8)
end
end
function sysCall_cleanup()
simUI.destroy(ui)
end
我們運行模擬。BubbleRob現在在嘗試避開障礙物的同時向前移動(以非常基本的方式)。在模擬仍在運行時,更改BubbleRob的速度,然後將其複制/粘貼幾次。在模擬仍在運行時,也嘗試擴展其中的一些。請注意,根據環境的不同,最小距離計算功能可能會嚴重降低仿真速度。您可以通過選中/取消選中“ 啟用所有距離計算”項,在“ 距離”對話框中打開和關閉該功能。
使用腳本控制機器人或模型只是一種方法。CoppeliaSim提供了許多不同的方法(也可以結合使用),請參閱外部控制器教程。
CoppeliaSim <<
Previous Next >> Line following BubbleRob