当前位置: 首页 > news >正文

PSDK的编译与ROS包封装

本文档讲述在NIVIDIA开发板上使用大疆提供的Payload SDK获取无人机实时GPS信息的方法,以及基于Payload SDK发布ROS GPS话题信息的方法。

文章目录

  • 0 实现目标
  • 1 Payload SDK
    • 1.1 PSDK 源码的编译
    • 1.2 PSDK 的使用
  • 2 遥测数据的读取
    • 2.1 示例代码结构
    • 2.2 读取机载GPS信息的逻辑
    • 2.3 运行效果
  • 3 将 PSDK 源码转化为 ROS 形式
    • 3.1 文件的布局
    • 3.2 主函数的改写
    • 3.3 CMakeLists.txt的编写
  • 4 结尾
  • 参考文档

0 实现目标

在大疆Matrice 350 RTK无人机上安装E-Port 开发者套件,再通过E-Port 开发者套件连接到英伟达开发板,便可以读取当前无人机飞行时的RTK数据和GPS数据。RTK数据与GPS数据在组合导航算法中具有重要重要作用。

本文将要实现的,一是编译大疆提供的Payload SDK,来获取实时GPS数据;二是将获取的GPS信息,以ROS话题的形式,发布出来,供组合导航中其他的ROS节点使用。

1 Payload SDK

Payload 是大疆提供的,用于在M350 RTK等机型上获取无人机自带传感器设备信息的SDK,所获取的信息包括无人机姿态、GPS信息、机载图像等,其可获取的所有信息见文末参考文档中的遥测数据订阅

Payload SDK代码可以从Github上的大疆官方页下载:

git clone https://github.com/dji-sdk/Payload-SDK.git

1.1 PSDK 源码的编译

用户使用SDK进行无人机二次开发前,需要编译源码,来产生后续开发用到的相关库文件。

SDK源码的结构如下:

CMakeLists.txt  doc  EULA.txt  psdk_lib  samples  tools

psdk_lib中包括了SDK中所有库的头文件,以及不同平台下的编译器;samples是大疆官方给出的代码示例,有C和C++两种代码,包含了GPS信息获取和图像传输等功能,后续的ROS代码也是在samples的基础上进行修改的;CMakeLists.txt则是使用CMake编译源码时的编译配置文件。

下面讲述本人在英伟达开发板上的PSDK的编译历程:

首先,在PSDK源码所在的路径下创建一个build文件夹,并切换到build目录下:

XXX@YYY:~/Payload-SDK$ ls
CMakeLists.txt  doc  EULA.txt  psdk_lib  samples  tools
XXX@YYY:~/Payload-SDK$ mkdir build
XXX@YYY:~/Payload-SDK$ cd build

随后使用cmake命令生成Makefile文件:

XXX@YYY:~/Payload-SDK/build$ cmake ..

以下命令执行的结果和出现的问题:

在这里插入图片描述

什么,OPUS?想必是缺少一个库,本人不知所云,然后发邮箱求助大疆客服:

在这里插入图片描述

照着客服的引导,我在英伟达开发板上源码安装了ffmpeg 4.1.3,结果还是报了那个错误。这真的让人哭笑不得,其实这个问题只需要安装opus的库就行了:

XXX@YYY:~/Payload-SDK/build$ sudo apt-get install libopus-dev

然后就cmake成功了:

dji_sdk_demo_linux_cxx...
...
-- Configuring done
-- Generating done
-- Build files have been written to: XXX/Payload-SDK/build
XXX@YYY:~/Payload-SDK/build$ ls
bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile  samples

可以看到,build路径下生成了Makefile,那下一步当然就是使用make命令进行编译啦:

make -j24

果然没猜错,又出现了问题,该问题的简要描述为:

fatal error: opencv2/dnn.hpp: No such file or directory(opencv4)

这应该是OpenCV的版本不满足要求。但是,版本为多少才是合适的呢,后来我新安装了OpenCV 4.8,并在CMakelists.txt中添加了下面的语句:

find_package(OpenCV 4.8 REQUIRED)

安装OpenCV 4.8时的cmake命令为:

sudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local -DENABLE_PRECOMPILED_HEADERS=OFF ..

之后就会发现编译成功了。

当然啦,上述本人遇到的OpenCV问题其他读者不一定遇见,还是安装并使用OpenCV 4.9为好,这是本人咨询大疆客服获知的:

在这里插入图片描述

好了,现在应该在自己的开发板上能看到对应的库了:

XXX@YYY:~$ ls /usr/local/lib
cmake                        libopencv_features2d.so.4.8.0  libopencv_imgproc.so          libopencv_stitching.so.408   libopencv_flann.so             libopencv_imgproc.so.408      libopencv_stitching.so.4.8.0
libopencv_calib3d.so         libopencv_flann.so.408         libopencv_imgproc.so.4.8.0    libopencv_videoio.so
libopencv_calib3d.so.408     libopencv_flann.so.4.8.0       libopencv_ml.so               libopencv_videoio.so.408
libopencv_calib3d.so.4.8.0   libopencv_gapi.so              libopencv_ml.so.408           libopencv_videoio.so.4.8.0   libopencv_core.so              libopencv_gapi.so.408          libopencv_ml.so.4.8.0        libopencv_video.so
libopencv_core.so.408        libopencv_gapi.so.4.8.0        libopencv_objdetect.so        libopencv_video.so.408
libopencv_core.so.4.8.0      libopencv_highgui.so           libopencv_objdetect.so.408    libopencv_video.so.4.8.0     libopencv_dnn.so               libopencv_highgui.so.408       libopencv_objdetect.so.4.8.0  								 libopus.a
libopencv_dnn.so.408         libopencv_highgui.so.4.8.0     libopencv_photo.so            
libopencv_dnn.so.4.8.0       libopencv_imgcodecs.so         libopencv_photo.so.408       
libopencv_features2d.so      libopencv_imgcodecs.so.408     libopencv_photo.so.4.8.0      python2.7
libopencv_features2d.so.408  libopencv_imgcodecs.so.4.8.0   libopencv_stitching.so        python3.8

