打造自己的HelloDrone 无人机APP过程《3》

目录

摘要


本周主要记录打造自己的HelloDrone 无人机APP过程《3》–如何实现APP给飞控发送数据相关逻辑,欢迎批评指正!!!


1.发送逻辑代码

    /**
     * 打开设备,执行mManagerTask任务
     * @param extras
     */
    protected void onConnectionOpened(Bundle extras) {
        if (mConnectionStatus.compareAndSet(MAVLINK_CONNECTING, MAVLINK_CONNECTED)) {
            extrasHolder.set(extras);
            mLogger.logInfo(TAG, "Starting manager thread.");
            Log.i("lxw"," mManagerTask主要处理mavlink信息");
            mTaskThread = new Thread(mManagerTask, "MavLinkConnection-Manager Thread");
            mTaskThread.start();
        }
    }

这里我们重点看: mTaskThread = new Thread(mManagerTask, “MavLinkConnection-Manager Thread”);创建了一个任务管理线程。并通过mTaskThread.start()启动创建的线程

    /**
     * 管理消息的接收和发送。主要处理mavlink信息
     * Manages the receiving and sending of messages.
     */
    private final Runnable mManagerTask = new Runnable() {

        @Override
        public void run() {
            Thread sendingThread = null;
            Thread loggingThread = null;

            try {
                final long connectionTime = System.currentTimeMillis();
                mConnectionTime.set(connectionTime);
                reportConnect(connectionTime);

                // Launch the 'Sending' thread
                mLogger.logInfo(TAG, "Starting sender thread.");
                Log.i("lxw"," Starting new thread.");
                sendingThread = new Thread(mSendingTask, "MavLinkConnection-Sending Thread");
                sendingThread.start();

                //Launch the 'Logging' thread
                mLogger.logInfo(TAG, "Starting logging thread.");
                Log.i("lxw"," Starting sender thread.");
                loggingThread = new Thread(mLoggingTask, "MavLinkConnection-Logging Thread");
                loggingThread.start();
                //协议解析
                final Parser parser = new Parser();
                //com.MAVLink.Parser
                Log.i("lxw"," parser:"+parser);
                //服务解析状态
                parser.stats.resetStats();
                //创建解析数据数组
                final byte[] readBuffer = new byte[READ_BUFFER_SIZE];

                while (mConnectionStatus.get() == MAVLINK_CONNECTED)
                {
                    //读取bufferSize
                    int bufferSize = readDataBlock(readBuffer);
                    //bufferSize=
                    Log.i("lxw"," bufferSize:"+bufferSize);
                    handleData(parser, bufferSize, readBuffer);
                }
            } catch (IOException e) {
                // Ignore errors while shutting down
                if (mConnectionStatus.get() != MAVLINK_DISCONNECTED) {
                    reportIOException(e);
                    mLogger.logErr(TAG, e);
                }
            } finally {
                if (sendingThread != null && sendingThread.isAlive()) {
                    sendingThread.interrupt();
                }

                if (loggingThread != null && loggingThread.isAlive()) {
                    loggingThread.interrupt();
                }

                disconnect();
                mLogger.logInfo(TAG, "Exiting manager thread.");
            }
        }

        /**
         * 开始进行数据处理
         * @param parser
         * @param bufferSize
         * @param buffer
         */
        private void handleData(Parser parser, int bufferSize, byte[] buffer) {
            if (bufferSize < 1) {
                return;
            }

            for (int i = 0; i < bufferSize; i++)
            {
                //解析包
                MAVLinkPacket receivedPacket = parser.mavlink_parse_char(buffer[i] & 0x00ff);
                if (receivedPacket != null)
                {
                    queueToLog(receivedPacket);
                    Log.i("lxw"," 开始报告解析:");
                    reportReceivedPacket(receivedPacket);
                }
            }
        }
    };

对于接收的函数我们不在讲解,在第二节打造自己的HelloDrone 无人机APP过程《2》已经讲述,本节主要分析发送数据到外界。


从上面代码可以看出,在mManagerTask线程中又定义子线程

            //定义发送线程
            Thread sendingThread = null;
            //定义log线程
            Thread loggingThread = null;

重点启动发送线程代码如下:

                //启动“发送”线程---- Launch the 'Sending' thread
                mLogger.logInfo(TAG, "Starting sender thread.");
                Log.i("lxw"," Starting new thread.");
                sendingThread = new Thread(mSendingTask, "MavLinkConnection-Sending Thread");
                sendingThread.start();

