基于大疆M300无人机平台进行开发,由于需要在无人机进入到正常航线之后再开启自己开发的检测功能,需要根据OSDK给出的航点信息来做控制。由于检测功能是基于ROS做的,所以SDK采用的是Onboard-SDK-ROS-4.1.0,环境和编译就不再说明了。
OSDK航点信息的发布主要在dji_vehicle_node_mission_services.cpp文件,其中需要的在updateMissionState和updateMissionEvent函数中,如下:
//10HZ push
E_OsdkStat VehicleNode::updateMissionState(T_CmdHandle *cmdHandle, const T_CmdInfo *cmdInfo,
const uint8_t *cmdData, void *userData) {
if (cmdInfo) {
if (userData) {
auto *vh_ = (VehicleNode *)userData;
auto *missionStatePushAck =
(DJI::OSDK::MissionStatePushAck *)cmdData;
dji_osdk_ros::WaypointV2MissionStatePush waypointV2MissionStatePushInfo;
waypointV2MissionStatePushInfo.commonDataVersion = missionStatePushAck->commonDataVersion;
waypointV2MissionStatePushInfo.commonDataLen = missionStatePushAck->commonDataLen;
waypointV2MissionStatePushInfo.state = missionStatePushAck->data.state;
waypointV2MissionStatePushInfo.curWaypointIndex = missionStatePushAck->data.curWaypointIndex;
waypointV2MissionStatePushInfo.velocity = missionStatePushAck->data.velocity;
vh_->waypointV2_mission_state_publisher_.publish(waypointV2MissionStatePushInfo);
} else {
DERROR("cmdInfo is a null value");
}
return OSDK_STAT_OK;
}
return OSDK_STAT_ERR_ALLOC;
}
/*! only push 0x00,0x10,0x11 event*/
E_OsdkStat VehicleNode::updateMissionEvent(T_CmdHandle *cmdHandle, const T_CmdInfo *cmdInfo,
const uint8_t *cmdData, void *userData) {
if (cmdInfo) {
if (userData) {
auto *MissionEventPushAck =
(DJI::OSDK::MissionEventPushAck *)cmdData;
auto *vh_ = (VehicleNode *)userData;
dji_osdk_ros::WaypointV2MissionEventPush waypointV2MissionEventPushInfo;
waypointV2MissionEventPushInfo.event = MissionEventPushAck->event;
if(MissionEventPushAck->event == 0x01)
{
waypointV2MissionEventPushInfo.interruptReason = MissionEventPushAck->data.interruptReason;
}
if(MissionEventPushAck->event == 0x02)
{
waypointV2MissionEventPushInfo.recoverProcess = MissionEventPushAck->data.recoverProcess;
}
if(MissionEventPushAck->event == 0x03)
{
waypointV2MissionEventPushInfo.finishReason = MissionEventPushAck->data.finishReason;
}
if(MissionEventPushAck->event == 0x10)
{
waypointV2MissionEventPushInfo.waypointIndex = MissionEventPushAck->data.waypointIndex;
}
if(MissionEventPushAck->event == 0x11)
{
waypointV2MissionEventPushInfo.currentMissionExecNum = MissionEventPushAck->data.MissionExecEvent.currentMissionExecNum;
waypointV2MissionEventPushInfo.finishedAllExecNum = MissionEventPushAck->data.MissionExecEvent.finishedAllExecNum;
}
vh_->waypointV2_mission_event_publisher_.publish(waypointV2MissionEventPushInfo);
return OSDK_STAT_OK;
}
}
return OSDK_STAT_SYS_ERR;
}
updateMissionState函数中提供飞行任务的状态信息,发布消息的类型为dji_osdk_ros::WaypointV2MissionStatePush,其中头文件的说明为:
uint16 commonDataLen
uint16 curWayPointIndex
uint8 state #0x0: ground station not start
#0x1: mission prepared
#0x2: enter mission
#0x3: execute flying route mission
#0x4:pause state
#0x5: enter misssion after ending pause
#0x6:exit mission
uint16 velocity #uint:0.01 m/s
updateMissionEvent函数中提供飞行任务事件信息,发布消息的类型为dji_osdk_ros::WaypointV2MissionEventPush,其中头文件的说明为:
uint8 event
uint32 FCTimestamp
#ID:0x01
uint8 interruptReason #0x00:rc triggered interrupt
#ID:0x02
uint8 recoverProcess #0x00: finished pause recover
#ID:0x03
uint8 finishReason #0x00:finisher normally; 0x10:External user trigger ended successfully
#ID:0x10
uint16 waypointIndex
#ID: 0x11
uint8 currentMissionExecNum
uint8 finishedAll ExecNum #0:not finished 1:finished all exec num
有了这两个消息就可以满足我程序启动和关闭的需求了,经过试验,updateMissionState函数会在无人机接收到起飞命令后就开始发布,由此可以经过判断获得无人机接到起飞命令但还没有离开地面的一个状态:
if(waypointV2MissionStatePushInfo.curWaypointIndex == 0)
{
//publish takeoff message
}
updateMissionEvent函数会在飞行到设定航点后发布对应的命令,其中事件类型为0x10时,代表无人机已经到达航点,开始到下一个航点的飞行;事件类型为0x11时,代表无人机已经结束了到下一个航点的飞行:
if(MissionEventPushAck->event == 0x10)
{
if(MissionEventPushAck->data.waypointIndex == 0)
{
//到达第一个航点
}
}
if(MissionEventPushAck->event == 0x11)
{
if(MissionEventPushAck->dagta.MissionExecEvent.finishedAllExecNum)
{
//航点结束
}
}