好了,总算把编译的问题彻底解决了。

1.2 PSDK 的使用

开始运行程序前,需要解决E-Port 开发者套件与英伟达开发板之间的连接问题,在大疆开发者社区里,本人发现了以下信息:

在这里插入图片描述

建议把”推荐“去掉,本人一开始使用的普通的TTL串口线,没使用FT232串口,以为能直接获取到GPS信息,结果屡次插拔串口线都未能如愿,这才着重注意到了这一句话。害,官方未能着重突出这条信息,就真只能多走弯路。

在运行程序之前,还需使用大疆官方的上位机来设置信息传输的相关参数(包括传输的波特率),详细的方法见参考文档【1】。

这下可以开始运行程序看看效果了,先找出编译成功的可执行文件dji_sdk_demo_linux,这个文件在编译好的文件目录bin中:

shallwing@9d57f9229b66:~/Payload-SDK/build$ ls
bin  CMakeCache.txt  CMakeFiles  cmake_install.cmake  Makefile  samples
shallwing@9d57f9229b66:~/Payload-SDK/build$ cd bin
shallwing@9d57f9229b66:~/Payload-SDK/build/bin$ ls
dji_sdk_demo_linux  dji_sdk_demo_linux_cxx
shallwing@9d57f9229b66:~/Payload-SDK/build/bin$ sudo ./dji_sdk_demo_linux

两个可执行文件里面,dji_sdk_demo_linux是C程序编译生成的,dji_sdk_demo_linux_cxx则是C++程序编译生成的。本人先运行了dji_sdk_demo_linux,然后报了下面的错误:

XXX@YYY:$ sudo ./dji_sdk_demo_linux
'Logs/latest.log' -> 'DJI_0001_20241220_00-22-55.log'
[0.004][user]-[Error]-[DjiUser_FillInUserInfo:578) Please fill in correct user information to 'samples/sample_c/platform/linux/manifold2/application/dji_sdk_app_info.h' file. 

破案了,大疆这是需要每个使用其SDK的开发者要填写自己的相关信息啊。好吧,那就在大疆官网上注册信息,网上搜了一下注册的方法,注册成功之后,便填写文件samples/sample_c/platform/linux/manifold2/application/dji_sdk_app_info.h中的信息:

/* Exported constants --------------------------------------------------------*/
// ATTENTION: User must goto https://developer.dji.com/user/apps/#all to create your own dji sdk application, get dji sdk        application
// information then fill in the application information here.
#define USER_APP_NAME               "your_app_name"
#define USER_APP_ID                 "your_app_id"
#define USER_APP_KEY                "your_app_key"
#define USER_APP_LICENSE            "your_app_license"
#define USER_DEVELOPER_ACCOUNT      "your_developer_account"
#define USER_BAUD_RATE              "460800"

请注意,这里的USER_BAUD_RATE 一定需要与上位机中设置的波特率保持一直。

填写完了,再次运行,终端打印的信息如下图:

在这里插入图片描述

“Waiting payload negotiate finish”?,这是什么问题,去网上找了很多帖子,包括大疆开发社区,都没有与此问题详细的解决方案。算了,还是问客服来得快一点:

在这里插入图片描述

果然解铃还需系铃人啊,问题交到PSDK的作者们手中一下就解决了,那就找到这个dji_sdk_config.h文件,然后修改CONFIG_HARDWARE_CONNECTION宏的内容吧。

dji_sdk_config.h在PSDK中的位置为:

Payload-SDK/samples/sample_c/platform/linux/manifold2/application

找到的这个宏定义:

/* Exported constants --------------------------------------------------------*/
#define DJI_USE_ONLY_UART                  (0)
#define DJI_USE_UART_AND_USB_BULK_DEVICE   (1)
#define DJI_USE_UART_AND_NETWORK_DEVICE    (2)/*!< Attention: Select your hardware connection mode here.
* */
#define CONFIG_HARDWARE_CONNECTION         DJI_USE_UART_AND_NETWORK_DEVICE

将其中的DJI_USE_UART_AND_NETWORK_DEVICE修改为DJI_USE_ONLY_UART,随后运行就正常了。好了,demo程序的运行没有问题了,下面就可以开始深入了解demo源码的含义,来自己编写代码获取想要的信息了。

2 遥测数据的读取

本章节以C++程序为例,讲述如何在main函数中订阅读取GPS信息和RTK信息。

2.1 示例代码结构

PSDK源码中给出的C++代码结构如下:

├── module_sample
│   ├── camera_manager
│   ├── flight_controller
│   ├── gimbal
│   ├── hms_manager
│   ├── liveview
│   └── perception
└── platform└── linux├── common├── manifold2│   ├── application│   │   ├── application.cpp│   │   ├── application.hpp│   │   ├── dji_sdk_app_info.h│   │   ├── dji_sdk_config.h│   │   ├── dji_sdk_config.json│   │   └── main.cpp│   ├── CMakeLists.txt│   └── hal└── nvidia_jetson

