px4源码学习六--uORB模块研究

2023-05-16

UORB模块研读

uORB函数解析:

uORB模块(Micro Object Request Broker,微对象请求代理器)

uORB是Pixhawk系统中关键的一个模块,肩负了数据传输任务。所有传感器,数据传输任务,GPS,PPM信号从芯片获取后通过uORB进行传输,到各个模块计算处理。(可以理解为数据中心仓库)

uORB是跨进程的IPC通信模块。实际多个进程打开同一设备文件,通过此文件节点进行数据交互和共享。

进程间通过命名(总线)交换消息成为topic

一个topic包含一种消息类型/数据类型。

每个进程可以订阅/发布topic,一个进程可以订阅多个主题,但一条总线始终只能有一条消息。

公告topic

extern int orb_advertise(const struct orb_metadata *meta,const void *data)

meta:uORB元对象,可以看topic的ID,通过ORB_ID赋值。

data:指向一个被初始化,发布者要发布的数据存储变量指针。

发布更新

extern int orb_publish(const struct orb_metadata *meta, int handle, const void *data)

handle:orb_advertise函数返回的句柄

data:指向发布数据的制作

订阅topic

要求的满足条件:

  • 调用ORB_DEFINE()或ORB_DEFINE_OPTIONAL()宏(在订阅头文件中包含他们)
  • 发布到主题的数据结构定义

extern int orb_subscribe(const struct orb_metadata *meta)

取消订阅

extern int orb_unsubscribe(int handle)

拷贝数据

订阅者不能引用从ORB中存储数据或其他订阅共享的数据,只能拷贝到临界缓冲区

extern int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)

检查更新

extern int orb_check(int handle, bool *updataed)

发布时间戳

extern int orb_stat(int handle,uint64_t *time)

Note:

  1. 必须要先orb_advertise()+orb_subscribe()后,才能使用orb_copy()
  2. 所有主题在Firmware/Build_px4fmu-v2_default/Src_Modules/uORB/Topics
  3. 也可以到Firmware/Msg下找到

uORB原理解析:
uorb实现原理

实现方式:

  1. 首先模块入口是uORBMain.cpp,这里会创建唯一的MasterNode实例,负责内部的设备节点的控制
  2. MasterNode简洁:继承自CDev,是一个字符设备,linux中设备都是文件,所以会在对应路径下生成文件,主要对Cdev的ioctl函数进行多态实现,类内部维护一个Nodemap的数据结构(后面有详细简绍),所有的DeviceNode都会加入其中管理。
  3. 当外部调用uORB的方法时候,实际间接调用了uORB::Manger类的方法,也可以理解做Manger是外部函数的管理入口,MasterNode是内部节点的管理器。
  4. 外部函数调用uORB时候都会通过uORB::Manger::get_instance()这个函数获取Manger的实例指针。这个函数是静态函数,根据判断命名空间中_Instance指针是否为空,确保全nameespace中只有这么一个Manger实例。
  5. 实际节点,DeviceNode,继承自CDev,每一个字符设备都会生成对应的文件。这个类重载了open,close,read,wirte,ioctl,还有其他一些函数。
  6. 当外部调用orb_advertise时,Manger会做如下的事情:
    1. 以发布者的身份调用node_open函数,最后返回对应文件的文件描述符fd。先确认一下是否这个主题对应实例的序号已经被发布过,如果是,会重新发布一下,否则(对应文件不存在,也就是这个主题对应ID的DeviceNode不存在),会调用node_advertise函数进行DeviceNode实例的创建。
    2. (调用node_open函数)
    3. 通过fd调用ioctl函数,返回DeiceNode对象的指针。
    4. 发布初始化的数据
  7. 当外部调用orb_publish时
    1. 根据传入的DeviceNode的指针,调用这个类的静态的发布数据的方法。就是将数据写入DeviceNode对象的属性中。
  8. 当外部调用orb_Subsctibe时,
    1. 使用Manger类的node_open函数,返回对应主题对应实例的文件描述符,其他信息都可以通过调用被DeviceNode多态实现过的ioctl函数获得。
    2. 取消订阅就将文件描述符关闭就可以了。