创建发送线程mSendingTask,通过sendingThread.start()启动线程。

    /**
     * 阻塞,直到有数据包要发送,然后发送它们。
     * Blocks until there's packet(s) to send, then dispatch them.
     */
    private final Runnable mSendingTask = new Runnable() {
        @Override
        public void run() {
            try {
               //当usb连接上时
                while (mConnectionStatus.get() == MAVLINK_CONNECTED) 
                {
                    byte[] buffer = mPacketsToSend.take();
                    try 
                    {
                        //发送数据
                        sendBuffer(buffer);
                        queueToLog(buffer);
                    } catch (IOException e) 
                    {
                        reportIOException(e);
                        mLogger.logErr(TAG, e);
                    }
                }
            } catch (InterruptedException e) 
            {
                mLogger.logVerbose(TAG, e.getMessage());
            } finally 
            {
                disconnect();
            }
        }
    };

2.设置无人机的飞行模式理解发送过程

首先设置UI界面,采用下拉列表显示模式
在这里插入图片描述

在主activity中设置点击事件
在这里插入图片描述
这里我们重点看下执行模式选择

其中Spinner提供了从一个数据集合中快速选择一项值的办法。默认情况下Spinner显示的是当前选择的值,点击Spinner会弹出一个包含所有可选值的dropdown菜单,从该菜单中可以为Spinner选择一个新值。


默认飞机上电会自动读取当前的飞行模式,具体实现后面讲解,我们先看下模式选择


                //执行飞行器模式选择
                onFlightModeSelected(view);
    /**
     * 执行模式选择
     *
     * @param view
     */
    public void onFlightModeSelected(View view) {
        //获取无人机的模式
        VehicleMode vehicleMode = (VehicleMode) this.modeSelector.getSelectedItem();
        //获取并设置模式
        VehicleApi.getApi(this.drone).setVehicleMode(vehicleMode, new AbstractCommandListener() {
            @Override
            public void onSuccess()
            {
                //执行成功
                alertUser("Vehicle mode change successful.");
            }

            @Override
            public void onError(int executionError) {
                //模式更改失败
                alertUser("Vehicle mode change failed: " + executionError);
            }

            @Override
            public void onTimeout() {
                //模式更改超时
                alertUser("Vehicle mode change timed out.");
            }
        });
    }

其中类enum VehicleMode的实现如下代码所示。

package com.o3dr.services.android.lib.drone.property;

import android.os.Parcel;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by fhuya on 10/28/14.
 */
public enum VehicleMode implements DroneAttribute {
    //固定翼模式设置
    PLANE_MANUAL(0, Type.TYPE_PLANE, "Manual"),
    PLANE_CIRCLE(1, Type.TYPE_PLANE, "Circle"),
    PLANE_STABILIZE(2, Type.TYPE_PLANE, "Stabilize"),
    PLANE_TRAINING(3, Type.TYPE_PLANE, "Training"),
    PLANE_ACRO(4, Type.TYPE_PLANE, "Acro"),
    PLANE_FLY_BY_WIRE_A(5, Type.TYPE_PLANE, "FBW A"),
    PLANE_FLY_BY_WIRE_B(6, Type.TYPE_PLANE, "FBW B"),
    PLANE_CRUISE(7, Type.TYPE_PLANE, "Cruise"),
    PLANE_AUTOTUNE(8, Type.TYPE_PLANE, "Autotune"),
    PLANE_AUTO(10, Type.TYPE_PLANE, "Auto"),
    PLANE_RTL(11, Type.TYPE_PLANE, "RTL"),
    PLANE_LOITER(12, Type.TYPE_PLANE, "Loiter"),
    PLANE_GUIDED(15, Type.TYPE_PLANE, "Guided"),
    //多旋翼模式设置
    COPTER_STABILIZE(0, Type.TYPE_COPTER, "Stabilize"), //姿态模式
    COPTER_ACRO(1, Type.TYPE_COPTER, "Acro"),          //速率模式
    COPTER_ALT_HOLD(2, Type.TYPE_COPTER, "Alt Hold"),  //定高模式
    COPTER_AUTO(3, Type.TYPE_COPTER, "Auto"),          //自动模式
    COPTER_GUIDED(4, Type.TYPE_COPTER, "Guided"),      //引导模式
    COPTER_LOITER(5, Type.TYPE_COPTER, "Loiter"),      //悬停模式
    COPTER_RTL(6, Type.TYPE_COPTER, "RTL"),            //返航模式
    COPTER_CIRCLE(7, Type.TYPE_COPTER, "Circle"),      //绕圈模式
    COPTER_LAND(9, Type.TYPE_COPTER, "Land"),          //着落模式
    COPTER_DRIFT(11, Type.TYPE_COPTER, "Drift"),       //漂移模式
    COPTER_SPORT(13, Type.TYPE_COPTER, "Sport"),       //运动模式
    COPTER_FLIP(14, Type.TYPE_COPTER, "Flip"),         //斜坡模式
    COPTER_AUTOTUNE(15, Type.TYPE_COPTER, "Autotune"), //自动调参模式
    COPTER_POSHOLD(16, Type.TYPE_COPTER, "PosHold"),   //位置保持模式
    COPTER_BRAKE(17,Type.TYPE_COPTER,"Brake"),         //刹车模式
    //无人车模式设置
    ROVER_MANUAL(0, Type.TYPE_ROVER, "Manual"),
    ROVER_LEARNING(2, Type.TYPE_ROVER, "Learning"),
    ROVER_STEERING(3, Type.TYPE_ROVER, "Steering"),
    ROVER_HOLD(4, Type.TYPE_ROVER, "Hold"),
    ROVER_AUTO(10, Type.TYPE_ROVER, "Auto"),
    ROVER_RTL(11, Type.TYPE_ROVER, "RTL"),
    ROVER_GUIDED(15, Type.TYPE_ROVER, "Guided"),
    ROVER_INITIALIZING(16, Type.TYPE_ROVER, "Initializing"),