可以看到,代码分为机载传感器模块代码,和主函数实现的代码,其中传感器模块代码实现了每个传感器数据接收的功能,这包括机载相机管理、飞行控制、云台控制(gimal)健康管理系统(HMS)实时视频流(liveview)、**视觉图像(perception)**等。

通过多次阅读PSDK的C++源码,可以得知,C++源码调用了C代码中的部分代码,这个发现影响了下一章节将PSDK源码改写为ROS代码的工作。

2.2 读取机载GPS信息的逻辑

先给出本人改写后的GPS信息和RTK信息的订阅代码:

int main(int argc, char **argv)
{Application application(argc, argv);T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();T_DjiReturnCode returnCode;T_DjiDataTimestamp timestamp = {0};T_DjiFcSubscriptionRtkPosition data = {0};T_DjiFcSubscriptionGpsPosition postion = {0};returnCode = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_RTK_POSITION, \DJI_DATA_SUBSCRIPTION_TOPIC_1_HZ, NULL);if(returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS)USER_LOG_ERROR("Subscribe RTK topic error.\n");elseprintf("Subscribe RTK topic success.\n");returnCode = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_POSITION, \DJI_DATA_SUBSCRIPTION_TOPIC_1_HZ, NULL);if(returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS)USER_LOG_ERROR("Subscribe GPS topic error.\n");elseprintf("Subscribe GPS topic success.\n");while (true) {returnCode = DjiFcSubscription_GetLatestValueOfTopic(DJI_FC_SUBSCRIPTION_TOPIC_RTK_POSITION, (uint8_t *)&data, sizeof(T_DjiFcSubscriptionRtkPosition), &timestamp);printf("microstamp == %u\n", timestamp.microsecond);printf("millistamp == %u\n", timestamp.millisecond);printf("longitude == %lf\n", data.longitude);printf("latitude == %lf\n", data.latitude);printf("hfsl == %lf\n", data.hfsl);returnCode = DjiFcSubscription_GetLatestValueOfTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_POSITION, (uint8_t *)&postion, sizeof(T_DjiFcSubscriptionGpsPosition), &timestamp);printf("GPS X == %d\n", postion.x);printf("GPS Y == %d\n", postion.y);printf("GPS Z == %d\n\n", postion.z);osalHandler->TaskSleepMs(2000);}return 0;
}

首先,程序需要创建一个Application,这个Application是一个类,当Application类创建时会调用相应的构造函数来创建一个Dji应用程序核心,这个核心与ROS核心类似。可以推测出,大疆对机载传感器的管理借鉴了ROS中传感器节点的管理方法,即将每一个传感器节点看作一个应用线程。若要了解更多与Application有关的信息,请直接阅读源码。

之后,程序开始定义各种后续需要使用的变量,其中T_DjiOsalHandler是一个**操作系统抽象层(Opertating System Level)**类,这个类用于实现与不同操作系统之间的兼容,本人在代码中使用了其延时的函数。

T_DjiDataTimestamp, T_DjiFcSubscriptionRtkPosition, T_DjiFcSubscriptionGpsPosition分别记录了时间戳、RTK和GPS信息,而此处的时间戳是指的程序启动到当前的运行时间间隔,并非是UNIX时间戳。很遗憾,大疆官方并没有在源码的头文件里面告诉大家后两个结构体中的详细成员,但是我们可以从源码文件sample_c/module_sample/fc_subscription/test_fc_subscription.c中窥视出其中些许的信息。

test_fc_subscription.c中的第152至第175行中,给出了FC话题订阅的方法,我们可以运用该示例代码,来实现GPS信息的订阅:

djiStat = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_POSITION,DJI_DATA_SUBSCRIPTION_TOPIC_1_HZ,NULL);if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {USER_LOG_ERROR("Subscribe topic gps position error.");return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;} 
djiStat = DjiFcSubscription_GetLatestValueOfTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_POSITION,(uint8_t *) &gpsPosition,sizeof(T_DjiFcSubscriptionGpsPosition),&timestamp);if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {USER_LOG_ERROR("get value of topic gps position error.");} else {USER_LOG_INFO("gps position: x = %d y = %d z = %d.", gpsPosition.x, gpsPosition.y, gpsPosition.z);}   

可以看到,GPS具有X,Y,Z三个信息,其中X表示经度(Longitude),Y表示纬度(Latitude),Z代表海拔高度。RTK与GPS的信息类似。PSDK中任何机载传感器的遥测数据都通过FC话题进行发布与订阅,订阅FC话题的函数为**DjiFcSubscription_SubscribeTopic,函数的第一个参数决定了遥测数据的类型,是一个宏,所有遥测数据及其对应的宏见参考文档中的遥测数据订阅;第二个参数则用于指定消息获取的频率,也是一个宏,本人在代码中设为了1HZ。通过订阅函数指定订阅话题之后,便可以使用DjiFcSubscription_GetLatestValueOfTopic函数来获取话题消息中的信息值,该函数的第一个参数和订阅函数一样,都是遥测数据对应的宏,第二个参数则是GPS结构体T_DjiFcSubscriptionGpsPosition对应的对象的地址;当使用DjiFcSubscription_GetLatestValueOfTopic**函数获取到GPS信息之后,便可以在GPS结构体对象gpsPosition中读取其GPS信息,

2.3 运行效果

以下是在英伟达开发板上的运行效果,供读者参考:

在这里插入图片描述
至此,读取机载GPS信息的逻辑介绍完毕。

3 将 PSDK 源码转化为 ROS 形式

在一般的项目中,通常是使用ROS来实现传感器数据的收集与管理,大疆无人机在使用时也是这样,本章节讲述如何将原始PSDK改写为ROS包。

3.1 文件的布局

一个PSDK中各个模块功能的实现需要多个头文件,以及头文件中定义的函数的C文件组成,因此,在ROS包下的应该具有这些头文件和C文件,把所有头文件放在ROS中的include文件夹中,并将所有.c文件放在src文件夹中。本人整理好的文件结构如下:

XXX@YYY:~/dji_ros/src/include$ ls
application.hpp     dji_sdk_config.h     gimbal          interest_point    utils
camera_emu          dji_sdk_config.json  gimbal_emu      liveview          waypoint_v2
camera_manager      fc_subscription      gimbal_manager  osal              waypoint_v3
data_transmission   flight_control       hms             perception        widget
dji_sdk_app_info.h  flight_controller    hms_manager     power_management  widget_interaction_test

以下是src的结构:

XXX@YYY:~/dji_ros/src/src$ ls
application.cpp      fc_subscription    gimbal_manager  liveview               positioning       widget
camera_emu           flight_control     hal             main.cpp               power_management  widget_interaction_test
camera_manager       flight_controller  hms             osal                   utils
data_transmission    gimbal             hms_manager     payload_collaboration  waypoint_v2
dji_sdk_config.json  gimbal_emu         interest_point  perception             waypoint_v3

好了,绝对会有人告诉我这是如何整理的。没有什么技巧,全靠蛮干,哈哈哈哈,就是把PSDK下sample_c和sample_c++的所有.c文件和.cpp文件全部整理好放在include和src文件里面就好了,慢慢来吧,不要心急,慢工出细活,哈哈哈哈。

3.2 主函数的改写

因为是ROS是基于C++或Python语言进行开发的,所以主函数应该选择PSDK中的main.cpp。修改main.cpp的方法也很简单,只需要把GPS的信息对应发布到消息类型为sensor_msgs/NatSatFix的话题中。

本人修改的地方主要集中在While死循环里:

#include <ros/ros.h>
#include <sensor_msgs/NavSatFix.h>//......ros::init(argc, argv, "dji_ros_gps");ros::NodeHandle nh;sensor_msgs::NavSatFix      msg_gps, msg_rtk;ros::Publisher pub_rtk = nh.advertise<sensor_msgs::NavSatFix>("/dji_ros/rtk_info",10);ros::Publisher pub_gps = nh.advertise<sensor_msgs::NavSatFix>("/dji_ros/gps_info",10);while(1){//......msg_gps.header.stamp = ros::Time::now();msg_gps.header.frame_id = "DJI-GPS";msg_gps.status.status = sensor_msgs::NavSatStatus::STATUS_FIX;msg_gps.status.service = sensor_msgs::NavSatStatus::SERVICE_GPS;msg_gps.latitude = postion.x;msg_gps.longitude = postion.y;msg_gps.altitude = postion.z;msg_rtk.header.stamp = ros::Time::now();msg_rtk.header.frame_id = "DJI-RTK";msg_rtk.status.status = sensor_msgs::NavSatStatus::STATUS_FIX;msg_rtk.status.service = sensor_msgs::NavSatStatus::SERVICE_GPS;msg_rtk.latitude = data.latitude;msg_rtk.longitude = data.longitude;msg_rtk.altitude = data.hfsl;pub_rtk.publish(msg_rtk);     pub_gps.publish(msg_gps);ROS_INFO("longitude == %lf, latitude == %lf, hfsl == %lf, GPS X == %d, GPS Y == %d, GPS Z == %d", \data.longitude, data.latitude, data.hfsl, postion.x, postion.y, postion.z);r.sleep();ros::spinOnce();}

NatSatFix是一个与地理坐标有关的消息类型,ROS官方给出的NatSatFix信息很齐全:

在这里插入图片描述

sensor_msgs是ROS中一个最重要的消息大类,除了NatSatFix之外,还有IMU、CameraInfo、Image等,它包含了当前常用传感器的数据类型定义。

3.3 CMakeLists.txt的编写

到了全文档中最难解决的部分了,CMakeLists.txt是全ROS包中最关键的文档,在这个文档里,我们需要添加源码的包含目录,使之能正常编译不报出undefined reference XXX的错误。最终形成的CMakeLists.txt如下:

cmake_minimum_required(VERSION 3.0.2)
project(dji_ros)find_package(catkin REQUIRED COMPONENTSnav_msgsroscppsensor_msgsstd_msgs
)aux_source_directory(./src SRC_LIST)
aux_source_directory(./src/fc_subscription SRC_LIST)
aux_source_directory(./src/hal SRC_LIST)
aux_source_directory(./src/data_transmission SRC_LIST)
aux_source_directory(./src/camera_manager SRC_LIST)
#aux_source_directory(./src/flight_controller SRC_LIST)
aux_source_directory(./src/gimbal SRC_LIST)
aux_source_directory(./src/hms_manager SRC_LIST)
aux_source_directory(./src/liveview SRC_LIST)
aux_source_directory(./src/perception SRC_LIST)
aux_source_directory(./src/osal SRC_LIST)
aux_source_directory(./src/utils SRC_LIST)
aux_source_directory(./src/flight_control SRC_LIST)
aux_source_directory(./src/gimbal_manager SRC_LIST)
aux_source_directory(./src/gimbal SRC_LIST)
aux_source_directory(./src/hms SRC_LIST)
aux_source_directory(./src/hms_manager SRC_LIST)
aux_source_directory(./src/waypoint_v2 SRC_LIST)
aux_source_directory(./src/waypoint_v3 SRC_LIST)
aux_source_directory(./src/widget SRC_LIST)
aux_source_directory(./src/widget_interaction_test SRC_LIST)
aux_source_directory(./src/interest_point SRC_LIST)
aux_source_directory(./src/power_management SRC_LIST)include_directories(${catkin_INCLUDE_DIRS}${CMAKE_CURRENT_SOURCE_DIR}/src
)add_executable(dji_nav ${SRC_LIST})target_link_libraries(dji_nav${catkin_LIBRARIES}mpayloadsdkpthread
)catkin_package(INCLUDE_DIRS includeLIBRARIES dji_rosCATKIN_DEPENDS roscpp sensor_msgs std_msgs
)

