近些年无人机编队很火热,大家也热衷于低成本的实现,大家看也在寻求着各种方案,很不幸,这个东西不是普通人可以玩转的东西。当DJI 推出了可以编程的Tello以后大家都觉得看到了希望,大量的人来涌入研究这个东西,但比较遗憾,由于无人机本身在设计上面对场景的不适配,效果不好,听见最多的声音就是定位不准。不过无所谓,它本身已经足够优秀了。
我去年的时候,发现了一个关于PX4+ROS设计的无人机,是一个俄罗斯的厂商。
由于都是通用器件,所以这个体积就很大。。。
不过无伤大雅,在基础构件提供的情况下,我发现还有一个编队的库,哇哦,这不就是正合我意了?
简单讲下编队的原理,有了图案,接着将这个东西离散化,相当于线变点,这些工作都不重要,很简单。最大的问题是,如何保持这个图像,我们绘画,因为是静态的坐标,所以我们都不关注这个问题,但是无人机不是会静止在一个地方的,而是有偏移的,也就是编队最大的问题,相对定位的问题。
没办法,想要编的过去只能解决这些问题,对于定位那是一个多传感器融合的问题了,这里使用ROS解决。可能不是最优的,但是是暂且可以使用的。
这里使用的是,第十三个发行版,念力忍者,针对的是Ubuntu 20.04 (Focal) 版本。然后ROS运行在树莓派上面,提供高层的服务。
在里面我也提过issue,询问是不是可以自己做这个包,这里说可以
就像这样
有一个web的工具
在这里
SSH的IP在这里可以设置
这里是自定义固件时候的脚本位置
这个是检查无人机的正确性的工具
就好像这样使用
rosrun 在启动节点时,也可以设置参数:
语法: rosrun 包名 节点名称 _参数名:=参数值
哥们儿今天领你看看什么叫ROS开发。rospy,你一直以为是个包,它确实是个包(放屁?)
rospy 是 ROS 的纯 Python 客户端库。rospy 客户端 API 使 Python 程序员能够快速与 ROS主题、服务和参数交互。rospy 的设计有利于实现速度(即开发人员时间)而不是运行时性能,以便算法可以在 ROS 中快速原型化和测试。它也是非关键路径代码的理想选择,例如配置和初始化代码。许多 ROS 工具都是用 rospy 编写的,以利用类型自省功能。
注意看,在这里被定义,源文件去ROS的Github上面找
这个是上层的安装包,这个就是使用的catkin安装的。
你看这个元消息,rospy是ROS的python客户端的原生实现
里面重要的东西有话题,服务,和参数服务器,走,去看看。
主题被命名为节点交换消息的总线。主题具有匿名发布/订阅语义,将信息的生产与消费分离。一般来说,节点不知道他们正在与谁通信。相反,对数据感兴趣的节点订阅相关主题;生成数据的节点发布到相关主题。一个主题可以有多个发布者和订阅者。
大概就是,哥们儿我就是发消息,你爱看不看。高傲!
太狂这也
主题旨在用于单向流式通信。需要执行远程过程调用(即接收对请求的响应)的节点应该使用服务来代替。还有用于维护少量状态的参数服务器。
主题类型
每个主题都由用于向其发布的 ROS消息类型强类型化,节点只能接收具有匹配类型的消息。Master不强制发布者之间的类型一致性,但订阅者不会建立消息传输,除非类型匹配。此外,所有 ROS 客户端都会检查以确保从msg 文件计算的 MD5匹配。此检查确保 ROS 节点是从一致的代码库编译的。
主题传输
ROS 目前支持基于 TCP/IP 和 UDP 的消息传输。基于 TCP/IP 的传输称为TCPROS,它通过持久的 TCP/IP 连接流式传输消息数据。TCPROS 是 ROS 中使用的默认传输,并且是客户端库需要支持的唯一传输。基于 UDP 的传输,称为UDPROS,目前仅在roscpp中支持,它将消息分离为 UDP 数据包。UDPROS 是一种低延迟、有损传输,因此最适合远程操作等任务。
ROS 节点在运行时协商所需的传输。例如,如果一个节点更喜欢 UDPROS 传输,但另一个节点不支持它,它可以回退到 TCPROS 传输。随着引人注目的用例的出现,这种协商模型可以随着时间的推移添加新的传输。
rostopic list
关于现在的节点情况,你可以使用这个命令看。
实现就是这么的朴实无华,Python一撸到底
这个std_msgs是一个测试使用的东西
std_msgs 包含 ROS 原始类型的包装器,这些包装器记录在msg 规范中。它还包含Empty类型,这对于发送空信号很有用。然而,这些类型并没有传达关于其内容的语义含义:每条消息都只是有一个名为“数据”的字段。因此,虽然此包中的消息可用于快速原型设计,但它们不适合“长期”使用。为了便于记录和协作,我们建议使用现有消息或创建新消息,以提供有意义的字段名称。
先看一个bool
虽然不爱英语,但是现在习惯看英语了
你看这个一个bool的定义
但是它实现起来是个宏,我也看不大懂下面的内容,参数倒是懂
大概就这样。接下来看看服务是什么?
发布/订阅模型是一种非常灵活的通信范式,但它的多对多单向传输不适用于分布式系统中经常需要的 RPC 请求/回复交互。请求/回复是通过服务完成的,该服务由一对消息定义:一个用于请求,一个用于回复。提供 ROS节点以字符串name提供服务,客户端通过发送请求消息并等待回复来调用服务。客户端库通常将这种交互呈现给程序员,就好像它是一个远程过程调用一样。
服务是使用srv文件定义的,这些文件由 ROS 客户端库编译成源代码。
客户端可以与服务建立持久连接,从而以降低对服务提供者更改的鲁棒性为代价实现更高的性能。
服务类型
与topic一样,服务具有关联的服务类型,即 .srv 文件的包资源名称。与其他基于 ROS 文件系统的类型一样,服务类型是包名称 + .srv文件的名称。例如,my_srvs/srv/PolledImage.srv具有服务类型my_srvs/PolledImage。
除了服务类型之外,服务还通过.srv文件的 MD5 和进行版本控制。只有当服务类型和 MD5 和都匹配时,节点才能进行服务调用。这确保了客户端和服务器代码是从一致的代码库构建的。
接下来是参数服务器:
参数服务器是一个共享的多变量字典,可通过网络 API 访问。节点使用此服务器在运行时存储和检索参数。由于它不是为高性能而设计的,因此最好用于静态、非二进制数据,例如配置参数。它旨在全局可见,以便工具可以轻松检查系统的配置状态并在必要时进行修改。
参数服务器使用 XMLRPC 实现并在 ROS Master内部运行,这意味着它的 API 可以通过普通的 XMLRPC 库访问。
在rospy的目录下有两个测试
在 rospy 程序中执行的第一个调用是对rospy.init_node()的调用,它为进程初始化 ROS 节点。rospy 进程中只能有一个节点,因此只能调用rospy.init_node()一次。
rospy.init_node('my_node_name')
rospy.init_node('my_node_name', 匿名=True)
在这里
在这里被定义
具体的以后有机会再看,继续看tf2的库的作用:
tf已经被弃用,取而代之的是tf2。tf2是转换库的第二代,它允许用户随时间跟踪多个坐标帧。tf2在时间缓冲的树结构中维护坐标帧之间的关系,并允许用户在任何所需的时间点在任意两个坐标帧之间转换点、向量等。
机器人系统通常具有许多随时间变化的三维坐标系,例如世界坐标系、基础坐标系、夹具坐标系、头部坐标系等。tf2随时间跟踪所有的这些坐标系,并可以解答下列问题:
①在5秒之前,头部坐标系相对于世界坐标系在哪;
②我抓手中的物体相对于我的底座的姿态是什么;
③地图坐标系中的基础坐标系当前位姿是什么。
tf2 可以在分布式系统中运行。这意味着有关机器人坐标系的所有信息都可用于系统中任何计算机上的所有 ROS 组件。 tf2 可以与包含所有转换信息的中央服务器一起运行,或者您可以让分布式系统中的每个组件构建自己的转换信息数据库。
tf2_geometry_msgs
下面这些是各种的消息
这里是要check的参数
这里是写明了一个从开机就执行的视觉任务
这个是摄像头的参数
from clover import srvfrom std_srvs.srv import Trigger
飞行之前要导入这些的消息。
这是一个基础的遥感消息
get_telemetry = rospy.ServiceProxy('get_telemetry', srv.GetTelemetry)navigate = rospy.ServiceProxy('navigate', srv.Navigate)navigate_global = rospy.ServiceProxy('navigate_global', srv.NavigateGlobal)set_position = rospy.ServiceProxy('set_position', srv.SetPosition)set_velocity = rospy.ServiceProxy('set_velocity', srv.SetVelocity)set_attitude = rospy.ServiceProxy('set_attitude', srv.SetAttitude)set_rates = rospy.ServiceProxy('set_rates', srv.SetRates)land = rospy.ServiceProxy('land', Trigger)
打印起来很简单
print('Take off and hover 1 m above the ground')navigate(x=0, y=0, z=1, frame_id='body', auto_arm=True)
控制飞行,就是这样的输入参数就行。
找到了实现的CPP函数
这是一些标志位
如果是busy,那就触发一个运行时的错误,接着把标志位重置,检查状态
又检查一个标志位
写了好多了,下篇继续
cat /proc/device-tree/model
树莓派的版本
打印一下内核
可能最快乐的事情就是catkin的logo这么好看
https://github.com/CopterExpress/clever-show
https://github.com/CopterExpress/clover
https://github.com/ros/ros
https://github.com/ros/ros_comm
https://www.ros.org/
编辑:黄飞
评论
查看更多