uORB

这个文件中所有的方法的实现方式都是调用ORB::Manger的方法,只是一个扩展接口的包装文件

因为这个没有在任何命名空间或者类中,这里将具体的ORB::Manger操作封装,使得其他类可以调用

orb_advertise(*meta, *data) orb_advert_t

参数列表含义:主题名称,初始数据

作为发布者做广播,如果正常,返回一个可以用来发布这个主题的句柄

orb_advertise(*meta, *data, *instance, priority) orb_advert_t

参数列表含义:主题名称,初始数据,实例ID的指针,实例优先级

一个主题下可以有多个实例,每个实例根据handle区分,最多5个

orb_pubshlist_auto(*meta, *handle, *data, *instance, priority) int

参数列表含义:同上

根据handle是否有效发布数据

orb_publish(*meta, handle, *data) int

参数列表含义:主题名称,主题的实例句柄,发布的数据

数据发布是原子操作,任何等待更新的订阅者都会被通知。其他没有等待的可以使用orb_check/orb_stat函数检查更新

orb_subscribe(*meta) int

参数列表含义: 主题名称

返回文件描述符,可以使用poll函数等待主题更新,就像使用topic_read/orb_check/orb_stat一样

即使这个主题没有发布订阅也可能成功,这种情况下,poll,复制它的值什么的操作都会失败,直到这个主题被发布未知。

如果系统不知道这样一个主题,那么会订阅失败

orb_subscribe_muti(*meta, instance) int

参数列表含义: 主题名称, 实例ID

orb_unsubscribe(handle) int

参数列表含义:实例句柄

orb_copy(*meta, handle, *buffer) int

参数列表含义:主题名称,实例句柄,缓冲区

这是唯一个可以重置内部主题是否更新标志的函数。一旦使用poll或者orb_check返回可用更新,必须使用这个方法更新参数

orb_check(handle, *updated) int

参数列表含义:实例的句柄,是否被更新的标志

检查在上次orb_copy后这个主题是否被重新发布过

更新以每个句柄为基础进行跟踪; 

这个调用将一直返回true直到使用相同的句柄调用orb_copy。

由于stat和copy之间的竞争窗口可能导致错过更新,所以此接口应优先于调用orb_stat。

orb_stat(handle, *time) int

返回上一次更新主题的时间

orb_exists(*meta, instance) int

检查主题是否存在

orb_group_count(*meta) int

返回主题的实例数量

orb_priority(handle, *priority) int

返回句柄的优先级

orb_set_interval(handle, interval) int

设置最小的更新间隙

uORBCommon

ORBSet

  • insert(*node_node) void
  • find(*node_name) bool
  • erase(*node_name) bool
  • unlinkNext(Node*) void

实现方式与ORBMap一毛一样,唯一的区别就是这个类维护的队列中的node节点是只有节点名字,没有节点设备。

ORBMap

  • insert(*node_name, *node) void
  • find(*node_name) bool
  • *get(*node) uORB::DeviceNode
  • unlinkNext(*a) void

类的实现流程:(太简单了吧,过分)

类中维护一个队列,使用对象top,end俩个指针标识队列,

当有新的数据结点,加入到end后面,查找、获取是从头到尾顺序查找队列,使用strcmp()比较node_name

uORBDevices_nuttx

namespace uORB
{
class DeviceNode;  //具体的节点
class DeviceMaster; //节点管理
}

DeviceNode

继承device::CDev(一切字符设备的基类)

DeviceNode(*meta, *name, *path, priority)

open(struct file *filp) int virtual

设备节点打开:算是虚拟的设备文件虽然继承与CDev类

根据文件信息,读取权限:(filp记录了这次打开文件的信息,比如权限,PID等数据)

如果文件写入权限,认为是发布者,设备节点属性发布者设为当前PID,使用CDev::open打开(但实际这个类也没干什么,可以忽略这一句),

如果是读取权限,认为是订阅者,申请SubscriberData给filp->f_priv,记录这个订阅对象fd所私有的数据,并且告诉对象属性又一个订阅者订阅了你