aux_source_directory是Cmake中用来递归添加文件的命令,通过这个命令,我们可以省去一些繁琐的步骤,只需要把先前展示的include中所有文件夹的内容添加上去即可。

4 结尾

大疆不是没有给出过类似的ROS包,在OSDK中就有官方自己编写的ROS代码——Onboard-SDK-ROS,本人在PSDK中的工作,只能算对OSDK-ROS的拙劣模仿吧,哈哈哈哈。

好了,本文到这里也就讲完了所有文件的编辑方法,后续经过catkin_make编译之后,只需要运行rosrun dji_ros dji_nav命令就可以启动GPS信息的话题发布节点,发布的话题消息在dji_ros/rtk_infodji_ros/gps_info中。本文在实现ROS包的过程中还是留有遗憾,因为时间较为紧张,项目急需要交付,所以flight_controller部分的代码没有编译(catkin_make编译是屡次报出"undefined reference XXX"的错误),这也是后续需要改进的地方吧,本文只是简简单单实现一个GPS ROS话题消息发布的功能,并记录一下自己的心路历程。

最后还是插一句话:果然,大疆客服在我屡次发邮件问问题之后,解答问题的速度加快了,哈哈哈哈

参考文档

【0】Payload SDK

PSDK详细介绍

【1】E-Port 开发者套件

飞行器硬件连接

PSDK各机型连接

【2】PSDK数据的订阅

遥测数据订阅

PSDK中如何订阅数据?

【3】拓展阅读

时间同步

PSDK各机型连接

飞行器硬件连接

PSDK各机型连接

【2】PSDK数据的订阅

遥测数据订阅

PSDK中如何订阅数据?

【3】拓展阅读

时间同步

NatSatFix数据类型

相关文章:

PSDK的编译与ROS包封装

本文档讲述在NIVIDIA开发板上使用大疆提供的Payload SDK获取无人机实时GPS信息的方法&#xff0c;以及基于Payload SDK发布ROS GPS话题信息的方法。 文章目录 0 实现目标1 Payload SDK1.1 PSDK 源码的编译1.2 PSDK 的使用 2 遥测数据的读取2.1 示例代码结构2.2 读取机载GPS信息…...

【工作流】工作顺序

背景 当时的情况是&#xff1a;没有产品经理&#xff0c;后端直接和需求方对接&#xff1b;前端只能短时间投入大部分时间要忙别的&#xff1b;只有3个角色&#xff1a;需求方&#xff0c;后端&#xff0c;前端&#xff1b; 当时直接执行的 直接使用会议了解需求&#xff0c…...

Unity2021.3.16f1可以正常打开,但是Unity2017.3.0f3却常常打开闪退或者Unity2017编辑器运行起来就闪退掉

遇到问题&#xff1a; 从今年开始&#xff0c;不知道咋回事&#xff0c;电脑上的Unity2017像是变了个人似得&#xff0c;突然特别爱闪退掉&#xff0c;有时候还次次闪退&#xff0c;真是让人无语&#xff0c;一直以来我都怀疑是不是电脑上安装了什么别的软件了&#xff0c;导致…...

Java基础面试题20:Java语言sendRedirect()和forward()方法有什么区别?

Java基础面试题&#xff1a;Java语言sendRedirect()和forward()方法有什么区别&#xff1f; 在 Java Web 开发中&#xff0c;sendRedirect() 和 forward() 是两个非常常用的方法&#xff0c;但它们有一些核心区别。我们来用最简单的方式给你解释清楚。 一、sendRedirect() 和 …...

2、光同步数字传送网的特点

同步复用 光同步数字传送网&#xff08;SDH&#xff09;采用同步复用方式。它将多个低速信号复用成高速信号&#xff0c;与准同步数字体系&#xff08;PDH&#xff09;的异步复用不同。在 SDH 中&#xff0c;各支路信号与复用后的高速信号是同步的&#xff0c;这种同步复用的方…...

3.4 stm32系列:定时器(PWM、定时中断)

一、定时器概述 1.1 软件定时原理 使用纯软件&#xff08;CPU死等&#xff09;的方式实现定时&#xff08;延时&#xff09;功能&#xff1b; 不精准的延迟&#xff1a; /* 微秒级延迟函数* 不精准* stm32存在压出栈过程需要消耗时间* 存在流水线&#xff0c;执行时间不确定…...

【环境搭建】Python、PyTorch与cuda的版本对应表