    UNKNOWN(-1, Type.TYPE_UNKNOWN, "Unknown");


    private final int mode;
    private final int droneType;
    private final String label;

    VehicleMode(int mode, int droneType, String label){
        this.mode = mode;
        this.droneType = droneType;
        this.label = label;
    }

    public int getMode() {
        return mode;
    }

    public int getDroneType() {
        return droneType;
    }

    public String getLabel() {
        return label;
    }

    @Override
    public String toString(){
        return getLabel();
    }

    @Override
    public int describeContents(){
        return 0;
    }

    @Override
    public void writeToParcel(final Parcel dest, final int flags){
        dest.writeString(name());
    }

    public static final Creator<VehicleMode> CREATOR = new Creator<VehicleMode>() {
        @Override
        public VehicleMode createFromParcel(Parcel source) {
            return VehicleMode.valueOf(source.readString());
        }

        @Override
        public VehicleMode[] newArray(int size) {
            return new VehicleMode[size];
        }
    };

    public static List<VehicleMode> getVehicleModePerDroneType(int droneType){
        VehicleMode[] availableModes = VehicleMode.values();
        final List<VehicleMode> vehicleModes = new ArrayList<VehicleMode>(availableModes.length);

        for(VehicleMode vehicleMode: availableModes){
            if(vehicleMode.getDroneType() == droneType)
                vehicleModes.add(vehicleMode);
        }

        return vehicleModes;
    }
}


对于我们多旋翼的使用模式主要是下面模式:
在这里插入图片描述
上面代码主要有两行比较重要:
1.获取当前模式:

 VehicleMode vehicleMode = (VehicleMode) this.modeSelector.getSelectedItem();

2.设置当前模式到飞控,采用匿名内部类实现

在这里插入图片描述
我们先不关注函数的参数,重点看下函数实现


    /**
     * 更改连接的无人机的车辆模式。
     * Change the vehicle mode for the connected drone.
     *
     * @param newMode  新车模式---new vehicle mode.
     * @param listener 注册回调以接收命令执行状态的更新。Register a callback to receive update of the command execution state.
     */
    public void setVehicleMode(VehicleMode newMode, AbstractCommandListener listener) {
        //新建参数
        Bundle params = new Bundle();
        //参数输出设置,一会外界会采用键值方式获取
        params.putParcelable(EXTRA_VEHICLE_MODE, newMode);
        //执行设置命令
        drone.performAsyncActionOnDroneThread(new Action(ACTION_SET_VEHICLE_MODE, params), listener);
    }

比较重要的函数有两个:

1.核心代码

 params.putParcelable(EXTRA_VEHICLE_MODE, newMode);

2.核心代码

drone.performAsyncActionOnDroneThread(new Action(ACTION_SET_VEHICLE_MODE, params), listener);

我们先看第一处代码:
在这里插入图片描述
设置的新模式,一会会传递出去:
1.ArduPilot.java
在这里插入图片描述
2.GenericMavLinkDrone.java处代码
在这里插入图片描述
上面具体如何使用,后续再看,先分析重点内容。

drone.performAsyncActionOnDroneThread(new Action(ACTION_SET_VEHICLE_MODE, params), listener);

