解决无人机移动后飞控位置偏移问题Fast-LIO到MAVROS视觉定位转换问题描述在使用无人机进行实际飞行时发现一个问题当将无人机移动到其他位置后再放回原处飞控的local position ned会发生改变导致无人机无法准确悬停在期望位置。经过分析怀疑是因为没有将外部视觉定位数据正确发送给飞控。本次使用的飞控版本是PX4 1.16.0 stable问题分析代码结构检查通过检查项目代码结构发现ego planner不直接发布/mavros/vision_pose/pose话题px4ctrl仅订阅通用odom话题但不将其转发到飞控Fast-LIO发布/Odometry话题但未直接与 MAVROS 集成关键代码分析查看px4ctrl模块的代码PX4CtrlFSM.cpp实现了状态机逻辑包括起飞、降落、悬停等模式input.h定义了Odom_Data_t结构体用于接收里程计数据px4ctrl_node.cpp订阅odom话题并绑定到Odom_Data_t::feed函数发现px4ctrl模块虽然接收了里程计数据用于控制但没有将这些数据发送回飞控进行位置修正。解决方案等待香橙派所有节点都启动完成后再启动本次的里程计转发节点创建一个转换节点将 Fast-LIO 发布的/Odometry话题数据转换并发布到/mavros/vision_pose/pose话题使飞控能够接收外部视觉定位数据。QGC设置飞控vision的ekf融合设置数传2口按图中设置否则不能识别vison_position_pose然后设置波特率实现步骤1. 创建功能包结构mkdir-p/home/rog/code/fast_drone_ws/src/fastlio_to_mavros/{launch,scripts}2. 配置文件package.xml定义功能包依赖和元信息CMakeLists.txt配置编译规则和安装路径fastlio_to_mavros.launch提供可配置的启动参数3. 核心实现优化后的转换脚本文件名fastlio_to_mavros.py#!/usr/bin/env python3# -*- coding: utf-8 -*-importrospyfromnav_msgs.msgimportOdometryfromgeometry_msgs.msgimportPoseStampedimporttfimportnumpyasnpfromcollectionsimportdeque# 滑动窗口平均类用于平滑 yaw 值classSlidingWindowAverage:def__init__(self,window_size):self.window_sizewindow_size self.data_queuedeque(maxlenwindow_size)# 使用固定大小的队列defadd_data(self,new_data):# 如果队列非空且新数据与最新数据差异过大重置队列ifself.data_queueandabs(new_data-self.data_queue[-1])0.01:self.data_queue.clear()self.data_queue.append(new_data)returnself.get_avg()defget_size(self):returnlen(self.data_queue)defget_avg(self):ifself.data_queue:returnsum(self.data_queue)/len(self.data_queue)else:return0.0classFastLIOToMavros:def__init__(self):rospy.init_node(fastlio_to_mavros,anonymousTrue)# 获取参数self.window_sizerospy.get_param(~window_size,8)publish_raterospy.get_param(~publish_rate,30.0)# 初始化位姿和四元数self.p_lidar_bodynp.zeros(3)self.q_mav[0,0,0,1]self.q_px4_odom[0,0,0,1]# 创建滑动窗口平均器self.swaSlidingWindowAverage(self.window_size)# 初始化标志self.init_flagFalseself.init_qtf.transformations.quaternion_from_euler(0,0,0)# 订阅和发布器self.vins_subrospy.Subscriber(~fastlio_odom,Odometry,self.fastlio_callback,queue_size10)self.px4_odom_subrospy.Subscriber(~px4_odom,Odometry,self.px4_odom_callback,queue_size10)self.vision_pubrospy.Publisher(~vision_pose,PoseStamped,queue_size10)# 定时器控制发布频率self.timerrospy.Timer(rospy.Duration(1.0/publish_rate),self.publish_vision_pose)rospy.loginfo(FastLIO to MAVROS converter initialized)rospy.loginfo(fWindow size:{self.window_size}, Publish rate:{publish_rate}Hz)deffrom_quaternion_to_yaw(self,q):# 将四元数转换为 yaw 角eulertf.transformations.euler_from_quaternion(q)returneuler[2]deffastlio_callback(self,msg):# 获取 Fast-LIO 提供的位姿和四元数self.p_lidar_bodynp.array([msg.pose.pose.position.x,msg.pose.pose.position.y,msg.pose.pose.position.z])self.q_mav[msg.pose.pose.orientation.x,msg.pose.pose.orientation.y,msg.pose.pose.orientation.z,msg.pose.pose.orientation.w]defpx4_odom_callback(self,msg):# 获取 PX4 的本地位置四元数并计算 yaw 角self.q_px4_odom[msg.pose.pose.orientation.x,msg.pose.pose.orientation.y,msg.pose.pose.orientation.z,msg.pose.pose.orientation.w]# 更新滑动窗口平均yawself.from_quaternion_to_yaw(self.q_px4_odom)self.swa.add_data(yaw)# 初始化 yaw 角ifself.swa.get_size()self.window_sizeandnotself.init_flag:init_yawself.swa.get_avg()self.init_qtf.transformations.quaternion_from_euler(0,0,init_yaw)self.init_flagTruerospy.loginfo(fInitial yaw initialized:{init_yaw:.3f}rad)defpublish_vision_pose(self,event):ifnotself.init_flag:return# 旋转位姿以对齐初始 yaw 角rot_matrixtf.transformations.quaternion_matrix(self.init_q)[:3,:3]p_enunp.dot(rot_matrix,self.p_lidar_body)# 构建视觉位姿消息vision_msgPoseStamped()vision_msg.header.stamprospy.Time.now()vision_msg.header.frame_idmap# 根据实际情况设置vision_msg.pose.position.xp_enu[0]vision_msg.pose.position.yp_enu[1]vision_msg.pose.position.zp_enu[2]vision_msg.pose.orientation.xself.q_mav[0]vision_msg.pose.orientation.yself.q_mav[1]vision_msg.pose.orientation.zself.q_mav[2]vision_msg.pose.orientation.wself.q_mav[3]# 发布消息self.vision_pub.publish(vision_msg)# 每100次发布打印一次信息减少终端输出ifrospy.get_time()%100.01:rospy.loginfo_throttle(1.0,fPosition (ENU): x{p_enu[0]:.3f}, y{p_enu[1]:.3f}, z{p_enu[2]:.3f})defmain():try:converterFastLIOToMavros()rospy.spin()exceptrospy.ROSInterruptException:rospy.loginfo(FastLIO to MAVROS converter shutting down)passif__name____main__:main()文件名fastlio_to_mavros.launchlaunchnodepkgfastlio_to_mavrostypefastlio_to_mavros.pynamefastlio_to_mavrosoutputscreen!-- Fast-LIO odometry topic --remapfrom~fastlio_odomto/Odometry/!-- PX4localposition odometry topic --remapfrom~px4_odomto/mavros/local_position/odom/!-- MAVROS vision pose topic --remapfrom~vision_poseto/mavros/vision_pose/pose/!-- 配置参数 --paramnamewindow_sizetypeintvalue8/paramnamepublish_ratetypedoublevalue30.0//node/launch关键技术实现1. 滑动窗口平均实现了SlidingWindowAverage类用于平滑 yaw 角数据提高定位稳定性classSlidingWindowAverage:def__init__(self,window_size):self.window_sizewindow_size self.data_queuedeque(maxlenwindow_size)# 使用固定大小的队列defadd_data(self,new_data):# 如果队列非空且新数据与最新数据差异过大重置队列ifself.data_queueandabs(new_data-self.data_queue[-1])0.01:self.data_queue.clear()self.data_queue.append(new_data)returnself.get_avg()2. 位姿转换与发布将 Fast-LIO 提供的位姿数据转换为 MAVROS 所需的格式并以稳定的频率发布defpublish_vision_pose(self,event):ifnotself.init_flag:return# 旋转位姿以对齐初始 yaw 角rot_matrixtf.transformations.quaternion_matrix(self.init_q)[:3,:3]p_enunp.dot(rot_matrix,self.p_lidar_body)# 构建视觉位姿消息vision_msgPoseStamped()vision_msg.header.stamprospy.Time.now()vision_msg.header.frame_idmapvision_msg.pose.position.xp_enu[0]vision_msg.pose.position.yp_enu[1]vision_msg.pose.position.zp_enu[2]vision_msg.pose.orientation.xself.q_mav[0]vision_msg.pose.orientation.yself.q_mav[1]vision_msg.pose.orientation.zself.q_mav[2]vision_msg.pose.orientation.wself.q_mav[3]# 发布消息self.vision_pub.publish(vision_msg)代码优化针对原始代码进行了以下优化使用 rospy.Timer 控制发布频率确保稳定的 30Hz 发布频率避免依赖 while 循环的精度问题使用固定大小的 deque简化滑动窗口实现自动管理队列大小添加参数化配置支持通过 launch 文件配置窗口大小和发布频率优化日志输出使用 throttle 减少终端输出频率提高性能改进初始化逻辑更清晰的初始化状态管理便于调试编译与运行编译功能包cd/home/rog/code/fast_drone_ws catkin_make--pkgfastlio_to_mavros运行功能包roslaunch fastlio_to_mavros fastlio_to_mavros.launch检查是否输出数据rostopicecho/mavros/vision_pose/pose查看话题订阅关系rqt_graph查看效果打开QGC到MAVLink检测查看VISION_POSITION_ESTIMATE视觉位置估计运行里程计转发节点查看EKF状态rostopicecho/mavros/estimator_status这份状态数据表明核心定位问题已经解决所有自动驾驶必需的状态位均已变为True飞控已经具备执行 AUTO_HOVER 等自主模式的条件。状态位关键变化解读标志位当前值含义状态判定attitude_status_flagTrue姿态滚转/俯仰/偏航有效✅ 基础条件满足velocity_horiz_status_flagTrue水平速度有效✅ 飞控能感知水平移动pos_horiz_rel_status_flagTrue相对水平位置有效✅核心外部里程计已被PX4识别并启用const_pos_mode_status_flagTrue位置控制模式已激活✅ 飞控已准备好执行悬停/定位指令pos_vert_abs_status_flagTrue垂直高度有效✅ 定高功能正常pos_horiz_abs_status_flagFalse绝对水平位置无效❌ 无GPS不影响我们用相对定位下一步测试 AUTO_HOVER 模式验证修复效果现在可以放心测试自主悬停步骤如下重启所有节点确保配置生效pkill-9roslaunchbash你的启动脚本.sh# 包含mavros/Fast-LIO/里程计转发解锁无人机通过RC遥控器切换到 AUTO_HOVER 模式观察飞控日志Failsafe activated提示应该彻底消失无人机应能稳定悬停无漂移。优化参数提升悬停稳定性若悬停时有轻微漂移可微调以下参数降低里程计噪声权重# 降低外部里程计的位置噪声让PX4更信任里程计数据rosrun mavros mavparamsetEKF2_POS_NOISE0.005rosrun mavros mavparamsetEKF2_VEL_NOISE0.005rosrun mavros mavparam save注意事项确保话题正确确保 Fast-LIO 正在发布/Odometry话题MAVROS 已正确连接并发布/mavros/local_position/odom话题飞控参数设置需要在 PX4 飞控中启用视觉定位输入EKF2 参数设置坐标系一致性检查 Fast-LIO 和 PX4 使用的坐标系定义是否一致启动顺序建议先启动 Fast-LIO 和 MAVROS再启动转换节点结论通过创建fastlio_to_mavros转换节点成功将 Fast-LIO 的视觉定位数据发送给飞控解决了无人机移动后飞控位置偏移的问题。该方案具有以下优点模块化设计作为独立功能包易于集成和维护可配置性支持通过参数调整窗口大小和发布频率稳定性使用滑动窗口平均提高了数据稳定性高效性优化的代码结构和日志输出减少了系统资源占用此实现为无人机提供了更准确的视觉定位确保无人机在移动后放回原处时能够准确悬停在期望位置。一键启动脚本tibostibos:~/auto_run$ cat auto_run_odom_to_PX4.sh#!/bin/bash# BEGIN EARLY_BOOT_VERIFY# Confirm this boot before startup delays to avoid accumulating warm-boot retries.echo[boot] Verifying bootloader and rootfs boot statusif[${EUID}-eq0];then/usr/sbin/nvbootctrl verifyelsesudo-n/usr/sbin/nvbootctrl verifyfiboot_verify_status$?if[${boot_verify_status}-ne0];thenecho[boot] Boot verification failed (status${boot_verify_status}); startup aborted2exit${boot_verify_status}fi# END EARLY_BOOT_VERIFYsleep10source/home/tibos/.bashrcsource/opt/ros/noetic/setup.bashecholivox_ros_driver2sleep10cd/home/tibos/code/livox_mid360s_wssourcedevel/setup.bashnohuproslaunch livox_ros_driver2 msg_MID360s.launchechofast_liosleep10nohuproslaunch fast_lio mapping_mid360.launchechomavrossleep10cd/home/tibos/code/mavros_wssourcedevel/setup.bashnohuproslaunch mavros px4.launchechofastlio_to_mavrossleep10cd/home/tibos/code/livox_mid360s_wssourcedevel/setup.bash# cd /home/tibos/code/fast_drone_ws# source devel/setup.bashnohuproslaunch fastlio_to_mavros fastlio_to_mavros.launch# echo fastlio_to_mavrossleep10cd/home/tibos/bag_save_auto1nohuprosbag record--split--duration60/livox/imu /livox/lidar /mavros/vision_pose/pose /mavros/setpoint_raw/attitude /mavros/gps_input/gps_input /mavros/local_position/posesleep10# sleep 99999exit0参考资料https://blog.csdn.net/qq_44998513/article/details/133144421https://blog.csdn.net/zlm2004/article/details/148501757?ops_request_miscelastic_search_miscrequest_id68cf906ad3b389dd1332eb1ff7323bbebiz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2allElasticSearch~search_v2-2-148501757-null-null.142v102pc_search_result_base2utm_termPX4%E6%97%A0%E4%BA%BA%E6%9C%BA%20mid360%E4%BD%BF%E7%94%A8fastliospm1018.2226.3001.4187https://blog.csdn.net/u010196944/article/details/134466325https://docs.px4.io/main/zh/ros/mavros_offboard_cpp
企业数字化 ERP 产品动态
相关推荐
【49】脑瘤数据集(有v5/v8模型)/YOLO脑瘤检测 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 18:46:28
ByteFF2:AI力场如何实现量子级液体预测突破? ByteFF2:AI力场如何实现量子级液体预测突破? 【免费下载链接】byteff2 项目地址: https://ai.gitcode.com/hf_mirrors/ByteDance-Seed/byteff2
导语:字节跳动最新发布的ByteFF2力场模型,通过融合图神经网络与量子力学数据… · 2026/11/3 18:46:28
70亿参数重塑音频智能:Kimi-Audio开源模型开启多模态交互新纪元 70亿参数重塑音频智能:Kimi-Audio开源模型开启多模态交互新纪元 【免费下载链接】Kimi-Audio-7B 我们推出 Kimi-Audio,一个在音频理解、生成与对话方面表现卓越的开源音频基础模型。本仓库提供 Kimi-Audio-7B 的模型检查点。 项目地址: https://ai.git… · 2026/11/3 18:44:26
什么是Unlimited-OCR-2?OCR-3.0时代百度无限文档解析模型完整指南 人工智能计算机视觉OCR多模态大模型 【免费下载链接】Unlimited-OCR-2 项目地址: https://ai.gitcode.com/hf_mirrors/baidu/Unlimited-OCR-2 点击查看 免费下载 Unlimited-OCR-2 是百度开源的超长文档解析模型(OCR 模型),主打&q… · 2026/11/3 19:26:23
Batch任务凌晨就提交,为什么仍错过08:00?把截止、兜底和去重补上 凌晨提交了一批AI摘要,08:00打开页面却发现任务还没完成。遇到这种情况,先确认程序有没有把“提交成功”当成“结果可用”:Batch是异步执行方式,拿到任务编号,并不代表已经生成了所有可交付的结果。 如果内容有明确截止… · 2026/11/3 19:26:23
Ego Lite怎样让AI操作网页?用一次真实表单演示看懂快照与回读 AI操作网页,不必每一步都盯着截图猜坐标。Ego Lite向Agent提供页面快照、填写、点击和结果读取等能力:模型先获得页面里有哪些控件,再调用工具操作浏览器,最后读取页面变化,决定是否继续。 下面用一个无账号、无外部请… · 2026/11/3 19:26:23
Fixture DRI Training_Fixture讲解 目录
一、坐标转换介绍
坐标转换介绍
坐标转换示例
如何实现坐标转换
CogTransform2DLinear 的方法介绍
形状坐标转换的方法介绍
坐标转换的功能
二、转换坐标
图像转换坐标
脚本转换坐标
用脚本转换坐标(MapPoint):
三、Mapping工具
MappingToolBlock流程
介绍 … · 2026/11/3 19:26:23
Docker Image-- 镜像命令详解与使用示例 目录
1. Docker 镜像是什么
2. 镜像命令详解
2.1 docker images
2.2 docker tag
2.3 docker pull
2.4 docker push
2.5 docker rmi
2.6 docker save
2.7 docker load
2.8 docker image inspect
2.9 docker history
2.10 docker image prune
2.11 docker build
2… · 2026/11/3 19:26:23
LinkedList知识 一、LinkedList 介绍LinkedList 是 List 接口的实现类,同时实现了Deque(双端队列)接口 ✅ List 共性:有序、可重复、带索引 底层:双向链表,每个 Node 节点:prev前驱指针 item数据 next后继指针… · 2026/11/3 19:25:22
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46