一个愿意伫立在巨人肩膀上的农民...... 在深度学习的世界里&#xff0c;选择合适的工具版本是项目成功的关键。CUDA、PyTorch和Python作为深度学习的三大支柱&#xff0c;它们的版本匹配问题不容忽视。错误的版本组合可能导致兼容性问题、性能下降甚至项目失败。因此&#xff0…...

【经验总结】AUTOSAR架构下基于TJA1145收发器偶发通信丢失不可恢复问题分析

目录 前言 正文 1.问题描述 2.尝试问题复现 3.尝试问题定位 4.直接原因 5.总结 前言 在《【CAN通信】TJA1145收发器重要功能介绍》一文中我们详细介绍了TJA1145收发器的重点内容,最近在开发测试过程中就遇到了一个CAN通信丢失且不可恢复的偶发问题,解决该问题的思路和…...

帝国CMS:如何去掉帝国CMS登录界面的认证码登录

如果在安装的时候&#xff0c;不小心选中了认证码选项&#xff0c;那么后面登录帝国后台都会要求输入认证码才能登录&#xff0c;如何去除这个设置呢&#xff0c;笔者以古诗词网 www.gushichi.com为例&#xff0c;为大家举例说明&#xff01; 去除步骤如下&#xff1a; 1.前往…...

CTF入门:单主机渗透——flag_XEE的常规思路

学习通过技术手段获取目标主机中预置的5个flag值。 在kali操作机中打开终端&#xff0c;然后使用nmap工具对目标机器进行端口扫描&#xff1a; nmap -sT 192.168.12.26 访问80端口。 网站首页是一个登录框&#xff0c;在界面上有一个提示的标签“弱口令”&#xff0c;说…...

Note2024122303_Code2Docu插件使用

Note2024122303_Code2Docu插件初使用V1.0 step1: 安装 跳转链接 文档阅读&#xff1a;下载文档阅读。 根据文档内容&#xff0c;大概知道首先下载并安装插件&#xff1a; 资料说明和安装方式&#xff1a; 意思是&#xff1a; 下载文件后直接运行 Code2Docu_Installati…...

深度学习之目标检测篇——残差网络与FPN结合

特征金字塔多尺度融合特征金字塔的网络原理 这里是基于resnet网络与Fpn做的结合&#xff0c;主要把resnet中的特征层利用FPN的思想一起结合&#xff0c;实现resnet_fpn。增强目标检测backone的有效性。代码实现如下&#xff1a; import torch from torch import Tensor from c…...

共模电感的工作原理

共模电感也称为共模扼流线圈&#xff0c;是一种抑制共模干扰的器件&#xff0c;它是由两个尺寸相同&#xff0c;匝数相同的线圈对称地绕制在同一个铁氧体环形磁芯上&#xff0c;形成的一个四端器件。当共模电流流过共模电感时&#xff0c;磁芯上的两个线圈产生的磁通相互叠加&a…...

mysql高阶语句

mysql高阶语句 1.对结果排序 SELECT id,name,score FROM info; #由于对id设置了主键约束&#xff0c;默认排序按id的大小升序排序 select name,score from info order by score; #默认按升序&#xff08;从小到大排序&#xff09; select name,score from info order by score…...

sfnt-pingpong -测试网络性能和延迟的工具

sfnt-pingpong 是一个用于测试网络性能和延迟的工具&#xff0c;通常用于测量不同网络环境下的数据包传输性能、吞吐量、延迟等指标。 它通常是基于某种网络协议&#xff08;如 TCP&#xff09;执行“ping-pong”式的测试&#xff0c;即客户端和服务器之间相互发送数据包&…...

PostgreSQL 的历史

title: PostgreSQL 的历史 date: 2024/12/23 updated: 2024/12/23 author: cmdragon excerpt: PostgreSQL 是一款功能强大且广泛使用的开源关系型数据库管理系统。其历史可以追溯到1986年,当时由加州大学伯克利分校的一个研究团队开发。文章将深入探讨 PostgreSQL 的起源、…...

【express-generator】01-安装和基本使用

创建和初始化项目 安装 npm i -g express-generator 创建一个express应用程序 //express 文件名 express blog_demo 跟着提示 cd blog_demo //移动到该目录下 npm install //初始化 npm start //启动服务 在页面打开localhost:3000&#xff08;默认启动的端口&#xff09…...

20241230 基础数学-线性代数-(1)求解特征值(numpy, scipy)

所有代码实现&#xff0c;基于教程中的理论通过python实现出来的。效率不高&#xff0c;但有代码可以看。 由于scipy/sckitlearn/sparkx 底层的实现都被封装了&#xff08;小白兔水平有限&#xff0c;fortran代码实在没看懂&#xff09;这里的实现至少可以和理论公式对应的上。…...

无人零售 4G 工业无线路由器赋能自助贩卖机高效运营

工业4G路由器为运营商赋予 “千里眼”&#xff0c;实现对贩卖机销售、库存、设备状态的远程精准监控&#xff0c;便于及时补货与维护&#xff1b;凭借强大的数据实时传输&#xff0c;助力深度洞察销售趋势、优化库存、挖掘商机&#xff1b;还能远程升级、保障交易安全、快速处理…...

python+opencv+棋盘格实现相机标定及相对位姿估计

pythonopencv棋盘格实现相机标定及相对位姿估计 引言1&#xff0c;使用相机采集含棋盘格图像14张2&#xff0c;进行相机标定&#xff08;1&#xff09;测试软件1标定结果&#xff08;内参及畸变系数&#xff09;&#xff08;2&#xff09;测试软件2标定结果&#xff08;内参及畸…...

