dji-sdk / Mobile-SDK-Android-V5

MSDK V5 Sample
Other
282 stars 145 forks source link

How to get the flight state? #326

Closed Chatvolant closed 1 month ago

Chatvolant commented 6 months ago

Hello DJI,

I'm currently making a program to move the drone and as the program is also using the takeoff function, I need to know when the drone has finished taking off (check if the takeoff state is "READY_TO_LAND") so I can execute the other commands (go forward, etc..).

I've found the function checkAndUpdateTakeOffLandingState and updateTakeOffStatus but they are private

Thank you in advance.

dji-dev commented 6 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

The method checkAndUpdateTakeOffLandingState is provided by the open-source widget. If you wish to utilize it, you are free to make modifications to this component. The KeyFlightMode is used to retrieve the current mode of the aircraft. Both FlightMode.AUTO_TAKE_OFF and FlightMode.TAKE_OFF_READY indicate that it is in the process of taking off. https://developer.dji.com/api-reference-v5/android-api/Components/IKeyManager/Key_FlightController_FlightControllerKey.html#key_flightcontroller_msdkflightmode_inline

°°°

Chatvolant commented 6 months ago

Thanks a lot for you clear answer. The problem with the KeyFlightMode is that there isn't any enum member indicating that the aircraft is ready to land.

dji-dev commented 6 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

You can use the KeyGoHomeStatus to determine whether the aircraft is landing and if the landing is completed.

°°°

Chatvolant commented 6 months ago

Thank you for your reply. Could you please tell me if we can get the drone status using KeyGoHomeStatus even it's flying indoors ?(meaning that the GPS would not function entirely)

dji-dev commented 6 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

It is also possible to obtain landing status indoors, as landing does not require GPS signal.

°°°

Chatvolant commented 6 months ago

Actually, I'm trying to know when the drone has finished taking off, not when it has finished landing. In TakeOffWidgetModel.kt I've seen there is a variable called takeOffLandingState which type is an enum class and inside we can find 10 states. What I wanted to do is to monitor the value and when takeOffLandingState would be in the state "READY_TO_LAND, make it do an action like going forward for example. Now I trying to use an another method, monitor the height of that drone and when it reaches the set height for the takeoff, make it do an action

dji-dev commented 6 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

Thank you for clarifying. I understand your point now. The takeOffLandingState is determined by combining FlightControllerKey.KeyAreMotorsOn and RemoteControllerKey.KeyRcMachineMode to check if the aircraft can land. KeyAreMotorsOn can indicate whether the drone's motors are running, while KeyRcMachineMode can show if the remote controller is ready for landing. Technically, these keys cannot determine if the aircraft has completed takeoff, but if you only need to know if the aircraft can land, you can refer to the explanation provided.

The height of the drone relative to the takeoff point can be monitored and obtained using FlightControllerKey.KeyAircraftLocation3D.

°°°

Chatvolant commented 6 months ago

Thanks a lot for your reply. So from I've understood (correct me if i'm wrong) in order to check if the drone can land I can either try to read the takeOffLandingState by adding an interface or I can read KeyAreMotorsOn and KeyRcMachineMode ? Also, which state is taken by KeyRCMachineMode when the remote controller is ready for landing? According to the TakeOffWidgetModel.kt, it's ready for landing when RCMode = SLAVE. Maybe it's better for me just to make the drone go forward after it has reached the takeoff height? Because I've just noticed that we can perform landing even if the taking off isn't over... Also, do you know if we can modify the takeoff height? Thank you

dji-dev commented 6 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

Your understanding may have some deviations. The aircraft can only land when RCMode is not equal to SLAVE. If the aircraft is reaching the flight altitude, then the aircraft has completed takeoff at this time. We do not have a direct way to determine if the aircraft has completed takeoff, but you can judge whether takeoff has been completed by FlightMode and the aircraft's altitude. When the aircraft is taking off, FlightMode will change to AUTO_TAKE_OFF. After completing takeoff, the aircraft's status will change to another state, but this state is not fixed. After takeoff is completed, the aircraft's relative altitude at this time is generally greater than 1 meter. Altitude can be obtained using KeyAircraftLocation3D.