close(*filp) int virtual

设备节点关闭:

如果是发布者调用的关闭,将属性发布者置为0

如果是订阅者调用,获取filp中的SubscriberData,从调用列表中删除,移除内部调用者

read(*filp, *buffer, buflen) ssize_t virtual

将类中数据_data读入到buffer中

write(*filp, *buffer, buflen) ssize_t virtual

将buffer的数据读入到类的_data属性中

ioctl(*filp, cmd, arg) int virtual

根据cmd的值调整arg的类型,输出对应数据属性

publish(*meta, handle, *data) ssize_t static

这是静态函数,所有实例公用一个

根据传入的句柄(即DeviceNode的指针),将data的数据写入类的对象属性_data中

//以下3个函数应该是设计远程调用IChannel接口的,这里不做讨论,因为没看懂,也没有示例使用

process_add_subscription(rateInHz) int16_t

process_remove_subscription() int16_t

process_received_message(length, *data) int16_t

将接受的数据写入_data属性中

add_internal_subscriber() void

remove_internal_subscriber() void

is_published() bool

//protected:

poll_state(*filp) pollevent_t virtual

判断主题是否推送给订阅者,需要推送返回POLLIN,否则0

poll_notify_one(struct pollfd *fds,pollevent_t events )

对于fds来说,如果有更新,调用Cdev::poll_notify_one()函数进行更新

appears_updated(SubscriberData *sd) bool

根据sd的信息,判断是否有更新(发布者调用这个函数)

update_deferred() void

监控拉的需求

private:
    struct SubscriberData {
        unsigned  generation; /**< last generation the subscriber has seen */
        unsigned  update_interval; /**< if nonzero minimum interval between updates */
        struct hrt_call update_call;  /**< deferred wakeup call if update_period is nonzero */
        void    *poll_priv; /**< saved copy of fds->f_priv while poll is active */
        bool    update_reported; /**< true if we have reported the update via poll/check */
        int   priority; /**< priority of publisher */
    };

    const struct orb_metadata *_meta; /**< object metadata information */
    uint8_t     *_data;   /**< allocated object buffer */
    hrt_abstime   _last_update; /**< time the object was last updated */
    volatile unsigned   _generation;  /**< object generation count */
    pid_t     _publisher; /**< if nonzero, current publisher */
    const int   _priority;  /**< priority of topic */
    bool _published;  /**< has ever data been published */

DeviceMaster

继承device::CDev,管理设备节点的类

DeviceMaster(Flavor f)

*GetDeviceNode(*node_name) uORB::DeviceNode

ioctl(*filp, cmd,arg ) int virtual

private:
    Flavor      _flavor;  //是PUBSUB还是OBJ
    static ORBMap _node_map; //所有的DeviceNode设备都在其中

uORBDevices_posix

nuttx是在px4在nuttx操作系统下运行的,这个应该是裸机运行的。

uORBManager

这个类管理着每一个UORB主题和节点,也实现了UORb的API

继承自IChannelRxHandler类,类中函数大多都在前面见过,我只大概描述一下实现,如果有必要的话

get_instance() Manager* static

获取生成的uORBManager实例,静态的,单个进程中只生成一个实例

orb_advertise(*meta,*data) orb_advert_t

orb_advertise_multi(*meta, *data, *instance, priority) orb_advert_t

根据主题和实例编号获取文件描述符,根据文件描述符获取当前发布者的指针并返回发布者的指针

orb_publish(*meta, handle, *data) int

发布数据,返回成功与否

实现:

调用DevicNode的publish方法,DeviceNode::publish是静态方法,调用handle->write()函数(write会使属性_generation++,标记数据版本的),将数据写入文件中

orb_subscribe(*meta) int

orb_subscribe_multi(*meta, instance) int

订阅的原理就是打开以只读打开文件,返回fd

(一个文件可以被打开多次,返回的fd都不一样,fd对应这file *filp这个指针(也就是你在DeivceNode类中参数filp一样,这个指针的结构体参数比较全),所以可以打开一次,有多个备份的filp)