【YashanDB知识库】in大量参数时查询性能慢

本文内容来自YashanDB官网&#xff0c;原文内容请见 https://www.yashandb.com/newsinfo/7802939.html?templateId1718516 **【标题】**in大量参数时查询性能慢 **【关键字】**in 大量参数 FAST FULL SCAN INDEX RANGE SCAN **【问题描述】**测试表数据量200w&#xff0c;表…...

kubevirt网络

六、KubeVirt网络 KubeVirt网络相关组件 用户在KubeVirt平台创建虚拟机只需创建一个vmi&#xff08;Virtual Machine Instance&#xff09;对象&#xff0c;之后virt-controller会根据vmi对象中的信息创建一个Pod&#xff0c;这里把这个Pod叫做vmi pod。Vmi pod中有kubevirt组…...

LeetCode100之腐烂的橘子(994)--Java

1.问题描述 在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b;值 1 代表新鲜橘子&#xff1b;值 2 代表腐烂的橘子。 每分钟&#xff0c;腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。 返回 直到单元…...

【Leetcode】855. 考场就座

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 在考场里&#xff0c;有 n n n 个座位排成一行&#xff0c;编号为 0 0 0 到 n − 1 n - 1 n−1。 当学生进入考场后&#xff0c;他必须坐在离最近的人最远的座位上。如果有多个…...

AI,cursor快速上手思维导图

https://cursor101.com/zh/tutorial/learn-cursor-tab...

【演化博弈】期望收益函数公式、复制动态方程——化简功能技巧

期望化简 在演化博弈论的研究中&#xff0c;期望收益函数和复制动态方程是核心工具。化简这些公式的功能技巧具有以下几个重要作用&#xff1a; 提高公式的可读性和理解度 复杂的数学表达式可能让人感到困惑。通过化简&#xff0c;公式变得更加简单和易读&#xff0c;使研究者…...

常用Linux命令

常用Linux命令介绍 1.ls命令用于列出当前目录的内容&#xff0c;包括目录、文件和压缩包等。 2.ls命令的参数可以以长格式显示文件信息&#xff0c;如修改时间、文件大小等。 3.使用ls -a参数可以显示隐藏文件和文件夹。 4.通过ls -lh命令可以以人类可读的方式显示文件和文件夹…...

记录树莓派4B安装向日葵的过程

到向日葵官网下载向日葵 for Linux的麒麟Arm64版本&#xff1b;sudo dpkg -i 文件名.deb 安装&#xff1b;安装依赖&#xff1a; sudo apt install libappindicator3-1 如果没有的话就使用&#xff1a; sudo apt install libayatana-appindicator3-1 关闭wayvnc服务及其自启动…...

模型 课题分离

系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。明确自我与他人责任。 1 课题分离的应用 1.1课题分离在心理治疗中的应用案例&#xff1a;李晓的故事 李晓&#xff0c;一位28岁的软件工程师&#xff0c;在北京打拼。他面临着工作、家庭和感情的多重…...

docker部署微信小程序自动构建发布和更新

通过 Jenkins 和 Docker 部署微信小程序&#xff0c;并实现自动构建、发布和版本更新&#xff0c;主要涉及以下几个步骤&#xff1a; 设置 Jenkins 环境配置 GitLab 与 Jenkins 的集成构建 Docker 镜像部署和发布微信小程序配置 Jenkins 自动构建 以下是详细的步骤说明&#…...

0.96寸OLED显示屏详解

我们之前讲了 LCD1602&#xff0c;今天我们将它的进阶模块——OLED。它接线更少&#xff0c;性能更强&#xff0c;也能显示中文和图像了。 大家在学习单片机的时候是否会遇到调试的问题呢&#xff1f;例如 “这串代码我到底运行成功了没有” &#xff0c;我相信很多刚开始学习…...

【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】

本教程的知识点为&#xff1a;操作系统 1. 常见的操作系统 4. 小结 ls命令选项 2. 小结 mkdir和rm命令选项 1. mkdir命令选项 压缩和解压缩命令 1. 压缩格式的介绍 2. tar命令及选项的使用 3. zip和unzip命令及选项的使用 4. 小结 编辑器 vim 1. vim 的介绍 2. vim 的工作模式 …...

H3C AC_AP基本配置流程

前置摘要 AP管理地址:10.115.8.0/ AP业务地址:10.115.10.0 SSID qdtest passwd 123chery map.txt system-view vlan 1010 quit interface GigabitEthernet 1/0/1 port link-type trunk port trunk permit vlan 1010AC配置 vlan 1008 des Ap_manager quit int vlan 1008 ip ad…...

准备写一个内网穿透的工具

准备写一个内网穿透的工具&#xff0c;目前只实现了HTTP内网穿透的GET方式&#xff0c;看能不能坚持写下去 git地址&#xff1a; xuejiazhi/PortRelay...

模型高效微调方式

除了LoRA&#xff08;Low-Rank Adaptation&#xff09;外&#xff0c;还有其他一些快速且效果好的模型微调方法。这些方法可以在保持模型性能的同时&#xff0c;减少计算和存储需求。以下是几种常见的方法&#xff1a; 1. 参数高效微调&#xff08;Parameter-Efficient Fine-T…...

Linux系统编程——理解系统内核中的信号捕获

目录 一、sigaction() 使用 信号捕捉技巧 二、可重入函数 三、volatile关键字 四、SIGCHLD信号 在信号这一篇中我们已经学习到了一种信号捕捉的调用接口&#xff1a;signal(),为了深入理解操作系统内核中的信号捕获机制&#xff0c;我们今天再来看一个接口&#xff1a;si…...