°°°

Chatvolant commented 6 months ago

Thank for your reply. I'll try the height solution afterwards. Actually the truth is that I've made a small program in VirtualStickFragment.kt for a button I create. The goal is to make the drone take off and then go forward. The condition is that it should have finished taking off. We created an instance of the class VirtualStickFlightControlParam and set the parameters in order for the drone to go forward.

Actually, what I'm trying to do is to check if the takeOffLandingState is equals to READY_TO_LAND. Here a part of the code

     private val takeOffLandingState_v: TakeOffLandingState = DISCONNECTED
    TakeOffWidget.ModelState.TakeOffLandingStateUpdated(takeOffLandingState_v)
    if (takeOffLandingState_v == TakeOffLandingState.READY_TO_LAND)
    {
    virtualStickVM.sendVirtualStickAdvancedParam(FlightParam)
   }
}

The problem here is that the code inside the if never executes, I'm not sure if this is the right method to get the TakeOffLandingState. Could you please help me with this matter ? Your help is very much appreciated.

dji-dev commented 6 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

The purpose of TakeOffLandingStateUpdated is to proactively update TakeOffLandingState, as it cannot retrieve updates from TakeOffLandingState. TakeOffWidget does not have a publicly accessible interface to access TakeOffWidget, so you will need to modify TakeOffWidget, for example, by adding a new interface.

°°°

Chatvolant commented 5 months ago

Thank for you answer, but I really struggle creating an instance of TakeoffWidget as I didn't found any example which parameters to put in there. However, I managed to create an instance of the class TakeOffWidgetModel (I called it takeOffWidgetModelInstance) and as this class have a method to update the state, I was thinking about using this class instead. Afterwards, I subscribed to takeOffWidgetModelInstance.takeOffLandingState and put a condition for the drone to do a particular action when the state of takeOffLandingState is "READY_TO_LAND"

            takeOffWidgetModelInstance.takeOffLandingState.subscribe { it ->
                if (it == TakeOffLandingState.READY_TO_LAND) {
                    ToastUtils.showToast("$it")
                    virtualStickVM.sendVirtualStickAdvancedParam(FlightParam)
dji-dev commented 5 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

TakeoffWidget is a component, so you need to use it in your layout before you can access the corresponding instance. Can you achieve your goal now by directly using TakeOffWidgetModel?

°°°

Chatvolant commented 5 months ago

I've forgotten to tell you but i'm actually working in the VirtualStickFragment page and I managed to instanciate the TakeOffWidgetModel class but not the TakeOffWidget class (I don't know how I can get the context). I've already created a new button in the layout frag_virtual_stick_page.xml so I can use the methods I want for the drone. The button is visible, there is no problem on this side. Is there a way to get the context of VirtualStickFragment so I can put it in the TakeOffWidget instance that I will create?

dji-lyt commented 5 months ago

I think that the correct way to use TakeOffWidget should be the same as Button. You need to place TakeOffWidget in the layout and then obtain its instance, just as shown in the image below. image image

Chatvolant commented 5 months ago

Thank you very much for your answer, it's very clear and precise. I have another question. I tried to run a code that makes the drone go forward and I put it in a while loop. The drone goes forward but doesn't pay attention to the obstacles anymore. Should I add a perception widget (like you did for the take off widget) and find the function that update the sensors information inside that loop (and add the obstacle condition) or is it wrong to use the while loop as it monopolize all the program?

dji-dev commented 5 months ago

Agent comment from yating.liao in Zendesk ticket #107011:

The reason why the drone is not avoiding obstacles may be because the obstacle avoidance feature of the drone is turned off. You can use getObstacleAvoidanceType to confirm the obstacle avoidance type of the drone.

Additionally, if you are using the Virtual Stick function to control the drone's movement, I do not recommend using a while loop for implementation. It is suggested to use a timer to send commands at a fixed frequency instead. The recommended frequency is between 5 to 25Hz.

°°°