DJI OSDK-flight_control_samples学习

本文档详细介绍了如何学习和使用DJI Onboard SDK(OSDK)中的flight_control_samples,包括flight_control_sample.hpp头文件,main.cpp主程序及flight_control_sample.cpp实现文件的解析和实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DJI OSDK-flight_control_samples学习

flight_control_sample.hpp

/*! @file flight_control_sample.hpp
 *  @version 3.3
 *  @date Jun 05 2017
 *
 *  @brief
 *  Flight Control API usage in a Linux environment.
 *  Provides a number of helpful additions to core API calls,
 *  especially for position control, attitude control, takeoff,
 *  landing.
 *
 *  @Copyright (c) 2016-2017 DJI
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#ifndef DJIOSDK_FLIGHTCONTROL_HPP
#define DJIOSDK_FLIGHTCONTROL_HPP

// System Includes
#include <cmath>

// DJI OSDK includes
#include "dji_status.hpp"
#include <dji_vehicle.hpp>

// Helpers
#include <dji_linux_helpers.hpp>

#define C_EARTH (double)6378137.0
#define DEG2RAD 0.01745329252

//!@note: All the default timeout parameters are for acknowledgement packets
//! from the aircraft. 所有默认超时参数均用于来自飞机的确认数据包。

/*! Monitored Takeoff
    This implementation of takeoff  with monitoring makes sure your aircraft
    actually took off and only returns when takeoff is complete.
    Use unless you want to do other stuff during takeoff - this will block
    the main thread.
!*/
bool monitoredTakeoff(DJI::OSDK::Vehicle* vehiclePtr, int timeout = 1); //声明监视起飞函数

// Examples of commonly used Flight Mode APIs

/*! Position Control. Allows you to set an offset from your current
    location. The aircraft will move to that position and stay there.
    Typical use would be as a building block in an outer loop that does not
    require many fast changes, perhaps a few-waypoint trajectory. For smoother
    transition and response you should convert your trajectory to attitude
    setpoints and use attitude control or convert to velocity setpoints
    and use velocity control.
!*/
bool moveByPositionOffset(DJI::OSDK::Vehicle *vehicle, float xOffsetDesired,  //声明位置控制函数
                          float yOffsetDesired, float zOffsetDesired,
                          float yawDesired, float posThresholdInM = 0.2,
                          float yawThresholdInDeg = 1.0);

/*! Monitored Landing (Blocking API call). Return status as well as ack.
    This version of takeoff makes sure your aircraft actually took off
    and only returns when takeoff is complete.

!*/
bool monitoredLanding(DJI::OSDK::Vehicle* vehiclePtr, int timeout = 1); //声明监视着陆函数

// Helper Functions

/*! Very simple calculation of local NED offset between two pairs of GPS
 * coordinates.
 *
 * Accurate when distances are small.
!*/
void localOffsetFromGpsOffset(DJI::OSDK::Vehicle*             vehicle,  //声明利用Gps偏移计算本地偏移的函数
                              DJI::OSDK::Telemetry::Vector3f& deltaNed,
                              void* target, void* origin);

DJI::OSDK::Telemetry::Vector3f toEulerAngle(void* quaternionData);      //声明四元数转化为欧拉角函数
bool startGlobalPositionBroadcast(DJI::OSDK::Vehicle* vehicle);         //声明全局位置广播函数


#endif // DJIOSDK_FLIGHTCONTROL_HPP

main.cpp

/*! @file flight-control/main.cpp
 *  @version 3.3
 *  @date Jun 05 2017
 *
 *  @brief
 *  main for Flight Control API usage in a Linux environment.
 *  Provides a number of helpful additions to core API calls,
 *  especially for position control, attitude control, takeoff,
 *  landing.
 *
 *  @Copyright (c) 2016-2017 DJI
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "flight_control_sample.hpp"

using namespace DJI::OSDK;
using namespace DJI::OSDK::Telemetry;

/*! main
 *
 */