上面函数传递两个参数:new Action(ACTION_SET_VEHICLE_MODE, params)和listener

    /**
     *执行异步行为
     */
    public boolean performAsyncActionOnDroneThread(Action action, AbstractCommandListener listener) {
        //执行异步行为处理
        return performAsyncActionOnHandler(action, this.handler, listener);
    }
    /**
     *执行异步行为
     */
    public boolean performAsyncActionOnHandler(Action action, Handler handler, AbstractCommandListener listener) {
        boolean value=false;
        Log.i("lxw","performAsyncActionOnHandler");
        final IDroneApi droneApi = droneApiRef.get();
        //org.droidplanner.services.android.impl.api.DroneApi
        Log.i("lxw","droneApi:"+droneApi);
        value=isStarted(droneApi);
        Log.i("lxw","isStarted value:"+value);
        if (value)
        {
            try {
                //执行行为
                Log.i("lxw","executeAsyncAction:");
                droneApi.executeAsyncAction(action, wrapListener(handler, listener));
                return true;
            } catch (RemoteException e)
            {
                Log.i("lxw","执行 RemoteException");
                Toast.makeText(getContext(), "异步执行2", Toast.LENGTH_LONG).show();
                handleRemoteException(e);
            }
        }
        Log.i("lxw","disconnect7");
        return false;
    }

重点分析这个函数:

 droneApi.executeAsyncAction(action, wrapListener(handler, listener));

    /**
     * 执行代码
     * @param action Action to perform.
     * @param listener Register a callback to be invoken when the action is executed.
     * @throws RemoteException
     */
    @Override
    public void executeAsyncAction(Action action, ICommandListener listener) throws RemoteException {
        Log.i("lxw","执行DroneApi中的executeAsyncAction");
        Log.i("zqj","执行DroneApi中的executeAsyncAction");
        //执行异步操作行为
        executeAction(action, listener);
    }
    @Override
    /**
     * 执行行为
     */
    public void
    executeAction(Action action, ICommandListener listener) throws RemoteException {
        //com.o3dr.services.android.lib.model.action.Action
        Log.i("lxw","executeAction action:"+action);

        if (action == null)
        {
            Log.i("zqj","executeAction action:"+action);
            Log.i("lxw","action null:");
            return;
        }

        String type = action.getType();
        //type com.o3dr.services.android.action.CONNECT
        Log.i("lxw","type:"+type);
        //type:com.o3dr.services.android.action.SET_VEHICLE_MODE
        Log.i("zqj","type:"+type);
        if (type == null)
        {
            Log.i("lxw","type null:");
            return;
        }

        Bundle data = action.getData();
        Log.i("lxw","Bundle data:"+data);
        //Bundle data:Bundle[{extra_vehicle_mode=Alt Hold}]
        Log.i("zqj","Bundle data:"+data);
        if (data != null) {
            Log.i("lxw","data not null:");
            data.setClassLoader(context.getClassLoader());
        }
        //获取设备
        Drone drone = getDrone();
        Log.i("lxw","drone1:"+drone);
        Log.i("lxw","mytype:"+type);
        Log.i("zqj","mytype:"+type);
        //mytype:com.o3dr.services.android.action.SET_VEHICLE_MODE
        switch (type) {
            // CONNECTION ACTIONS
            case ConnectionActions.ACTION_CONNECT:
                ConnectionParameter parameter = data.getParcelable(ConnectionActions.EXTRA_CONNECT_PARAMETER);
                Log.i("lxw","ConnectionActions:");
                //进行连接
                connect(parameter);
                break;

            case ConnectionActions.ACTION_DISCONNECT:
                disconnect();
                break;

            // CAMERA ACTIONS
            case CameraActions.ACTION_START_VIDEO_STREAM: {
                Surface videoSurface = data.getParcelable(CameraActions.EXTRA_VIDEO_DISPLAY);
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");

                Bundle videoProps = data.getBundle(CameraActions.EXTRA_VIDEO_PROPERTIES);
                if (videoProps == null) {
                    //Only case where it's null is when interacting with a deprecated client version.
                    //In this case, we assume that the client is attempting to start a solo stream, since that's
                    //the only api that was exposed.
                    videoProps = new Bundle();
                    videoProps.putInt(CameraActions.EXTRA_VIDEO_PROPS_UDP_PORT, VideoManager.ARTOO_UDP_PORT);
                }

                CommonApiUtils.startVideoStream(drone, videoProps, ownerId, videoTag, videoSurface, listener);
                break;
            }

            case ExperimentalActions.ACTION_START_VIDEO_STREAM_FOR_OBSERVER: {
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");
                CommonApiUtils.startVideoStreamForObserver(drone, ownerId, videoTag, listener);
                break;
            }

            case CameraActions.ACTION_STOP_VIDEO_STREAM: {
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");
                CommonApiUtils.stopVideoStream(drone, ownerId, videoTag, listener);
                break;
            }

            case ExperimentalActions.ACTION_STOP_VIDEO_STREAM_FOR_OBSERVER: {
                String videoTag = data.getString(CameraActions.EXTRA_VIDEO_TAG, "");
                CommonApiUtils.stopVideoStreamForObserver(drone, ownerId, videoTag, listener);
                break;
            }

            // MISSION ACTIONS
            case MissionActions.ACTION_BUILD_COMPLEX_MISSION_ITEM:
                if (drone instanceof MavLinkDrone || drone == null) {
                    CommonApiUtils.buildComplexMissionItem((MavLinkDrone) drone, data);
                } else {
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_UNSUPPORTED, listener);
                }
                break;

            case MissionActions.ACTION_SAVE_MISSION: {
                Mission mission = data.getParcelable(MissionActions.EXTRA_MISSION);
                Uri saveUri = data.getParcelable(MissionActions.EXTRA_SAVE_MISSION_URI);
                if (saveUri == null) {
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
                } else {
                    MissionUtils.saveMission(context, mission, saveUri, listener);
                }
                break;
            }

            case MissionActions.ACTION_LOAD_MISSION: {
                Uri loadUri = data.getParcelable(MissionActions.EXTRA_LOAD_MISSION_URI);
                boolean setMission = data.getBoolean(MissionActions.EXTRA_SET_LOADED_MISSION, false);
                if (loadUri != null) {
                    Mission mission = MissionUtils.loadMission(context, loadUri);
                    if(mission != null){
                        // Going back to the caller.
                        data.putParcelable(MissionActions.EXTRA_MISSION, mission);

                        if(setMission){
                            Bundle params = new Bundle();
                            params.putParcelable(EXTRA_MISSION, mission);
                            params.putBoolean(EXTRA_PUSH_TO_DRONE, false);
                            executeAction(new Action(ACTION_SET_MISSION, params), listener);
                        }
                    }
                }
                break;
            }

            default:
                if (droneMgr != null)
                {
                    Log.i("zqj","droneMgr:"+droneMgr);
                    droneMgr.executeAsyncAction(clientInfo, action, listener);
                } else {
                    Log.i("zqj","droneMgr1:"+droneMgr);
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
                }
                break;
        }
    }

