ROS无人机初始化GPS定位漂移误差,确保无人机稳定飞行
引言: 由于GPS在室外漂移的误差比较大,在长时间静止后启动,程序发布的位置可能已经和预期的位置相差较大,导致无法完成任务,尤其是气压计的数据不准,可能会导致无人机不能起飞或者一飞冲天。本文主要是在进行程序控制的时候,首先拿到最新的漂移误差,在此基础上进行程序控制,可以保证程序的稳定运行。
步骤一:创建订阅者订阅无人机的里程计信息
//创建一个Subscriber订阅者,订阅名为/mavros/local_position/odom的topic,注册回调函数local_pos_cb
ros::Subscriber local_pos_sub = nh.subscribe<nav_msgs::Odometry>("/mavros/local_position/odom", 10, local_pos_cb);
步骤二:创建相关变量,获取无人机的实时位置信息
这里定义了较多的变量,最重要的是位置和标志为,其余的可以自行设置
//定义变量,用于接收无人机的里程计信息
tf::Quaternion quat;
double roll, pitch, yaw;
float init_position_x_take_off =0;
float init_position_y_take_off =0;
float init_position_z_take_off =0;
bool flag_init_position = false;
nav_msgs::Odometry local_pos;
步骤三:定义回调函数,在回调函数中获取漂移值
//回调函数接收无人机的里程计信息
void local_pos_cb(const nav_msgs::Odometry::ConstPtr& msg)
{local_pos = *msg;if (flag_init_position==false && (local_pos.pose.pose.position.z!=0)){init_position_x_take_off = local_pos.pose.pose.position.x;init_position_y_take_off = local_pos.pose.pose.position.y;init_position_z_take_off = local_pos.pose.pose.position.z;flag_init_position = true; }tf::quaternionMsgToTF(local_pos.pose.pose.orientation, quat); tf::Matrix3x3(quat).getRPY(roll, pitch, yaw);
}
注:启动这个控制节点后,或订阅最新的初始位置,并且通过标志为控制只订阅一次,这个值就是最新的漂移值
步骤四:发布目标点,一定要把获取到的初始漂移值加上,如下:
//发布期望位置信息
pose.pose.position.x =init_position_x_take_off + 0;
pose.pose.position.y =init_position_y_take_off + 0;
pose.pose.position.z =init_position_z_take_off + ALTITUDE;
local_pos_pub.publish(pose);
这里ALTITUDE是我宏定义的0.5,表明无人机飞0.5米高度即可。室外使用的话,最好高度设置大于1米
步骤五:整体代码如下:
//包含ROS和MAVROS相关头文件
#include <string>
#include <ros/ros.h>
#include <geometry_msgs/PoseStamped.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <actionlib/client/simple_action_client.h>
#include <std_msgs/Bool.h>
#include <geometry_msgs/TwistStamped.h>
#include <mavros_msgs/PositionTarget.h>
#include <cmath>
#include <tf/transform_listener.h>
#include <nav_msgs/Odometry.h>
#include <mavros_msgs/CommandLong.h>
#include <string>
#include <geometry_msgs/Twist.h>#define ALTITUDE 0.5//定义变量,用于接收无人机的状态信息
mavros_msgs::State current_state;
void state_cb(const mavros_msgs::State::ConstPtr& msg);//定义变量,用于接收无人机的里程计信息
tf::Quaternion quat;
double roll, pitch, yaw;
float init_position_x_take_off =0;
float init_position_y_take_off =0;
float init_position_z_take_off =0;
bool flag_init_position = false;
nav_msgs::Odometry local_pos;
void local_pos_cb(const nav_msgs::Odometry::ConstPtr& msg);//回调函数接收无人机的状态信息
void state_cb(const mavros_msgs::State::ConstPtr& msg)
{current_state = *msg;
}//回调函数接收无人机的里程计信息
void local_pos_cb(const nav_msgs::Odometry::ConstPtr& msg)
{local_pos = *msg;if (flag_init_position==false && (local_pos.pose.pose.position.z!=0)){init_position_x_take_off = local_pos.pose.pose.position.x;init_position_y_take_off = local_pos.pose.pose.position.y;init_position_z_take_off = local_pos.pose.pose.position.z;flag_init_position = true; }tf::quaternionMsgToTF(local_pos.pose.pose.orientation, quat); tf::Matrix3x3(quat).getRPY(roll, pitch, yaw);
}
int main(int argc, char **argv)
{//防止中文乱码setlocale(LC_ALL, "");//ROS节点初始化,节点名为offboard_single_positionros::init(argc, argv, "offboard_single_position");//创建节点句柄ros::NodeHandle nh;ros::Publisher local_pos_pub = nh.advertise<geometry_msgs::PoseStamped>("mavros/setpoint_position/local", 10);//创建一个Subscriber订阅者,订阅名为/mavros/state的topic,注册回调函数state_cbros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>("mavros/state", 10, state_cb);//创建一个Subscriber订阅者,订阅名为/mavros/local_position/odom的topic,注册回调函数local_pos_cbros::Subscriber local_pos_sub = nh.subscribe<nav_msgs::Odometry>("/mavros/local_position/odom", 10, local_pos_cb);//创建一个服务客户端,连接名为/mavros/cmd/arming的服务,用于请求无人机解锁ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>("mavros/cmd/arming");//创建一个服务客户端,连接名为/mavros/set_mode的服务,用于请求无人机进入offboard模式ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode>("mavros/set_mode");//设置话题发布频率,需要大于2Hz,飞控连接有500ms的心跳包ros::Rate rate(20.0);//等待连接到飞控while(ros::ok() && !current_state.connected){ros::spinOnce();rate.sleep();}//设置无人机的期望位置geometry_msgs::PoseStamped pose;pose.pose.position.x =init_position_x_take_off + 0;pose.pose.position.y =init_position_y_take_off + 0;pose.pose.position.z =init_position_z_take_off + ALTITUDE;//send a few setpoints before startingfor(int i = 100; ros::ok() && i > 0; --i){local_pos_pub.publish(pose);ros::spinOnce();rate.sleep();}//定义客户端变量,设置为offboard模式mavros_msgs::SetMode offb_set_mode;offb_set_mode.request.custom_mode = "OFFBOARD";//定义客户端变量,请求无人机解锁mavros_msgs::CommandBool arm_cmd;arm_cmd.request.value = true;//记录当前时间,并赋值给变量last_requestros::Time last_request = ros::Time::now();while(ros::ok()){//请求进入OFFBOARD模式if( current_state.mode != "OFFBOARD" && (ros::Time::now() - last_request > ros::Duration(5.0))){if( set_mode_client.call(offb_set_mode) && offb_set_mode.response.mode_sent){ROS_INFO("Offboard enabled");}last_request = ros::Time::now();}else {//请求解锁if( !current_state.armed && (ros::Time::now() - last_request > ros::Duration(5.0))){if( arming_client.call(arm_cmd) && arm_cmd.response.success){ROS_INFO("Vehicle armed");}last_request = ros::Time::now();}}if(fabs(local_pos.pose.pose.position.z- init_position_z_take_off -ALTITUDE)<0.2){ if(ros::Time::now() - last_request > ros::Duration(3.0)){break;}}//发布期望位置信息pose.pose.position.x =init_position_x_take_off + 0;pose.pose.position.y =init_position_y_take_off + 0;pose.pose.position.z =init_position_z_take_off + ALTITUDE;local_pos_pub.publish(pose);ros::spinOnce();rate.sleep();} while(ros::ok()){pose.pose.position.x =init_position_x_take_off + 0;pose.pose.position.y =init_position_y_take_off + 0;pose.pose.position.z =init_position_z_take_off + ALTITUDE; local_pos_pub.publish(pose);ros::spinOnce();rate.sleep();}return 0;
}相关文章:
ROS无人机初始化GPS定位漂移误差,确保无人机稳定飞行
引言: 由于GPS在室外漂移的误差比较大,在长时间静止后启动,程序发布的位置可能已经和预期的位置相差较大,导致无法完成任务,尤其是气压计的数据不准,可能会导致无人机不能起飞或者一飞冲天。本文主要是在进…...
k8s网络类型
k8s中的通信模式: pod内部之间容器与容器之间的通信。 在同一个pod中的容器共享资源和网络,使用同一个网络命名空间。可以直接通信的。 同一个node节点之内,不同pod之间的通信。 每一个pod都有一个全局的真实的IP地址,同一个n…...
Seata 中封装了四种分布式事务模式,分别是: AT 模式, TCC 模式, Saga 模式, XA 模式,
文章目录 seata概述Seata 中封装了四种分布式事务模式,分别是:AT 模式,TCC 模式,Saga 模式,XA 模式, 今天我们来聊聊seata seata 概述 在微服务架构下,由于数据库和应用服务的拆分,…...
为什么设计制造行业需要数据加密?
设计制造行业是一个涉及多种技术、工艺、材料和产品的广泛领域,它对经济和社会的发展有着重要的影响。然而,随着数字化、智能化和网络化的发展,设计制造行业也面临着越来越多的数据安全风险,如数据泄露、数据篡改、数据窃取等。这…...
查看ios app运行日志
摘要 本文介绍了一款名为克魔助手的iOS应用日志查看工具,该工具可以方便地查看iPhone设备上应用和系统运行时的实时日志和奔溃日志。同时还提供了奔溃日志分析查看模块,可以对苹果奔溃日志进行符号化、格式化和分析,极大地简化了开发者的调试…...
怎么卸载macOS上的爱思助手如何卸载macOS上的logitech g hub,如何卸载顽固macOS应用
1.在App Store里下载Cleaner One Pro (注意,不需要订阅付费!!!白嫖基础功能就完全够了!!!) 2.运行软件,在左侧目录中选择“应用程序管理”,然后点…...
侦探IP“去推理化”:《名侦探柯南》剧场版走过26年
2023年贺岁档,柯南剧场版的第26部《黑铁的鱼影》如期上映。 这部在日本狂卷票房128亿日元的作品,被誉为有史以来柯南剧场版在商业成绩上最好的一部。 但该作在4月份日本还未上映前,就于国内陷入了巨大的争议。 试映内容里,灰原…...
图论 经典例题
1 拓扑排序 对有向图的节点排序,使得对于每一条有向边 U-->V U都出现在V之前 *有环无法拓扑排序 indegree[], nxs[];//前者表示节点 i 的入度,后者表示节点 i 指向的节点 queue [] for i in range(n):if indege[i] 0: queue.add(i)// 入度为0的节…...
Oracle数据updater如何回滚
1.查询update语句执行的时间节点 ; select t.FIRST_LOAD_TIME, t.SQL_TEXT from v$sqlarea t where to_char(t.FIRST_LOAD_TIME) > 2023-03-19/17:00:00 order by t.FIRST_LOAD_TIME desc;开启表的行迁移 alter table test enable row movement;3.回滚表数据到…...
redis开启密码验证
开启密码验证 (1)配置文件中设置 redis.conf文件里面配置requirepass参数,redis认证密码:foobared,然后重启redis服务 ./redis-cli 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> CONFIG SET requi…...
一种删除 KubeSphere 中一直卡在 Terminating 的 Namespace--KubeSphere Logging System的简单方法
文章目录 一、问题提出二、删除方法1,获取kubesphere-logging-syste的详细信息json文件2,编辑kubesphere-logging-system.json3,执行清理命令 三、检查结果 一、问题提出 在使用 KubeSphere 的时候发现有一个日志服务KubeSphere Logging Sys…...
Flink1.17实战教程(第七篇:Flink SQL)
系列文章目录 Flink1.17实战教程(第一篇:概念、部署、架构) Flink1.17实战教程(第二篇:DataStream API) Flink1.17实战教程(第三篇:时间和窗口) Flink1.17实战教程&…...
nest定时任务调用service报错
报错: ERROR [Scheduler] ValidationError: Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instances identity map, use allowGlobalContext configuration option or fork() i…...
[Angular] 笔记 11:可观察对象(Observable)
chatgpt: 在 Angular 中,Observables 是用于处理异步数据流的重要工具。它们被广泛用于处理从异步操作中获取的数据,比如通过 HTTP 请求获取数据、定时器、用户输入等。Observables 提供了一种机制来订阅这些数据流,并可以在数据到达时执行相…...
【论文阅读】Resource Allocation for Text Semantic Communications
这是一篇关于语义通信中资源分配的论文。全文共5页,篇幅较短。 目录在这里 摘要关键字引言语义通信资源分配贡献公式符号 系统模型DeepSC TransmitterTransmission ModelDeepSC Receiver 语义感知资源分配策略Semantic Spectral Efficiency (S-SE&#…...
VMware16 pro 安装openEuler-23.09-x86_64,详细操作流程+详图。
1.环境: win11, vmware16 pro, openEuler-23.09-x86_64-dvd.iso 社区版openEuler 23.09官方下载地址: openEuler下载 | 欧拉系统ISO镜像 | openEuler社区官网欧拉操作系统(openEuler, 简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、…...
Mybatis 动态 SQL - script,bind,多数据库支持
script 在使用注解的映射器类中使用动态SQL时,可以使用<script>元素。例如: Update({"<script>","update Author"," <set>"," <if testusername ! null>username#{username},</if&g…...
Scikit-Learn线性回归(一)
Scikit-Learn线性回归一 1、线性回归概述1.1、回归1.2、线性1.3、线性回归1.4、线性回归的优缺点1.5、线性回归与逻辑回归2、线性回归的原理2.1、线性回归的定义与原理2.2、线性回归的损失函数3、Scikit-Learn线性回归3.1、Scikit-Learn库3.2、Scikit-Learn线性回归API3.3、Sci…...
Mybatis 动态 SQL - choose, when, otherwise
有时候我们并不希望所有的条件都生效,而是只想在多个选项中选择一个。类似于Java中的switch语句,MyBatis提供了 <choose>元素。 让我们使用上面的例子,但现在如果提供了标题,则只搜索标题;如果提供了作者&a…...
idea Spring Boot项目使用JPA创建与数据库链接
1.pom.xml文件中添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
