理解 Spot 編程(Understanding Spot Programming)
前言大綱
本指南將幫助您了解驅動 Spot 和 Spot Python SDK 的編程原則。
- 基礎機器人服務(Fundamental Robot Services)
- 理解“id”命令(Understanding the “id” command)
- 列表服務(Listing Services)
- 理解如何設置與命令機器人移動(Understanding How to Setup and Command Spot to Move)
- 創建SDK物件(Create the SDK object)
- 創建機器人物件(Create a Robot object)
- 檢索機器人ID(Retrieve the Robot ID)
- 閉塞vs非同步,機器人Python SDK 函式功能(Blocking vs. Asynchronous Spot Python SDK functions)
- 檢視機器人狀態(Inspecting robot state)
- 服務與授權(Services and Authentication)
- 處理機器人狀態(Retrieving Robot State)
- 機器人狀態是一種訊息,定義在 Protobufs (Robot State was a Message, Messages are defined by Protobufs)
- 機器人幀框(Spot’s Frames)
- 擷取並看相機圖像(Capture and View Camera images)
- 配置電機起動授權-軟體的急停(Configuring “Motor Power Authority” - software E-Stop)
- 創建並註冊急停端點(Create and register an E-Stop Endpoint)
- 清除急停(Clear the E-Stop)
- 取得機器人的擁有權(Taking ownership of Spot -Leases)
- 啟動機器人(Powering on the robot)
- 建立時間同步(Establishing timesync)
- 下命令給機器人(Commanding the robot)
- 機器人關機(Powering off the robot)
基礎機器人服務(Fundamental Robot Services)
理解“id”命令(Understanding the “id” command)
用 --verbose 指定詳細標誌,你會得到很多信息!我們將解釋這些片段……
2020-03-26 17:30:27,571 - DEBUG - Creating standard Sdk, cert glob: "None"
2020-03-26 17:30:27,610 - DEBUG - Created client for robot-id
2020-03-26 17:30:27,615 - DEBUG - Created channel to 192.168.80.3 at port 443 with authority id.spot.robot
...
第一個輸出行創建一個 Spot SDK 物件。所有 Spot API 程序都以這種方式啟動。
第三行創建 Spot 的機器人 ID robot-id 服務的 客戶端 client。 Spot API 通過一組網絡可訪問服務公開機器人功能 - 類似於 微服務microservice 架構。
2020-03-26 17:30:27,616 - DEBUG - blocking request: b'/bosdyn.api.RobotIdService/GetRobotId' header { request_timestamp { seconds: 1585258227 nanos: 616570624 } client_name: "BosdynClientbblank02:__main__.py-28906" }
在上面的輸出中,可以看到對 bosdyn.api.RobotIdService 進行了區塊性的 GetRobotId RPC。
2020-03-26 17:30:27,650 - DEBUG - response: b'/bosdyn.api.RobotIdService/GetRobotId'
header {
request_header {
request_timestamp {
seconds: 1585258227
nanos: 616570624
}
client_name: "BosdynClientbblank02:__main__.py-28906"
}
request_received_timestamp {
seconds: 1585258226
nanos: 224952738
}
response_timestamp {
seconds: 1585258226
nanos: 224990830
}
error {
code: CODE_OK
}
request {
type_url: "type.googleapis.com/bosdyn.api.RobotIdRequest"
value: "\n6\n\014\010\363\275\364\363\005\020\200\276\200\246\002\022&BosdynClientbblank02:__main__.py-28906"
}
}
robot_id {
serial_number: "beta-BD-90490007"
species: "spot"
version: "V3"
software_release {
version {
major_version: 2
}
changeset_date {
seconds: 1583941992
}
changeset: "b11205d698e"
install_date {
seconds: 1583953617
}
}
nickname: "beta29"
computer_serial_number: "02-19904-9903"
}
列表服務(Listing Services)
$ python -m bosdyn.client --user user --password password 192.168.80.3 dir list $ python -m bosdyn.client --user user --password password 192.168.80.3 dir list $ python -m bosdyn.client --user user --password password 192.168.80.3 dir list name type authority tokens --------------------------------------------------------------------------------------------------- auth bosdyn.api.AuthService auth.spot.robot directory bosdyn.api.DirectoryService api.spot.robot user directory-registration bosdyn.api.DirectoryRegistrationService api.spot.robot user estop bosdyn.api.EstopService estop.spot.robot user graph-nav-service bosdyn.api.graph_nav.GraphNavService graph-nav.spot.robot user image bosdyn.api.ImageService api.spot.robot user lease bosdyn.api.LeaseService api.spot.robot user ...
有關 Spot 的 API 架構Spot’s API Architecture 的更多詳細信息,請參閱概念文檔。
理解如何設置與命令機器人移動(Understanding How to Setup and Command Spot to Move)
從命令行運行 Spot 以了解命令 Spot 的基礎知識很有用。
Python 3.6.8 (default, Jan 14 2019, 11:02:34)
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import bosdyn.client
創建SDK物件(Create the SDK object)
所有波士頓動力 API 程序都首先創建一個帶有客戶端名稱參數的 SDK 物件。客戶端名稱用於幫助調試,並且沒有任何語義信息 - 因此請使用對您有幫助的任何字符串。
創建機器人物件(Create a Robot object)
要像我們在 Spot Python SDK 快速入門QuickStart 中所做的那樣檢索機器人 ID,我們首先需要創建一個機器人物件,並使用其網絡地址作為參數。
檢索機器人ID(Retrieve the Robot ID)
如前所述,Spot 通過許多服務公開其功能。波士頓動力 Python API 為每個服務都有一組相應的客戶端,這些客戶端是從機器人物件創建的。
>>>id_client.get_id()
serial_number: "beta-BD-90490007"
species: "spot"
.....
閉塞vs非同步,機器人Python SDK 函式功能(Blocking vs. Asynchronous Spot Python SDK functions)
>>>id_client.get_id(timeout=0.0001) Traceback (most recent call last): File "/mnt/c/spot_v2_0/bblank_spot_v2_0_env/lib/python3.6/site-packages/bosdyn/client/common.py", line 290, in call response = rpc_method(request, **kwargs) File "/mnt/c/spot_v2_0/bblank_spot_v2_0_env/lib/python3.6/site-packages/grpc/_channel.py", line 826, in __call__ return _end_unary_response_blocking(state, call, False, None) File "/mnt/c/spot_v2_0/bblank_spot_v2_0_env/lib/python3.6/site-packages/grpc/_channel.py", line 729, in _end_unary_response_blocking raise _InactiveRpcError(state) grpc._channel._InactiveRpcError: <_inactiverpcerror call.cc="" core="" created="" debug_error_string="{" description="" details="Deadline Exceeded" eadline="" exceeded="" file="" file_line="" from="" grpc_message="" grpc_status="" ipv4:192.168.80.3:443="" lib="" of="" peer="" received="" rpc="" rror="" src="" status="StatusCode.DEADLINE_EXCEEDED" surface="" terminated="" that="" with:="">
>>>fut.result()
serial_number: "beta-BD-90490007"
species: "spot"
.....
檢視機器人狀態(Inspecting robot state)
服務與授權(Services and Authentication)
假設用戶名是 user,密碼是 password,發出以下命令。
如果您提供了錯誤的憑據,則會引發異常。
處理機器人狀態(Retrieving Robot State)
>>>state_client.get_robot_state()
power_state {
timestamp {
seconds: 1585324337
nanos: 644209920
}
... a whole lot more
機器人狀態是一種訊息,定義在 Protobufs (Robot State was a Message, Messages are defined by Protobufs)
機器人幀框(Spot’s Frames)
擷取並看相機圖像(Capture and View Camera images)
>>>image_client = robot.ensure_client(ImageClient.default_service_name)
>>>sources = image_client.list_image_sources()
>>>[source.name for source in sources]
['back_depth', 'back_depth_in_visual_frame', 'back_fisheye_image', 'frontleft_depth', 'frontleft_depth_in_visual_frame', 'frontleft_fisheye_image', 'frontright_depth', 'frontright_depth_in_visual_frame', 'frontright_fisheye_image', 'left_depth', 'left_depth_in_visual_frame', 'left_fisheye_image', 'right_depth', 'right_depth_in_visual_frame', 'right_fisheye_image']
使用上面列出的來源名稱,我們可以從一個或多個圖像源捕獲圖像。 這些圖像可以以 RAW 格式或 JPG 格式(具有指定畫質)捕獲。 在單個 RPC 中請求的多個圖像將在硬件時間上彼此同步。 讓我們檢索 left_fisheye_image 並顯示它(除非您使用的是 MacOS 或 WSL)……
>>>from PIL import Image
>>>import io
>>>image = Image.open(io.BytesIO(image_response.shot.image.data))
>>>image.show()
配置電機起動授權-軟體的急停(Configuring “Motor Power Authority” - software E-Stop)
我們通過為急停服務“E-Stop”創建一個客戶端並請求狀態來看看機器人的初始急停狀態:
>>>estop_client.get_status()
stop_level: ESTOP_LEVEL_CUT
stop_level_details: "Not all endpoints are registered"
stop_level: ESTOP_LEVEL_CUT 行表示將不會啟用電源,因為 E-Stop 級別為 CUT。
創建並註冊急停端點(Create and register an E-Stop Endpoint)
安全注意事項:註冊端點的行為將觸發機器人的緊急停止,因此僅當 Spot 的電機已關閉時才執行此步驟。
>>>estop_endpoint.force_simple_setup()
急停端點應定期檢查機器人,以確保機器人得到安全控制。 如果超過 estop_timeout 秒,電機電源將被切斷。 調整這個數字很重要:數字太小,可能會因為暫時的網絡問題而斷電; 數量太大,您將面臨在沒有安全監督的情況下 Spot 運營的風險。
force_simple_setup 調用會發出一些 API 調用,使您的急停端點成為新急停配置中的唯一端點。
>>>estop_client.get_status()
endpoints {
endpoint {
role: "PDB_rooted"
name: "my_estop"
unique_id: "0"
timeout {
seconds: 9
}
cut_power_timeout {
seconds: 13
}
}
stop_level: ESTOP_LEVEL_CUT
time_since_valid_response {
}
}
stop_level: ESTOP_LEVEL_CUT
stop_level_details: "Endpoint requested stop"
現在出現一個名為 my_estop 的急停端點。 端點本身說 ESTOP_LEVEL_CUT,來自很久以前 time_since_valid_response 的響應。 尚未發生來自 E-Stop Endpoint 的簽到。 端點和 E-Stop 系統的停止級別都是 ESTOP_LEVEL_CUT - 如果單個端點想要斷電,則整個系統將斷電。
清除急停(Clear the E-Stop)
要更改 E-Stop 狀態並允許通電,端點需要定期檢查。我們將使用 EstopKeepAlive 類別從後台執行緒定期執行這些簽入。
>>>estop_keep_alive = bosdyn.client.estop.EstopKeepAlive(estop_endpoint)
>>>estop_client.get_status()
endpoints {
endpoint {
role: "PDB_rooted"
name: "my_estop"
unique_id: "0"
timeout {
seconds: 9
}
cut_power_timeout {
seconds: 13
}
}
stop_level: ESTOP_LEVEL_NONE
time_since_valid_response {
nanos: 996009984
}
}
stop_level: ESTOP_LEVEL_NONE
請注意,在許多實現中,您應該為 EstopKeepAlive 指定 keep_running_cb 參數,該函數由後台執行緒調用以查看是否應繼續簽入。 例如,交互式 UI 應該為 E-Stop 系統提供一個 keep_running_cb 函數,該函數會阻塞直到 UI 執行緒運行一個循環。 這可以防止凍結的客戶端繼續為機器人供電。
取得機器人的擁有權(Taking ownership of Spot -Leases)
為了控制機器人,客戶需要獲得 Lease 租約。 對機器人的每個移動命令都必須提供有效的租約。 當客戶不再想控制機器人時,可以退還租約。
與 E-Stop 一樣,租賃持有者需要定期與 Spot 簽到,以表明他們仍在主動控制機器人。 如果距離簽到時間過長,機器人將開始通訊丟失程序 - 坐下在可以的情況下,然後關閉電源。
讓我們為 lease 租用服務創建一個 LeaseClient 並列出當前 租用leases:
>>>lease_client = robot.ensure_client('lease')
>>>lease_client.list_leases()
[resource: "body"
lease {
resource: "body"
epoch: "IOSDMpfEqvdTHZGV"
sequence: 0
}
lease_owner {
}
]
啟動機器人(Powering on the robot)
現在您已通過 Spot 身份驗證、創建 E-Stop 端點並獲得租約,是時候啟動機器人了。
power_on 輔助函數首先向機器人發出較低級別的啟動命令,然後等待啟動命令反饋。 該命令在機器人通電後返回,或者如果啟動命令因任何原因失敗則拋出錯誤。 通常需要幾秒鐘才能完成。
robot.power_on(timeout_sec=20)
機器人對象提供了一種檢查機器人電源狀態的方法。這只是使用 RobotStateService 來檢查 PowerState:
True
建立時間同步(Establishing timesync)
>>>robot.time_sync.wait_for_sync()
下命令給機器人(Commanding the robot)
API 提供了一個輔助函數來支持 Spot。 此命令包裝了多個 RobotCommand RPC 調用。 首先發出站立命令。 機器人檢查一些基本的先決條件(通電、未故障、未緊急停止)並返回命令 ID。 然後可以將此命令 id 傳遞給機器人命令反饋 RPC。 此 call 調用返回高級反饋(“機器人是否仍在處理命令?”)以及命令特定反饋feedback (在站立的情況下,“機器人是否站立?”)。
>>>command_client = robot.ensure_client(RobotCommandClient.default_service_name)
>>>blocking_stand(command_client, timeout_sec=10)
機器人現在應該是站立的。 此外,可以修改站立命令以控制身體的高度以及身體相對於footprint frame足跡幀框 的方向。 足跡幀框是重力對齊幀框,其原點位於腳的幾何中心。 Z 軸向上,X 軸向前。
命令 proto 可以非常具有表現力,因此,如果超出默認參數,則非常重要。 為了增加簡單性,Spot API 提供了幾個輔助函數,將 Spot API RPC 命令組合成單行函數。
我們鼓勵您嘗試使用這些不同的參數,參考用於一般波士頓動力機器人的 robots_command proto 父類別和機器人命令 robot command proto 子類別。
# Command Spot to rotate about the Z axis.
>>> from bosdyn.geometry import EulerZXY
>>> footprint_R_body = EulerZXY(yaw=0.4, roll=0.0, pitch=0.0)
>>> from bosdyn.client.robot_command import RobotCommandBuilder
>>> cmd = RobotCommandBuilder.stand_command(footprint_R_body=footprint_R_body)
>>> command_client.robot_command(cmd)
# Command Spot to raise up.
>>> cmd = RobotCommandBuilder.stand_command(body_height=0.1)
>>> command_client.robot_command(cmd)
機器人關機(Powering off the robot)
參考資料
- Understanding Spot Programming
- 微服務microservice : 微服務是一種軟體架構風格,它是以專注於單一責任與功能的小型功能區塊 為基礎,利用模組化的方式組合出複雜的大型應用程式,各功能區塊使用與語言無關 的API集相互通訊。
- tweak : 調整, 擰
- intercept : 截聽
- quaternion : 四元數
留言
張貼留言
Aron阿龍,謝謝您的留言互動!