在无人机自主飞行系统中,精确的位置估计是实现稳定悬停和路径跟踪的基础。最近在调试搭载PX4飞控和Fast-LIO激光SLAM系统的无人机时,发现一个棘手问题:当手动移动无人机后放回原位时,飞控的本地位置估计(local_position_ned)会出现明显偏移,导致无人机无法准确回到原始悬停点。
经过系统排查,发现问题根源在于飞控系统未能正确接收外部视觉定位数据。具体表现为:
当前系统的节点通信关系如下图所示(简化版):
code复制[Fast-LIO] --> /Odometry --> [Ego-Planner]
|
v
[PX4Ctrl] --> 控制指令 --> [MAVROS]
关键缺陷点:
PX4的扩展卡尔曼滤波(EKF2)支持多源数据融合,其输入源优先级如下:
要使飞控采用外部视觉定位,必须满足:
新增转换节点后的数据流:
code复制[Fast-LIO] --> /Odometry --> [Converter Node]
| |
v v
[Ego-Planner] /mavros/vision_pose/pose --> [MAVROS]
针对yaw角跳变问题,实现加权滑动窗口滤波:
python复制class YawFilter:
def __init__(self, window_size=5):
self.window = collections.deque(maxlen=window_size)
self.weights = np.hanning(window_size) # 汉宁窗加权
def update(self, new_yaw):
# 角度归一化处理
if self.window:
diff = new_yaw - self.window[-1]
if diff > np.pi:
new_yaw -= 2*np.pi
elif diff < -np.pi:
new_yaw += 2*np.pi
self.window.append(new_yaw)
return np.average(list(self.window), weights=self.weights)
激光雷达坐标系到飞控ENU坐标系的转换:
python复制def transform_to_enu(lidar_pose, init_q):
# 位姿解算
T_lidar = tf.transformations.quaternion_matrix(lidar_pose.orientation)
T_lidar[:3,3] = lidar_pose.position
# 初始对齐变换
T_init = tf.transformations.quaternion_matrix(init_q)
# 复合变换
T_enu = np.dot(T_init, T_lidar)
# 提取ENU位姿
enu_pose = PoseStamped()
enu_pose.pose.position.x = T_enu[0,3]
enu_pose.pose.position.y = T_enu[1,3]
enu_pose.pose.position.z = T_enu[2,3]
enu_pose.pose.orientation = quaternion_from_matrix(T_enu)
return enu_pose
通过QGroundControl或MAVLink命令设置:
code复制ekf2_aid_mask = 24 # 启用视觉位置和姿态融合
ekf2_hgt_mode = 3 # 使用视觉高度
ekf2_ev_noise = 0.01 # 视觉位置噪声
在launch文件中配置:
xml复制<node pkg="fastlio_to_mavros" type="converter_node" name="fastlio_converter">
<param name="window_size" value="5" />
<param name="publish_rate" value="30.0" />
<param name="odom_topic" value="/Odometry" />
<param name="vision_topic" value="/mavros/vision_pose/pose" />
</node>
推荐启动顺序:
使用launch文件管理依赖关系:
xml复制<launch>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch" />
<!-- Fast-LIO -->
<node pkg="fast_lio" type="fastlio_mapping" name="fast_lio" output="screen" />
<!-- 转换节点(延迟启动) -->
<node pkg="fastlio_to_mavros" type="converter_node" name="converter"
launch-prefix="bash -c 'sleep 5; $0 $@'" />
</launch>
检查EKF融合状态:
bash复制rostopic echo /mavros/estimator_status
验证数据流:
bash复制rqt_graph
rostopic hz /mavros/vision_pose/pose
问题1:飞控不响应视觉定位
ekf2_aid_mask参数问题2:位置估计漂移
ekf2_ev_noise参数问题3:yaw角跳变
建议采用硬件同步:
增加异常检测机制:
python复制def sanity_check(pose):
# 位置合理性检查
if np.linalg.norm(pose.position) > 50.0:
raise ValueError("Abnormal position")
# 四元数归一化检查
q = pose.orientation
norm = np.sqrt(q.x**2 + q.y**2 + q.z**2 + q.w**2)
if abs(norm - 1.0) > 0.01:
raise ValueError("Invalid quaternion")
集成dynamic_reconfigure实现运行时参数调整:
python复制from dynamic_reconfigure.server import Server
from fastlio_to_mavros.cfg import ConverterConfig
def callback(config, level):
rospy.loginfo("Reconfigure: window_size=%d", config.window_size)
self.filter.update_window_size(config.window_size)
return config
srv = Server(ConverterConfig, callback)
本方案不仅适用于Fast-LIO,还可扩展至:
只需修改话题订阅和坐标转换部分,即可实现不同定位源与飞控的集成。