Bootstrap

大疆OSDK-ROS 根据航点信息启动和关闭指定功能

    基于大疆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)
    {
        //航点结束
    }
}

;