如何通過 DJI SDK 控制無人機運動
在確定連線上飛行機後,從 DJIAircraft 物件上獲取 DJIFlightController 例項:flightController。 切換到 api 控制模式的程式碼很簡單,只有一行:
flightController.setVirtualStickModeEnabled(true, withCompletion: nil) 複製程式碼
但是這行程式碼執行未必都會成功,需要滿足以下兩種情況才能切換:
- 飛控程式沒有在執行控制飛行器運動路徑。如果飛行器在執行 waypoint、hotpoint、跟隨任務時,無法切換。
- FlightOrientationMode 需要設定為 aircraftHeading。
flightController.setFlightOrientationMode(.aircraftHeading, withCompletion: nil) 複製程式碼
FlightOrientationMode 預設方向定位模式就是根據當前無人機朝向。加這個限制應該是出於安全的原因,想要移動飛行器,通常是根據圖傳視訊來判斷位置移動。 ofollow,noindex">FlightOrientationMode 還有兩種方式:Course Lock 和 Home Lock。都是鎖定了某個位置來判斷移動方位,特殊任務中有幫助,但是如果通過程式控制飛行器還是按照飛行器的當前朝向符合直覺。
成功切換到程式控制飛行器運動後,遙控器上的操作杆會出於無效的狀態
這是非常非常重要且被忽略的一點。這個設計應該也是出於安全考慮,希望飛行器在某個時刻只有一個明確的控制權,如果一個時刻遙控器發出往左,程式控制往右。兩個指令都擁有一樣的優先順序,不知道誰優先。所以在控制運動完成後切記把 VirtualStickMode 設定為 false。
VirtualStickFlightControlData
在切換到程式控制運動模式後,就可以傳送控制指令了。和遙控器上的兩個搖桿控制能力一樣,你可以控制飛行器的升降、水平旋轉、水平方向的前進後退、向左向右。 運動指令的引數是一個 DJIVirtualStickFlightControlData 型別的結構體,前面提到可以控制四個維度的運動,因此有四個浮點型的值可以設定:
typedef struct { float pitch; float roll; float yaw; float verticalThrottle; } DJIVirtualStickFlightControlData 複製程式碼
為了讓使用者可以更加靈活的控制飛行器運動,這四個維度的引數值在不同模式下代表著不同的含義。

RollPitchControlMode
水平方向 X、Y 軸的運動的控制模式是一致的,因此組合在一起,列舉名叫 RollPitchControlMode。 在設定水平運動的值時需要先確定此時選擇的參考座標系。為了更方便的控制姿態,DJI 提供了兩個座標系:Body Coordinate 和 Ground(World) Coordinate。
座標系
設定座標系的方式很簡單,設定 rollPitchCoordinateSystem 即可:
flightController.rollPitchCoordinateSystem = .ground 複製程式碼
機身座標系:Body Coordinate

機身座標系類似第一人稱視角,飛行器的正前方是 X 軸,與前方垂直的側面測試 Y 軸。
世界座標系:Ground(World) Coordinate

地面座標系就像是地面有個控制中心的視角,南北方向是 X 軸,東西方向是 Y 軸。
RollPitchControlModeAngle
如果是機身座標系,角度就是機身X、Y軸的旋轉角度。取值範圍是 - 30 到 30 度。

如果是地面座標系,那麼就是相對地面的移動角度。
RollPitchControlModeVelocity
X、Y 軸的移動速度,取值範圍 -15 到 15 米每秒。根據座標系不同 X、Y 軸的方向不同,前面已經說明過。
YawControlMode
Yaw 從地面角度看就是飛機原地旋轉,也就是調整機頭方位。同樣引數有兩種模式:
Angle
相對於機頭的旋轉角度,取值範圍注意不是 0 - 360,而是 -180 到 180。正的角度表示順時針旋轉,負的角度值表示逆時針。
AngularVelocity
旋轉時的角速度,取值範圍是 -100 到 100。負數表示逆時針方向旋轉。如果你想要飛行器以個指定的角速度勻速旋轉,那麼應該選擇這個模式。
VerticalControlMode
豎直方向高度的控制也有兩種。
Velocity
調整高度的速度,取值範圍是 -4 到 4。正的值表示往高處飛,負數表示下降時的速度。
Position
直接設定想要到達的高度值,取值範圍是 0 到 500 米。也就是說最高可以讓飛行器飛到 500 米的高度。
傳送指令
傳送控制的指令程式碼很簡單,只有一行:
flightController.send(controlData, withCompletion: { error in}) 複製程式碼
但是事情並不如程式碼看上去這樣簡單。VirtualStick API 設計參照的是遙控器操縱桿的通訊方式,比如你把一個搖桿往上推,飛行器此時對應的操作是升高。那麼在你往上推的時刻,遙控器是以一個頻率持續給飛行器傳送升高指令。在你鬆開的時候,搖桿回到中心,指令停止。並不是只發送了一條指令。和這個場景類似,如果你要控制飛行器運動,你的指令也應該是持續傳送的。 官方給出的傳送頻率是 10 到 25 赫茲。換算一下,那麼程式應該以 0.04 秒 - 0.1 秒的頻率就傳送一次控制指令。可能對於程式而言,非常清楚飛行器運動的終點是哪,覺得只要呼叫一次介面,但是出於安全考慮, 如果指令不是持續傳送的,飛行器收到指令也可能不去執行 。 為了避免發出指令飛行器認為是通訊失誤而沒有執行,可以採取用一個 timer 以一個固定的 interval 傳送指令。簡單一些可以正確的頻率傳送 5 次,如果是 0.1 秒的頻率,那麼等於確保一條指令飛行器認可花 0.5 秒時間。另外一個思路是指令傳送後從 KeyManager 獲取飛行器的姿態資訊(DJISDKVector3D),如果指令傳送過程中姿態資料改變了,那麼一定是執行了控制指令。
奇志動聯 MeshKit 是奇志資訊科技有限公司旗下的一個基於無人機+人工智慧的物聯網作業平臺,為企業級使用者及專業級個人使用者提供易用便捷的無人機軟體及雲端計算解決方案,通過任務自動化、多機協同、場景定製開發功能、人工智慧等核心技術,大幅提升客戶使用無人機等智慧物聯網裝置解決實際生產問題的效率。 我們在杭州和深圳招聘 iOS、Android 工程師,如果感興趣歡迎給我們投簡歷:奇志資訊科技招聘資訊。