在Ubuntu 20.04上,ROS 2 Foxy,GCC版本9.4.0,C++ rclcpp节点。
完全没有文档记录的消息构建器模式的工作原理如下(例如Odometry)。
#include <nav_msgs/msg/odometry.hpp>
// https://docs.ros2.org/foxy/api/nav_msgs/msg/Odometry.html
nav_msgs::msg::Odometry const odom = nav_msgs::build<nav_msgs::msg::Odometry>()
.header(std_msgs::msg::Header()) .child_frame_id("")
.pose(geometry_msgs::msg::PoseWithCovariance())
.twist(geometry_msgs::msg::TwistWithCovariance());
// This works // Excuse typos
这与“经典”风格相反(因为ROS委员会不允许使用参数进行初始化):
nav_msgs::msg::Odometry odom; // Notice can't make it const
odom.header = std_msgs::msg::Header();
odom.header.stamp = builtin_interfaces::msg::Time(); // or = node.get_clock()->now();
odom.header.frame_id = "...";
// ... etc, fill in other odometry members
问题:但是很多时候我会遇到一个隐含的错误,我不知道为什么。例如,如果我尝试:
odom.header = std_msgs::build<std_msgs::msg::Header>() // Error here, on ')'
.stamp(node.get_clock()->now()).frame_id("map");
**错误:**在扣除auto
之前使用auto std_msgs::build() [with MessageType = std_msgs::msg::Header_<std::allocator<void> >]
我试图使类型尽可能明确;强制转换为目标类型,创建目标类型的中间变量,没有错误的更改。甚至要理解构建器模式的存在,除非你在互联网上找到一些神秘的涂鸦(像这样),你必须深入研究生成的头文件,所以我这样做了。你会发现
/// vim /opt/ros/foxy/include/std_msgs/msg/header.hpp
// generated from rosidl_generator_cpp/resource/idl.hpp.em
// generated code does not contain a copyright notice
#ifndef STD_MSGS__MSG__HEADER_HPP_
#define STD_MSGS__MSG__HEADER_HPP_
#include "std_msgs/msg/detail/header__struct.hpp"
#include "std_msgs/msg/detail/header__builder.hpp"
#include "std_msgs/msg/detail/header__traits.hpp"
#endif // STD_MSGS__MSG__HEADER_HPP_
/// vim /opt/ros/foxy/include/std_msgs/msg/detail/header__builder.hpp
// ...
namespace std_msgs {
namespace msg {
namespace builder {
// ... bunch of builder classes calling the next, ex:
class Init_Header_stamp { ... };
} // namespace builder
} // namespace msg
template<typename MessageType>
auto build();
template<>
inline
auto build<::std_msgs::msg::Header>()
{
return std_msgs::msg::builder::Init_Header_stamp();
}
} // namespace std_msgs
以此为指导,我想知道如果我在代码中重复/复制粘贴模板声明,并用实际类型替换auto
,会不会起作用......但在这一点上,我的c++ fu已经用尽了,所有的鹅卵石替换只是给出了更多奇怪的错误。
1条答案
按热度按时间bzzcjhmw1#
解决方案:父类型包含子类型定义,但不包含构建器定义。在本例中,要包含Odometry并在Header上使用构建器模式,还需要
#include <std_msgs/msg/header.hpp>
。为什么:(不,真的,为什么要这样实现,文档在哪里)
因此,如果您使用它的构建器模式,请手动包含每个标题。