Anafi Gimbal and Video Stream issues

Hello, We are doing a project where we need to keep the video stream going while we adjust the gimbal pitch. we are running in to issues.

  1. It seems that doing gimbal.control() operation, the video stream freezes. is this a bug? .
  2. Additionally, when we try to read the current gimbal attitude(pitch) using gimbal.getAttitude(), it doesn’t update the values as the gimbal is rotating… it keeps returning the starting pitch value, even if I periodically read it. is this a bug as well?
  3. lastly, while doing this we start see the following log messages continuously:
    W/sdkcore.pool: Pool ‘cmd’ allocating more than maximum (50) items
    W/sdkcore.pool: Pool ‘RecvCmdPool’ allocating more than maximum (50) items

Any timely input would be helpful.

Hello,

  1. You should be able to control the gimbal without any freeze in the video stream.
  2. The attitude value should update while the gimbal is rotating
  3. Those logs informs that we are both trying to send commands to the drone faster than they can get out on the air, and receiving commands from the drone faster than we can process them. The container objects that we use internally to represent commands are fetched from a (size-capped at 50) pool to reduce allocations; here, since we are not fast enough, the pools are empty, so each time we need to process a command, we have to resort to do an allocation instead, which may affect performance a bit. This is just a warning, but it should not impair any functionality.

That being said, I cannot reproduce your issue. Our application in production has roughly the same use case (controlling the gimbal while rendering the live stream from the drone), and it works well.
Could you provide some sample app/project to reproduce this issue so that I can give it a deeper look ?

Thanks

Thank you for the response. I am testing this using the Kotlin sample app that you have provided. I added another button and a simple button click method calls the following snippet in a method on its own thread, with a value in range (-90, +90) for degrees parameter:

private fun setGimbalangle(degrees: Int){
        if (drone!=null){
           gimbalRef = drone?.getPeripheral(Gimbal::class.java) { gimbal ->
                if (gimbal != null) {
                    if (!gimbal.isCalibrated) {
                        gimbal.control(Gimbal.ControlMode.POSITION, null, degrees.toDouble(), null)
                        pitch = gimbal.getAttitude(Gimbal.Axis.PITCH)
                        while (Math.abs(pitch - degrees.toDouble()) > 1.0) {
                            pitch = gimbal.getAttitude(                             Gimbal.Axis.PITCH,Gimbal.FrameOfReference.ABSOLUTE  )
                            Log.i("Gimbalangle", "Gimbalangle: $pitch")
                            waitfor(500) // sleep 500
                        }
                        Log.i("Gimbalangle", "Gimbalangle: position set to $degrees")
                    }
                } else {
                    Log.i("Gimbalangle", "Gimbalangle: Error: Can not get gimbal access")
                }
            }
     }
}
private fun onRoutineClick() {  // button click method
 try {
         thread(start = true) {
                 Log.d("onRoutineClick", "setting Gimbal -90");
                 setGimbalangle(-90)   // the above code..
      }  catch (e: Exception  ){}
}

It prints the initial value and may be the first incremental change… then it keeps printing that same value even though the gimbal is moving to its target pitch. The video freezes as soon as this is called. Is there anything missing in the way I call the methods?

Thank you.

Hi,

All GroundSdk APIs must be used from main thread (except in some rare cases, clearly stated otherwise in the documentation); calling them from some random thread will lead to undefined behavior. Here, you cannot start a background thread to control the gimbal. On top of that, the Gimbal observer closure will be called by groundsdk on the main thread also, which means, you are blocking the main thread forever as soon as the while { … waitFor … } loop is entered . This is why everything freezes and also explains the pool warnings you get in the logs.

Below is sample code (in the context of the Kotlin sample app) that allows to control the gimbal and logs current gimbal pitch:

class MainActivity : AppCompatActivity() {
    ...
    /** Reference to the current drone gimbal Peripheral. */
    private var gimbalRef: Ref<Gimbal>? = null
    ...
    /* Gimbal control button. */
    private lateinit var gimbalBt: Button
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        gimbalBt = findViewById(R.id.button2)
        gimbalBt.setOnClickListener { onGimbalClick() }
    }

    private fun startDroneMonitors() {
        ...
        // Monitor gimbal
        monitorGimbal()
    }

    private fun stopDroneMonitors() {
        ...
        gimbalRef?.close()
        gimbalRef = null
    }

    /**
     * Monitors current drone gimbal.
     */
    private fun monitorGimbal() {
        gimbalRef = drone?.getPeripheral(Gimbal::class.java) { gimbal ->
            gimbal?.getAttitude(Gimbal.Axis.PITCH)?.also { 
                Log.i("Gimbalangle", "Gimbalangle: $it") 
            }
        }
    }

    /**
     * Called on gimbal button click.
     */
    private fun onGimbalClick() {
        gimbalRef?.get()?.control(Gimbal.ControlMode.POSITION, null, -90.toDouble(), null)
    }

}