打印可以监视代码执行顺序
在这里插入图片描述

    /**
     * 执行异步行为
     */
    public boolean executeAsyncAction(DroneApi.ClientInfo clientInfo, Action action, ICommandListener listener) {
        String type = action.getType();
        Bundle data = action.getData();
        Log.i("lxw","DT4");
        Log.i("zqj","DT4");
        Log.i("zqj","type:"+type);
        switch (type) 
        {
            case ControlActions.ACTION_ENABLE_MANUAL_CONTROL:
                data.putString(EXTRA_CLIENT_APP_ID, clientInfo.appId);
                break;
        }
        Log.i("zqj","type1:"+type);
        return executeAsyncAction(action, listener);
    }

开始分析核心代码:return executeAsyncAction(action, listener);

    protected boolean executeAsyncAction(Action action, ICommandListener listener) {
        String type = action.getType();
        Log.i("zqj","type2:"+type);
        switch (type) {

            //***************** CONTROL ACTIONS *****************//
            case ControlActions.ACTION_ENABLE_MANUAL_CONTROL:
                if (drone != null) {
                    drone.executeAsyncAction(action, listener);
                } else {
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
                }
                return true;

            default:
                if (drone != null) 
                {
                    Log.i("zqj","drone:"+drone);
                    return drone.executeAsyncAction(action, listener);
                } else 
                {
                        Log.i("zqj","listener:"+listener);
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
                    return true;
                }
        }
    }

    /**
     * 首先执行的方法
     * @param action
     * @param listener
     * @return
     */
    @Override
    public boolean executeAsyncAction(Action action, final ICommandListener listener) {
        //获取类型
        String type = action.getType();
        //获取数据
        Bundle data = action.getData();
        if (data == null) {
            data = new Bundle();
        }
        Log.i("zqj"," Ardupilot mytype:"+type);
        switch (type) {
                //执行任务行为----- MISSION ACTIONS
            case MissionActions.ACTION_LOAD_WAYPOINTS:
                CommonApiUtils.loadWaypoints(this);
                return true;
                //设置任务行为
            case MissionActions.ACTION_SET_MISSION:
                data.setClassLoader(com.o3dr.services.android.lib.drone.mission.Mission.class.getClassLoader());
                com.o3dr.services.android.lib.drone.mission.Mission mission = data.getParcelable(MissionActions.EXTRA_MISSION);
                boolean pushToDrone = data.getBoolean(MissionActions.EXTRA_PUSH_TO_DRONE);
                CommonApiUtils.setMission(this, mission, pushToDrone);
                return true;
            //开始任务行为
            case MissionActions.ACTION_START_MISSION:
                boolean forceModeChange = data.getBoolean(MissionActions.EXTRA_FORCE_MODE_CHANGE);
                boolean forceArm = data.getBoolean(MissionActions.EXTRA_FORCE_ARM);
                CommonApiUtils.startMission(this, forceModeChange, forceArm, listener);
                return true;

            //实验动作---- EXPERIMENTAL ACTIONS
            case ExperimentalActions.ACTION_EPM_COMMAND:
                boolean release = data.getBoolean(ExperimentalActions.EXTRA_EPM_RELEASE);
                CommonApiUtils.epmCommand(this, release, listener);
                return true;
           // 触发照相行为
            case ExperimentalActions.ACTION_TRIGGER_CAMERA:
                CommonApiUtils.triggerCamera(this);
                return true;
            // 做任务
            case ExperimentalActions.ACTION_SET_ROI:
                LatLongAlt roi = data.getParcelable(ExperimentalActions.EXTRA_SET_ROI_LAT_LONG_ALT);
                if (roi != null) {
                    MavLinkDoCmds.setROI(this, roi, listener);
                }
                return true;
            // ACTION_SET_RELAY
            case ExperimentalActions.ACTION_SET_RELAY:
                int relayNumber = data.getInt(ExperimentalActions.EXTRA_RELAY_NUMBER);
                boolean isOn = data.getBoolean(ExperimentalActions.EXTRA_IS_RELAY_ON);
                MavLinkDoCmds.setRelay(this, relayNumber, isOn, listener);
                return true;

            case ExperimentalActions.ACTION_SET_SERVO:
                int channel = data.getInt(ExperimentalActions.EXTRA_SERVO_CHANNEL);
                int pwm = data.getInt(ExperimentalActions.EXTRA_SERVO_PWM);
                MavLinkDoCmds.setServo(this, channel, pwm, listener);
                return true;

            //控制行为--- CONTROL ACTIONS
            case ControlActions.ACTION_SEND_GUIDED_POINT: {
                data.setClassLoader(LatLong.class.getClassLoader());
                boolean force = data.getBoolean(ControlActions.EXTRA_FORCE_GUIDED_POINT);
                LatLong guidedPoint = data.getParcelable(ControlActions.EXTRA_GUIDED_POINT);
                CommonApiUtils.sendGuidedPoint(this, guidedPoint, force, listener);
                return true;
            }
            //ACTION_LOOK_AT_TARGET
            case ControlActions.ACTION_LOOK_AT_TARGET:
                boolean force = data.getBoolean(ControlActions.EXTRA_FORCE_GUIDED_POINT);
                LatLongAlt lookAtTarget = data.getParcelable(ControlActions.EXTRA_LOOK_AT_TARGET);
                CommonApiUtils.sendLookAtTarget(this, lookAtTarget, force, listener);
                return true;
            //设置引导高度
            case ControlActions.ACTION_SET_GUIDED_ALTITUDE:
                double guidedAltitude = data.getDouble(ControlActions.EXTRA_ALTITUDE);
                CommonApiUtils.setGuidedAltitude(this, guidedAltitude);
                return true;

            //执行参数行为PARAMETER ACTIONS
            case ParameterActions.ACTION_REFRESH_PARAMETERS:
                CommonApiUtils.refreshParameters(this);
                return true;
            //写参数行为
            case ParameterActions.ACTION_WRITE_PARAMETERS:
                data.setClassLoader(com.o3dr.services.android.lib.drone.property.Parameters.class.getClassLoader());
                com.o3dr.services.android.lib.drone.property.Parameters parameters = data.getParcelable(ParameterActions.EXTRA_PARAMETERS);
                CommonApiUtils.writeParameters(this, parameters);
                return true;

            //设置HOME点行为---- DRONE STATE ACTIONS
            case StateActions.ACTION_SET_VEHICLE_HOME:
                LatLongAlt homeLoc = data.getParcelable(StateActions.EXTRA_VEHICLE_HOME_LOCATION);
                if (homeLoc != null) {
                    MavLinkDoCmds.setVehicleHome(this, homeLoc, new AbstractCommandListener() {
                        @Override
                        public void onSuccess() {
                            CommonApiUtils.postSuccessEvent(listener);
                            requestHomeUpdate();
                        }

                        @Override
                        public void onError(int executionError) {
                            CommonApiUtils.postErrorEvent(executionError, listener);
                            requestHomeUpdate();
                        }

                        @Override
                        public void onTimeout() {
                            CommonApiUtils.postTimeoutEvent(listener);
                            requestHomeUpdate();
                        }
                    });
                } else {
                    CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
                }
                return true;

            //校准行为-----CALIBRATION ACTIONS
            case CalibrationActions.ACTION_START_IMU_CALIBRATION:
                CommonApiUtils.startIMUCalibration(this, listener);
                return true;
            //IMU校准应答
            case CalibrationActions.ACTION_SEND_IMU_CALIBRATION_ACK:
                int imuAck = data.getInt(CalibrationActions.EXTRA_IMU_STEP);
                CommonApiUtils.sendIMUCalibrationAck(this, imuAck);
                return true;
            //地磁校准
            case CalibrationActions.ACTION_START_MAGNETOMETER_CALIBRATION:
                boolean retryOnFailure = data.getBoolean(CalibrationActions.EXTRA_RETRY_ON_FAILURE, false);
                boolean saveAutomatically = data.getBoolean(CalibrationActions.EXTRA_SAVE_AUTOMATICALLY, true);
                int startDelay = data.getInt(CalibrationActions.EXTRA_START_DELAY, 0);
                CommonApiUtils.startMagnetometerCalibration(this, retryOnFailure, saveAutomatically, startDelay);
                return true;
            //取消地磁校准
            case CalibrationActions.ACTION_CANCEL_MAGNETOMETER_CALIBRATION:
                CommonApiUtils.cancelMagnetometerCalibration(this);
                return true;
            //接受地磁校准
            case CalibrationActions.ACTION_ACCEPT_MAGNETOMETER_CALIBRATION:
                CommonApiUtils.acceptMagnetometerCalibration(this);
                return true;

            //************万向节动作 Gimbal ACTIONS *************//
            case GimbalActions.ACTION_SET_GIMBAL_ORIENTATION:
                float pitch = data.getFloat(GimbalActions.GIMBAL_PITCH);
                float roll = data.getFloat(GimbalActions.GIMBAL_ROLL);
                float yaw = data.getFloat(GimbalActions.GIMBAL_YAW);
                MavLinkDoCmds.setGimbalOrientation(this, pitch, roll, yaw, listener);
                return true;

            case GimbalActions.ACTION_RESET_GIMBAL_MOUNT_MODE:
            case GimbalActions.ACTION_SET_GIMBAL_MOUNT_MODE:
                int mountMode = data.getInt(GimbalActions.GIMBAL_MOUNT_MODE, MAV_MOUNT_MODE.MAV_MOUNT_MODE_RC_TARGETING);
                Timber.i("Setting gimbal mount mode: %d", mountMode);

                Parameter mountParam = getParameterManager().getParameter("MNT_MODE");
                if (mountParam == null) {
                    msg_mount_configure msg = new msg_mount_configure();
                    msg.target_system = getSysid();
                    msg.target_component = getCompid();
                    msg.mount_mode = (byte) mountMode;
                    msg.stab_pitch = 0;
                    msg.stab_roll = 0;
                    msg.stab_yaw = 0;
                    getMavClient().sendMessage(msg, listener);
                } else {
                    MavLinkParameters.sendParameter(this, "MNT_MODE", 1, mountMode);
                }
                return true;

            default:
                Log.i("zqj"," 执行父类方法executeAsyncAction:");
                return super.executeAsyncAction(action, listener);
        }
    }