int
main(int argc, char** argv)
{
   
  // Initialize variables
  int functionTimeout = 1;

  // Setup OSDK.
  LinuxSetup linuxEnvironment(argc, argv);
  Vehicle*   vehicle = linuxEnvironment.getVehicle();
  if (vehicle == NULL)
  {
   
    std::cout << "Vehicle not initialized, exiting.\n";
    return -1;
  }

  // Obtain Control Authority
  vehicle->obtainCtrlAuthority(functionTimeout);

  // Display interactive prompt
  std::cout
    << "| Available commands:                                            |"
    << std::endl;
  std::cout
    << "| [a] Monitored Takeoff + Landing                                |"
    << std::endl;
  std::cout
    << "| [b] Monitored Takeoff + Position Control + Landing             |"
    << std::endl;
  char inputChar;
  std::cin >> inputChar;

  switch (inputChar)
  {
   
    case 'a':
      monitoredTakeoff(vehicle);
      monitoredLanding(vehicle);
      break;
    case 'b':
      monitoredTakeoff(vehicle);
      moveByPositionOffset(vehicle, 0, 6, 6, 30);
      moveByPositionOffset(vehicle, 6, 0, -3, -30);
      moveByPositionOffset(vehicle, -6, -6, 0, 0);
      monitoredLanding(vehicle);
      break;
    default:
      break;
  }

  return 0;
}

flight_control_sample.cpp

