四旋翼利用mavros进行GPS坐标指点飞行

 先介绍一般px4飞控的xyz坐标指点飞行:

利用mavros的 /mavros/setpoint_raw/local 话题可以发送东北天(ENU)坐标给px4飞控进行指点飞行。ENU坐标原点在起飞点,东向为x坐标,北向为y坐标,天向为z坐标。z坐标高度对应 /mavros/local_position/local 中的z坐标,根据px4设置的不同可能是气压计、高度传感器或者差分GPS高度。

下面介绍如何进行gps坐标指点飞行:

户外我们往往希望给定一个gps坐标让四旋翼飞过去,而不是给定一个相对于起飞点的xyz坐标。这时有两种方案:

方法一、直接发送gps坐标

一种方法是利用mavros的 /mavros/setpoint_raw/global 话题直接发送gps坐标和高度给px4飞控,但是我不建议这么做。首先是因为很多人试过用这个话题但是没有成功,其次这个话题里的z坐标高度含义也不那么清晰,我还没明白这个高度到底是对地高度?gps高度?气压计高度?还是海拔高度?实际使用中也极其不建议直接就发gps坐标进行指点飞行,因为我们对经纬度的大小也没有一个直观的感受,经纬度小数点后6位才大致对应1m,给出的经纬度坐标稍有偏差飞机就不知道会飞向何方了,这不利于安全。

方法二、先将gps坐标转化为ENU坐标

第二种方法是将gps坐标先转化为ENU坐标系下的xyz坐标,然后还是用 /mavros/setpoint_raw/local 话题发送给px4飞控。如果你去阅读px4源码里的mavlink_receiver.cpp代码(这是px4接收mavros等mavlink信息的文件),你会发现即使你是用第一种方案向 /mavros/setpoint_raw/global 话题直接发送gps坐标,px4还是会先将gps坐标转化为相对于起飞点的xyz坐标,然后再和 /mavros/setpoint_raw/local 的坐标指令一样地处理。这个px4源码里用的gps坐标转换为ENU坐标的代码如下: 

 其中map_projection_project函数就是根据给定的参考点gps坐标ref、目标点gps坐标lat和lon,来计算两点之间的xy坐标差(这个x是东,y是北?)。对于原点在起飞点的ENU坐标系,参考点gps坐标其实就是起飞点的gps坐标啦。

map_projection_reproject则是给定ENU坐标系下的xy坐标差和一个参考点gps坐标ref,计算出目标点的gps坐标lat和lon。

这两个转换函数很简单也很常用,但是转换结果未必十分精准。因为地球毕竟是椭球形,将球形平面的经纬度坐标转换为平面内的笛卡尔坐标xy必然有转换误差(主要来源于对椭球的描述偏差)。由此可见,即使是给px4直接发送gps坐标指点飞行,飞机也不是用gps坐标直接进行位置环反馈控制,因此飞行的gps结果也未必十分精准。

我们还在网上找到了更精准的gps坐标转笛卡尔坐标的代码,它将地球按照维度分为了五段,计算过程更复杂但也更准确,xy输出结果和以上px4内部的转换代码大致相差1%。代码链接:  使用时引用头文件,然后直接调用函数。也可以参考uavros_simulation/uavros_wrzf_sitl/src/uav_controller.cpp · Peixuan Shu/UAVros - 码云 - 开源中国 (gitee.com)中的gps_to_local函数写法(注意引用头文件WGS84toCartesian.hpp)

注意px4中ENU坐标系用的原点gps坐标未必是home点,一般ENU的原点是飞控上电稳定后的点,但是飞机可能有被搬动或者多次起降的情况,这时home点会变化但是ENU的原点不会变,而且home点更新很慢也容易出错。因此在读取参考点gps坐标时,最好的方式是等飞控和上位机程序启动稳定后(否则读到的gps坐标是错误的!),同时读取当前gps坐标(/mavros/global_position/global) 和ENU坐标 (/mavros/local_position/pose), 利用gps_to_local函数或者前文提到的map_projection_project 算出目标点和当前点的xy坐标差,加上当前的ENU坐标,就能得到目标点的ENU坐标了!这里也可以参考uavros_simulation/uavros_wrzf_sitl/src/uav_controller.cpp · Peixuan Shu/UAVros - 码云 - 开源中国 (gitee.com)

注意

户外gps指点飞行很危险,再三确认坐标值正确,经纬度和xy前后顺序正确,高度正确,再进行指点飞行。直接发送xy坐标指点飞行时,使用的是px4自带的位置环控制,会有大角度机动出现,px4的位置环PID参数为MPC_X等,最大限速v_max也可以修改(QGroundControl地面站中修改)

而且不建议利用指点飞行起飞。如果直接给定飞机上方一点坐标使其起飞,电机会突然从停转状态达到最大转速,飞机也会噌地一下快速飞起来。建议用px4自带的takeoff模式起飞,它会有一个递增的坡度限幅使得电机转速慢慢增加,飞机也是平稳起飞。如果转速增加太慢,可以修改px4的ramp值(QGC搜索ramp或者takeoff)。如果室内用uwb飞行则不能用takeoff模式,因为它的local坐标值是用uwb位置填充的,起飞点就不是(0,0),(而且没有gps导致home点也不会更新?自动降落可能也会出问题)飞机自动起飞时会直接侧倾向uwb的零点飞过去

### PX4 Local 坐标系定义 在PX4中,局部坐标系(Local Coordinate System)通常指的是相对于起飞点的地心地固坐标系(ECEF),或者是北东地坐标系(NED)。这种坐标系用于描述无人机当前位置与起始位置之间的相对关系[^3]。 #### 定义 - **北东地 (North-East-Down, NED)** 是最常用的局部坐标系之一。在这个坐标系下,“北”方向对应于正X轴;“东”方向对应于正Y轴;而Z轴指向地面下方,表示高度减少的方向。 - 局部坐标系允许开发者更容易理解和处理无人机周围的环境数据,因为其原点固定在一个已知地点——通常是无人机的初始启动位置或设定的目标参考点。 ### 使用场景 当涉及到导航、路径规划以及避障等功能时,使用本地坐标系是非常必要的。它使得计算更加直观简单,并且能够更好地反映实际地理空间内的运动特性。例如,在执行特定任务期间,如自动着陆或者跟随目标物体移动,都需要依赖精确可靠的定位信息来进行决策判断。 ### 转换方法 为了将全球卫星定位系统(GPS)获取的数据转换成适用于NED框架下的表达形式,一般会采用如下步骤: 1. 将经纬度坐标(Latitude/Longitude)转化为地球中心直角坐标(ECEF),这一步骤可以通过标准公式完成; 2. 接下来利用四元数或其他旋转矩阵技术把ECEF坐标映射至基于当前起点建立起来的新坐标体系(NED)内; 3. 对于连续性的航迹跟踪,则需不断更新基底参照物的位置参数以保持准确性。 以下是Python代码片段展示了一个简单的GPS到NED坐标的转换过程: ```python import math def gps_to_ned(lat0, lon0, h0, lat, lon, h): """ Convert GPS coordinates to local North East Down (NED) frame. Parameters: lat0, lon0, h0 : Reference point's latitude, longitude and altitude lat, lon, h : Target point's latitude, longitude and altitude Returns: n, e, d : Position differences in meters along north, east, down axes respectively """ R = 6_378_137 # Earth radius at equator phi_m = math.radians((lat + lat0)/2) w = 1 / ((1 - 0.00669438 * pow(math.sin(phi_m), 2))**(1/2)) r = (R*w)*math.cos(phi_m) dx = math.radians(lon-lon0)*(r) dy = math.radians(lat-lat0)*(R*w) dz = -(h-h0) return dy, dx, dz ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值