当前位置: 首页 > news >正文

Autoware 定位之初始姿态输入(九)

0. 简介

这一讲按照《Autoware 技术代码解读(三)》梳理的顺序,我们来说一说Autoware中的初始化操作,这个软件包当中完成了ekf_localizer发送初始姿态的包。它接收来自GNSS/用户的粗略估计的初始姿态。将姿态传递给ndt_scan_matcher,并通过服务从ndt_scan_matcher获取计算出的自我姿态。最后,它将初始姿态发布到ekf_localizer。

在这里插入图片描述

1. 代码阅读

1.1 copy_vector_to_array.hpp

定义了两个模板函数。第一个函数copy_vector_to_array将std::vector中的数据复制到std::array中。它首先检查输入的vector和目标数组array的大小是否相同,如果不同则抛出异常。然后使用std::copy_n函数将vector中的前N个元素复制到array中。

第二个函数get_covariance_parameter的作用是从节点获取具有特定名称的协方差参数,并将其转换为长度为36的std::array。它首先从节点中获取参数,然后创建一个长度为36的std::array并调用copy_vector_to_array函数将获取的参数复制到std::array中,最后返回这个std::array。

/// @brief 将std::vector中的数据复制到std::array中
/// @tparam T 向量和数组中元素的类型
/// @tparam N 表示目标数组的大小
/// @param vector 输入的std::vector对象
/// @param array 要将数据复制到的std::array对象
template <typename T, size_t N>
void copy_vector_to_array(const std::vector<T> & vector, std::array<T, N> & array)
{if (N != vector.size()) {//检查输入的vector和目标数组array的大小是否相同// throws the error to prevent causing an anonymous bug// such as only partial array is initializedconst auto v = std::to_string(vector.size());const auto n = std::to_string(N);throw std::invalid_argument("Vector size (which is " + v + ") is different from the copy size (which is " + n + ")");//如果不同,则抛出一个std::invalid_argument异常}std::copy_n(vector.begin(), N, array.begin());//它使用std::copy_n函数将vector中的前N个元素复制到array中
}/// @brief 该函数的作用是从节点获取具有特定名称的协方差参数,并将其转换为长度为36的std::array。
/// @tparam NodeT 表示节点的类型
/// @param node 指向节点的指针
/// @param name 要获取的参数的名称
/// @return 
template <class NodeT>
std::array<double, 36> get_covariance_parameter(NodeT * node, const std::string & name)
{const auto parameter = node->template declare_parameter<std::vector<double>>(name);std::array<double, 36> covariance;copy_vector_to_array(parameter, covariance);return covariance;
}

1.2 ekf_localization_trigger_module.cpp

这段代码是一个用于与 ROS 节点通信的模块,它初始化了一个日志记录器和一个用于与 EKF 触发服务通信的客户端。构造函数接受一个指向 ROS 节点的指针,然后初始化了日志记录器和客户端。

send_request 函数用于发送 EKF 触发请求,接受一个布尔类型的参数,表示是否激活或停止 EKF 定位模块。根据输入的参数,确定了具体的 EKF 触发命令名称,然后检查服务是否准备就绪,如果不准备就绪则抛出异常。

接着异步发送 EKF 触发请求,然后通过获取响应结果来输出相应的信息,表示 EKF 触发成功或失败。整体来说,这段代码是一个用于与 EKF 触发服务通信的模块,提供了初始化和发送请求的功能。通过构造函数初始化客户端和日志记录器,然后通过 send_request 函数发送 EKF 触发请求,并处理响应结果。

/// @brief 构造函数,它接受一个指向ROS节点的指针,并在其中初始化了一个日志记录器和一个用于与EKF触发服务通信的客户端
/// @param node 指向ROS节点的指针
EkfLocalizationTriggerModule::EkfLocalizationTriggerModule(rclcpp::Node * node)
: logger_(node->get_logger())
{client_ekf_trigger_ = node->create_client<SetBool>("ekf_trigger_node");
}/// @brief 用于发送EKF触发请求。它接受一个布尔类型的参数flag
/// @param flag 是否激活或者停止EKF定位模块
void EkfLocalizationTriggerModule::send_request(bool flag) const
{const auto req = std::make_shared<SetBool::Request>();std::string command_name;req->data = flag;if (flag) {command_name = "Activation";} else {command_name = "Deactivation";}//根据输入的flag值,确定了EKF触发的具体命令名称,分别为"Activation"和"Deactivation"。//检查EKF触发服务是否准备就绪if (!client_ekf_trigger_->service_is_ready()) {throw component_interface_utils::ServiceUnready("EKF triggering service is not ready");}//异步发送EKF触发请求auto future_ekf = client_ekf_trigger_->async_send_request(req);//通过future_ekf获取响应结果,在成功时输出信息表示EKF触发成功if (future_ekf.get()->success) {RCLCPP_INFO(logger_, "EKF %s succeeded", command_name.c_str());} else {RCLCPP_INFO(logger_, "EKF %s failed", command_name.c_str());throw ServiceException(Initialize::Service::Response::ERROR_ESTIMATION, "EKF " + command_name + " failed");}
}

1.3 gnss_module.cpp

这段代码是一个用于处理GNSS定位模块数据的类,其中包括了构造函数和获取位置信息的函数。构造函数接受一个指向ROS节点的指针作为参数,用于初始化订阅GNSS定位数据的功能。获取位置信息的函数首先检查是否收到了GNSS定位数据,然后计算位置信息的时间戳是否超时。如果位置信息仍在有效期内,就获取并处理最新的位置信息,并对位置信息进行拟合处理,得到拟合结果。最终返回处理后的位置信息。整体来说,这段代码主要是用于从GNSS定位模块获取位置信息,并对位置信息进行处理和拟合。

/// @brief GnssModule类的构造函数,接受一个rclcpp::Node类型的指针作为参
/// @param node 指向ROS节点的指针
GnssModule::GnssModule(rclcpp::Node * node) : fitter_(node)
{sub_gnss_pose_ = node->create_subscription<PoseWithCovarianceStamped>("gnss_pose_cov", 1, [this](PoseWithCovarianceStamped::ConstSharedPtr msg) { pose_ = msg; });clock_ = node->get_clock();timeout_ = node->declare_parameter<double>("gnss_pose_timeout");
}/// @brief 该函数用于获取GNSS定位模块的位置信息
/// @return 返回一个PoseWithCovarianceStamped类型的对象
geometry_msgs::msg::PoseWithCovarianceStamped GnssModule::get_pose()
{using Initialize = localization_interface::Initialize;
// 函数内部首先检查是否收到了GNSS定位数据if (!pose_) {throw component_interface_utils::ServiceException(Initialize::Service::Response::ERROR_GNSS, "The GNSS pose has not arrived.");}
// 计算当前时间与最新收到位置信息的时间戳之间的差值elapsedconst auto elapsed = rclcpp::Time(pose_->header.stamp) - clock_->now();if (timeout_ < elapsed.seconds()) {throw component_interface_utils::ServiceException(Initialize::Service::Response::ERROR_GNSS, "The GNSS pose is out of date.");}//如果位置信息仍在有效期内,那么就获取并处理最新的位置信息PoseWithCovarianceStamped pose = *pose_;const auto fitted = fitter_.fit(pose.pose.pose.position, pose.header.frame_id);//位置信息进行拟合处理,得到拟合结果fitted,对应了map下面的map_height_fitterif (fitted) {pose.pose.pose.position = fitted.value();}return pose;
}

1.4 ndt_localization_trigger_module.cpp

用于与 NDT(Normal Distribution Transform)触发器服务进行通信。构造函数初始化了该类的日志记录器和与 NDT 触发器服务的通信客户端。send_request 方法用于向 NDT 触发器服务发送请求,请求包括一个布尔值,表示要执行的操作。根据布尔值的不同,确定要执行的命令名称,然后通过客户端异步发送请求,并跟踪请求的状态。如果请求成功,则记录日志并返回成功消息;如果失败,则记录日志并抛出服务异常。在发送请求之前,还会检查 NDT 触发器服务是否准备就绪,如果不准备就绪,则抛出服务未准备就绪的异常。

/// @brief 构造函数,用于初始化NdtLocalizationTriggerModule对象
/// @param node 指向ROS节点的指针
NdtLocalizationTriggerModule::NdtLocalizationTriggerModule(rclcpp::Node * node)
: logger_(node->get_logger())
{client_ndt_trigger_ = node->create_client<SetBool>("ndt_trigger_node");
}/// @brief 发送请求给Ndt触发器服务
/// @param flag bool类型的flag,表示要执行的操作
void NdtLocalizationTriggerModule::send_request(bool flag) const
{const auto req = std::make_shared<SetBool::Request>();std::string command_name;//根据flag的值确定command_namereq->data = flag;if (flag) {command_name = "Activation";} else {command_name = "Deactivation";}if (!client_ndt_trigger_->service_is_ready()) {// 检查ndt触发器服务是否准备就绪throw component_interface_utils::ServiceUnready("NDT triggering service is not ready");}auto future_ndt = client_ndt_trigger_->async_send_request(req);//通过客户端client_ndt_trigger_异步发送请求req,并获得future_ndt以跟踪请求的状态if (future_ndt.get()->success) {RCLCPP_INFO(logger_, "NDT %s succeeded", command_name.c_str());} else {RCLCPP_INFO(logger_, "NDT %s failed", command_name.c_str());throw ServiceException(Initialize::Service::Response::ERROR_ESTIMATION, "NDT " + command_name + " failed");}
}

1.5 stop_check_module.cpp

构造函数接受一个Node句柄和一个缓冲区时间作为参数,并使用这些参数初始化StopCheckModule对象。在构造函数中,它创建了一个订阅者(subscription),用于订阅名为"stop_check_twist"的TwistWithCovarianceStamped消息,并指定回调函数为on_twist

…详情请参照古月居

相关文章:

Autoware 定位之初始姿态输入(九)

0. 简介 这一讲按照《Autoware 技术代码解读&#xff08;三&#xff09;》梳理的顺序&#xff0c;我们来说一说Autoware中的初始化操作&#xff0c;这个软件包当中完成了ekf_localizer发送初始姿态的包。它接收来自GNSS/用户的粗略估计的初始姿态。将姿态传递给ndt_scan_match…...

C# 自定义传值窗体-适合多参数传值

将子窗体的值回传到父窗体中&#xff0c;或者最简单的需要一个设置参数的对话框&#xff0c;其作用也就是得到其中的参数。下面我们详细介绍实现的过程。 文章目录 一、定义一个事件类二、在参数窗体中定义事件三、订阅事件消息 一、定义一个事件类 首先&#xff0c;我们必须…...

Ubuntu20.04+ros-noetic配置Cartographer

一、概述 因为要配置激光SLAM&#xff0c;Cartographer属于激光雷达SLAM 中比较经典的一款&#xff0c;在学习之前先将其在Ubuntu20.04首先配置出来并成功运行demo。 二、具体操作 &#xff08;一&#xff09;概述 使用平台是Windows的wsl2上的Ubuntu20.04子系统&#xff0c;…...

Visual Studio 2022 下载和安装

文章目录 概述一&#xff0c;下载步骤二&#xff0c;安装过程 概述 Visual Studio 提供 AI 增强功能&#xff0c;例如用于上下文感知代码补全的 IntelliSense 和可利用开源代码中的 AI 模式的 IntelliCode。 集成的 GitHub Copilot 提供 AI 支持的代码补全、聊天辅助、调试建议…...

在 Windows 环境下实现免密登录 Linux 服务器

在 Windows 环境下实现免密登录 Linux 服务器 1. 生成 SSH 密钥对2. 手动将公钥上传到服务器方法 1&#xff1a;使用 scp 传输公钥文件方法 2&#xff1a;使用 Windows 内置工具或编辑器手动复制 3. 测试免密登录4. 可能需要的工具 以下是在 Windows 中实现免密登录的步骤&…...

Computer Exercise

每日一练 单选题 在计算机机箱前面板接口插针上&#xff08;     C   &#xff09;表示复位开关。 A.SPK    B.PWRLED    C.RESET    D.HDDLED每台PC机最多可接&#xff08;     B   &#xff09;块IDE硬盘。 A.2    B.4    C.6    D.8&#xff08;    …...

利用Stable Diffusion AI图像模型评估智能车模型算法表现(下篇)

今天小李哥将介绍亚马逊云科技的Jupyter Notebook机器学习托管服务Amazon SageMaker上&#xff0c;通过AI图像生成模型Stable Diffusion Upscale和Depth、向量知识库和LangChain Agent&#xff0c;生成用于AI 智能车模型训练的图像数据集并评估模型表现。 本系列共分为上下两篇…...

音视频入门基础:WAV专题(8)——FFmpeg源码中计算WAV音频文件AVStream的time_base的实现

一、引言 本文讲解FFmpeg源码对WAV音频文件进行解复用&#xff08;解封装&#xff09;时&#xff0c;其AVStream的time_base是怎样被计算出来的。 二、FFmpeg源码中计算WAV音频文件AVStream的time_base的实现 从《音视频入门基础&#xff1a;WAV专题&#xff08;5&#xff09…...

springboot中的请求过滤filter与拦截interceptor分析

首先我们要定义一个类&#xff0c;实现标准的过滤器 import lombok.extern.slf4j.Slf4j;import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException;WebFilter("/*") Slf4j public class AuthFilter implements Filter {Overr…...

Node.js入门与生态全解析:包管理与构建工具详解

Node.js入门与生态全解析&#xff1a;包管理与构建工具详解 目录 &#x1f3af; 包管理 使用 npm 和 yarn&#xff1a;项目依赖管理的利器创建和发布 npm 包&#xff1a;实现模块化与共享 ⚙️ 构建工具 使用 Webpack 和 Babel&#xff1a;高效打包与代码转换配置构建流程&am…...

828华为云征文|华为云Flexus X实例docker部署harbor镜像仓库

828华为云征文&#xff5c;华为云Flexus X实例docker部署harbor镜像仓库 华为云最近正在举办828 B2B企业节&#xff0c;Flexus X实例的促销力度非常大&#xff0c;特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Nginx等服务的需求&#xff0c;一定不要错…...

fedora siliverblue adb

开始 1、找到手机 usb 的 idV&#xff1a; $ lsusb ... Bus 001 Device 012: ID 22d9:2766 OPPO Electronics Corp. PECM30是 22d9 2、在 toolbox 外面添加 udev&#xff1a; sudo nano /etc/udev/rules.d/51-android.rulesSUBSYSTEM"usb", ATTR{idVendor}"…...

mybatisplus查询指定字段

使用mybatisplus查询指定字段 实体类 package com.test.entity;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annota…...

探寻 IP 代理地址繁多之因

在当今的网络天地里&#xff0c;IP 代理服务随处可见&#xff0c;且令人称奇的是&#xff0c;它们常常手握海量的 IP 地址可供挑选。那么&#xff0c;究竟是什么原因使得 IP 代理拥有如此众多的地址呢&#xff1f;现在&#xff0c;就让我们一同深入探究这个神秘现象背后的缘由。…...

MyBatis常见面试题

文章目录 说说 MyBatis 执行流程&#xff1f;1. 加载配置文件和映射文件2. 构建 SqlSessionFactory3. 创建 SqlSession4. 调用 Mapper 方法5. 处理参数和结果映射6. 事务管理7. 释放资源简化流程图&#xff1a; MyBatis 和 Hibernate 有什么不同&#xff1f;1. **对象关系映射层…...

Swift 运算符

Swift 运算符 Swift 是一种强类型编程语言,由苹果公司开发,用于iOS、macOS、watchOS和tvOS应用程序的开发。Swift 运算符是其核心特性之一,它允许开发者执行各种数学和逻辑操作。本文将详细介绍 Swift 中的运算符,包括它们的功能、用法和类型。 Swift 运算符概述 Swift …...

PDF转PPT神器揭秘!3步操作,轻松打造2024年会议爆款PPT

现在是数字化的时代&#xff0c;PDF 和 PPT 对职场的人来说可重要了。PDF 文件格式稳&#xff0c;也好分享&#xff0c;所以大家都爱用。PPT 演示起来很厉害&#xff0c;在开会、讲座的时候特别管用。不过呢&#xff0c;要是有好多 PDF 文件&#xff0c;咋能快点把它们变成好看…...

✨机器学习笔记(一)—— 监督学习和无监督学习

1️⃣ 监督学习&#xff08;supervised learning&#xff09; ✨ 两种主要类型的监督学习问题&#xff1a; 回归&#xff08;regression&#xff09;&#xff1a;predict a number in infinitely many possible outputs. 分类&#xff08;classification&#xff09;&#xff1…...

【Netty】实战:基于Http的Web服务器

目录 一、实现ChannelHandler 二、实现ChannelInitializer 三、实现服务器启动程序 四、测试 本文来实现一个简单的Web服务器&#xff0c;当用户在浏览器访问Web服务器时&#xff0c;可以返回响应的内容给用户。很简单&#xff0c;就三步。 一、实现ChannelHandler pack…...

4K4D: Real-Time 4D View Synthesis at 4K Resolution 学习笔记

本文是学习4K4D的笔记记录 Project Page&#xff1a;https://zju3dv.github.io/4k4d/ 文章目录 1 Pipeline1.1 特征向量的计算1.2 几何建模1.3 外观建模⭐1&#xff09; 球谐函数SH模型2&#xff09; 图像融合技术 1.4 可微分深度剥离渲染 2 Train&#xff08;loss&#xff09;…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...