dji-sdk / Mobile-SDK-iOS

DJI Mobile SDK for iOS: http://developer.dji.com/mobile-sdk/
Other
577 stars 256 forks source link

Waypoint V2 Interval take pictures Problem #432

Open BCoulange opened 3 years ago

BCoulange commented 3 years ago

Hi,I'm trying to program the M300 with Zenmuse H20 with Waypoint V2 so that it takes photos each 3 seconds between two waypoints.(I'm working on the iOS Mobile SDK version 4.14-trial2).

I've tried the following code and sometimes it works, some other times it doesn't work : 

Here is the code I'm using :         

// create a take photo each 3 seconds action        
let ap = DJIWaypointV2Action.init()        
ap.actionId = 9999 // set an unique id        

// create the trigger       
let aptrigger = DJIWaypointV2Trigger.init()        
aptrigger.actionTriggerType = .interval // interval trigger        
// param of the trigger        
let p = DJIWaypointV2IntervalTriggerParam.init()        
p.actionIntervalType = .time // based on time        
p.interval = 3 // each 3 seconds        
p.startIndex = 0 // starting on the first waypoint        
aptrigger.intervalTriggerParam = p // set the param       
ap.trigger = aptrigger // set the trigger        

// create the actuator        
let apactuator = DJIWaypointV2Actuator.init()        
apactuator.actuatorIndex = 0 // index of camera        
apactuator.type = .camera // camera actuator (we want to take pictures)        
let p2 = DJIWaypointV2CameraActuatorParam.init()        
p2.operationType = .takePhoto // take photo as action        
apactuator.cameraActuatorParam = p2 // set the param        
ap.actuator = apactuator // set the actuator

Any idea what can cause this kind of problem?

Some complementary infos that can matter : 

Thanks for your help!

Matheus193dn commented 3 years ago

@BCoulange Hi, can you try again with my code? P/S:

BCoulange commented 3 years ago

@Matheus193dn I don't see any difference between your code and mine, is there something different?

I've also tried to remove all listener with no difference in the behavior

Matheus193dn commented 3 years ago

@BCoulange

You can replace my worked sample with your code. https://github.com/Matheus193dn/Mobile-SDK-iOS/blob/master/Sample%20Code/SwiftSampleCode/DJISDKSwiftDemo/Camera/fpv/CameraFPVViewController.swift

BCoulange commented 3 years ago

