|
|
@ -28,6 +28,7 @@
|
|
|
|
#include "cartographer/common/port.h"
|
|
|
|
#include "cartographer/common/port.h"
|
|
|
|
#include "cartographer/common/thread_pool.h"
|
|
|
|
#include "cartographer/common/thread_pool.h"
|
|
|
|
#include "cartographer/common/time.h"
|
|
|
|
#include "cartographer/common/time.h"
|
|
|
|
|
|
|
|
#include "cartographer/kalman_filter/pose_tracker.h"
|
|
|
|
#include "cartographer/mapping/global_trajectory_builder_interface.h"
|
|
|
|
#include "cartographer/mapping/global_trajectory_builder_interface.h"
|
|
|
|
#include "cartographer/mapping/proto/submaps.pb.h"
|
|
|
|
#include "cartographer/mapping/proto/submaps.pb.h"
|
|
|
|
#include "cartographer/mapping/sensor_collator.h"
|
|
|
|
#include "cartographer/mapping/sensor_collator.h"
|
|
|
@ -51,6 +52,7 @@
|
|
|
|
#include "gflags/gflags.h"
|
|
|
|
#include "gflags/gflags.h"
|
|
|
|
#include "glog/log_severity.h"
|
|
|
|
#include "glog/log_severity.h"
|
|
|
|
#include "glog/logging.h"
|
|
|
|
#include "glog/logging.h"
|
|
|
|
|
|
|
|
#include "nav_msgs/Odometry.h"
|
|
|
|
#include "pcl/point_cloud.h"
|
|
|
|
#include "pcl/point_cloud.h"
|
|
|
|
#include "pcl/point_types.h"
|
|
|
|
#include "pcl/point_types.h"
|
|
|
|
#include "pcl_conversions/pcl_conversions.h"
|
|
|
|
#include "pcl_conversions/pcl_conversions.h"
|
|
|
@ -80,6 +82,7 @@ namespace cartographer_ros {
|
|
|
|
namespace {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
using ::cartographer::transform::Rigid3d;
|
|
|
|
using ::cartographer::transform::Rigid3d;
|
|
|
|
|
|
|
|
using ::cartographer::kalman_filter::PoseCovariance;
|
|
|
|
namespace proto = ::cartographer::sensor::proto;
|
|
|
|
namespace proto = ::cartographer::sensor::proto;
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(hrapp): Support multi trajectory mapping.
|
|
|
|
// TODO(hrapp): Support multi trajectory mapping.
|
|
|
@ -94,6 +97,7 @@ constexpr char kLaserScanTopic[] = "/scan";
|
|
|
|
constexpr char kMultiEchoLaserScanTopic[] = "/echoes";
|
|
|
|
constexpr char kMultiEchoLaserScanTopic[] = "/echoes";
|
|
|
|
constexpr char kPointCloud2Topic[] = "/points2";
|
|
|
|
constexpr char kPointCloud2Topic[] = "/points2";
|
|
|
|
constexpr char kImuTopic[] = "/imu";
|
|
|
|
constexpr char kImuTopic[] = "/imu";
|
|
|
|
|
|
|
|
constexpr char kOdometryTopic[] = "/odom";
|
|
|
|
|
|
|
|
|
|
|
|
Rigid3d ToRigid3d(const geometry_msgs::TransformStamped& transform) {
|
|
|
|
Rigid3d ToRigid3d(const geometry_msgs::TransformStamped& transform) {
|
|
|
|
return Rigid3d(Eigen::Vector3d(transform.transform.translation.x,
|
|
|
|
return Rigid3d(Eigen::Vector3d(transform.transform.translation.x,
|
|
|
@ -105,6 +109,17 @@ Rigid3d ToRigid3d(const geometry_msgs::TransformStamped& transform) {
|
|
|
|
transform.transform.rotation.z));
|
|
|
|
transform.transform.rotation.z));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rigid3d ToRigid3d(const geometry_msgs::Pose& pose) {
|
|
|
|
|
|
|
|
return Rigid3d(
|
|
|
|
|
|
|
|
Eigen::Vector3d(pose.position.x, pose.position.y, pose.position.z),
|
|
|
|
|
|
|
|
Eigen::Quaterniond(pose.orientation.w, pose.orientation.x,
|
|
|
|
|
|
|
|
pose.orientation.y, pose.orientation.z));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PoseCovariance ToPoseCovariance(const boost::array<double, 36ul>& covariance) {
|
|
|
|
|
|
|
|
return Eigen::Map<const Eigen::Matrix<double, 6, 6>>(covariance.data());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(hrapp): move to msg_conversion.cc.
|
|
|
|
// TODO(hrapp): move to msg_conversion.cc.
|
|
|
|
geometry_msgs::Transform ToGeometryMsgTransform(const Rigid3d& rigid) {
|
|
|
|
geometry_msgs::Transform ToGeometryMsgTransform(const Rigid3d& rigid) {
|
|
|
|
geometry_msgs::Transform transform;
|
|
|
|
geometry_msgs::Transform transform;
|
|
|
@ -132,7 +147,7 @@ geometry_msgs::Pose ToGeometryMsgPose(const Rigid3d& rigid) {
|
|
|
|
|
|
|
|
|
|
|
|
// This type is a logical union, i.e. only one proto is actually filled in. It
|
|
|
|
// This type is a logical union, i.e. only one proto is actually filled in. It
|
|
|
|
// is only used for time ordering sensor data before passing it on.
|
|
|
|
// is only used for time ordering sensor data before passing it on.
|
|
|
|
enum class SensorType { kImu, kLaserScan, kLaserFan3D };
|
|
|
|
enum class SensorType { kImu, kLaserScan, kLaserFan3D, kOdometry };
|
|
|
|
struct SensorData {
|
|
|
|
struct SensorData {
|
|
|
|
SensorData(const string& init_frame_id, proto::Imu init_imu)
|
|
|
|
SensorData(const string& init_frame_id, proto::Imu init_imu)
|
|
|
|
: type(SensorType::kImu), frame_id(init_frame_id), imu(init_imu) {}
|
|
|
|
: type(SensorType::kImu), frame_id(init_frame_id), imu(init_imu) {}
|
|
|
@ -144,12 +159,21 @@ struct SensorData {
|
|
|
|
: type(SensorType::kLaserFan3D),
|
|
|
|
: type(SensorType::kLaserFan3D),
|
|
|
|
frame_id(init_frame_id),
|
|
|
|
frame_id(init_frame_id),
|
|
|
|
laser_fan_3d(init_laser_fan_3d) {}
|
|
|
|
laser_fan_3d(init_laser_fan_3d) {}
|
|
|
|
|
|
|
|
SensorData(const string& init_frame_id, const Rigid3d& init_pose,
|
|
|
|
|
|
|
|
const PoseCovariance& init_covariance)
|
|
|
|
|
|
|
|
: type(SensorType::kOdometry),
|
|
|
|
|
|
|
|
frame_id(init_frame_id),
|
|
|
|
|
|
|
|
odometry{init_pose, init_covariance} {}
|
|
|
|
|
|
|
|
|
|
|
|
SensorType type;
|
|
|
|
SensorType type;
|
|
|
|
string frame_id;
|
|
|
|
string frame_id;
|
|
|
|
proto::Imu imu;
|
|
|
|
proto::Imu imu;
|
|
|
|
proto::LaserScan laser_scan;
|
|
|
|
proto::LaserScan laser_scan;
|
|
|
|
proto::LaserFan3D laser_fan_3d;
|
|
|
|
proto::LaserFan3D laser_fan_3d;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
|
|
|
Rigid3d pose;
|
|
|
|
|
|
|
|
PoseCovariance covariance;
|
|
|
|
|
|
|
|
} odometry;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Node that listens to all the sensor data that we are interested in and wires
|
|
|
|
// Node that listens to all the sensor data that we are interested in and wires
|
|
|
@ -166,12 +190,16 @@ class Node {
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
void HandleSensorData(int64 timestamp,
|
|
|
|
void HandleSensorData(int64 timestamp,
|
|
|
|
std::unique_ptr<SensorData> sensor_data);
|
|
|
|
std::unique_ptr<SensorData> sensor_data);
|
|
|
|
|
|
|
|
void OdometryMessageCallback(const nav_msgs::Odometry::ConstPtr& msg);
|
|
|
|
void ImuMessageCallback(const sensor_msgs::Imu::ConstPtr& msg);
|
|
|
|
void ImuMessageCallback(const sensor_msgs::Imu::ConstPtr& msg);
|
|
|
|
void LaserScanMessageCallback(const sensor_msgs::LaserScan::ConstPtr& msg);
|
|
|
|
void LaserScanMessageCallback(const sensor_msgs::LaserScan::ConstPtr& msg);
|
|
|
|
void MultiEchoLaserScanMessageCallback(
|
|
|
|
void MultiEchoLaserScanMessageCallback(
|
|
|
|
const sensor_msgs::MultiEchoLaserScan::ConstPtr& msg);
|
|
|
|
const sensor_msgs::MultiEchoLaserScan::ConstPtr& msg);
|
|
|
|
void PointCloud2MessageCallback(
|
|
|
|
void PointCloud2MessageCallback(
|
|
|
|
const string& topic, const sensor_msgs::PointCloud2::ConstPtr& msg);
|
|
|
|
const string& topic, const sensor_msgs::PointCloud2::ConstPtr& msg);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AddOdometry(int64 timestamp, const string& frame_id, const Rigid3d& pose,
|
|
|
|
|
|
|
|
const PoseCovariance& covariance);
|
|
|
|
void AddImu(int64 timestamp, const string& frame_id, const proto::Imu& imu);
|
|
|
|
void AddImu(int64 timestamp, const string& frame_id, const proto::Imu& imu);
|
|
|
|
void AddHorizontalLaserFan(int64 timestamp, const string& frame_id,
|
|
|
|
void AddHorizontalLaserFan(int64 timestamp, const string& frame_id,
|
|
|
|
const proto::LaserScan& laser_scan);
|
|
|
|
const proto::LaserScan& laser_scan);
|
|
|
@ -197,10 +225,12 @@ class Node {
|
|
|
|
ros::Subscriber imu_subscriber_;
|
|
|
|
ros::Subscriber imu_subscriber_;
|
|
|
|
ros::Subscriber laser_subscriber_2d_;
|
|
|
|
ros::Subscriber laser_subscriber_2d_;
|
|
|
|
std::vector<ros::Subscriber> laser_subscribers_3d_;
|
|
|
|
std::vector<ros::Subscriber> laser_subscribers_3d_;
|
|
|
|
|
|
|
|
ros::Subscriber odometry_subscriber_;
|
|
|
|
string tracking_frame_;
|
|
|
|
string tracking_frame_;
|
|
|
|
string odom_frame_;
|
|
|
|
string odom_frame_;
|
|
|
|
string map_frame_;
|
|
|
|
string map_frame_;
|
|
|
|
bool provide_odom_;
|
|
|
|
bool provide_odom_frame_;
|
|
|
|
|
|
|
|
bool expect_odometry_data_;
|
|
|
|
double laser_min_range_;
|
|
|
|
double laser_min_range_;
|
|
|
|
double laser_max_range_;
|
|
|
|
double laser_max_range_;
|
|
|
|
double laser_missing_echo_ray_length_;
|
|
|
|
double laser_missing_echo_ray_length_;
|
|
|
@ -237,6 +267,23 @@ Rigid3d Node::LookupToTrackingTransformOrThrow(
|
|
|
|
ros::Duration(kMaxTransformDelaySeconds)));
|
|
|
|
ros::Duration(kMaxTransformDelaySeconds)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Node::OdometryMessageCallback(const nav_msgs::Odometry::ConstPtr& msg) {
|
|
|
|
|
|
|
|
auto sensor_data = ::cartographer::common::make_unique<SensorData>(
|
|
|
|
|
|
|
|
msg->header.frame_id, ToRigid3d(msg->pose.pose),
|
|
|
|
|
|
|
|
ToPoseCovariance(msg->pose.covariance));
|
|
|
|
|
|
|
|
sensor_collator_.AddSensorData(
|
|
|
|
|
|
|
|
kTrajectoryId,
|
|
|
|
|
|
|
|
::cartographer::common::ToUniversal(FromRos(msg->header.stamp)),
|
|
|
|
|
|
|
|
kOdometryTopic, std::move(sensor_data));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Node::AddOdometry(int64 timestamp, const string& frame_id,
|
|
|
|
|
|
|
|
const Rigid3d& pose, const PoseCovariance& covariance) {
|
|
|
|
|
|
|
|
const ::cartographer::common::Time time =
|
|
|
|
|
|
|
|
::cartographer::common::FromUniversal(timestamp);
|
|
|
|
|
|
|
|
trajectory_builder_->AddOdometerPose(time, pose, covariance);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Node::ImuMessageCallback(const sensor_msgs::Imu::ConstPtr& msg) {
|
|
|
|
void Node::ImuMessageCallback(const sensor_msgs::Imu::ConstPtr& msg) {
|
|
|
|
auto sensor_data = ::cartographer::common::make_unique<SensorData>(
|
|
|
|
auto sensor_data = ::cartographer::common::make_unique<SensorData>(
|
|
|
|
msg->header.frame_id, ToCartographer(*msg));
|
|
|
|
msg->header.frame_id, ToCartographer(*msg));
|
|
|
@ -352,7 +399,8 @@ void Node::Initialize() {
|
|
|
|
tracking_frame_ = lua_parameter_dictionary.GetString("tracking_frame");
|
|
|
|
tracking_frame_ = lua_parameter_dictionary.GetString("tracking_frame");
|
|
|
|
odom_frame_ = lua_parameter_dictionary.GetString("odom_frame");
|
|
|
|
odom_frame_ = lua_parameter_dictionary.GetString("odom_frame");
|
|
|
|
map_frame_ = lua_parameter_dictionary.GetString("map_frame");
|
|
|
|
map_frame_ = lua_parameter_dictionary.GetString("map_frame");
|
|
|
|
provide_odom_ = lua_parameter_dictionary.GetBool("provide_odom");
|
|
|
|
provide_odom_frame_ = lua_parameter_dictionary.GetBool("provide_odom_frame");
|
|
|
|
|
|
|
|
expect_odometry_data_ = lua_parameter_dictionary.GetBool("expect_odometry_data");
|
|
|
|
laser_min_range_ = lua_parameter_dictionary.GetDouble("laser_min_range");
|
|
|
|
laser_min_range_ = lua_parameter_dictionary.GetDouble("laser_min_range");
|
|
|
|
laser_max_range_ = lua_parameter_dictionary.GetDouble("laser_max_range");
|
|
|
|
laser_max_range_ = lua_parameter_dictionary.GetDouble("laser_max_range");
|
|
|
|
laser_missing_echo_ray_length_ =
|
|
|
|
laser_missing_echo_ray_length_ =
|
|
|
@ -445,7 +493,11 @@ void Node::Initialize() {
|
|
|
|
expected_sensor_identifiers.insert(kImuTopic);
|
|
|
|
expected_sensor_identifiers.insert(kImuTopic);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TODO(hrapp): Add odometry subscribers here.
|
|
|
|
if (expect_odometry_data_) {
|
|
|
|
|
|
|
|
odometry_subscriber_ = node_handle_.subscribe(
|
|
|
|
|
|
|
|
kOdometryTopic, kSubscriberQueueSize, &Node::OdometryMessageCallback, this);
|
|
|
|
|
|
|
|
expected_sensor_identifiers.insert(kOdometryTopic);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sensor_collator_.AddTrajectory(
|
|
|
|
sensor_collator_.AddTrajectory(
|
|
|
|
kTrajectoryId, expected_sensor_identifiers,
|
|
|
|
kTrajectoryId, expected_sensor_identifiers,
|
|
|
@ -550,7 +602,7 @@ void Node::PublishPose(const int64 timestamp) {
|
|
|
|
stamped_transform.header.frame_id = map_frame_;
|
|
|
|
stamped_transform.header.frame_id = map_frame_;
|
|
|
|
stamped_transform.child_frame_id = odom_frame_;
|
|
|
|
stamped_transform.child_frame_id = odom_frame_;
|
|
|
|
|
|
|
|
|
|
|
|
if (provide_odom_) {
|
|
|
|
if (provide_odom_frame_) {
|
|
|
|
::cartographer::common::MutexLocker lock(&mutex_);
|
|
|
|
::cartographer::common::MutexLocker lock(&mutex_);
|
|
|
|
stamped_transform.transform = ToGeometryMsgTransform(local_to_map);
|
|
|
|
stamped_transform.transform = ToGeometryMsgTransform(local_to_map);
|
|
|
|
tf_broadcaster_.sendTransform(stamped_transform);
|
|
|
|
tf_broadcaster_.sendTransform(stamped_transform);
|
|
|
@ -599,6 +651,11 @@ void Node::HandleSensorData(const int64 timestamp,
|
|
|
|
AddLaserFan3D(timestamp, sensor_data->frame_id,
|
|
|
|
AddLaserFan3D(timestamp, sensor_data->frame_id,
|
|
|
|
sensor_data->laser_fan_3d);
|
|
|
|
sensor_data->laser_fan_3d);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case SensorType::kOdometry:
|
|
|
|
|
|
|
|
AddOdometry(timestamp, sensor_data->frame_id, sensor_data->odometry.pose,
|
|
|
|
|
|
|
|
sensor_data->odometry.covariance);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LOG(FATAL);
|
|
|
|
LOG(FATAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|