在 DJI SDK 中 Mission 的执行是由各自对应的 operator 管理的,WaypointMission 的生命周期由 DJIWaypointMissionOperator 管理。
基本流程
检查任务
在上一篇文章中介绍了 mission 和 waypoint 可以进行的配置。很多配置项要在对应的模式下才有效,因此在开始任务前需要检查一下任务的配置是否正确。这里的检查函数有两个,一个检查 mission 的配置,一个检查 waypoint 的配置:
// 检查任务的参数配置是否有效mission.checkParameters()// 检查 waypoint 的配置是否有效mission.checkValidity()
加载、上传任务
任务的执行是由 DJIWaypointMissionOperator 管理的,所以首先需要把任务加载到 operator 中:
guard let missionOperator = DJISDKManager.missionControl()?.waypointMissionOperator() else { return }missionOperator.load(mission)
加载成功后需要把任务数据上传到无人机的飞控中。Waypoint 是一个一个上传的,如果 waypoint 比较多可能上传时间会久一些。要注意和无人机的通信状况是否良好,这一步很容易因为通信状况不佳失败。
missionOperator.uploadMission { (error) inif let error = error {// 处理上传失败的错误}}
考虑到可能有多个对象关心航点的上传进度,DJI 使用观察者模式来处理上传的进度通知。
// 添加观察者/*** Adds listener to receive the event related to upload.*/- (void)addListenerToUploadEvent:(id)listenerwithQueue:(nullable dispatch_queue_t)queueandBlock:(DJIWaypointMissionOperatorUploadEventBlock)block;// 移除观察者- (void)removeListenerOfUploadEvents:(id)listener;
通过回调的 DJIWaypointMissionUploadEvent 实例可以获取到当前的上传进度和任务的状态。
missionOperator.addListener(toUploadEvent: self, with: listenerQueue) { (uploadEvent) inif let progress = uploadEvent.progress {print("progress: \(progress.uploadedWaypointIndex)/\(progress.totalWaypointCount)")}if uploadEvent.currentState == .readyToExecute {missionOperator.removeListener(ofUploadEvents: self)}}
当 uploadEvent 中的当前任务状态是 readyToExecute 时说明航点已经上传结束,无人机准备就绪。
任务控制
任务的控制有:开始、暂停、继续、停止四种操作。
- (void)startMissionWithCompletion:(DJICompletionBlock)completion;- (void)pauseMissionWithCompletion:(DJICompletionBlock)completion;- (void)resumeMissionWithCompletion:(DJICompletionBlock)completion;- (void)stopMissionWithCompletion:(DJICompletionBlock)completion;
只要任务在对应正确的状态时这些操作才会成功。比如只有当任务是在执行的状态时暂停和停止才能正确执行,否则会返回一个错误。
任务进度监听
与上传航点的监听方式一致,任务的执行进度通知也采用了一样的的观察者模式。
/*** Adds listener to receive the event related to execution.*/- (void)addListenerToExecutionEvent:(id)listenerwithQueue:(nullable dispatch_queue_t)queueandBlock:(DJIWaypointMissionOperatorExecutionEventBlock)block;
ExecutionEvent 返回的 DJIWaypointMissionExecutionEvent 实例。DJIWaypointMissionExecutionEvent 包含了任务当前的状态和任务执行的进度。
@interface DJIWaypointMissionExecutionEvent : NSObject/*** The previous state of the operator.*/@property (nonatomic, readonly) DJIWaypointMissionState previousState;/*** The current state of the operator.*/@property (nonatomic, readonly) DJIWaypointMissionState currentState;/*** The execution progress of the mission. It is `nil` if there is an error during* the execution.*/@property (nonatomic, readonly, nullable) DJIWaypointExecutionProgress *progress;/*** The encountered error during the execution if there is any. Otherwise, it is* `nil`.*/@property (nonatomic, readonly, nullable) NSError *error;@end
通过 ExecutionEvent 中的 error 属性可以判断执行是否遇到错误,currentState 和 previousState 反应了此时的任务状态。progress 可以知道当前无人机飞过的航点进度。
@interface DJIWaypointExecutionProgress : NSObject/*** Index of the waypoint for the next mission to which the aircraft will proceed.*/@property(nonatomic, readonly) NSInteger targetWaypointIndex;/*** YES when the aircraft reaches a waypoint. After the waypoint actions and heading* change is complete, the `targetWaypointIndex` will increment and this property* will become NO.*/@property(nonatomic, readonly) BOOL isWaypointReached;/*** Current execution state of the aircraft.*/@property(nonatomic, readonly) DJIWaypointMissionExecuteState execState;@end
targetWaypointIndex 表示飞机正在飞向的航点的索引,在飞行过程中 isWaypointReached 的值是 false。当无人机到达航点航点位置时 isWaypointReached 的值会变成 true。接着无人机根据设置调整 heading,执行 waypoint action。执行完成后 targetWaypointIndex 加 1,朝下一个航点飞去。

通常我们认为任务结束时 targetWaypointIndex 会是最后一个点,但是如果刚好 finishAction 是 goFirstWaypoint,无人机飞到最后一个点后会返回第一个航点,所以最后任务结束时的  targetWaypointIndex 会是 0。
另外一个容易理解错误的是 ExecutionEvent 是一个定时回调的事件,不是在 value changed 的时候才回调。所以无人机飞行过程中你可能会一直收到同样的值的 ExecutionEvent。
任务结束监听
任务结束的通知也采用了一样的的观察者模式。
/*** Adds listener to receive the notification when a waypoint mission is finished.*/- (void)addListenerToFinished:(id)listenerwithQueue:(nullable dispatch_queue_t)queueandBlock:(DJICompletionBlock)block;
任务结束的回调有三种可能:
- 回调有 error,任务执行过程中遇到了错误,任务终止
 - 回调无 error,到达过最后一个航点,任务正常结束
 回调无 error,没有到达过最后一个航点,任务过程中用户主动停止了任务或者过程中触发无人机返航
任务状态
在任务生命周期中很多操作都和任务的状态有关。Operator 上的 currentState 能取到最近一次同步的任务状态。任务状态
DJIWaypointMissionState总共有以下几种状态:Unknown:和无人机没有正常的通信,无法确认任务当前状态
- Disconnected:无人机断开连接
 - Recovering:手机和遥控器、无人机间的连接正在重连,任务状态正在同步中
 - NotSupported:连接的设备不支持该任务的状态同步
 - ReadyToUpload:无人机现在可以上传航点数据
 - Uploading:上传航点数据中
 - ReadyToExecute:航点数据上传成功,准备好开始执行任务
 - Executing:任务执行中
 - Paused:任务被暂停
下载任务
Waypoint mission 因为航点是一次性上传到飞控中,默认又是遥控器丢失信号任务继续执行。所以可能出现任务过程中应用退出,应用重新连接上无人机后,无人机虽然在执行任务,但是 sdk 中已经取不到 waypointMission 中的航点信息了。如果这个时候你需要在任务结束后重新进行一次同样的任务,那么任务 start 的时候就会报错,因为本地没有航点信息可以上传。针对这个情况 Operator 提供了下载航点的方法,和上传航点类似,需要注意的是只有在任务暂停和执行状态时下载航点才有效。 ```objectivec /**- Downloads information of each waypoint from aircraft and save it to
 loadedMission. If a download operation is started, the operator will download- the information of waypoints missing in 
loadedMissionone-by-one in ascending - order. If 
loadedMissionis already complete (containing all the waypoints), - this method will call 
completionimmediately without error. It can only be - called when the 
currentStateis one of the following: - DJIWaypointMissionStateExecuting-DJIWaypointMissionStateExecutionPaused*/
 - (void)downloadMissionWithCompletion:(DJICompletionBlock)completion; // 监听下载的进度
 - (void)addListenerToDownloadEvent:(id)listener
```withQueue:(nullable dispatch_queue_t)queueandBlock:(DJIWaypointMissionOperatorDownloadEventBlock)block;
 
