22 #include "cartographer/mapping_3d/proto/optimizing_local_trajectory_builder_options.pb.h" 25 #include "cartographer/mapping_3d/scan_matching/proto/ceres_scan_matcher_options.pb.h" 30 #include "glog/logging.h" 33 namespace mapping_3d {
39 class VelocityDeltaCostFunctor {
41 explicit VelocityDeltaCostFunctor(
const double scaling_factor)
44 VelocityDeltaCostFunctor(
const VelocityDeltaCostFunctor&) =
delete;
45 VelocityDeltaCostFunctor& operator=(
const VelocityDeltaCostFunctor&) =
delete;
48 bool operator()(
const T*
const old_velocity,
const T*
const new_velocity,
60 class RelativeTranslationAndYawCostFunction {
62 RelativeTranslationAndYawCostFunction(
const double translation_scaling_factor,
63 const double rotation_scaling_factor,
69 RelativeTranslationAndYawCostFunction(
70 const RelativeTranslationAndYawCostFunction&) =
delete;
71 RelativeTranslationAndYawCostFunction& operator=(
72 const RelativeTranslationAndYawCostFunction&) =
delete;
75 bool operator()(
const T*
const start_translation,
76 const T*
const start_rotation,
const T*
const end_translation,
77 const T*
const end_rotation, T* residual)
const {
78 const transform::Rigid3<T> start(
79 Eigen::Map<
const Eigen::Matrix<T, 3, 1>>(start_translation),
80 Eigen::Quaternion<T>(start_rotation[0], start_rotation[1],
81 start_rotation[2], start_rotation[3]));
82 const transform::Rigid3<T> end(
83 Eigen::Map<
const Eigen::Matrix<T, 3, 1>>(end_translation),
84 Eigen::Quaternion<T>(end_rotation[0], end_rotation[1], end_rotation[2],
87 const transform::Rigid3<T> delta = end.inverse() * start;
88 const transform::Rigid3<T> error = delta.inverse() *
delta_.cast<T>();
105 const proto::LocalTrajectoryBuilderOptions& options)
108 options.ceres_scan_matcher_options().ceres_solver_options())),
111 motion_filter_(options.motion_filter_options()) {}
121 const Eigen::Vector3d& angular_velocity) {
123 time, linear_acceleration, angular_velocity,
134 std::unique_ptr<OptimizingLocalTrajectoryBuilder::InsertionResult>
138 CHECK_GT(ranges.size(), 0);
143 for (
const Eigen::Vector3f&
hit : ranges) {
144 const Eigen::Vector3f delta =
hit - origin;
145 const float range = delta.norm();
146 if (range >=
options_.min_range()) {
147 if (range <=
options_.max_range()) {
148 point_cloud.push_back(
hit);
153 auto high_resolution_options =
154 options_.high_resolution_adaptive_voxel_filter_options();
155 high_resolution_options.set_min_num_points(
156 high_resolution_options.min_num_points() /
159 high_resolution_options);
161 high_resolution_adaptive_voxel_filter.
Filter(point_cloud);
163 auto low_resolution_options =
164 options_.low_resolution_adaptive_voxel_filter_options();
165 low_resolution_options.set_min_num_points(
166 low_resolution_options.min_num_points() /
169 low_resolution_options);
171 low_resolution_adaptive_voxel_filter.
Filter(point_cloud);
176 Batch{
time, point_cloud, high_resolution_filtered_points,
177 low_resolution_filtered_points,
178 State(Eigen::Vector3d::Zero(), Eigen::Quaterniond::Identity(),
179 Eigen::Vector3d::Zero())});
183 time, point_cloud, high_resolution_filtered_points,
184 low_resolution_filtered_points,
201 static_cast<size_t>(
options_.scans_per_accumulation())) {
221 const auto& velocity = batch.state.velocity;
222 const Eigen::Vector3d new_velocity =
224 Eigen::Vector3d(velocity[0], velocity[1], velocity[2]);
230 std::unique_ptr<OptimizingLocalTrajectoryBuilder::InsertionResult>
238 ceres::Problem problem;
239 const Submap*
const matching_submap =
245 for (
size_t i = 0; i <
batches_.size(); ++i) {
247 problem.AddResidualBlock(
249 ceres::DYNAMIC, 3, 4>(
251 options_.optimizing_local_trajectory_builder_options()
252 .high_resolution_grid_weight() /
253 std::sqrt(static_cast<double>(
259 problem.AddResidualBlock(
261 ceres::DYNAMIC, 3, 4>(
263 options_.optimizing_local_trajectory_builder_options()
264 .low_resolution_grid_weight() /
265 std::sqrt(static_cast<double>(
274 problem.SetParameterBlockConstant(batch.
state.
rotation.data());
276 problem.SetParameterBlockConstant(batch.
state.
velocity.data());
279 new ceres::QuaternionParameterization());
284 for (
size_t i = 1; i <
batches_.size(); ++i) {
285 problem.AddResidualBlock(
286 new ceres::AutoDiffCostFunction<VelocityDeltaCostFunctor, 3, 3, 3>(
287 new VelocityDeltaCostFunctor(
288 options_.optimizing_local_trajectory_builder_options()
289 .velocity_weight())),
290 nullptr,
batches_[i - 1].state.velocity.data(),
293 problem.AddResidualBlock(
294 new ceres::AutoDiffCostFunction<TranslationCostFunction, 3, 3, 3, 3>(
296 options_.optimizing_local_trajectory_builder_options()
297 .translation_weight(),
299 nullptr,
batches_[i - 1].state.translation.data(),
300 batches_[i].state.translation.data(),
301 batches_[i - 1].state.velocity.data());
305 problem.AddResidualBlock(
306 new ceres::AutoDiffCostFunction<RotationCostFunction, 3, 4, 4>(
308 options_.optimizing_local_trajectory_builder_options()
311 nullptr,
batches_[i - 1].state.rotation.data(),
318 interpolation_buffer.
Push(odometer_data.time, odometer_data.pose);
320 for (
size_t i = 1; i <
batches_.size(); ++i) {
332 current_odometer_pose.
inverse() * previous_odometer_pose;
333 problem.AddResidualBlock(
334 new ceres::AutoDiffCostFunction<RelativeTranslationAndYawCostFunction,
336 new RelativeTranslationAndYawCostFunction(
337 options_.optimizing_local_trajectory_builder_options()
338 .odometry_translation_weight(),
339 options_.optimizing_local_trajectory_builder_options()
340 .odometry_rotation_weight(),
342 nullptr,
batches_[i - 1].state.translation.data(),
343 batches_[i - 1].state.rotation.data(),
344 batches_[i].state.translation.data(),
349 ceres::Solver::Summary summary;
362 Eigen::Vector3f::Zero(), {}, {}};
364 for (
const auto& batch :
batches_) {
366 (optimized_pose.
inverse() * batch.state.ToRigid()).cast<float>();
367 for (
const Eigen::Vector3f& point : batch.points) {
368 accumulated_range_data_in_tracking.
returns.push_back(transform * point);
373 accumulated_range_data_in_tracking);
376 std::unique_ptr<OptimizingLocalTrajectoryBuilder::InsertionResult>
381 range_data_in_tracking.
origin,
387 if (filtered_range_data.
returns.empty()) {
388 LOG(WARNING) <<
"Dropped empty range data.";
393 time, optimized_pose,
395 optimized_pose.cast<
float>())};
405 std::unique_ptr<OptimizingLocalTrajectoryBuilder::InsertionResult>
412 const Submap*
const matching_submap =
414 std::vector<const Submap*> insertion_submaps;
415 for (
int insertion_index :
submaps_->insertion_indices()) {
416 insertion_submaps.push_back(
submaps_->Get(insertion_index));
419 const Eigen::Quaterniond kFakeGravityOrientation =
420 Eigen::Quaterniond::Identity();
423 pose_observation.
cast<
float>()),
424 kFakeGravityOrientation);
426 return std::unique_ptr<InsertionResult>(
428 matching_submap, insertion_submaps});
436 while (it->time > start_time) {
444 const Eigen::Quaterniond start_rotation(
447 const Eigen::Quaterniond orientation = start_rotation * result.
delta_rotation;
451 const Eigen::Vector3d position =
452 Eigen::Map<const Eigen::Vector3d>(start_state.
translation.data()) +
454 Eigen::Map<const Eigen::Vector3d>(start_state.
velocity.data());
455 const Eigen::Vector3d velocity =
456 Eigen::Map<const Eigen::Vector3d>(start_state.
velocity.data()) +
460 return State(position, orientation, velocity);
void AddImuData(common::Time time, const Eigen::Vector3d &linear_acceleration, const Eigen::Vector3d &angular_velocity) override
proto::RangeDataInserterOptions options_
PointCloud TransformPointCloud(const PointCloud &point_cloud, const transform::Rigid3f &transform)
std::deque< ImuData > imu_data_
sensor::PointCloud low_resolution_filtered_points
const double translation_scaling_factor_
std::unique_ptr< InsertionResult > InsertIntoSubmap(const common::Time time, const sensor::RangeData &range_data_in_tracking, const transform::Rigid3d &pose_observation)
bool IsSimilar(common::Time time, const transform::Rigid3d &pose)
std::array< double, 4 > rotation
mapping_3d::Submaps * submaps() override
const transform::Rigid3d delta_
const HybridGrid & high_resolution_hybrid_grid() const
MotionFilter motion_filter_
PointCloud VoxelFiltered(const PointCloud &point_cloud, const float size)
const ceres::Solver::Options ceres_solver_options_
State PredictState(const State &start_state, const common::Time start_time, const common::Time end_time)
std::unique_ptr< InsertionResult > AddRangefinderData(common::Time time, const Eigen::Vector3f &origin, const sensor::PointCloud &ranges) override
transform::Rigid3d local_pose() const
sensor::PointCloud high_resolution_filtered_points
UniversalTimeScaleClock::time_point Time
~OptimizingLocalTrajectoryBuilder() override
RangeData TransformRangeData(const RangeData &range_data, const transform::Rigid3f &transform)
const proto::LocalTrajectoryBuilderOptions options_
const double scaling_factor_
PointCloud Filter(const PointCloud &point_cloud) const
std::deque< OdometerData > odometer_data_
Eigen::Matrix< T, 3, 1 > delta_velocity
std::deque< Batch > batches_
const HybridGrid & low_resolution_hybrid_grid() const
const PoseEstimate & pose_estimate() const override
const double rotation_scaling_factor_
void AddOdometerData(common::Time time, const transform::Rigid3d &pose) override
std::unique_ptr< InsertionResult > AddAccumulatedRangeData(common::Time time, const transform::Rigid3d &pose_observation, const sensor::RangeData &range_data_in_tracking)
ceres::Solver::Options CreateCeresSolverOptions(const proto::CeresSolverOptions &proto)
std::vector< Eigen::Vector3f > PointCloud
void TransformStates(const transform::Rigid3d &transform)
std::unique_ptr< InsertionResult > MaybeOptimize(common::Time time)
double ToSeconds(const Duration duration)
OptimizingLocalTrajectoryBuilder(const proto::LocalTrajectoryBuilderOptions &options)
PoseEstimate last_pose_estimate_
std::array< double, 3 > translation
Eigen::Quaternion< T > delta_rotation
void RemoveObsoleteSensorData()
std::unique_ptr< mapping_3d::Submaps > submaps_
std::array< double, 3 > velocity
_Unique_if< T >::_Single_object make_unique(Args &&...args)
IntegrateImuResult< double > IntegrateImu(const std::deque< ImuData > &imu_data, const common::Time start_time, const common::Time end_time, std::deque< ImuData >::const_iterator *it)
std::unique_ptr< Submaps > submaps_