跳到正文

Wiki

即時迴圈與非同步通訊

約 4 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

通訊執行緒負責等裝置,控制執行緒負責按週期處理最新資料。本節先把執行緒與資料所有權劃清楚,再接序列埠。

1.示例 1:把兩條執行路徑畫出來

通信线程
  接收字节 → 拼帧 → 校验 → 保存完整反馈快照
  读取待发目标 → 打包 → 异步写设备

控制线程
  read → 取最新完整反馈,更新状态接口
  update → 控制器处理目标与反馈
  write → 保存待发目标,不等待设备回复

序列埠可能以 50 Hz 返回,控制迴圈以 100 Hz 執行。某一輪沒有新反饋時,可以使用上一份仍有效的快照;超過明確的超時時間則進入錯誤處理。

2.示例 2:閱讀 realtime buffer

開啟 realtime_tools/include/realtime_tools/realtime_buffer.hpp,定位:

  • writeFromNonRT(data):非即時側寫入。
  • readFromRT():即時側嘗試取得最新資料。

當前版本 readFromRT 使用 try-lock;拿不到鎖時繼續返回現有即時側資料。它不是“每讀一次都等待寫執行緒完成”。writeFromNonRT 則可能等待,所以不能因為型別名字包含 realtime,就把所有成員函式都放進即時迴圈。

2.1.為什麼控制器採用固定大小的 Target

在從零編寫控制器中,目標快照只有兩個 double 和一個標記。資料驗證在接收回調完成,update 只讀快照並寫介面,減少控制週期中的字串處理與動態分配。

readFromRT() 返回的指標不應被任意執行緒長期儲存後繼續訪問。按類的併發約定使用,並在當前 update 中複製需要的資料。

3.示例 3:判斷一段 read 是否合適

下面是反例虛擬碼,不應作為外掛實現:

read:
  阻塞读取,直到收到完整一帧
  等待设备回复
  sleep 100 ms
  返回

如果一輪只有約 10 ms 預算,上述等待會拖延所有使用該管理器的控制器。

下一章提供可執行的學習實現:接收與寫序列埠都在獨立 Asio 執行緒;read/write 用 try-lock 交接固定大小資料;取不到鎖保留上一份快照,並用反饋時間戳檢查過期。

3.1.try-lock 是否就等於硬即時

不是。執行緒排程、驅動、原子操作實現、記憶體、日誌和演算法都影響即時性。下一章程式碼是可觀察的通訊教學實現,沒有宣稱經過硬即時認證。

4.資料交接的四個問題

問題 本教程的處理
一次反饋是否完整 先拼幀、解析、驗證,再更新整組快照
資料是否過期 單調時鐘記錄最近有效反饋時間
消費速度低於產生速度 狀態只保留最新值,丟棄過期快照
發包是否堆積 同一時刻只保留一個非同步寫操作

“只保留最新值”適合連續位置目標,未必適合使能、復位或離散任務。後者往往需要可靠佇列、序號與確認機制。

5.兩種超時必須區分

上游命令超時意味著目標不再更新;下游反饋超時意味著裝置狀態不再可信。差速控制器的 cmd_vel_timeout 不能代替硬體反饋看門狗,ROS 節點退出也不能代替下位機獨立看門狗。

原始碼:realtime_tools/include/realtime_tools/realtime_buffer.hpp、ros2_controllers/forward_command_controller/src/forward_controllers_base.cpp。對照 writeFromNonRT 和 readFromRT 的呼叫執行緒,而不只看函式名。


返回 Humble 總覽 · 上一篇:管理器與資源管理原始碼 · 下一篇:虛擬序列埠與模擬下位機