My code is to different from the sample to integrate it, here is the code :

        var missionUploadStarted = false
        var actionUploadStarted = false
        var speed:Float = 2

        let wp1 = DJIWaypointV2.init(
            coordinate: CLLocationCoordinate2D.init(
                 latitude: 50.58001823992862, 
                 longitude: 2.1089524182042974
           )
        )
        wp1.altitude = 20
        wp1.heading = 123
        wp1.headingMode = .waypointCustom
        wp1.isUsingWaypointAutoFlightSpeed = true
        wp1.autoFlightSpeed = speed
        wp1.isUsingWaypointMaxFlightSpeed = true
        wp1.maxFlightSpeed = speed
        wp1.flightPathMode = .goToPointInAStraightLineAndStop

        // note that only the altitude changes
        let wp2 = DJIWaypointV2.init(
            coordinate: CLLocationCoordinate2D.init(
                 latitude: 50.58001823992862, 
                 longitude: 2.1089524182042974
           )
        )
        wp2.altitude = 100
        wp2.heading = 123
        wp2.headingMode = .waypointCustom
        wp2.isUsingWaypointAutoFlightSpeed = true
        wp2.autoFlightSpeed = speed
        wp2.isUsingWaypointMaxFlightSpeed = true
        wp2.maxFlightSpeed = speed
        wp2.flightPathMode = .goToPointInAStraightLineAndStop

        // create a take photo each 3 seconds action
        let ap = DJIWaypointV2Action.init()
        ap.actionId = 9999 // set an unique id
        // create the trigger
        let aptrigger = DJIWaypointV2Trigger.init()
        aptrigger.actionTriggerType = .interval // interval trigger

        // param of the trigger
        let p = DJIWaypointV2IntervalTriggerParam.init()
        p.actionIntervalType = .time // based on time
        p.interval = 3 // each 3 seconds
        p.startIndex = 0 // starting on the first waypoint
        aptrigger.intervalTriggerParam = p // set the param
        ap.trigger = aptrigger // set the trigger

        // create the actuator
        let apactuator = DJIWaypointV2Actuator.init()
       apactuator.actuatorIndex = 0 // index of camera
        apactuator.type = .camera // camera actuator (we want to take pictures)
        let p2 = DJIWaypointV2CameraActuatorParam.init()
        p2.operationType = .takePhoto // take photo as action
        apactuator.cameraActuatorParam = p2 // set the param
        ap.actuator = apactuator // set the actuator        

        // start the mission : 
        DJISDKManager.missionControl()?.unscheduleEverything()
        let wpOperator2 = DJISDKManager.missionControl()?.waypointV2MissionOperator()
        wpOperator2?.removeAllListeners()

       // what is done when the mission is uploaded
      wpOperator2?.addListener(toActionUploadEvent: self, with: nil, andBlock: { (event:DJIWaypointV2MissionActionUploadEvent) in
                if(event.error != nil){
                    print("ERROR UPLOADING ACTIONS:",event.error.debugDescription)
                }
               // if ready to execute, we can start the mission
                if (event.currentState == .readyToExecute) && actionUploadStarted {
                   // Start mission
                    wpOperator2!.startMission { (error:Error?) in
                        if(error == nil){
                            print("Mission Started!")
                        }else{
                            print("Failed starting mission")
                            print(error)
                        }
                    }
                }
            })

            // a waypoint mission
            let wpmiss2 = DJIMutableWaypointV2Mission.init()

            wpmiss2.addWaypoints([wp1,wp2])
            wpmiss2.finishedAction = DJIWaypointV2MissionFinishedAction.noAction // what to do when finished
            wpmiss2.exitMissionOnRCSignalLost = true // stop if lose signal
            wpmiss2.maxFlightSpeed = 15
            // prepare upload mission and actions
            wpOperator2?.addListener(toUploadEvent: self, with: nil, andBlock: { (event:DJIWaypointV2MissionUploadEvent) in
                if event.error != nil {
                   print("upload mission error")
                }

                if((event.currentState == DJIWaypointV2MissionState.readyToExecute) && missionUploadStarted){
                    wpOperator2!.uploadWaypointActions(self.djiWaypoints2Actions, withCompletion: { (e:Error?) in
                        if(e != nil){
                            print("Error uploading actions:",e.debugDescription)
                        }else{
                            actionUploadStarted = true
                        }

                    })
                }
            })

            // load the mission
            wpOperator2!.load(wpmiss2)

            // upload the mission
            wpOperator2?.uploadMission(completion: { (error:Error?) in
                if(error == nil){
                    missionUploadStarted = true
                    print("uploaded mission")
                }else{
                    print("Fail uploading mission")
                    print("current state :",wpOperator2!.currentState.description())
                    print(error.debugDescription)
                }
            })

And finally to start the mission :

                    wpOperator2!.startMission { (error:Error?) in
                        if(error == nil){
                            print("Mission Started!")
                        }else{
                            print("Failed starting mission")
                            print(error)
                        }
                    }

Note that I did some tests in addition of the pure vertical flight :

I feel like there is a bug in the sdk :(

BCoulange commented 3 years ago

@Matheus193dn I'll try to reformat my code to look like the sample code to see if the behavior changes. But don't hesitates if you see any problem in my code

BCoulange commented 3 years ago

Towards your other questions :

BCoulange commented 3 years ago

Just tried with a code very similar to the sample, same behavior.

Matheus193dn commented 3 years ago

@BCoulange

image Yes, there is a func to set Jpeg, just make sure these pics will be saved correctly.

BCoulange commented 3 years ago
  • Did you set JPEG for photo before flight Yes and this returns the JPEG type :

    lens?.getPhotoFileFormat(completion: { (f:DJICameraPhotoFileFormat, e:Error?) in
    f == .JPEG // true
    })
  • First, try with ap.actionid = 0 instead 9999.

  • Second, don't set actuatorIndex, it seems your selected camera was busy at that time.

Just tried that with the same position but different altitude. I have the same behavior :

the drone flights between the two waypoints but only 2 photos taken instead of each 3s, seems to be the first and second waypoint)

  • Third, did you try with 2 different locations?

