> 技术文档 > 无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗

无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗

目前无人机行业中多数无人机都是单人单控,主要用于航拍、巡检、农业等行业。其中大疆DJI等无人机平台已经开放了控制接口,如psdk,osdk等接口协议,我们可以加装机载智能模块并开发相关功能包通过这些sdk协议去控制无人机,可实现民用无人机群控、智能控制、任务级操控等功能。接下来对大疆psdk协议的控制开发经验进行分享。

step1:查阅DJI官网关于psdk的介绍,协议接口的了解。

https://developer.dji.com/cn/payload-sdk/
无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗
可以看到官网的标语:将算力模块、传感器、机械组件等专用负载与行业领先的飞行平台结合,开启全新市场机遇。本身开放的目的就是为了让用户可以自由开发控制无人机已有的一些功能,实现diy自动化控制。
无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗
目前psdk协议提供了很多功能接口,比如航点和飞行控制、相机和云台控制、视频数据传输、载荷控制等功能
无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗
以下是支持的开发系统和无人机平台
无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗
注意:并不是所有大疆无人机都支持,且不用飞机支持的版本不同
无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗

step2:以无人机群控为目的,以运动控制功能为例介绍如何开发智能模块程序对大疆无人机进行控制

飞行控制:

概述
使用 PSDK 的飞行器飞行控制功能,能够设置并获取飞行器各项基础参数,控制飞行器执行基础飞行动作,通过 Joystick 功能控制飞行器执行复杂的飞行动作。

#基础概念
#飞行器基础信息
PSDK 开放了设置飞行器基础参数的接口,开发者通过设置并获取飞行器的基础参数,能够实现对飞行器的精准控制:

开启或关闭 RTK 功能和避障功能(水平避障、上视觉避障、下视觉避障)
设置飞行器的返航点和返航高度
设置失控行为(Matrice 30/30T, Mavic 3 行业系列)
支持获取飞行器的国家区域码,便于产品适配不同国家的法规要求
具有信息管理 功能的应用程序,能够方便用户获取飞行器基础参数的信息:

获取 RTK 功能和避障功能的状态(水平避障、上视觉避障、下视觉避障)
获取飞行器返航点和返航高度
#飞行器基础飞行动作
飞行器的基础飞行动作主要包含飞行器锁定、飞行器起飞降落和飞行器返航三类,开发者使用 PSDK 提供的接口,即可根据实际的控制需求,控制飞行器执行指定的飞行动作。

使用飞行控制功能

使用飞行器飞行控制功能需要先初始化飞行控制模块,再设置飞行器的基础参数,最后再使用 Joystick 中的功能。

说明: 当完全脱离遥控器使用 PSDK 控制飞机时,需要通过订阅飞机端的关键数据,严格检查飞机的当前状态是否允许进行飞行控制。务必检查当前电量、返航点、失控行为、RTK 开关、避障开关等关键飞行参数。此外,还需要严格遵守当地的飞行器法规要求,如美国需要强制上报 RID 信息,否则会导致飞机阻飞,需要第三方开发者保证 RID 信息的准确性。在飞行任务过程中,需要实时监控飞行器实时的状态和告警信息,用来辅助远程驾驶员或者程序的决策,参考 “信息管理” 和 “HMS 功能” 章节。

1. 初始化飞行控制模块
在使用飞行控制功能的相关接口之前,需要先调用DjiTest_FlightControlInit 接口初始化飞行控制模块。

