目录
摘要
本周主要记录打造自己的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;
}