0

I'm currently working on enabling a DJI product to execute waypoint missions autonomously, adapting from a DJI tutorial (https://developer.dji.com/mobile-sdk/documentation/ios-tutorials/GSDemo.html). So I'm trying to integrating all the processes into one function. Here are the two completion blocks that I would have to integrate:

[[self missionOperator] uploadMissionWithCompletion:^(NSError * _Nullable error) {
    if (error){
        ShowMessage(@"Upload Mission failed", error.description, @"", nil, @"OK");
    }else {
        ShowMessage(@"Upload Mission Finished", @"", @"", nil, @"OK");
    }
}];

and:

[[self missionOperator] startMissionWithCompletion:^(NSError * _Nullable error) {
    if (error){
        ShowMessage(@"Start Mission Failed", error.description, @"", nil, @"OK");
    }else
    {
        ShowMessage(@"Mission Started", @"", @"", nil, @"OK");
    }
}];

In order for the second one to run successfully, the first one must first execute completely. This doesn't seem like a hard problem, but I could not figure it out after trying to add delays or dispatches.

Any help is appreciate. Thanks.

Inffzy
  • 9
  • 1
  • What is the behavior now? That info would probably help. Why not set a boolean in the first function, then check in the second function for it. – l'L'l May 25 '18 at 18:37
  • I have tried to confirm the state of execution with booleans. But the problem is that as the upload command executes, the ShowMessage command executes immediately, but all the processes in it is not done immediately. So as the boolean value changes, the start command executes, and the program finds that it is unable to run because the uploading is not completed. – Inffzy May 25 '18 at 18:47
  • Yeah you’ll want to use an async dispatch queue in that case. – l'L'l May 25 '18 at 18:50
  • Why isn't it sync dispatch since I need things to execute sequentially? Sorry I'm new to this XD – Inffzy May 25 '18 at 19:37
  • Serial queue? NSOperations with dependency? – matt May 25 '18 at 20:34

2 Answers2

1

From the iOS version of the docs you linked, the docs for -[DJIWaypointMissionOperator uploadMissionWithCompletion:] say:

If it is started successfully, use addListenerToUploadEvent:withQueue:andBlock to receive the detailed progress.

So, you would do something like this:

[[self missionOperator] uploadMissionWithCompletion:^(NSError * _Nullable error) {
    if (error)
    {
        ShowMessage(@"Upload Mission failed", error.description, @"", nil, @"OK");
    }
    else
    {
        ShowMessage(@"Upload Mission Started", @"", @"", nil, @"OK");

        [[self missionOperator] addListenerToUploadEvent:self
                                               withQueue:nil
                                                andBlock:^(DJIWaypointMissionUploadEvent *event){
            if (event.currentState == DJIWaypointMissionStateReadyToExecute)
            {
                [[self missionOperator] startMissionWithCompletion:^(NSError * _Nullable error) {
                    if (error)
                    {
                        ShowMessage(@"Start Mission Failed", error.description, @"", nil, @"OK");
                    }
                    else
                    {
                        ShowMessage(@"Mission Started", @"", @"", nil, @"OK");
                    }
                }];
            }
            else if (event.error)
            {
                ShowMessage(@"Upload Mission failed", event.error.description, @"", nil, @"OK");
            }
        }];
    }
}];
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • You would be correct if these are two general completion blocks. But in the background, there is a variable tracking the state of the process. I am able to access the value of it but don't know how to change. So uploadMissionWithCompletion changes that variable from "ready to upload" to "uploading". When the uploading is actually finished, then the state changes to "uploaded". And only when the state becomes "uploaded", "startMissionWithCompletion" would execute. – Inffzy May 26 '18 at 01:58
  • Here is a page related to that (https://developer.dji.com/api-reference/android-api/Components/Missions/DJIWaypointMissionState.html#djiwaypointmissionstate). – Inffzy May 26 '18 at 01:58
  • So the completion handler you supply to the `upload...` method is called when the upload is not really finished? – Ken Thomases May 26 '18 at 02:00
  • Yes. So I think I should add a delay somewhere. But I need to make sure that as startMission is waiting, uploadMission should keep running until it's fully finished. – Inffzy May 26 '18 at 03:03
  • Why do you log "Upload Mission Finished" if it's not really finished? It's a really strange design to have a completion handler that's called before the thing is complete. Anyway, I've edited my answer to show an alternative. – Ken Thomases May 26 '18 at 10:42
  • Omg it worked. I've been on this for two days XD. Thank you so much. I still have so much to learn. I thought I needed sync requests. I must find out how listeners work. But again, thank you very much. – Inffzy May 27 '18 at 23:07
0

Your code looks correct. I ran into the same issue whereby after my mission finished uploading, my missionOperator's currentState would revert back to DJIWaypointMissionStateReadyToUpload rather than DJIWaypointMissionStateReadyToExecute. The mission had passed the validity check but in fact was invalid due to invalid curve requirements on individual waypoints (cornerRadiusInMeters property).

From the documentation:

/**
 *  Corner radius of the waypoint. When the flight path mode  is
 *  `DJIWaypointMissionFlightPathCurved` the flight path near a waypoint will be  a
 *  curve (rounded corner) with radius [0.2,1000]. When there is a corner radius,
 *  the aircraft will never  go through the waypoint. By default, the radius is 0.2
 *  m. If the corner is made of three adjacent waypoints (Short for A,B,C)  . Then
 *  the radius of A(short for Ra) plus radius of B(short for Rb) must be smaller
 *  than the distance between  A and B. The radius of the first and the last
 *  waypoint in a mission does not affect the flight path and it should keep the
 *  default value (0.2m).
 */

Hope this helps someone.

Wes Hager
  • 181
  • 1
  • 6