执行完上面的方法后,会调用父类的实现方法

    /**
     * 执行异步行为
     */
    public boolean executeAsyncAction(Action action, ICommandListener listener) {
        String type = action.getType();
        Bundle data = action.getData();
        Log.i("lxw","DT3");
        Log.i("zqj","GenericMavlinkDrone mytype:"+type);
        switch (type) {
            //MISSION ACTIONS
            case MissionActions.ACTION_GENERATE_DRONIE:
                float bearing = CommonApiUtils.generateDronie(this);
                if (bearing != -1) {
                    Bundle bundle = new Bundle(1);
                    bundle.putFloat(AttributeEventExtra.EXTRA_MISSION_DRONIE_BEARING, bearing);
                    notifyAttributeListener(AttributeEvent.MISSION_DRONIE_CREATED, bundle);
                }
                return true;
            //跳转到航点
            case MissionActions.ACTION_GOTO_WAYPOINT:
                int missionItemIndex = data.getInt(MissionActions.EXTRA_MISSION_ITEM_INDEX);
                CommonApiUtils.gotoWaypoint(this, missionItemIndex, listener);
                return true;
            //改变航点速度行为
            case MissionActions.ACTION_CHANGE_MISSION_SPEED:
                float missionSpeed = data.getFloat(MissionActions.EXTRA_MISSION_SPEED);
                MavLinkCommands.changeMissionSpeed(this, missionSpeed, listener);
                return true;

            //解锁行为---- STATE ACTIONS
            case StateActions.ACTION_ARM:
                return performArming(data, listener);
            //设置模式行为
            case StateActions.ACTION_SET_VEHICLE_MODE:
                Log.i("zqj","ACTION_SET_VEHICLE_MODE:");
                return setVehicleMode(data, listener);

            case StateActions.ACTION_UPDATE_VEHICLE_DATA_STREAM_RATE:
                return updateVehicleDataStreamRate(data, listener);

            //控制行为,执行起飞 CONTROL ACTIONS
            case ControlActions.ACTION_DO_GUIDED_TAKEOFF:
                return performTakeoff(data, listener);
            //发送刹车行为
            case ControlActions.ACTION_SEND_BRAKE_VEHICLE:
                return brakeVehicle(listener);
            //设置偏航控制
            case ControlActions.ACTION_SET_CONDITION_YAW:
                // Retrieve the yaw turn speed.
                float turnSpeed = 2; // Default turn speed.

                ParameterManager parameterManager = getParameterManager();
                if (parameterManager != null) {
                    Parameter turnSpeedParam = parameterManager.getParameter("ACRO_YAW_P");
                    if (turnSpeedParam != null) {
                        turnSpeed = (float) turnSpeedParam.getValue();
                    }
                }

                float targetAngle = data.getFloat(ControlActions.EXTRA_YAW_TARGET_ANGLE);
                float yawRate = data.getFloat(ControlActions.EXTRA_YAW_CHANGE_RATE);
                boolean isClockwise = yawRate >= 0;
                boolean isRelative = data.getBoolean(ControlActions.EXTRA_YAW_IS_RELATIVE);

                MavLinkCommands.setConditionYaw(this, targetAngle, Math.abs(yawRate) * turnSpeed, isClockwise, isRelative, listener);
                return true;
            //设置速度行为
            case ControlActions.ACTION_SET_VELOCITY:
                return setVelocity(data, listener);

            case ControlActions.ACTION_ENABLE_MANUAL_CONTROL:
                return enableManualControl(data, listener);

            // EXPERIMENTAL ACTIONS
            case ExperimentalActions.ACTION_SEND_MAVLINK_MESSAGE:
                data.setClassLoader(MavlinkMessageWrapper.class.getClassLoader());
                MavlinkMessageWrapper messageWrapper = data.getParcelable(ExperimentalActions.EXTRA_MAVLINK_MESSAGE);
                CommonApiUtils.sendMavlinkMessage(this, messageWrapper);
                return true;

            // INTERNAL DRONE ACTIONS
            case ACTION_REQUEST_HOME_UPDATE:
                requestHomeUpdate();
                return true;

            //**************** CAPABILITY ACTIONS **************//
            case CapabilityActions.ACTION_CHECK_FEATURE_SUPPORT:
                return checkFeatureSupport(data, listener);

            default:
                CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_UNSUPPORTED, listener);
                return true;
        }
    }

