运动规划
概述
DJI PSDK 为满足用户对控制无人机飞行自动化的需求,提供了运动规划功能;开发者使用运动规划功能,可根据实际的使用需求设计相应的航点任务和热点任务,制定控制无人机自动化飞行的控制逻辑。
航点任务
航点规划是一个控制无人机按照指定的航线飞行,实现无人机飞行自动化的控制功能。开发者通过调用DJI PSDK 的接口,能够控制无人机以指定的高度飞往指定位置并执行相应动作,根据实际的使用需求,还可控制无人机重复多次执行指定的任务,实现自动化巡航等功能。
航点
开发者在使用航点任务时,需要指定航点数量和对应的航点类型。
- 航点数量
使用航点任务时,开发者需使用PSDK 中的API 接口指定无人机所需飞达的航点,DJI PSDK 支持开发者在一个任务中最多添加65535 个航点,至少2个航点。 - 航点类型
航点类型是指无人机在执行航点任务时,飞向该航点的方式,其中包含曲率飞行、直线飞行和协调转弯。- 曲率飞行
- 无人机以曲率连续的方式执行飞行任务时,到达指定的航点不停留。
- 无人机以曲率连续的方式执行飞行任务时,在航点处停留。
- 无人机以曲率不连续的方式执行飞行任务时,在航点处停留。
- 直线飞行
- 直线进入
- 直线退出
- 协调转弯:无人机在到达航点前提前转弯
- 曲率飞行
动作
开发者在使用航点任务时,开发者或用户可为无人机在指定的航点处添加对应的动作,如拍照、录像或悬停等。
- 动作信息
动作信息主要由动作ID、触发该动作的触发器和执行该动作的执行器组成。- 动作ID,开发者可指定全局唯一的动作ID 标识用户设置的动作。
- 触发器:触发无人机执行动作的触发器,包含触发器的类型,以及该触发类型所对应的参数。每个触发器仅支持一种触发类型。
- 执行器:执行用户指定动作的模块,包含执行器的类型和执行器的编号,以及该执行器所对应的参数。每个执行器仅支持一种执行类型
- 动作数量
DJI PSDK 支持开发者最多在一个任务中总共可添加65535 个动作。 - 动作管理:
- 支持将相机对焦变焦的动作配置到地面站中自动执行。
- 支持云台角度增量控制
- 支持配置多个云台多个相机
- 动作触发
如需在无人机执行航点任务的过程中,触发无人机执行指定的动作,需要添加触发该动作的条件:- 定时触发
- 距离触发
- 动作串行触发
- 动作并行触发
- 航点触发:无人机在航点飞行时,在第N个航点结束航点任务
速度控制
PSDK 为开发者提供了速度控制功能,能够使开发者为指定的航点配置不同的速度(为同一个航点设置多个速度),支持开发者在无人机执行航线飞行任务时,修改或查询无人机全局巡航速度。
断连控制
新增支持配置遥控器失联后继续执行航线任务的功能。
说明
- 基于PSDK 开发的应用程序在控制无人机执行任务时,用户可使用遥控器控制无人机如无人机的飞行速度、飞行高度和飞行航向等。
- 无人机每次只能执行一个自动化飞行任务,上传新的任务后,已有的飞行任务将会被覆盖。
- 在航点任务中,无人机的航点与无人机的动作没有必然关系,开发者可根据实际情况添加航点和无人机飞行时的动作。
工作流程
航点任务功能按如下流程,控制无人机执行航点任务:
- 上传航线任务的整体信息
一个航点任务包含航点任务的ID、航点任务的航点数、任务重复次数、航点任务结束后的动作、最大飞行速度和巡航速度。 - 上传航点信息
基础参数:航点坐标(设置航点的经度、纬度和相对于起飞点的高度)、航点类型、航向类型和飞行速度。
可选参数:缓冲距离、航向角度、转向模式、兴趣点、单点最大飞行速度、单点巡航速度。
说明: 仅开发者设置航点信息所有的基础参数后,才能设置航点信息的可选参数。
- 设置动作信息(可选)
设置动作的ID、触发器和执行器 - 上传无人机的航点任务的信息
- 控制无人机执行航点任务
上传无人机航点和对应的动作信息后,开发者即可通过指定的接口控制航点任务,如开始、停止或暂停任务,设置或获取巡航速度等。
使用航点任务 - Waypoint 2.0
说明: Waypoint 2.0功能目前只支持 Matrice 300 RTK 和 Matrice 350 RTK
Waypoint 2.0功能提供了上传航线任务、获取和设置巡航速度、监控航线状态和控制航线执行动作等功能。
1. 航点任务初始化
初始化航点任务的信息,向无人机飞行控制器发送航点任务的整体信息和航点信息,其中航点任务的整体信息包括无人机的巡航速度、断连控制和航点信息等;航点信息包含航点高度,航点经纬度等。
returnCode = DjiTest_WaypointV2Init();
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Init waypoint V2 sample failed, error code: 0x%08X", returnCode);
USER_LOG_INFO("Waypoint V2 sample end");
return returnCode;
}
USER_LOG_INFO("--> Step 2: Subscribe gps fused data");
DjiTest_WidgetLogAppend("--> Step 2: Subscribe gps fused data");
returnCode = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_POSITION_FUSED,
DJI_DATA_SUBSCRIPTION_TOPIC_50_HZ, NULL);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Subscribe gps fused data failed, error code: 0x%08X", returnCode);
goto out;
}
USER_LOG_INFO("--> Step 3: Register waypoint V2 event and state callback\r\n");
DjiTest_WidgetLogAppend("--> Step 3: Register waypoint V2 event and state callback\r\n");
returnCode = DjiWaypointV2_RegisterMissionEventCallback(DjiTest_WaypointV2EventCallback);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Register waypoint V2 event failed, error code: 0x%08X", returnCode);
goto out;
}
returnCode = DjiWaypointV2_RegisterMissionStateCallback(DjiTest_WaypointV2StateCallback);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Register waypoint V2 state failed, error code: 0x%08X", returnCode);
goto out;
}
osalHandler->TaskSleepMs(timeOutMs);
2. 上传航点任务
- 上传航点任务
T_DjiReturnCode returnCode;
uint16_t polygonNum = missionNum - 2;
dji_f32_t radius = 6;
uint16_t actionNum = 5;
T_DjiWayPointV2MissionSettings missionInitSettings = {0};
T_DJIWaypointV2ActionList actionList = {NULL, 0};
/*! Generate actions*/
actionList.actions = DjiTest_WaypointV2GenerateWaypointV2Actions(actionNum);
actionList.actionNum = actionNum;
/*! Init waypoint settings*/
missionInitSettings.missionID = s_missionID + 10;
USER_LOG_DEBUG("Generate mission id:%d", missionInitSettings.missionID);
missionInitSettings.repeatTimes = 1;
missionInitSettings.finishedAction = DJI_WAYPOINT_V2_FINISHED_GO_HOME;
missionInitSettings.maxFlightSpeed = 10;
missionInitSettings.autoFlightSpeed = 2;
missionInitSettings.actionWhenRcLost = DJI_WAYPOINT_V2_MISSION_KEEP_EXECUTE_WAYPOINT_V2;
missionInitSettings.gotoFirstWaypointMode = DJI_WAYPOINT_V2_MISSION_GO_TO_FIRST_WAYPOINT_MODE_POINT_TO_POINT;
missionInitSettings.mission = DjiTest_WaypointV2GeneratePolygonWaypointV2(radius, polygonNum);
missionInitSettings.missTotalLen = missionNum;
missionInitSettings.actionList = actionList;
returnCode = DjiWaypointV2_UploadMission(&missionInitSettings);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Init waypoint V2 mission setting failed, ErrorCode:0x%lX", returnCode);
return returnCode;
}
3. 控制无人机执行航点任务
- 开始执行航点任务 无人机开始执行航点任务前,将先检查用户上传的任务信息,若检查失败,无人机将无法执行航点任务,详情请查看错误码信息。
T_DjiReturnCode DjiWaypointV2_Start(void);
- 暂停执行航点任务 控制无人机暂停执行航点任务。
T_DjiReturnCode DjiWaypointV2_Pause(void);
- 恢复执行航点任务 控制无人机从暂停的位置,继续执行为完成的航点任务。
T_DjiReturnCode DjiWaypointV2_Resume(void);
- 停止执行航点任务 控制无人机停止执行航点任务。
T_DjiReturnCode DjiWaypointV2_Stop(void);
4. 设置无人机的巡航速度
设置或获取无人机在执行航点任务时的巡航速度。
- 设置巡航速度
T_DjiReturnCode DjiWaypointV2_SetGlobalCruiseSpeed(T_DjiWaypointV2GlobalCruiseSpeed cruiseSpeed);
- 获取巡航速度
T_DjiReturnCode DjiWaypointV2_GetGlobalCruiseSpeed(T_DjiWaypointV2GlobalCruiseSpeed *cruiseSpeed);
使用航点任务 - Waypoint 3.0
说明: waypoint v3.0 支持 Matrice 30 Series、Mavic 3 Enterprise Series 和 Matrice 3D/3TD 机型,不支持 Matrice 300 RTK 和 Matrice 350 RTK。
Waypoint 3.0功能提供了上传航线任务、监控航线状态和控制航线执行动作等功能。相比Waypoint 2.0,可以直接导入标准格式的KMZ文件,通用性和兼容性更好。KMZ格式请参考:航线文件格式。
1. 航点任务初始化
在使用航线任务-Waypoint 3.0功能之前,需要先调用接口DjiWaypointV3_Init
接口进行初始化操作。
returnCode = DjiWaypointV3_Init();
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Waypoint v3 init failed.");
return returnCode;
}
2. 上传航点任务
相比Waypoint 2.0复杂的航线配置,Waypoint 3.0的KMZ文件更加简单易用。用户可以通过调用DjiWaypointV3_UploadKmzFile
直接传入KMZ文件数据,执行航线任务。KMZ文件可以在DJI Pilot提前规划好航线导出。
T_DjiReturnCode DjiWaypointV3_UploadKmzFile(const uint8_t *data, uint32_t dataLen);
3. 控制无人机执行航点任务
当航线上传完成之后,即可调用DjiWaypointV3_Action
执行航线任务,包括开始、停止、暂停和继续执行航线任务。
T_DjiReturnCode DjiWaypointV3_Action(E_DjiWaypointV3Action action);
4. 监测航线状态
在用户开始执行航线任务之前,建议注册航线状态回调接口,在执行航线过程中,可以通过注册的回调函数实时接收航线状态信息,保证飞行安全。
returnCode = DjiWaypointV3_RegMissionStateCallback(DjiTest_WaypointV3StateCallback);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Register waypoint v3 state callback failed.");
goto out;
}
static T_DjiReturnCode DjiTest_WaypointV3StateCallback(T_DjiWaypointV3MissionState missionState)
{
USER_LOG_INFO("Waypoint v3 mission state: %d", missionState.state);
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}
使用兴趣点环绕任务 - POI(Point of Interest)
说明: POI 功能仅支持 Mavic 3 行业系列机型,其他机型暂不支持。
POI 功能提供了开启兴趣点环绕、关闭兴趣点环绕、设置环绕速度、监控环绕任务状态等功能。
1. 环绕任务初始化
在使用 POI 环绕任务功能之前,需要先调用接口DjiInterestPoint_Init
接口进行初始化操作。
returnCode = DjiWaypointV3_Init();
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("Waypoint v3 init failed.");
return returnCode;
}
2. 设置环绕速度
在执行环绕任务之前或者执行环绕任务中,可以调用DjiInterestPoint_SetSpeed
接口设置环绕任务的速度。
DjiInterestPoint_SetSpeed(5.0f);
3. 选择环绕点,开始环绕
选择合适的环绕点,可以调用DjiInterestPoint_Start
接口开始环绕任务,环绕的半径会根据当前飞机位置和目标点的GPS坐标自动计算得出。
interestPointSettings.latitude = 22.542812;
interestPointSettings.longitude = 113.958902;
returnCode = DjiInterestPoint_RegMissionStateCallback(DjiUser_InterestPointMissionStateCallback);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_INFO("Register mission state callback failed, errno=%lld", returnCode);
return returnCode;
}
returnCode = DjiInterestPoint_Start(interestPointSettings);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_INFO("Point interest start failed, errno=%lld", returnCode);
return returnCode;
}
4. 检测环绕状态
在用户开始执行环绕任务之前,建议注册环绕任务状态回调接口,在执行任务过程中,可以通过注册的回调函数实时接收环绕任务状态信息(环绕任务状态、环绕速度、环绕半径等),从而保证飞行安全。
returnCode = DjiInterestPoint_RegMissionStateCallback(DjiUser_InterestPointMissionStateCallback);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_INFO("Register mission state callback failed, errno=%lld", returnCode);
return returnCode;
}
5. 停止环绕
在执行环绕任务中,可以通过调用DjiInterestPoint_Stop
接口停止环绕任务。
returnCode = DjiInterestPoint_Stop();
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_INFO("Point interest stop failed, errno=%lld", returnCode);
return returnCode;
}
DjiFlightController_StartForceLanding();
returnCode = DjiInterestPoint_DeInit();
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_INFO("Point interest deinit failed, errno=%lld", returnCode);
return returnCode;
}