**关闭。**此题需要debugging details。目前不接受答复。
编辑问题以包含desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答这个问题。
5天前关闭。
Improve this question
我创建了一个使用sensor_msgs IMU
的C++ ROS2节点。在头文件中包含sensor_msg,还声明了IMU传感器消息。仍然没有真正明确的错误来。当构建它时,我得到了错误:
error: ‘using element_type = const struct sensor_msgs::msg::Imu_<std::allocator<void> >’ {aka ‘const struct sensor_msgs::msg::Imu_<std::allocator<void> >’} has no member named ‘imu’
199 | imu_q.w() = imu_msg->imu.orientation.w;
ROS节点为:
#include <backhoe_perception/plane_segmentation.hpp>
#include <limits>
#include <vector>
#include <memory>
#include <string>
namespace backhoe_perception {
PlaneSegmentation::PlaneSegmentation(
const rclcpp::NodeOptions &options,
const std::string node_name):
XNode(node_name, options),
buffer_(5) {
/* message filter buffer size */
this->buffer_ = this->getParameterValue(
"buffer", this->buffer_);
// === parameters related to pub/sub ==
// whether the input pcd is a pcd with normals
this->is_pcd_with_normal_ = this->getParameterValue(
"is_pcd_with_normal", false);
// for speed, publish only ground plane coeffs
this->publish_only_gd_plane_coeffs_ = this->getParameterValue(
"publish_only_coeffs", true);
// === parameters related to iterative RANSAC ==
// minimum number of inliers for a planar segment
// to be considered a ground plane candidate
this->min_inliers_ = this->getParameterValue(
"min_inliers", 300);
// min number of iterative RANSAC trials
this->min_iterative_ransac_trials_ = this->getParameterValue(
"min_iterative_ransac_trials", 2);
// max number of iterative RANSAC trials
this->max_iterative_ransac_trials_ = this->getParameterValue(
"max_iterative_ransac_trials", 5);
// min number of points to perform RANSAC on
this->min_points_iterative_ransac_ = this->getParameterValue(
"min_points_iterative_ransac", 1000);
// min ratio of inliers:input pcd to perform early stopping
// on iterative RANSAC
this->iterative_ransac_early_stopping_inlier_ratio_ =
this->getParameterValue(
"iterative_ransac_early_stopping_inlier_ratio", 0.5f);
// == RANSAC settings (per-iteration) ==
this->use_normal_with_ransac_ = this->getParameterValue(
"use_normal_with_ransac", true);
this->ransac_num_threads_ = this->getParameterValue(
"ransac_num_threads", 1);
this->ransac_max_iterations_ = this->getParameterValue(
"ransac_max_iterations", 50);
this->ransac_outlier_threshold_ = this->getParameterValue(
"ransac_outlier_threshold", 0.3);
this->ransac_normal_distance_weight_ = this->getParameterValue(
"ransac_normal_distance_weight", 0.3);
this->tree_ = pcl::search::KdTree<PointC>::Ptr(
new pcl::search::KdTree<PointC>);
this->kdtree_ = pcl::KdTreeFLANN<PointC>::Ptr(
new pcl::KdTreeFLANN<PointC>);
this->ne_ = pcl::NormalEstimationOMP<PointC, PointN>::Ptr(
new pcl::NormalEstimationOMP<PointC, PointN>);
this->poke();
}
void PlaneSegmentation::onInit() {
rclcpp::QoS qos(rclcpp::KeepLast(3));
this->pub_plane_coeffs_ = this->create_publisher<PlaneCoefficients>(
"output_plane_coefficients", qos);
if (!this->publish_only_gd_plane_coeffs_) {
this->pub_gd = this->create_publisher<PointCloud2>(
"output_gd_points", qos);
this->pub_non_gd = this->create_publisher<PointCloud2>(
"output_non_gd_points", qos);
this->pub_indices_ = this->create_publisher<ClusterPointIndices>(
"output_indices", qos);
}
}
void PlaneSegmentation::subscribe() {
// if our pointcloud comes with normals
if (this->is_pcd_with_normal_) {
this->sub_cloud2_ = std::make_shared<
message_filters::Subscriber<PointCloud2>>(
this, "input_points");
this->sub_imu2_ = std::make_shared<
message_filters::Subscriber<Imu>>(this, "input_imu");
this->sync_joint_ = std::make_unique<
message_filters::Synchronizer<SyncPolicyJoint>>(this->buffer_);
this->sync_joint_->connectInput(*sub_cloud2_, *sub_imu2_);
this->sync_joint_->registerCallback(
std::bind(&PlaneSegmentation::jointPcdCallback,
this, ph::_1, ph::_2));
} else { // if we get the pcd and normals separately
this->sub_cloud_ = std::make_shared<
message_filters::Subscriber<PointCloud2>>(this,
"input_points");
this->sub_normal_ = std::make_shared<
message_filters::Subscriber<PointCloud2>>(this,
"input_normals");
this->sub_imu_ = std::make_shared<message_filters::Subscriber<
Imu>>(this, "input_imu");
this->sync_separate_ = std::make_unique<
message_filters::Synchronizer<SyncPolicySeparate>>(this->buffer_);
this->sync_separate_->connectInput(*sub_cloud_, *sub_normal_,
*sub_imu_);
this->sync_separate_->registerCallback(
std::bind(&PlaneSegmentation::separatePcdCallback,
this, ph::_1, ph::_2, ph::_3));
}
}
/**
* Joint callback for the plane segmentation node.
*
* If the input pcd already contains normals, this callback will be used
* to split the pcd into separate point+normal pcds for processing.
*
* @param cloud_msg PointCloud2 msg with normals.
* @param imu_msg sensor_msgs/Imu msg containing excavator imu.
*/
void PlaneSegmentation::jointPcdCallback(
const PointCloud2::ConstSharedPtr &cloud_msg,
const Imu::ConstSharedPtr &imu_msg) {
std::lock_guard<std::mutex> lock(this->mutex_);
PointCloudCN::Ptr point_normals(new PointCloudCN);
pcl::fromROSMsg(*cloud_msg, *point_normals);
// split PointCloudCN pcd into separate pts pcd & normals pcd
PointCloudC::Ptr cloud(new PointCloudC);
PointCloudN::Ptr normals(new PointCloudN);
backhoe::pcl_utils::splitPointsAndNormals(cloud, normals, point_normals);
this->extractGroundPlane(cloud, normals, imu_msg, cloud_msg->header);
}
/**
* Separate callback for the plane segmentation node.
*
* If the pcd and pcd normals input to the node come as separate
* messages, this callback will be used.
*
* @param cloud_msg PointCloud2 msg containing pcd points.
* @param normal_msg PointCloud2 msg containing pcd normals.
* @param imu_msg sensor_msgs/Imu msg containing excavator imu.
*/
void PlaneSegmentation::separatePcdCallback(
const PointCloud2::ConstSharedPtr &cloud_msg,
const PointCloud2::ConstSharedPtr &normal_msg,
const Imu::ConstSharedPtr &imu_msg) {
std::lock_guard<std::mutex> lock(this->mutex_);
// convert cloud and normals from ROS msgs
PointCloudC::Ptr cloud(new PointCloudC);
pcl::fromROSMsg(*cloud_msg, *cloud);
PointCloudN::Ptr normals(new PointCloudN);
pcl::fromROSMsg(*normal_msg, *normals);
this->extractGroundPlane(cloud, normals, imu_msg, cloud_msg->header);
}
/**
* Extract ground plane from input pcd+normals, based on the input imu.
*
* This is the primary routine for calculating and publishing the
* ground plane in the input pcd+normals. The ground plane candidates
* are compared with the input imu, and the plane with normal
* most similar to the imu is chosen as the ground plane.
* Planar segmentation is performed using iterative RANSAC.
*
* @param cloud input pcd
* @param normals normals of the input pcd
* @param imu_msg sensor_msgs/Imu msg containing excavator imu.
* @param header header to use for publishing output topics
*/
void PlaneSegmentation::extractGroundPlane(
const PointCloudC::Ptr cloud,
const PointCloudN::Ptr normals,
const Imu::ConstSharedPtr &imu_msg,
const Header header) {
RCLCPP_INFO(this->get_logger(), "Starting ground plane extraction");
// convert imu message to eigen quaternion
Eigen::Quaternionf imu_q;
Imu imu;
imu_q.w() = imu_msg->imu.orientation.w;
imu_q.x() = imu_msg->imu.orientation.x;
imu_q.y() = imu_msg->imu.orientation.y;
imu_q.z() = imu_msg->imu.orientation.z;
....
我还在头文件中包含了#include <sensor_msgs/msg/imu.hpp>
。还是不明白错误是从哪里来的。有什么帮助吗?
1条答案
按热度按时间fhity93d1#
该错误表明IMU消息不包含字段
imu
。看看API,你也会发现没有这样的成员存在。相反,
sensor_msgs::msg::Imu
直接暴露orientation
,因此您需要做的是例如: