打造自己的HelloDrone 无人机APP过程《1》
目录
摘要
本节主要记录HelloDrone的连接过程及Mavlink协议解析过程。
1.实例化无人机及地面站控制对象
核心内容:
controlTower = new ControlTower(context);
drone = new Drone(context);
@Override
/**
* 重写onCreate方法,在onStart方法之前启动
*/
protected void onCreate(Bundle savedInstanceState) {
//调用父类的onCreate
super.onCreate(savedInstanceState);
//设置主窗口显示信息
setContentView(R.layout.activity_main);
Log.i("lxw","+++++");
//获取app文件名称
final Context context = getApplicationContext();
//创建控制
controlTower = new ControlTower(context);
//创建无人机实例
drone = new Drone(context);
//模式选择
this.modeSelector = (Spinner) findViewById(R.id.modeSelect);
//增加模式选择监听事件
this.modeSelector.setOnItemSelectedListener(new Spinner.OnItemSelectedListener()
{
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
onFlightModeSelected(view);
}
@Override
public void onNothingSelected(AdapterView<?> parent)
{
// Do nothing
}
});
final Button takePic = (Button) findViewById(R.id.take_photo_button);
takePic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
takePhoto();
}
});
final Button toggleVideo = (Button) findViewById(R.id.toggle_video_recording);
toggleVideo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleVideoRecording();
}
});
videoView = (TextureView) findViewById(R.id.video_content);
videoView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
alertUser("Video display is available.");
startVideoStream.setEnabled(true);
startVideoStreamUsingObserver.setEnabled(true);
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
startVideoStream.setEnabled(false);
startVideoStreamUsingObserver.setEnabled(false);
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
}
});
startVideoStream = (Button) findViewById(R.id.start_video_stream);
startVideoStream.setEnabled(false);
startVideoStream.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertUser("Starting video stream.");
startVideoStream(new Surface(videoView.getSurfaceTexture()));
}
});
stopVideoStream = (Button) findViewById(R.id.stop_video_stream);
stopVideoStream.setEnabled(false);
stopVideoStream.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertUser("Stopping video stream.");
stopVideoStream();
}
});
startVideoStreamUsingObserver = (Button) findViewById(R.id.start_video_stream_using_observer);
startVideoStreamUsingObserver.setEnabled(false);
startVideoStreamUsingObserver.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertUser("Starting video stream using observer for video stream packets.");
startVideoStreamForObserver();
}
});
stopVideoStreamUsingObserver = (Button) findViewById(R.id.stop_video_stream_using_observer);
stopVideoStreamUsingObserver.setEnabled(false);
stopVideoStreamUsingObserver.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertUser("Stopping video stream using observer for video stream packets.");
stopVideoStreamForObserver();
}
});
// Initialize media codec manager to decode video stream packets.
HandlerThread mediaCodecHandlerThread = new HandlerThread("MediaCodecHandlerThread");
mediaCodecHandlerThread.start();
Handler mediaCodecHandler = new Handler(mediaCodecHandlerThread.getLooper());
mediaCodecManager = new MediaCodecManager(mediaCodecHandler);
mainHandler = new Handler(getApplicationContext().getMainLooper());
}
2.绑定服务
@Override
public void onStart()
{
Log.i("lxw","Hello Drone onStart启动");
super.onStart();
//执行连接任务
Log.i(MAGTAG,"onStart");
Log.i(MAGTAG,"this:"+this); //this:hello.MainActivity
Log.i(MAGTAG,"this2:"+getApplicationContext()); //this2:hello.StarterApplication
//执行控制器连接
this.controlTower.connect(this,getApplicationContext());
//更新模式类型
updateVehicleModesForType(this.droneType);
Log.i(MAGTAG,"connect");
}
核心代码是:
this.controlTower.connect(this,getApplicationContext());
实现服务的绑定o3drServicesConnection
public void connect(TowerListener listener,Context context) {
boolean value;
Log.i("LXW","AAA");
//没有监听这,条件判断
if (towerListener != null && (isServiceConnecting.get() || isTowerConnected()))
return;
//是空
if (listener == null)
{
throw new IllegalArgumentException("ServiceListener argument cannot be null.");
}
Log.i("LXW","CCC");
towerListener = listener;
Log.i("LXW","DDD");
if (!isTowerConnected() && !isServiceConnecting.get())
{
Intent serviceIntent = ApiAvailability.getInstance().getAvailableServicesInstance(context);
//value1:Intent { act=com.o3dr.services.android.lib.model.IDroidPlannerServices
// cmp=com.o3dr.sample.hellodrone/org.droidplanner.services.android.impl.api.DroidPlannerService }
Log.i("LXW","value1:"+ApiAvailability.getInstance().getAvailableServicesInstance(context));
value= this.context.bindService(serviceIntent, o3drServicesConnection, Context.BIND_AUTO_CREATE);
//value2:true
Log.i("LXW","value2:"+value);
isServiceConnecting.set(value);
}
Log.i("LXW","EEE");
}
绑定服务后,首先启动的是onCreate(),然后进行onBind()方法
我们需要在清单文件中声明服务
我们去看下DroidPlannerService的代码,发现他是继承Service的,这也满足了服务的要求。
/**
DroneKit安卓后台服务实现。
* DroneKit-Android background service implementation.
*/
public class DroidPlannerService extends Service {
/**
* Status bar notification id
*/
private static final int FOREGROUND_ID = 101;
/**
* Set of actions to notify the local app's components of the service events.
*/
public static final String ACTION_DRONE_CREATED = Utils.PACKAGE_NAME + ".ACTION_DRONE_CREATED";
public static final String ACTION_DRONE_DESTROYED = Utils.PACKAGE_NAME + ".ACTION_DRONE_DESTROYED";
public static final String ACTION_RELEASE_API_INSTANCE = Utils.PACKAGE_NAME + ".action.RELEASE_API_INSTANCE";
public static final String EXTRA_API_INSTANCE_APP_ID = "extra_api_instance_app_id";
/**
* Used to broadcast service events.
*/
private LocalBroadcastManager lbm;
/**
* Stores drone api instances per connected client. The client are denoted by their app id.
*/
final ConcurrentHashMap<String, DroneApi> droneApiStore = new ConcurrentHashMap<>();
/**
* Caches drone managers per connection type.
*/
final ConcurrentHashMap<ConnectionParameter, DroneManager> droneManagers = new ConcurrentHashMap<>();
private DPServices dpServices;
private CameraInfoLoader cameraInfoLoader;
private List<CameraDetail> cachedCameraDetails;
/**
* Generate a drone api instance for the client denoted by the given app id.
*
* @param listener Used to retrieve api information.
* @param appId Application id of the connecting client.
* @return a IDroneApi instance
*/
DroneApi registerDroneApi(IApiListener listener, String appId) {
if (listener == null)
return null;
DroneApi droneApi = new DroneApi(this, listener, appId);
droneApiStore.put(appId, droneApi);
lbm.sendBroadcast(new Intent(ACTION_DRONE_CREATED));
updateForegroundNotification();
return droneApi;
}
/**
* Release the drone api instance attached to the given app id.
*
* @param appId Application id of the disconnecting client.
*/
void releaseDroneApi(String appId) {
if (appId == null)
return;
DroneApi droneApi = droneApiStore.remove(appId);
if (droneApi != null) {
Timber.d("Releasing drone api instance for " + appId);
droneApi.destroy();
lbm.sendBroadcast(new Intent(ACTION_DRONE_DESTROYED));
updateForegroundNotification();
}
}
/**
* 使用给定的连接参数与车辆建立连接。
* Establish a connection with a vehicle using the given connection parameter.
*
* @param connParams 用于连接到车辆的参数---Parameters used to connect to the vehicle.
* @param appId 连接应用程序的客户端id---Application id of the connecting client.
* @param listener 回调以接收无人机事件。Callback to receive drone events.
* @return 一个DroneManager实例,充当连接的车辆和正在侦听的客户端之间的路由器。
* A DroneManager instance which acts as router between the connected vehicle and the listeneing client(s).
*/
DroneManager connectDroneManager(ConnectionParameter connParams, String appId, DroneApi listener) {
if (connParams == null || TextUtils.isEmpty(appId) || listener == null)
{
Log.i("lxw","connectDroneManager NULL");
return null;
}
DroneManager droneMgr = droneManagers.get(connParams);
Log.i("lxw","MYdroneMgr:"+droneMgr);
if (droneMgr == null) {
final DroneManager temp = DroneManager.generateDroneManager(getApplicationContext(), connParams, new Handler(Looper.getMainLooper()));
Log.i("lxw","temp:"+temp);
droneMgr = droneManagers.putIfAbsent(connParams, temp);
Log.i("lxw","MYdroneMgr2:"+droneMgr);
if(droneMgr == null){
Log.i("lxw","Generating:");
Timber.d("Generating new drone manager.");
droneMgr = temp;
}
else{
temp.destroy();
}
}
Timber.d("Drone manager connection for " + appId);
Log.i("lxw","Generating connect");
//进行连接
droneMgr.connect(appId, listener, connParams);
return droneMgr;
}
/**
* Disconnect the given client from the vehicle managed by the given drone manager.
*
* @param droneMgr Handler for the connected vehicle.
* @param clientInfo Info of the disconnecting client.
*/
void disconnectDroneManager(DroneManager droneMgr, DroneApi.ClientInfo clientInfo) {
if (droneMgr == null || clientInfo == null || TextUtils.isEmpty(clientInfo.appId))
return;
String appId = clientInfo.appId;
Timber.d("Drone manager disconnection for " + appId);
droneMgr.disconnect(clientInfo);
if (droneMgr.getConnectedAppsCount() == 0) {
Timber.d("Destroying drone manager.");
droneMgr.destroy();
droneManagers.remove(droneMgr.getConnectionParameter());
}
}
/**
* Retrieves the set of camera info provided by the app.
*
* @return a list of {@link CameraDetail} objects.
*/
synchronized List<CameraDetail> getCameraDetails() {
if (cachedCameraDetails == null) {
List<String> cameraInfoNames = cameraInfoLoader.getCameraInfoList();
List<CameraInfo> cameraInfos = new ArrayList<>(cameraInfoNames.size());
for (String infoName : cameraInfoNames) {
try {
cameraInfos.add(cameraInfoLoader.openFile(infoName));
} catch (Exception e) {
Timber.e(e, e.getMessage());
}
}
List<CameraDetail> cameraDetails = new ArrayList<>(cameraInfos.size());
for (CameraInfo camInfo : cameraInfos) {
cameraDetails.add(new CameraDetail(camInfo.name, camInfo.sensorWidth,
camInfo.sensorHeight, camInfo.sensorResolution, camInfo.focalLength,
camInfo.overlap, camInfo.sidelap, camInfo.isInLandscapeOrientation));
}
cachedCameraDetails = cameraDetails;
}
return cachedCameraDetails;
}
@Override
//这里是不是返回null了
public IBinder onBind(Intent intent) {
Log.d("lxw","onBind service " + intent);
final String action = intent.getAction();
if (IDroidPlannerServices.class.getName().equals(action))
{
// Return binder to ipc client-server interaction.
return dpServices;
} else
{
return null;
}
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
super.onCreate();
Log.d("lxw","Binding DroidPlannerService onCreate " );
Timber.d("Creating DroneKit-Android.");
final Context context = getApplicationContext();
dpServices = new DPServices(this);
lbm = LocalBroadcastManager.getInstance(context);
this.cameraInfoLoader = new CameraInfoLoader(context);
updateForegroundNotification();
}
@SuppressLint("NewApi")
private void updateForegroundNotification() {
final Context context = getApplicationContext();
//Put the service in the foreground
final NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context)
.setContentTitle("DroneKit-Android")
.setPriority(NotificationCompat.PRIORITY_MIN)
.setSmallIcon(R.drawable.ic_stat_notify);
final int connectedCount = droneApiStore.size();
if (connectedCount > 1) {
notifBuilder.setContentText(connectedCount + " connected apps");
}
final Notification notification = notifBuilder.build();
startForeground(FOREGROUND_ID, notification);
}
@Override
public void onDestroy() {
super.onDestroy();
Timber.d("Destroying DroneKit-Android.");
for (DroneApi droneApi : droneApiStore.values()) {
droneApi.destroy();
}
droneApiStore.clear();
for (DroneManager droneMgr : droneManagers.values()) {
droneMgr.destroy();
}
droneManagers.clear();
dpServices.destroy();
stopForeground(true);
//Disable this service. It'll be reenabled the next time its local client needs it.
enableDroidPlannerService(getApplicationContext(), false);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("lxw","MYintent:"+intent);
if (intent != null) {
final String action = intent.getAction();
switch (action) {
case ACTION_RELEASE_API_INSTANCE:
final String appId = intent.getStringExtra(EXTRA_API_INSTANCE_APP_ID);
releaseDroneApi(appId);
break;
}
}
stopSelf();
return START_NOT_STICKY;
}
/**
* Toggles the DroidPlannerService component
* @param context
* @param enable
*/
public static void enableDroidPlannerService(Context context, boolean enable){
final ComponentName serviceComp = new ComponentName(context, DroidPlannerService.class);
final int newState = enable ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
: PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
context.getPackageManager().setComponentEnabledSetting(serviceComp, newState, PackageManager.DONT_KILL_APP);
}
}
执行完onbind后,会返回
然后会执行
/**
* 创建连接服务
*/
private final ServiceConnection o3drServicesConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
isServiceConnecting.set(false);
Log.i("lxw","onServiceConnected");
o3drServices = IDroidPlannerServices.Stub.asInterface(service);
try {
o3drServices.asBinder().linkToDeath(binderDeathRecipient, 0);
Log.i("lxw","onServiceConnected try ");
//通知连接
notifyTowerConnected();
} catch (RemoteException e) {
//通知没有连接
notifyTowerDisconnected();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("lxw","EEE777");
isServiceConnecting.set(false);
notifyTowerDisconnected();
}
};
核心函数:notifyTowerConnected()
/**
* 通知连接
*/
void notifyTowerConnected()
{
Log.i("lxw","notifyTowerConnected");
if (towerListener == null)
return;
//调用连接
Log.i("lxw","onTower");
towerListener.onTowerConnected();
}
我们关注这个函数:towerListener.onTowerConnected();主要实现注册无人机和注册监听者。
public void onTowerConnected() {
//提示连接成功
alertUser("DroneKit-Android Connected");
this.controlTower.registerDrone(this.drone, this.handler);
Log.i("lxw","onTowerConnected");
this.drone.registerDroneListener(this);
Log.i("lxw","registerDroneListener");
}
3.增加连接点击事件及进行连接
MainActivity实现点击按钮事件
public void onBtnConnectTap(View view)
{
//判断是否连接状态,如果是连接,点击的话,提示端口连接
if (this.drone.isConnected())
{
Log.i("lxw","端开连接");
this.drone.disconnect();
} else
{
Log.i("lxw","进行连接");
//Spinner提供了从一个数据集合中快速选择一项值的办法。默认情况下Spinner显示的是当前选择的值,
// 点击Spinner会弹出一个包含所有可选值的dropdown菜单,从该菜单中可以为Spinner选择一个新值
Spinner connectionSelector = (Spinner) findViewById(R.id.selectConnectionType);
//获取到下拉框属性
int selectedConnectionType = connectionSelector.getSelectedItemPosition();
//判断现在的连接是不是USB连接,如果是的话进行usb连接,否则是udp连接
//conntParams:ConnectionParameter{connectionType=0, paramsBundle=[extra_usb_baud_rate=115200]}
ConnectionParameter connectionParams = selectedConnectionType == ConnectionType.TYPE_USB
? ConnectionParameter.newUsbConnection(null)
: ConnectionParameter.newUdpConnection(null);
Log.i("lxw","connectionParams:"+connectionParams);
//内部类实现连接事件
this.drone.connect(connectionParams, new LinkListener()
{
@Override
public void onLinkStateUpdated(@NonNull LinkConnectionStatus connectionStatus)
{
Log.i("lxw","connectionStatus:"+connectionStatus);
}
});
}
}
核心代码:匿名内部类实现连接事件
//匿名内部类实现连接事件
this.drone.connect(connectionParams, new LinkListener()
{
@Override
public void onLinkStateUpdated(@NonNull LinkConnectionStatus connectionStatus)
{
Log.i("lxw","connectionStatus:"+connectionStatus);
}
});
public void connect(ConnectionParameter connParams, LinkListener linkListener) {
Log.i("lxw","开始进行drone连接操作");
//USB连接
VehicleApi.getApi(this).connect(connParams);
this.connectionParameter = connParams;
this.linkListener = linkListener;
Log.i("lxw","this.connectionParameter:"+this.connectionParameter);
Log.i("lxw","this.linkListener:"+this.linkListener);
}
继续研究核心代码:VehicleApi.getApi(this).connect(connParams);
public void connect(ConnectionParameter parameter) {
Bundle params = new Bundle();
//params:Bundle[{}]
Log.i("lxw","Bundle params:"+params);
params.putParcelable(EXTRA_CONNECT_PARAMETER, parameter);
Action connectAction = new Action(ACTION_CONNECT, params);
//无人机执行异步操作
//com.o3dr.services.android.lib.model.action.Action
Log.i("lxw","Bundle connectAction:"+connectAction);
drone.performAsyncAction(connectAction);
}
分析:drone.performAsyncAction(connectAction);
public boolean performAsyncAction(Action action) {
//异步执行线程
return performAsyncActionOnDroneThread(action, null);
}
分析代码:performAsyncActionOnDroneThread
public boolean performAsyncActionOnDroneThread(Action action, AbstractCommandListener listener) {
//执行异步行为处理
return performAsyncActionOnHandler(action, this.handler, listener);
}
分析performAsyncActionOnHandler
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));
/**
* 执行行为
*/
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("lxw","action null:");
return;
}
String type = action.getType();
//type com.o3dr.services.android.action.CONNECT
Log.i("lxw","type:"+type);
if (type == null)
{
Log.i("lxw","type null:");
return;
}
Bundle data = action.getData();
Log.i("lxw","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);
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) {
droneMgr.executeAsyncAction(clientInfo, action, listener);
} else {
CommonApiUtils.postErrorEvent(CommandExecutionError.COMMAND_FAILED, listener);
}
break;
}
}
这里我们选择USB连接,重点执行的函数
/**
* 执行连接任务
* @param connParams
*/
public void connect(ConnectionParameter connParams) {
try {
Log.i("lxw","connParams:"+connParams);
//Validate the given connection parameter
connParams = checkConnectionParameter(connParams);
Log.i("lxw","connParams1:"+connParams);
//Validate the current connection parameter for the drone
ConnectionParameter currentConnParams = this.connectionParams == null
? this.connectionParams
: checkConnectionParameter(this.connectionParams);
Log.i("lxw","currentConnParams:"+currentConnParams);
if (!connParams.equals(currentConnParams))
{
Log.i("lxw","droneMgr:"+droneMgr);
if (this.droneMgr != null)
{
Log.i("lxw","droneMgr is not null:");
LinkConnectionStatus connectionStatus = LinkConnectionStatus
.newFailedConnectionStatus(LinkConnectionStatus.ADDRESS_IN_USE,
"Connection already started with different connection parameters");
onConnectionStatus(connectionStatus);
return;
}
this.connectionParams = connParams;
Log.i("lxw","this.connectionParams:"+this.connectionParams);
//ownerId:com.o3dr.sample.hellodrone
Log.i("lxw","ownerId:"+ownerId);
//进行连接管理调用
this.droneMgr = service.connectDroneManager(this.connectionParams, ownerId, this);
Log.i("lxw","this.droneMgr:"+this.droneMgr);
Log.i("lxw","bufdata:"+isEventsBufferingEnabled());
if(isEventsBufferingEnabled())
{
Log.i("lxw","isEventsBufferingEnabled:");
eventsBuffer.clear();
handler.postDelayed(eventsDispatcher, this.connectionParams.getEventsDispatchingPeriod());
}
}
} catch (ConnectionException e)
{
Log.i("lxw","link connect:");
LinkConnectionStatus connectionStatus = LinkConnectionStatus
.newFailedConnectionStatus(LinkConnectionStatus.INVALID_CREDENTIALS, e.getMessage());
onConnectionStatus(connectionStatus);
disconnect();
}
}
分析代码:this.droneMgr = service.connectDroneManager(this.connectionParams, ownerId, this);
/**
* 使用给定的连接参数与车辆建立连接。
* Establish a connection with a vehicle using the given connection parameter.
*
* @param connParams 用于连接到车辆的参数---Parameters used to connect to the vehicle.
* @param appId 连接应用程序的客户端id---Application id of the connecting client.
* @param listener 回调以接收无人机事件。Callback to receive drone events.
* @return 一个DroneManager实例,充当连接的车辆和正在侦听的客户端之间的路由器。
* A DroneManager instance which acts as router between the connected vehicle and the listeneing client(s).
*/
DroneManager connectDroneManager(ConnectionParameter connParams, String appId, DroneApi listener) {
if (connParams == null || TextUtils.isEmpty(appId) || listener == null)
{
Log.i("lxw","connectDroneManager NULL");
return null;
}
DroneManager droneMgr = droneManagers.get(connParams);
Log.i("lxw","MYdroneMgr:"+droneMgr);
if (droneMgr == null) {
final DroneManager temp = DroneManager.generateDroneManager(getApplicationContext(), connParams, new Handler(Looper.getMainLooper()));
Log.i("lxw","temp:"+temp);
droneMgr = droneManagers.putIfAbsent(connParams, temp);
Log.i("lxw","MYdroneMgr2:"+droneMgr);
if(droneMgr == null){
Log.i("lxw","Generating:");
Timber.d("Generating new drone manager.");
droneMgr = temp;
}
else{
temp.destroy();
}
}
Timber.d("Drone manager connection for " + appId);
Log.i("lxw","Generating connect");
//进行连接
droneMgr.connect(appId, listener, connParams);
return droneMgr;
}
分析代码:droneMgr.connect(appId, listener, connParams);
public synchronized void connect(String appId, DroneApi listener, ConnectionParameter connParams) {
//org.droidplanner.services.android.impl.api.DroneApi
Log.i("lxw","listener:"+listener);
Log.i("lxw","listener2:"+TextUtils.isEmpty(appId));
if (listener == null || TextUtils.isEmpty(appId)) {
Log.i("lxw","listener return:");
return;
}
connectedApps.put(appId, listener);
//开始连接
Log.i("lxw","doConnect:");
doConnect(appId, listener, connParams);
}
分析:doConnect(appId, listener, connParams);
protected void doConnect(String appId, DroneApi listener, ConnectionParameter connParams) {
Log.i("lxw"," MavlinkDrone Manager doConnect:");
if (mavClient.isDisconnected()) {
Timber.i("Opening connection for %s", appId);
mavClient.openConnection();
Log.i("lxw"," mavClientdoConnect:1");
} else {
if (isConnected()) {
listener.onDroneEvent(DroneInterfaces.DroneEventsType.CONNECTED, drone);
if (!drone.isConnectionAlive())
listener.onDroneEvent(DroneInterfaces.DroneEventsType.HEARTBEAT_TIMEOUT, drone);
}
Log.i("lxw"," mavClientdoConnect:2");
}
mavClient.registerForTLogLogging(appId, connParams.getTLogLoggingUri());
Log.i("lxw"," updateDroneStreamRate:");
updateDroneStreamRate(connParams);
}
重点关注: mavClient.openConnection();
public synchronized void openConnection()
{
if(isConnected() || isConnecting())
{
Log.i("lxw"," openConnection:1");
return;
}
final String tag = toString();
//创建Mavlink----Create the mavlink connection
final int connectionType = connParams.getConnectionType();
final Bundle paramsBundle = connParams.getParamsBundle();
Log.i("lxw"," connectionType:"+connectionType); //0
Log.i("lxw"," paramsBundle:"+paramsBundle); //波特率
Log.i("lxw"," mavlinkConn:"+mavlinkConn); //UsbConnection
if(mavlinkConn == null) {
switch (connectionType) {
//USB类型
case ConnectionType.TYPE_USB: //0
final int baudRate = paramsBundle.getInt(ConnectionType.EXTRA_USB_BAUD_RATE,
ConnectionType.DEFAULT_USB_BAUD_RATE);
mavlinkConn = new UsbConnection(context, baudRate);
Log.i("lxw"," mavlinkConn:6"+mavlinkConn);
Timber.i("Connecting over usb.");
break;
//蓝牙类型
case ConnectionType.TYPE_BLUETOOTH:
//Retrieve the bluetooth address to connect to
final String bluetoothAddress = paramsBundle.getString(ConnectionType.EXTRA_BLUETOOTH_ADDRESS);
mavlinkConn = new BluetoothConnection(context, bluetoothAddress);
Timber.i("Connecting over bluetooth.");
break;
//TCP类型
case ConnectionType.TYPE_TCP:
//Retrieve the server ip and port
final String tcpServerIp = paramsBundle.getString(ConnectionType.EXTRA_TCP_SERVER_IP);
final int tcpServerPort = paramsBundle.getInt(ConnectionType
.EXTRA_TCP_SERVER_PORT, ConnectionType.DEFAULT_TCP_SERVER_PORT);
mavlinkConn = new AndroidTcpConnection(context, tcpServerIp, tcpServerPort, new WifiConnectionHandler(context));
Timber.i("Connecting over tcp.");
break;
//UDP类型
case ConnectionType.TYPE_UDP:
final int udpServerPort = paramsBundle
.getInt(ConnectionType.EXTRA_UDP_SERVER_PORT, ConnectionType.DEFAULT_UDP_SERVER_PORT);
mavlinkConn = new AndroidUdpConnection(context, udpServerPort, new WifiConnectionHandler(context));
Timber.i("Connecting over udp.");
break;
//SOLO类型
case ConnectionType.TYPE_SOLO: {
Timber.i("Creating solo connection");
final String soloLinkId = paramsBundle.getString(ConnectionType.EXTRA_SOLO_LINK_ID, null);
final String linkPassword = paramsBundle.getString(ConnectionType.EXTRA_SOLO_LINK_PASSWORD, null);
mavlinkConn = new SoloConnection(context, soloLinkId, linkPassword);
break;
}
default:
Timber.e("Unrecognized connection type: %s", connectionType);
return;
}
}
Log.i("lxw"," mavlinkConn:7");
Log.i("lxw"," mConnectionListener:"+mConnectionListener);
mavlinkConn.addMavLinkConnectionListener(tag, mConnectionListener);
//Check if we need to ping a server to receive UDP data stream.
if (connectionType == ConnectionType.TYPE_UDP)
{
final String pingIpAddress = paramsBundle.getString(ConnectionType.EXTRA_UDP_PING_RECEIVER_IP);
if (!TextUtils.isEmpty(pingIpAddress)) {
try {
final InetAddress resolvedAddress = InetAddress.getByName(pingIpAddress);
final int pingPort = paramsBundle.getInt(ConnectionType.EXTRA_UDP_PING_RECEIVER_PORT);
final long pingPeriod = paramsBundle.getLong(ConnectionType.EXTRA_UDP_PING_PERIOD,
ConnectionType.DEFAULT_UDP_PING_PERIOD);
final byte[] pingPayload = paramsBundle.getByteArray(ConnectionType.EXTRA_UDP_PING_PAYLOAD);
((AndroidUdpConnection) mavlinkConn).addPingTarget(resolvedAddress, pingPort, pingPeriod, pingPayload);
} catch (UnknownHostException e) {
Timber.e(e, "Unable to resolve UDP ping server ip address.");
}
}
}
Log.i("lxw"," mavlinkConn:888");
if (mavlinkConn.getConnectionStatus() == MavLinkConnection.MAVLINK_DISCONNECTED)
{
Log.i("lxw"," 开始执行Mavlink 连接");
mavlinkConn.connect(null);
}
}
重点函数:执行mavlink相关mavlinkConn.connect(null);
public void connect(Bundle extras) {
Log.i("lxw"," mavlinkConn:999");
if (mConnectionStatus.compareAndSet(MAVLINK_DISCONNECTED, MAVLINK_CONNECTING)) {
extrasHolder.set(extras);
mLogger.logInfo(TAG, "Starting connection thread.");
Log.i("lxw"," mavlink连接任务创建");
mConnectThread = new Thread(mConnectingTask, "MavLinkConnection-Connecting Thread");
//启动连接
mConnectThread.start();
//报告链接状态
reportConnecting();
}
}
/**
* 启动连接进程。Start the connection process.
*/
private final Runnable mConnectingTask = new Runnable() {
@Override
public void run() {
// Load the connection specific preferences
loadPreferences();
// Open the connection
try {
Log.i("lxw"," 开始执行打开openConnection run");
openConnection(extrasHolder.get());
Log.i("lxw"," mavlinkConn:111");
} catch (IOException e) {
Log.i("lxw"," mavlinkConn:2222");
// Ignore errors while shutting down
if (mConnectionStatus.get() != MAVLINK_DISCONNECTED) {
reportIOException(e);
mLogger.logErr(TAG, e);
}
disconnect();
}
mLogger.logInfo(TAG, "Exiting connecting thread.");
}
};
继续看代码:openConnection(extrasHolder.get());
@Override
protected void openConnection(Bundle connectionExtras) throws IOException {
boolean id_device;
Log.i("lxw"," mUsbConnection:"+mUsbConnection);
if (mUsbConnection != null) {
try {
Log.i("lxw"," BBB123");
mUsbConnection.openUsbConnection(connectionExtras);
Log.d(TAG, "Reusing previous usb connection.");
return;
} catch (IOException e) {
Log.i("lxw"," BBB456");
Log.e(TAG, "Previous usb connection is not usable.", e);
mUsbConnection = null;
}
}
id_device=isFTDIdevice(context);
Log.i("lxw","id_device:"+id_device);
if (id_device)
{
final UsbConnectionImpl tmp = new UsbFTDIConnection(context, this, mBaudRate);
try {
tmp.openUsbConnection(connectionExtras);
// If the call above is successful, 'mUsbConnection' will be set.
mUsbConnection = tmp;
Log.d(TAG, "Using FTDI usb connection.");
} catch (IOException e) {
Log.d(TAG, "Unable to open a ftdi usb connection. Falling back to the open "
+ "usb-library.", e);
}
}
// Fallback
if (mUsbConnection == null) {
Log.i("lxw"," KKK");
Log.i("lxw"," BT:"+mBaudRate);
Log.i("lxw"," BT2:"+context);
final UsbConnectionImpl tmp = new UsbCDCConnection(context, this, mBaudRate);
Log.i("lxw"," BT3:"+tmp);
// If an error happens here, let it propagate up the call chain since this is the fallback.
tmp.openUsbConnection(connectionExtras);
Log.i("lxw"," BT5:");
mUsbConnection = tmp;
Log.i("lxw"," BT6:"+mUsbConnection);
Log.d(TAG, "Using open-source usb connection.");
}
}
继续看代码:tmp.openUsbConnection(connectionExtras);
protected void openUsbConnection(Bundle extras) throws IOException {
Log.i("lxw"," cdc");
extrasHolder.set(extras);
registerUsbPermissionBroadcastReceiver();
// Get UsbManager from Android.
UsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
//Get the list of available devices
List<UsbDevice> availableDevices = UsbSerialProber.getAvailableSupportedDevices(manager);
Log.i("lxw"," availableDevices:"+availableDevices);
if (availableDevices.isEmpty())
{
Log.i("lxw"," CDC NULL");
Log.d(TAG, "No Devices found");
throw new IOException("No Devices found");
}
//Pick the first device
UsbDevice device = availableDevices.get(0);
if (manager.hasPermission(device))
{
openUsbDevice(device, extras);
} else {
removeWatchdog();
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.schedule(permissionWatchdog, 15, TimeUnit.SECONDS);
Log.d(TAG, "Requesting permission to access usb device " + device.getDeviceName());
manager.requestPermission(device, usbPermissionIntent);
}
}
继续看代码:openUsbDevice(device, extras);
private void openUsbDevice(UsbDevice device, Bundle extras) throws IOException {
//从Android获取UsbManager。--- Get UsbManager from Android.
UsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
//找到第一个可用的驱动程序。--- Find the first available driver.
final UsbSerialDriver serialDriver = UsbSerialProber.openUsbDevice(manager, device);
if (serialDriver == null) {
Log.d(TAG, "No Devices found");
throw new IOException("No Devices found");
} else {
Log.d(TAG, "Opening using Baud rate " + mBaudRate);
try {
serialDriver.open();
serialDriver.setParameters(mBaudRate, 8, UsbSerialDriver.STOPBITS_1, UsbSerialDriver.PARITY_NONE);
serialDriverRef.set(serialDriver);
onUsbConnectionOpened(extras);
} catch (IOException e)
{
Log.e(TAG, "Error setting up device: " + e.getMessage(), e);
try {
serialDriver.close();
} catch (IOException e2) {
// Ignore.
}
}
}
}
继续onUsbConnectionOpened(extras);
protected void onUsbConnectionOpened(Bundle extras) {
parentConnection.onConnectionOpened(extras);
}
/**
* 打开设备,执行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();
}
}
匿名内部类实现最终mavlink协议处理相关
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);
}
}
}
};
其中比较重要的APP往外界发送的内容:
其中比较重要的APP往外界发送的内容:
其中比较重要的APP往外界发送的内容:
private final Runnable mSendingTask = new Runnable() {
@Override
public void run() {
try {
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();
}
}
};
我们这里重点还是关注接收
核心处理:handleData(parser, bufferSize, readBuffer);
核心处理:handleData(parser, bufferSize, readBuffer);
核心处理:handleData(parser, bufferSize, readBuffer);
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);
}
}
}
private void reportReceivedPacket(MAVLinkPacket packet)
{
//监听者是否非空
if (mListeners.isEmpty())
{
return;
}
for (MavLinkConnectionListener listener : mListeners.values())
{
Log.i("lxw"," onReceivePacket:");
//接收数据处理
listener.onReceivePacket(packet);
}
}
public void onReceivePacket(final MAVLinkPacket packet) {
Log.i("lxw"," notifyReceivedData:");
listener.notifyReceivedData(packet);
Log.i("lxw"," receivedMsg END:");
}
public void notifyReceivedData(MAVLinkPacket packet) {
MAVLinkMessage receivedMsg = packet.unpack();
Log.i("lxw"," receivedMsg:"+receivedMsg);
if (receivedMsg == null)
return;
Log.i("lxw"," MSGID:"+receivedMsg.msgid);
if (receivedMsg.msgid == msg_command_ack.MAVLINK_MSG_ID_COMMAND_ACK)
{
Log.i("lxw"," command ack:");
msg_command_ack commandAck = (msg_command_ack) receivedMsg;
handleCommandAck(commandAck);
} else
{
Log.i("lxw"," Handler receiveData :");
this.mavLinkMsgHandler.receiveData(receivedMsg);
if (this.drone != null)
{
Log.i("lxw"," 核心处理mavlink信息:");
this.drone.onMavLinkMessageReceived(receivedMsg);
}
}
if (!connectedApps.isEmpty())
{
Log.i("lxw"," spp :"+connectedApps.values());
//org.droidplanner.services.android.impl.api.DroneApi
for (DroneApi droneEventsListener : connectedApps.values())
{
droneEventsListener.onReceivedMavLinkMessage(receivedMsg);
}
}
}
这里的代码有两部分比较重要:带应答和不应答的协议,我们这主要关注不带应答的协议。
先调用Ardupilot中的方法:
public void onMavLinkMessageReceived(MAVLinkMessage message) {
Log.i("lxw","ardupilot message.sysid :"+message.sysid );
if ((message.sysid != this.getSysid()) && !isMavLinkMessageException(message)) {
// Reject Messages that are not for the system id
return;
}
// Filter Components IDs to be specifically the IDs that can be processed
int compId = message.compid;
if (compId != AUTOPILOT_COMPONENT_ID
&& compId != ARTOO_COMPONENT_ID
&& compId != SiK_RADIO_FIXED_COMPID ){
return;
}
if (!getParameterManager().processMessage(message)) {
getWaypointManager().processMessage(message);
getCalibrationSetup().processMessage(message);
switch (message.msgid) {
case msg_statustext.MAVLINK_MSG_ID_STATUSTEXT:
// These are any warnings sent from APM:Copter with
// gcs_send_text_P()
// This includes important thing like arm fails, prearm fails, low
// battery, etc.
// also less important things like "erasing logs" and
// "calibrating barometer"
msg_statustext msg_statustext = (msg_statustext) message;
processStatusText(msg_statustext);
break;
case msg_vfr_hud.MAVLINK_MSG_ID_VFR_HUD:
processVfrHud((msg_vfr_hud) message);
break;
case msg_raw_imu.MAVLINK_MSG_ID_RAW_IMU:
msg_raw_imu msg_imu = (msg_raw_imu) message;
mag.newData(msg_imu);
break;
case msg_radio.MAVLINK_MSG_ID_RADIO:
msg_radio m_radio = (msg_radio) message;
processSignalUpdate(m_radio.rxerrors, m_radio.fixed, m_radio.rssi,
m_radio.remrssi, m_radio.txbuf, m_radio.noise, m_radio.remnoise);
break;
case msg_rc_channels_raw.MAVLINK_MSG_ID_RC_CHANNELS_RAW:
rc.setRcInputValues((msg_rc_channels_raw) message);
break;
case msg_servo_output_raw.MAVLINK_MSG_ID_SERVO_OUTPUT_RAW:
rc.setRcOutputValues((msg_servo_output_raw) message);
break;
case msg_camera_feedback.MAVLINK_MSG_ID_CAMERA_FEEDBACK:
getCamera().newImageLocation((msg_camera_feedback) message);
break;
case msg_mount_status.MAVLINK_MSG_ID_MOUNT_STATUS:
processMountStatus((msg_mount_status) message);
break;
case msg_named_value_int.MAVLINK_MSG_ID_NAMED_VALUE_INT:
processNamedValueInt((msg_named_value_int) message);
break;
//*************** Magnetometer calibration messages handling *************//
case msg_mag_cal_progress.MAVLINK_MSG_ID_MAG_CAL_PROGRESS:
case msg_mag_cal_report.MAVLINK_MSG_ID_MAG_CAL_REPORT:
getMagnetometerCalibration().processCalibrationMessage(message);
break;
default:
break;
}
}
Log.i("lxw","super message.sysid :"+message.sysid );
//这里实现调用父类的方法
super.onMavLinkMessageReceived(message);
}
public void onMavLinkMessageReceived(MAVLinkMessage message) {
Log.i("lxw","message.sysid :"+message.sysid );
if ( (message.sysid != this.getSysid()) && !isMavLinkMessageException(message) )
{
// Reject messages that are not for this drone's system id
return;
}
onHeartbeat(message);
switch (message.msgid) {
case msg_radio_status.MAVLINK_MSG_ID_RADIO_STATUS:
msg_radio_status m_radio_status = (msg_radio_status) message;
processSignalUpdate(m_radio_status.rxerrors, m_radio_status.fixed, m_radio_status.rssi,
m_radio_status.remrssi, m_radio_status.txbuf, m_radio_status.noise, m_radio_status.remnoise);
break;
case msg_attitude.MAVLINK_MSG_ID_ATTITUDE:
msg_attitude m_att = (msg_attitude) message;
processAttitude(m_att);
break;
case msg_heartbeat.MAVLINK_MSG_ID_HEARTBEAT:
msg_heartbeat msg_heart = (msg_heartbeat) message;
processHeartbeat(msg_heart);
break;
case msg_vibration.MAVLINK_MSG_ID_VIBRATION:
msg_vibration vibrationMsg = (msg_vibration) message;
processVibrationMessage(vibrationMsg);
break;
//*************** EKF State handling ******************//
case msg_ekf_status_report.MAVLINK_MSG_ID_EKF_STATUS_REPORT:
processEfkStatus((msg_ekf_status_report) message);
break;
case msg_sys_status.MAVLINK_MSG_ID_SYS_STATUS:
msg_sys_status m_sys = (msg_sys_status) message;
processSysStatus(m_sys);
break;
case msg_global_position_int.MAVLINK_MSG_ID_GLOBAL_POSITION_INT:
processGlobalPositionInt((msg_global_position_int) message);
break;
case msg_gps_raw_int.MAVLINK_MSG_ID_GPS_RAW_INT:
processGpsState((msg_gps_raw_int) message);
break;
case msg_mission_item.MAVLINK_MSG_ID_MISSION_ITEM:
processHomeUpdate((msg_mission_item) message);
break;
case msg_mission_current.MAVLINK_MSG_ID_MISSION_CURRENT:
missionStats.setWpno(((msg_mission_current) message).seq);
break;
case msg_mission_item_reached.MAVLINK_MSG_ID_MISSION_ITEM_REACHED:
missionStats.setLastReachedWaypointNumber(((msg_mission_item_reached) message).seq);
break;
case msg_nav_controller_output.MAVLINK_MSG_ID_NAV_CONTROLLER_OUTPUT:
msg_nav_controller_output m_nav = (msg_nav_controller_output) message;
setDisttowpAndSpeedAltErrors(m_nav.wp_dist, m_nav.alt_error, m_nav.aspd_error);
break;
}
}
整体协议处理流程就是这样,后续会细致分析。
本文地址:https://blog.csdn.net/lixiaoweimashixiao/article/details/108851017