orb_unsubscribe(handle) int

orb_copy(*meta, handle, buffer) int

从handle中读取相应长度的数据到buffer中

orb_check(handle, *updated) int

使用ioctl方法(ioctrl方法有DeviceNode类实现)

这个检查的办法是对比filp中维护的SubscriberData数据和对象中属性generation是否一致,虽然filp有多个,但是文件(或者说DeviceNode对象只有一个),所以可以进行判断。(更新版本是在写入时候generation++)

orb_stat(handle, *time) int

使用ioctl方法

orb_exists(*meta, instance) int

主题的对应实例是否有

根据参数生成路径,然后试图打开对应文件

orb_priority(handle, *priority) int

使用ioctl方法

orb_set_interval(handle, interval) int

使用ioctl方法

set_uorb_communicator(*comm_channel) void

get_uorb_communicator() IChannel*

is_remote_subscriber_present(*messageName) bool

private:

node_advertise(*meta, *instance, priority) int

通过调用控制设备MasterNode的ioctl函数(被重载过),让控制文件去创建对应的DeviceNode对象(有了对象,对应路径下就有了文件)

node_open(Flavor, *meta, *data, advertiser, *instance, priority) int

根据订阅发布的属性打开对应的设备文件,返回文件描述符

这个函数让你屏蔽是否存在这样的设备文件,根据你的需求去解决。

如果你是订阅者,存在,直接返回。不存在,那就创建一个,方法同下。

如果你是发布者,存在,关闭fd。重新打开一次,(这时node_advertise调用将自动进入下一个空闲条目)不存在,调用node_advertise发布创建一个DeviceNode对象(有了对象自然会有文件)

实现:

判断输入的逻辑合法性

根据订阅者还是发布者,选择对应读取权限打开文件

如果是发布者&&打开成功,说明这个文件存在

关闭文件重新调用node_advertise发布再打开文件

返回文件描述符fd

process_add_subscription(*messageName, msgRate) int16_t

处理订阅的回调函数,Manger类实现的

实现逻辑:

将主体加入订阅主题的集合中

根据对应信息获取路径,再从设备管理器DeviceMaster获取对应的设备节点

具体设备节点处理订阅频率

process_remove_subscription(*messageName) int16_t

处理移除订阅的回调函数,Manger类实现

实现逻辑:

将主题移除主题集合

获取对应的设备节点

具体设备节点处理移除事件

process_received_message(*message, length, *data) int16_t

处理接受信息的回调函数,Manger类实现

实现逻辑:

获取对应的设备节点

具体的设备节点处理接受的信息

    static Manager *_Instance; //全局唯一的管理器
    // the communicator channel instance.
    uORBCommunicator::IChannel *_comm_channel;
    ORBSet _remote_subscriber_topics;

uORBUtils

工具类Utils中只有2个同名的静态函数

int node_mkpath(char* buf, Flavor f, const struct orb_metadata *meta, int *instance)
int node_mkpath(char* buf, Flavor f, const char* orbMsgName)

参数含义:

buf:输出路径的字符串

f:  标志,是发布订阅还是作为参数(PUBSUB/PARAM)

meta: 通过meta->o_name = orbMsgName

instance: 如果是多个实例,对应相应的,否则默认为0

生成路径为/(obj?param)/orbMsgName/instance ,应该是节点设备的文件路径

uORBCommunicator

namespace uORBCommunicator
{
 //俩个类都为纯虚类,可以认为java中的接口类
class IChannel; // 可以理解为这个是客户端
class IChannelRxHandler; //这个是服务器端
}

IChannel

启用远程订阅的接口,接口的实现类需要管理通信信道,快速RPC/TCP/IP

add_subscription(*messageName, msgRateInHz) int16_t

参数列表含义:主题名称(全局唯一),最大消息更新速率

通知有兴趣的远程实体订阅消息的接口

remove_subscription(*messageName) int16_t

通知远程实体移除订阅的接口

register_handler(IChannelRxHandler *handler) int16_t

注册消息句柄

send_message(*messageName, length, *data) int16_t