/*! @file flight_control_sample.cpp
 *  @version 3.3
 *  @date Jun 05 2017
 *
 *  @brief
 *  Flight Control API usage in a Linux environment.
 *  Provides a number of helpful additions to core API calls,
 *  especially for position control, attitude control, takeoff,
 *  landing.
 *  在Linux环境中使用Flight Control API。 为核心API的调用提供了许多有用的补充,尤其是在位置控制,姿态控制,起飞,着陆方面。
 *  @Copyright (c) 2016-2017 DJI
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include "flight_control_sample.hpp"

using namespace DJI::OSDK;
using namespace DJI::OSDK::Telemetry;

/*! Monitored Takeoff (Blocking API call). Return status as well as ack.
    This version of takeoff makes sure your aircraft actually took off
    and only returns when takeoff is complete.
    Use unless you want to do other stuff during takeoff - this will block
    the main thread.
	监视起飞(阻止API调用)。返回状态以及确认。此版本的起飞确保您的飞机
	实际起飞并且仅在起飞完成后才返回。除非您要在起飞过程中做其他事情,否
	则请使用-这会阻塞主线程。
!*/
bool
monitoredTakeoff(Vehicle* vehicle, int timeout) //定义监视起飞函数,vehicle定义为一个指针,类型是Vehicle
{
   
  //@todo: remove this once the getErrorCode function signature changes
  char func[50];                                                        //声明func[50],用于存储返回的消息字符串,类型为char       
  int  pkgIndex;                                                        //声明pkgIndex,类型为int

  if (!vehicle->isM100() && !vehicle->isLegacyM600())                   //M100和M600均向后不兼容,执行if语句
  {
   
    // Telemetry: Verify the subscription                               //校验订阅
    
	ACK::ErrorCode subscribeStatus;                                     //声明订阅状态,类型为ACK::ErrorCode
    subscribeStatus = vehicle->subscribe->verify(timeout);              //verify(timeout)版本匹配的阻塞调用,返回版本匹配后的确认消息ack

    if (ACK::getError(subscribeStatus) != ACK::SUCCESS)                 //如果调用失败,通过ACK::getError()和ACK::getErrorCodeMessage()函数分析失败的
    {
                                                                      //原因,调用成功则不执行if判断
      ACK::getErrorCodeMessage(subscribeStatus, func);                  
      return false;                                                     //返回false
    }

    // Telemetry: Subscribe to flight status and mode at freq 10 Hz     //遥测:以10Hz的频率订阅飞行状态和模式这两个话题
    pkgIndex                  = 0;                                      //初始化功能包的ID,pkgIndex=0
    int       freq            = 10;                                     //初始化频率freq=10
    TopicName topicList10Hz[] = {
    TOPIC_STATUS_FLIGHT,                  //声明订阅的话题列表,TOPIC_STATUS_FLIGHT提供高达50Hz的飞机内部飞行状态。
                                  TOPIC_STATUS_DISPLAYMODE };           //TOPIC_STATUS_DISPLAYMODE提供高达50Hz的各种任务/飞行模式的精细状态表示。
    int  numTopic        = sizeof(topicList10Hz) / sizeof(topicList10Hz[0]);  //声明话题的个数为2
    bool enableTimestamp = false;                                       //不允许使用时间戳

    bool pkgStatus = vehicle->subscribe->initPackageFromTopicList(  
      pkgIndex, numTopic, topicList10Hz, enableTimestamp, freq);        //声明初始化功能包函数,返回值赋给pkgStatus
	                                                                    //initPackageFromTopicList:这是用户生成订阅功能包的最终接口。
																		//pkgIndex:将生成功能包的ID。topicList10Hz:
																		//在功能包中需要订阅的话题名称的列表返回一个bool值
    if (!(pkgStatus))                                                   //初始化成功则不执行if判断,否则执行if判断,并且返回pkgStatus的bool值
    {
   
      return pkgStatus;
    }
    subscribeStatus = vehicle->subscribe->startPackage(pkgIndex, timeout); //开始功能包的阻塞调用,返回一个ack的确认消息,并传输到subscribeStatus
    if (ACK::getError(subscribeStatus) != ACK::SUCCESS)                 //如果调用成功,则不执行if语句,调用失败,则通过ACK::getErrorCodeMessage()	                                                                   
    {
                                                                      //函数返回失败的原因
      ACK::getErrorCodeMessage(subscribeStatus, func);                 
      // Cleanup before return                                          //在返回之前清理掉调用失败的功能包
      vehicle->subscribe->removePackage(pkgIndex, timeout);             //移除功能包的非阻塞调用
      return false;
    }
  }

  // Start takeoff                                                      //开始起飞
  ACK::ErrorCode takeoffStatus = vehicle->control->takeoff(timeout);    //声明起飞状态takeoffStatus,类型是ACK::ErrorCode,
																	    //takeoff(timeout):起飞的封装函数
  if (ACK::getError(takeoffStatus) != ACK::SUCCESS)                     //如果调用失败,通过ACK::getErrorCodeMessage()来返回失败的原因
  {
   
    ACK::getErrorCodeMessage(takeoffStatus, func);                      	                                                                    
    return false;
  }

  // First check: Motors started                                        //检查电机是否启动
  int motorsNotStarted = 0;                                             //声明motorsNotStarted
  int timeoutCycles    = 20;                                            //声明周期阈值

  if (!vehicle->isM100() && !vehicle->isLegacyM600())                   //M100和M600版本都不向后兼容,则执行if语句
  {
   
    while (vehicle->subscribe->getValue<TOPIC_STATUS_FLIGHT>() !=       //飞机处于STOPPED模式
             VehicleStatus::FlightStatus::ON_GROUND &&                  // VehicleStatus::FlightStatus:STOPED = 0, ON_GROUND = 1, IN_AIR = 2 
           vehicle->subscribe->getValue<TOPIC_STATUS_DISPLAYMODE>() !=  //飞机电机没有启动
             VehicleStatus::DisplayMode::MODE_ENGINE_START &&           //MODE_ENGINE_START:电动机启动模式。 MODE_ENGINE_START = 41,
           motorsNotStarted < timeoutCycles)                            //电机启动时间小于设定的阈值
    {
   
      motorsNotStarted++;                                               //增加时间
      usleep(100000);                                                   //usleep函数能把线程挂起一段时间(0.1s),单位是微秒(千分之一毫秒)
    }

    if (motorsNotStarted == timeoutCycles)                              //时间未到达阈值,不执行
    {
   
      std::cout << "Takeoff failed. Motors are not spinning." << std::endl; //输出起飞失败,电机没有旋转
      // Cleanup                                                        //清理package
      if (!vehicle->isM100() && !vehicle->isLegacyM600())               //M100和M600版本都不向后兼容,则执行if语句
      {
   
        vehicle->subscribe->removePackage(0, timeout);                  //移除功能包0的非阻塞调用
      }
      return false;                                                     //返回false
    }
    else                                                                //飞机处于ON_GROUND模式,并且电机已经启动
    {
   
      std::cout << "Motors spinning...\n";                              //电机正在旋转
    }
  }
  else if (vehicle->isLegacyM600())                                     //M600向后兼容(M600和M100用的是广播)
  {
   
    while ((vehicle->broadcast->getStatus().flight <                    //Get Status (flight status, mode, gear and error) from local cache
            DJI::OSDK::VehicleStatus::FlightStatus::ON_GROUND) &&
           motorsNotStarted < timeoutCycles)
    {
   
      motorsNotStarted++;
      usleep(100000);
    }

    i
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值