在这里插入图片描述
这个函数执行子类的方法而不是父类的。除非在解锁模式下

    @Override
    protected boolean setVehicleMode(Bundle data, ICommandListener listener) {
        Log.i("zqj"," ARDUPILOT:");
        data.setClassLoader(VehicleMode.class.getClassLoader());
        VehicleMode newMode = data.getParcelable(StateActions.EXTRA_VEHICLE_MODE);
        CommonApiUtils.changeVehicleMode(this, newMode, listener);
        Log.i("zqj"," ARDUPILOT: FINISH");
        return true;
    }

在这里插入图片描述

父类中也有类似的实现方法:

    protected boolean setVehicleMode(Bundle data, ICommandListener listener) {
        data.setClassLoader(VehicleMode.class.getClassLoader());
        //还记得之前提起的地方吗EXTRA_VEHICLE_MODE。在这里实现
        VehicleMode newMode = data.getParcelable(StateActions.EXTRA_VEHICLE_MODE);
        Log.i("zqj"," newMode:"+newMode);
        if (newMode != null) {
            switch (newMode) {
                //是不是着落模式
                case COPTER_LAND:
                    MavLinkCommands.sendNavLand(this, listener);
                    break;
                //返航模式
                case COPTER_RTL:
                    MavLinkCommands.sendNavRTL(this, listener);
                    break;
                //引导模式
                case COPTER_GUIDED:
                    MavLinkCommands.sendPause(this, listener);
                    break;
                //是不是自动模式
                case COPTER_AUTO:
                    MavLinkCommands.startMission(this, listener);
                    break;
            }
        }
        Log.i("zqj"," MODE return:");
        return true;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔城烟雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值