ISP算法之BNR降噪(Bayer域)

概述 BNR&#xff08;Bayer Noise Reduction&#xff09;即Bayer域降噪算法。对于噪声的分类如下表所示&#xff1a; 高斯噪声&#xff08; Gaussian&#xff09; 高斯噪声也被称为热噪声&#xff0c;通常是由于电路系统中自由电子的热运动&#xff0c;这种噪声幅度分布服从高…...

HBuilder快捷键大全

目录 一、最常用快捷键 二、文件操作快捷键 三、选择操作快捷键 四、插入操作快捷键 五、编辑操作快捷键 六、删除操作快捷键 七、查找操作快捷键 八、标签规范快捷键 八、运行操作快捷键 九、转换操作快捷键 十、跳转操作快捷键 十一、附加功能快捷键 十二、快捷键…...

Diffusion_Policy项目测试报错记录

1、项目连接 paper&#xff1a;2303.04137 (arxiv.org) github: real-stanford/diffusion_policy: [RSS 2023] Diffusion Policy Visuomotor Policy Learning via Action Diffusion (github.com) 2、问题与解决办法 1&#xff09; 运行 python train.py --..... 显示无法Err…...

Linux内核学习资源

老版本内核源码&#xff1a; https://mirrors.edge.kernel.org/pub/linux/kernel/Historic/old-versions/ 内核源码分析开源项目&#xff1a; https://github.com/ultraji/linux-0.12/tree/master/srchttps://gitee.com/wslyx/linux-0.12https://github.com/0voice/linux_ke…...

NGINX的安装和配置(Linux环境)

目录 NGINX 安装方式1、 离线编译安装2、 在线仓库安装 NGINX 常用命令1、进程管理命令2、信息查看命令 NGINX 配置文件1、进程使用的配置2、配置文件格式3、配置文件层级 NGINX 全局配置1、全局配置常用指令2、连接相关配置 NGINX 配置MIME1、MIME 标准2、types 配置块3、defa…...

Leetcode打卡:考场就坐

执行结果&#xff1a;通过 题目&#xff1a; 855 考场就坐 在考场里&#xff0c;有 n 个座位排成一行&#xff0c;编号为 0 到 n - 1。 当学生进入考场后&#xff0c;他必须坐在离最近的人最远的座位上。如果有多个这样的座位&#xff0c;他会坐在编号最小的座位上。(另外&am…...

STM32——“SPI Flash”

引入 在给单片机写程序的时候&#xff0c;有时会用到显示屏&#xff0c;就拿市面上的0.96寸单色显示器来说&#xff0c;一张全屏的图片就占用8x1281024个字节&#xff0c;即1kb的空间&#xff0c;这对于单片机来说确实有点奢侈&#xff0c;于是我买了一个8Mb的SPI Flash&#x…...

Zookeeper基本命令解析

ZooKeeper -server host:port -client-configuration properties-file cmd args addWatch [-m mode] path # optional mode is one of [PERSISTENT, PERSISTENT_RECURSIVE] - default is PERSISTENT_RECURSIVE addauth scheme auth 一、整体命令格式 ZooKeeper -serve…...

React-更新state的数据,dom没有重新渲染

{entourageList.map((person) > (<Row key{person.id}> {/* 使用唯一的 person.id */}<Col span{16}><Row gutter{16}><Col lg{9} md{18} sm{24}><FormItem label{姓名}>{getFieldDecorator(name-${person.id}, {initialValue: person.name,…...

消息队列技术的发展历史

消息队列技术的演进历程宛如一幅波澜壮阔的科技画卷&#xff0c;历经多个标志性阶段&#xff0c;各阶段紧密贴合不同的技术需求与市场风向&#xff0c;下面为您详细道来。 第一阶段&#xff1a;消息中间件的起源&#xff08;1970 年代末期 - 1980 年代中期&#xff09; 在计算…...

20.抽卡只有金,带保底(WPF) C#

这是一个界面应用化后的抽卡&#xff0c;目前只能抽金&#xff0c;只有基础概率加保底概率 适合界面化应用初学者。 这是展示图&#xff1a; 使用的是WPF不是winform&#xff0c;我也是第一次做WPF内容&#xff0c;就可以试一试&#xff0c;代码都在这里了&#xff0c;简单来…...

DALFox-一款XSS自动化扫描工具

声明&#xff01;本文章所有的工具分享仅仅只是供大家学习交流为主&#xff0c;切勿用于非法用途&#xff0c;如有任何触犯法律的行为&#xff0c;均与本人及团队无关&#xff01;&#xff01;&#xff01; 目录标题 一、介绍及使用启动及使用1. 单个扫描2. 多个扫描3. 文件扫描…...

软件测试之压力测试【详解】

压力测试 压力测试是一种软件测试&#xff0c;用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力&#xff0c;并确保软件在危急情况下不会崩溃。它甚至可以测试超出正常工作点的测试&#xff0c;并评估软件在极端…...

电视大全 1.3.8|汇聚多频道资源,秒切换流畅播放

电视大全TV版是一款功能丰富的TV端直播软件&#xff0c;由悠兔电视的同一开发者打造。最新版本更新了更多频道&#xff0c;包括央视、卫视和地方频道等&#xff0c;提供了多线路流畅播放体验&#xff0c;并支持节目回看、线路选择、开机自启等功能。该应用免登录且无购物频道&a…...