returnCode = DjiTest_FlightControlInit(ridInfo);if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { USER_LOG_ERROR(\"Init flight Control sample failed,error code:0x%08llX\", returnCode); return returnCode;}

2. 获取飞行器控制权
在调用飞行器控制接口之前,需要先调用DjiFlightController_ObtainJoystickCtrlAuthority 接口来获取飞行器的控制权,在飞行器控制权生效前,飞行器控制命令接口将无法生效。

returnCode = DjiFlightController_ObtainJoystickCtrlAuthority();if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { USER_LOG_ERROR(\"Obtain joystick authority failed, error code: 0x%08X\", returnCode); goto out;}s_osalHandler->TaskSleepMs(1000);

3. 获取和设置飞行器参数
在控制飞行器自动飞行之前,需要先检查和设置飞行器的相关参数,飞行控制模块提供了一系列 Set 和 Get 的接口,可以获取和设置飞行器参数,实时生效。

/*! Turn on horizontal vision avoid enable */ USER_LOG_INFO(\"--> Step 1: Turn on horizontal visual obstacle avoidance\"); DjiTest_WidgetLogAppend(\"--> Step 1: Turn on horizontal visual obstacle avoidance\"); returnCode = DjiFlightController_SetHorizontalVisualObstacleAvoidanceEnableStatus( DJI_FLIGHT_CONTROLLER_ENABLE_OBSTACLE_AVOIDANCE); if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { USER_LOG_ERROR(\"Turn on horizontal visual obstacle avoidance failed, error code: 0x%08X\", returnCode); goto out; }; s_osalHandler->TaskSleepMs(1000); USER_LOG_INFO(\"--> Step 2: Get horizontal horizontal visual obstacle status\\r\\n\"); DjiTest_WidgetLogAppend(\"--> Step 2: Get horizontal horizontal visual obstacle status\\r\\n\"); returnCode = DjiFlightController_GetHorizontalVisualObstacleAvoidanceEnableStatus( &horizontalVisualObstacleAvoidanceStatus); if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { USER_LOG_ERROR(\"Get horizontal visual obstacle avoidance failed, error code: 0x%08X\", returnCode); goto out; } USER_LOG_INFO(\"Current horizontal visual obstacle avoidance status is %d\\r\\n\",  horizontalVisualObstacleAvoidanceStatus); s_osalHandler->TaskSleepMs(1000); /*! Turn on horizontal radar avoid enable */ USER_LOG_INFO(\"--> Step 3: Turn on horizontal radar obstacle avoidance\"); DjiTest_WidgetLogAppend(\"--> Step 3: Turn on horizontal radar obstacle avoidance\"); returnCode = DjiFlightController_SetHorizontalRadarObstacleAvoidanceEnableStatus( DJI_FLIGHT_CONTROLLER_ENABLE_OBSTACLE_AVOIDANCE); if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { USER_LOG_ERROR(\"Turn on horizontal radar obstacle avoidance failed, error code: 0x%08X\", returnCode); goto out; }; s_osalHandler->TaskSleepMs(1000);

4. 控制飞行器执行基础飞行动作
开发者使用 PSDK 提供的接口,即可根据实际的控制需求,控制飞行器执行指定的飞行动作。考虑到飞行控制安全,建议通过数据订阅订阅相关的飞行器参数进行闭环检查和控制,确保飞行动作执行正确

T_DjiReturnCode djiStat;//! Start takeoffdjiStat = DjiFlightController_StartTakeoff();if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { USER_LOG_ERROR(\"Request to take off failed, error code: 0x%08X\", djiStat); return false;}//! Motors start checkif (!DjiTest_FlightControlMotorStartedCheck()) { USER_LOG_ERROR(\"Takeoff failed. Motors are not spinning.\"); return false;} else { USER_LOG_INFO(\"Motors spinning...\");}//! In air checkif (!DjiTest_FlightControlTakeOffInAirCheck()) { USER_LOG_ERROR(\"Takeoff failed. Aircraft is still on the ground, but the \"  \"motors are spinning\"); return false;} else { USER_LOG_INFO(\"Ascending...\");}//! Finished takeoff checkif (!takeoffFinishedCheck()) { USER_LOG_ERROR(\"Takeoff finished, but the aircraft is in an unexpected mode. \"  \"Please connect DJI GO.\"); return false;}

step3:动手实践一下

1)首先下载psdk协议:https://github.com/dji-sdk/Payload-SDK

里面给出了封装的控制接口函数。

(2)在对接口进行调用前,我们应选用一款机载智能平台进行程序开发,并通过相关程序对控制接口进行调用,根据官方选用指南,https://developer.dji.com/doc/payload-sdk-tutorial/cn/model-instruction/choose-develop-platform.html

本处选用了linux系统的nvdia的控制版,并安装了ROS2系统(目前此公众号分享的案例都将基于ros2开发,需要沟通开发经验的可进文章末尾的开发群)。

(3)建立一个ROS2工程,并构建几个功能包,分别为dji控制功能包,dji_msg消息功能包,平台接口模块,psdklib。
无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗

(4)dji_msg分别包括常用的ROS2中的msg、service、action等标准消息格式

图片
(4)dji控制功能包中实现机载控制功能,接收机载的一些任务、避障、智能控制等指令,并通过相关状态机或行为树对控制功能进行管理,发布消息或者服务。

首先,建立关于获取控制权、解锁、起飞的客户端

go_home_client_ = this->create_client<std_srvs::srv::Trigger>(\"psdk_ros2/start_go_home\");takeoff_client_ = this->create_client<std_srvs::srv::Trigger>(\"psdk_ros2/takeoff\");land_client_ = this->create_client<std_srvs::srv::Trigger>(\"psdk_ros2/land\");obtain_ctrl_authority_client_ = this->create_client<std_srvs::srv::Trigger>(\"psdk_ros2/obtain_ctrl_authority\"); release_ctrl_authority_client_ = this->create_client<std_srvs::srv::Trigger>(\"psdk_ros2/release_ctrl_authority\"); turn_on_motors_client_ = this->create_client<std_srvs::srv::Trigger>(\"psdk_ros2/turn_on_motors\"); turn_off_motors_client_ = this->create_client<std_srvs::srv::Trigger>(\"psdk_ros2/turn_off_motors\");

然后在控制状态机中根据实时控制状态进行服务调用

 case State::READY_TO_ARM: RCLCPP_INFO(this->get_logger(), \"Ready to arm.\"); Arm(); RCLCPP_INFO(this->get_logger(), \"Arming...\"); state_ = State::TAKEOFF; break;
void DjiAdapter::Arm() { // 发送 arm 命令 // 发送获取控制权指令请求 { auto request = std::make_shared<std_srvs::srv::Trigger::Request>(); auto future = obtain_ctrl_authority_client_->async_send_request(request); // 获取响应 if (rclcpp::spin_until_future_complete(shared_from_this(),future) == rclcpp::FutureReturnCode::SUCCESS) { auto response = future.get(); RCLCPP_INFO(this->get_logger(), \"obtain_ctrl_authority command sent Success: %d, Message: %s\", response->success, response->message.c_str()); } } // 发送 arm 命令 { auto request = std::make_shared<std_srvs::srv::Trigger::Request>(); auto future = turn_on_motors_client_->async_send_request(request); // 获取响应 if (rclcpp::spin_until_future_complete(shared_from_this(), future) == rclcpp::FutureReturnCode::SUCCESS) { auto response = future.get(); RCLCPP_INFO(this->get_logger(), \"Arm command sent Success: %d, Message: %s\", response->success, response->message.c_str()); } } }

(5)平台接口模块主要为服务端,接受到服务调用后,通过建立与sdk接口的连接进行控制。

obtain_ctrl_authority_srv_ = create_service<Trigger>( \"psdk_ros2/obtain_ctrl_authority\", std::bind(&FlightControlModule::obtain_ctrl_authority_cb, this, std::placeholders::_1, std::placeholders::_2)); release_ctrl_authority_srv_ = create_service<Trigger>( \"psdk_ros2/release_ctrl_authority\", std::bind(&FlightControlModule::release_ctrl_authority_cb, this, std::placeholders::_1, std::placeholders::_2)); turn_on_motors_srv_ = create_service<Trigger>( \"psdk_ros2/turn_on_motors\", std::bind(&FlightControlModule::turn_on_motors_cb, this, std::placeholders::_1, std::placeholders::_2));
voidFlightControlModule::turn_on_motors_cb( const std::shared_ptr<Trigger::Request> request, const std::shared_ptr<Trigger::Response> response){ (void)request; auto result = DjiFlightController_TurnOnMotors(); if (result != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { RCLCPP_ERROR(get_logger(),  \"Could not get turn ON motors. Error code is: %ld\", result); response->success = false; return; } RCLCPP_INFO(get_logger(), \"Motors have been turned ON\"); response->success = true;}

接受服务调用后,对sdk协议函数DjiFlightController_TurnOnMotors进行调用并返回调用结果,该函数由下载的psdk模块提供。

以上就是一个解锁的功能的通过机载智能模块对无人机进行控制的示例。关于无人机的群体控制和智能控制等方法,可以以这个为例进行开发,这条路通畅后可以把精力放在机载智能模块的智能算法开发上,输出的平台接口可以根据机型多开发几种,如PX4、DJI和一些其余飞机。

后期的开发经验将会继续分享,大家可关注此公众号,或者加入我的开发群共同讨论开发经验。过期可添加UavFree95
无人机开发分享——大疆无人机PSDK机载智能模块开发方法_大疆psdk可以脱离遥控器吗