通过通讯链接发送数据

IChannelRxHandler

通过通信链路回调的类

process_add_subscription(*messageName, msgRateInHz) int16_t

处理从远程接受添加的接口函数

process_remove_subscription(*messageName) int16_t

处理远程移除订阅的接口

process_received_message(*messageName, length, *data) int16_t

处理远程发送数据的类

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

px4源码学习六--uORB模块研究 的相关文章

  • PX4使用I2C方式添加自定义传感器(1)

    PX4使用I2C方式添加自定义传感器 xff08 1 xff09 前言 毕业设计就是要在PX4上添加一个传感器 xff08 角度传感器 xff09 xff0c 由于板子上的接口数量很少 xff0c 很是宝贵 最后只能选择通过I2C通信方式
  • 编译PX4固件

    PX4编译 文章目录 PX4编译疑难杂症bug1bug2catkin build isolated 官方脚本Step1Step2 安装常用依赖Step3 创建并运行脚本Step4 补全代码子模块Step5 验证仿真 官方offboard 例
  • PX4/Pixhawk---uORB深入理解和应用

    The Instructions of uORB PX4 Pixhawk 软件体系结构 uORB 主题发布 主题订阅 1 简介 1 1 PX4 Pixhawk的软件体系结构 PX4 Pixhawk的软件体系结构主要被分为四个层次 xff0c
  • Nuttx下移植uorb笔记

    Nuttx下移植uorb笔记 之前接触过ros下的消息机制 xff08 生产者 消费者 xff09 模型 xff0c 第一感觉是灵活好用 xff0c 但是在资源有限的嵌入式环境里面 xff0c 邮箱 消息 显得就有点不那么灵活 xff0c
  • [pixhawk笔记]6-uORB流程及关键函数解析

    本文中将结合代码 文档及注释 xff0c 给出uORB执行流程及关键函数的解析 xff0c 由于uORB的机制实现较为复杂 xff0c 所以本文主要学习如何使用uORB的接口来实现通信 回到上一篇笔记中的代码 xff1a include l
  • Ubuntu20.04+MAVROS+PX4+Gazebo保姆级安装教程

    Ubuntu20 04 43 MAVROS 43 PX4 43 Gazebo 安装PX4步骤安装MAVROS安装QGCPX4仿真 安装PX4步骤 从github上clone源码 span class token function git s
  • 基于F4/F7/H7飞控硬件和px4飞控固件的廉价自主无人机系统(1)-飞控

    前言 穿越机F4 F7 H7飞控是一系列采用stm32系列F4xx和F7xx处理器的飞控的统称 xff0c 是目前穿越机爱好者非常喜欢使用的飞控硬件 xff0c 其价格也非常便宜180 xff5e 410 而px4则是一款常见的开源飞控固件
  • PX4 Bootloader下载及编译过程中的问题解决

    买来的雷迅的板子都是Bootloader已经烧进去了 xff0c Fireware也已经刷进去了 如果是自制的板子 xff0c 上位机根本没法识别板子 xff0c 必须先烧写下载Bootloader后编译好的bin文件 这篇记一下自己下载及
  • Ubuntu下构建PX4软件

    本搭建过程基于http dev px4 io starting building html xff0c 希望大家互相交流学习 原文 xff1a Building PX4 Software xff08 构建PX4软件 xff09 PX4 ca
  • 初学PX4之环境搭建

    文章转自 xff1a http www jianshu com p 36dac548106b 前言 前段时间linux崩溃了 xff0c 桌面进去后只有背景 xff0c 折腾好久没搞定 xff0c 为了节省时间索性重装了系统 xff0c 同
  • PX4模块设计之十三:WorkQueue设计

    PX4模块设计之十三 xff1a WorkQueue设计 1 WorkQueue启动2 WorkQueue接口2 1 基本接口2 2 辅助接口2 3 WorkQueue任务函数2 3 1 Flat Build2 3 2 Protected
  • PX4模块设计之二十一:uORB消息管理模块

    PX4模块设计之二十一 xff1a uORB消息管理模块 1 uORB模块构建模式2 uORB消息管理函数2 1 状态查询2 2 资源利用2 3 模块启动2 4 模块停止3 uORB消息接口3 1 消息主题注册3 2 消息主题去注册3 3
  • PX4模块设计之二十三:自定义FlightTask

    PX4模块设计之二十三 xff1a 自定义FlightTask Step1 创建飞行模式文件夹Step2 创建飞行模式源代码和CMakeLists txt文件Step3 更新CMakeLists txt文件Step4 更新FlightTas
  • PX4模块设计之二十四:内部ADC模块

    PX4模块设计之二十四 xff1a 内部ADC模块 1 内部ADC模块简介2 模块入口函数2 1 主入口board adc main2 2 自定义子命令custom command 3 内部ADC模块重要函数3 1 task spawn3
  • px4_simple_example和uorb机制

    px4 simple app PX4 Autopilot src exampes px4 simple app xff0c 这个程序是用c语言调用orb API和poll机制订阅和发布通讯数据 xff0c 但是这个例子并不是既有接收又有发送
  • 【px4】运行mavsdk中的offboard example

    运行MAVSDK中的offboard例子时无人机不执行 想控制无人机前后左右移动 xff0c 在按照官方教程实现offboard 插件的时候 发现用action插件能正常起飞和降落 但是一旦执行到offboard的插件代码的时候就会自动降落
  • px4无人机常识介绍(固件,px4等)

    专业名词解释 aircraft 任何可以飞或者可以携带物品还是搭载旅客的飞行器统称为飞机 航空器 uav 无人驾驶飞机 vehicle 飞行器 airplane plane aero plane 有机翼和一个或多个引擎的飞行器统称为飞机 D
  • PX4项目学习::(五)模块代码启动流程

    54条消息 PX4 模块代码启动流程 zhao23333的博客 CSDN博客
  • 无人机PX4使用动捕系统mocap的位置实现控制+MAVROS

    动捕系统Optitrack xff0c 有很高的定位精度 xff0c 能够给无人机提供比较精确的位置信息 xff0c 因此如果实验室有条件 xff0c 都可以买一套动捕系统 动捕系统的原理 xff1a 光学式动作捕捉依靠一整套精密而复杂的光
  • uORB笔记

    不同的类调用同一函数orb subscribe ORB ID vehicle gps position xff0c 来订阅GPS信息是 xff0c 该函数返回的值不同 xff0c 也就是说每个订阅者针对同一主题 xff0c 在调用函数orb