Yes, I updated the position of the second waypoint by changing the lattitude :

thanks for your help!

Matheus193dn commented 3 years ago

Do you have another drones instead of M300? I think it will work as your expectation. For M300, i still see a lot of bugs from sdk, hope they will fix them soon.

BCoulange commented 3 years ago

Do you know if there are other drones that use WaypointsV2?

Matheus193dn commented 3 years ago

Do you know if there are other drones that use WaypointsV2?

Currently, it only supported M300, but you can test interval shooting with Timeline or WaypointV1

BCoulange commented 3 years ago

Yep I've tested that and it works with Mavic Pro 2, so bad the M300 is basically unusable :(

federiconicoli commented 3 years ago

@dji-dev Hey! Any progress on this issue?

I'm facing a similar behavior but with distance as action interval type. This is how I'm creating the action:

  let cameraActuatorParam = DJIWaypointV2CameraActuatorParam()
  cameraActuatorParam.operationType = .takePhoto

  let waypointActuator = DJIWaypointV2Actuator()
  waypointActuator.type = .camera
  waypointActuator.cameraActuatorParam = cameraActuatorParam

  let cameraTriggerParam = DJIWaypointV2IntervalTriggerParam()
  cameraTriggerParam.actionIntervalType = .distance
  cameraTriggerParam.interval = 1
  cameraTriggerParam.startIndex = 0

  let cameraTrigger = DJIWaypointV2Trigger()
  cameraTrigger.actionTriggerType = .interval
  cameraTrigger.intervalTriggerParam = cameraTriggerParam

  let cameraAction = DJIWaypointV2Action()
  cameraAction.actuator = waypointActuator
  cameraAction.trigger = cameraTrigger
  cameraAction.actionId = 1

The action is uploaded successfully but the drone only takes a couple of photos between waypoint 0 and 1.

DJI SDK: 4.14 Matrice 300 RTK: V02.02.0301 Zenmuse H20: V02.02.0100

ethanJY commented 2 years ago

Yep I've tested that and it works with Mavic Pro 2, so bad the M300 is basically unusable :(

Sorry for the trouble. As far as I know, the most likely reason is that H20 would take several seconds to process the data generated by the shot. So If the amount of data to be processed is large, it may not respond to the shot command during a few seconds. Have you ever tried to increase the interval seconds? That may reduce the probability of this problem.

ethanJY commented 2 years ago

@dji-dev Hey! Any progress on this issue?

I'm facing a similar behavior but with distance as action interval type. This is how I'm creating the action:

  let cameraActuatorParam = DJIWaypointV2CameraActuatorParam()
  cameraActuatorParam.operationType = .takePhoto

  let waypointActuator = DJIWaypointV2Actuator()
  waypointActuator.type = .camera
  waypointActuator.cameraActuatorParam = cameraActuatorParam

  let cameraTriggerParam = DJIWaypointV2IntervalTriggerParam()
  cameraTriggerParam.actionIntervalType = .distance
  cameraTriggerParam.interval = 1
  cameraTriggerParam.startIndex = 0

  let cameraTrigger = DJIWaypointV2Trigger()
  cameraTrigger.actionTriggerType = .interval
  cameraTrigger.intervalTriggerParam = cameraTriggerParam

  let cameraAction = DJIWaypointV2Action()
  cameraAction.actuator = waypointActuator
  cameraAction.trigger = cameraTrigger
  cameraAction.actionId = 1

The action is uploaded successfully but the drone only takes a couple of photos between waypoint 0 and 1.

DJI SDK: 4.14 Matrice 300 RTK: V02.02.0301 Zenmuse H20: V02.02.0100

Hi, I think that 1 second is not enough for H20 to process data generated by last shot. So please try to increase time interval. That may help. Thx