ROS2 C++消息生成器模式:在自动扣除之前错误使用自动

kzmpq1sx  于 2023-02-14  发布在  其他
关注(0)|答案(1)|浏览(182)

在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已经用尽了,所有的鹅卵石替换只是给出了更多奇怪的错误。

bzzcjhmw

bzzcjhmw1#

解决方案:父类型包含子类型定义,但不包含构建器定义。在本例中,要包含Odometry并在Header上使用构建器模式,还需要#include <std_msgs/msg/header.hpp>
为什么:(不,真的,为什么要这样实现,文档在哪里)

/// In vim /opt/ros/foxy/include/nav_msgs/msg/detail/odometry__struct.hpp
// Include directives for member types
// Member 'header'
#include "std_msgs/msg/detail/header__struct.hpp"
// Member 'pose'
#include "geometry_msgs/msg/detail/pose_with_covariance__struct.hpp"
// Member 'twist'
#include "geometry_msgs/msg/detail/twist_with_covariance__struct.hpp"
/// Notice, doesn't include the full child header, which also includes __builder.hpp,
/// but just the sub-header with type definitions, __struct.hpp!

因此,如果您使用它的构建器模式,请手动包含每个标题。

相关问题