随机推荐

  • Tensorflow代码学习-8-3下载google图像识别网络inception-v3并查看结构

    下载google图像识别网络inception v3并查看结构 课程 xff1a 炼数成金GITHUBCSDN知乎欢迎点亮star span class token keyword import span tensorflow span c
  • Tensorflow代码学习-10-3验证码识别

    验证码识别 课程 xff1a 炼数成金GITHUBCSDN知乎欢迎点亮star span class token comment coding utf 8 span span class token keyword import span
  • 腾讯云ubuntu远程桌面

    1 首先要连接上你的服务器 xff0c 然后安装vncserver xff0c 这个是用来远程连接用的 命令如下 apt get install vnc4server 2 安装图形界面 apt get install xfce4如果安装不上
  • 如何快速上手期刊、会议论文latex的小技巧

    来自学习经验 xff0c 如有更好可评论告知 xff01 适用于各种期刊 会议的小技巧 xff01 xff01 可节省非常多时间 xff01 xff01 知乎专栏 简单描述如下 xff1a 1 找一篇与要投的期刊一篇论文 2 去arxiv网
  • 解决 树莓派自带的VNC版本不能进行文件传输

    在树莓派4B上使用的VNCSERVER是可以进行文件传输的 xff0c 就想应该是树莓派3B 43 上的操作系统自带的VNC版本太旧 xff0c 因此就想直接用命令sudo apt upgrade tightvncserver更新 xff0
  • Git submodule - Git子模块简介

    目录 建立仓库 1 1 创建主仓库 1 2 创建子仓库提交内容 2 1 提交到主工程的仓库 2 2 提交到子模块的仓库克隆带子模块的仓库到本地更新子仓库总结参考文档 正文 软件开发中有一个DRY Don t Repeat yourself
  • IR2101驱动

    下面是datasheet上的内部框图及应用电路 xff1a 由内部框图及输入输出时序图可知 xff1a HIN输入高则HO输出高 xff0c 输入低则输出低 低端也一样 由典型应用电路图分析 xff1a 当HIN LIN同时输入高 xff0
  • Cannot convert a symbolic Tensor to a numpy array错误的解决

    最近写代码的时候发生了一件奇怪的错误 NotImplementedError Cannot convert a symbolic Tensor bert encoder layer 0 attention self strided slic
  • ubuntu进入tty1、tty2等界面的操作

    想要进入tty1或者tty2 xff0c 需要ctrl 43 alt 43 f1 xff0c 注意如果是笔记本电脑 xff0c 需要输入ctrl 43 alt 43 fn 43 f1 xff0c 注意如果tty1界面进入不了的时候 xff0
  • 移植Mavlink协议到STM32F103详细教程

    环境配置 win10系统 43 STM32F103ZET6 步骤 参考MAVLINK官网 1 安装python3 6以上的版本 xff0c 我安装的是python3 8 Python3 8下载地址 详细安装步骤可参考 xff1a pytho
  • pid调试

    1 PID调试步骤 没有一种控制算法比PID 调节规律更有效 更方便的了 现在一些时髦点 的调节器基本源自PID 甚至可以这样说 xff1a PID 调节器是其它控制调节算法的吗 为什么PID应用如此广泛 又长久不衰 xff1f 因为PID
  • MAVLINK协议理解

    mavlink协议的载体是一下格式 xff1a 这是载体格式 这是载体的具体格式说明 mavlink的结构 主要有3部分 mavlink messages 比如 0 心跳包 这个message 就是各种数据帧里的数据 xff0c 例如 xf
  • 关于&0xFF的理解

    做协议解析时候 xff0c 一个byte的0xFE xff0c 直接转化int xff0c 应该是254 xff0c 但是最终结果是 2 xff0c 在网上一查 xff0c 有的人说是因为java用补码表示的byte 网址 xff1a ht
  • tensoflow2.x中tensor转numpy问题

    这里写自定义目录标题 AttributeError 39 Tensor 39 object has no attribute 39 numpy 39 AttributeError Tensor object has no attribute
  • A算法与A*算法区别

    A算法由 f n 61 g n 43 h n 俩个因素决定 xff0c g n 是这一步的代价函数 h n 是这一步的预估函数 xff1b 对于A 算法来说 xff0c 评判函数也是 f n 61 g n 43 h n 这个 xff0c 只
  • PARWAN处理器架构特点

    PARWAN处理器架构特点 PARWAN处理器结构图 xff08 搬运工系列 xff09 各个部分说明 xff1a Applied toCategtoriesSignal Name FunctionallyAC 累加计数器 Register
  • PX4源码学习一--Pix和APM的区别

    pixhawk是硬件平台 xff0c PX4是pixhawk的原生固件 xff0c 专门为pixhawk开发的 APM xff08 Ardupilot Mega xff09 也是硬件 Ardupilot是APM的固件 xff0c 所以称Ar
  • px4源码学习三--px4源码结构分析

    px4源码结构分析 Px4源码目录 cmake xff1a 是存放的 Cmake 编辑脚本文件夹 xff0c 其中 Cmake Configs 是存放的不同硬件的编译脚本 xff0c nuttx mindpx v2 default 是 PI
  • px4源码学习五--固定翼位置控制模块

    fw pos control模块 class landingslope 为固定翼着陆的角度变化模块 calulateSlopeValues void private 更新H1 H0 d1 根据log xff08 H0 H1 xff09 的比
  • px4源码学习六--uORB模块研究

    UORB模块研读 uORB函数解析 xff1a uORB模块 xff08 Micro Object Request Broker xff0c 微对象请求代理器 xff09 uORB是Pixhawk系统中关键的一个模块 xff0c 肩负了数据