map_builder.cc
Go to the documentation of this file.
1 /*
2  * Copyright 2016 The Cartographer Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
30 #include "cartographer/mapping/proto/internal/legacy_serialized_data.pb.h"
36 
37 namespace cartographer {
38 namespace mapping {
39 
40 namespace {
41 
42 using mapping::proto::SerializedData;
43 
44 std::vector<std::string> SelectRangeSensorIds(
45  const std::set<MapBuilder::SensorId>& expected_sensor_ids) {
46  std::vector<std::string> range_sensor_ids;
47  for (const MapBuilder::SensorId& sensor_id : expected_sensor_ids) {
48  if (sensor_id.type == MapBuilder::SensorId::SensorType::RANGE) {
49  range_sensor_ids.push_back(sensor_id.id);
50  }
51  }
52  return range_sensor_ids;
53 }
54 
55 } // namespace
56 
57 proto::MapBuilderOptions CreateMapBuilderOptions(
58  common::LuaParameterDictionary* const parameter_dictionary) {
59  proto::MapBuilderOptions options;
60  options.set_use_trajectory_builder_2d(
61  parameter_dictionary->GetBool("use_trajectory_builder_2d"));
62  options.set_use_trajectory_builder_3d(
63  parameter_dictionary->GetBool("use_trajectory_builder_3d"));
64  options.set_num_background_threads(
65  parameter_dictionary->GetNonNegativeInt("num_background_threads"));
66  *options.mutable_pose_graph_options() = CreatePoseGraphOptions(
67  parameter_dictionary->GetDictionary("pose_graph").get());
68  CHECK_NE(options.use_trajectory_builder_2d(),
69  options.use_trajectory_builder_3d());
70  return options;
71 }
72 
73 MapBuilder::MapBuilder(const proto::MapBuilderOptions& options)
74  : options_(options), thread_pool_(options.num_background_threads()) {
75  CHECK(options.use_trajectory_builder_2d() ^
76  options.use_trajectory_builder_3d());
77  if (options.use_trajectory_builder_2d()) {
78  pose_graph_ = common::make_unique<PoseGraph2D>(
79  options_.pose_graph_options(),
80  common::make_unique<optimization::OptimizationProblem2D>(
81  options_.pose_graph_options().optimization_problem_options()),
82  &thread_pool_);
83  }
84  if (options.use_trajectory_builder_3d()) {
85  pose_graph_ = common::make_unique<PoseGraph3D>(
86  options_.pose_graph_options(),
87  common::make_unique<optimization::OptimizationProblem3D>(
88  options_.pose_graph_options().optimization_problem_options()),
89  &thread_pool_);
90  }
91  if (options.collate_by_trajectory()) {
92  sensor_collator_ = common::make_unique<sensor::TrajectoryCollator>();
93  } else {
94  sensor_collator_ = common::make_unique<sensor::Collator>();
95  }
96 }
97 
99  const std::set<SensorId>& expected_sensor_ids,
100  const proto::TrajectoryBuilderOptions& trajectory_options,
101  LocalSlamResultCallback local_slam_result_callback) {
102  const int trajectory_id = trajectory_builders_.size();
103  if (options_.use_trajectory_builder_3d()) {
104  std::unique_ptr<LocalTrajectoryBuilder3D> local_trajectory_builder;
105  if (trajectory_options.has_trajectory_builder_3d_options()) {
106  local_trajectory_builder = common::make_unique<LocalTrajectoryBuilder3D>(
107  trajectory_options.trajectory_builder_3d_options(),
108  SelectRangeSensorIds(expected_sensor_ids));
109  }
110  DCHECK(dynamic_cast<PoseGraph3D*>(pose_graph_.get()));
111  trajectory_builders_.push_back(
112  common::make_unique<CollatedTrajectoryBuilder>(
113  sensor_collator_.get(), trajectory_id, expected_sensor_ids,
115  std::move(local_trajectory_builder), trajectory_id,
116  static_cast<PoseGraph3D*>(pose_graph_.get()),
117  local_slam_result_callback)));
118  } else {
119  std::unique_ptr<LocalTrajectoryBuilder2D> local_trajectory_builder;
120  if (trajectory_options.has_trajectory_builder_2d_options()) {
121  local_trajectory_builder = common::make_unique<LocalTrajectoryBuilder2D>(
122  trajectory_options.trajectory_builder_2d_options(),
123  SelectRangeSensorIds(expected_sensor_ids));
124  }
125  DCHECK(dynamic_cast<PoseGraph2D*>(pose_graph_.get()));
126  trajectory_builders_.push_back(
127  common::make_unique<CollatedTrajectoryBuilder>(
128  sensor_collator_.get(), trajectory_id, expected_sensor_ids,
130  std::move(local_trajectory_builder), trajectory_id,
131  static_cast<PoseGraph2D*>(pose_graph_.get()),
132  local_slam_result_callback)));
133 
134  if (trajectory_options.has_overlapping_submaps_trimmer_2d()) {
135  const auto& trimmer_options =
136  trajectory_options.overlapping_submaps_trimmer_2d();
137  pose_graph_->AddTrimmer(common::make_unique<OverlappingSubmapsTrimmer2D>(
138  trimmer_options.fresh_submaps_count(),
139  trimmer_options.min_covered_area() /
140  common::Pow2(trajectory_options.trajectory_builder_2d_options()
141  .submaps_options()
142  .grid_options_2d()
143  .resolution()),
144  trimmer_options.min_added_submaps_count()));
145  }
146  }
147  if (trajectory_options.pure_localization()) {
148  constexpr int kSubmapsToKeep = 3;
149  pose_graph_->AddTrimmer(common::make_unique<PureLocalizationTrimmer>(
150  trajectory_id, kSubmapsToKeep));
151  }
152  if (trajectory_options.has_initial_trajectory_pose()) {
153  const auto& initial_trajectory_pose =
154  trajectory_options.initial_trajectory_pose();
155  pose_graph_->SetInitialTrajectoryPose(
156  trajectory_id, initial_trajectory_pose.to_trajectory_id(),
157  transform::ToRigid3(initial_trajectory_pose.relative_pose()),
158  common::FromUniversal(initial_trajectory_pose.timestamp()));
159  }
160  proto::TrajectoryBuilderOptionsWithSensorIds options_with_sensor_ids_proto;
161  for (const auto& sensor_id : expected_sensor_ids) {
162  *options_with_sensor_ids_proto.add_sensor_id() = ToProto(sensor_id);
163  }
164  *options_with_sensor_ids_proto.mutable_trajectory_builder_options() =
165  trajectory_options;
166  all_trajectory_builder_options_.push_back(options_with_sensor_ids_proto);
167  CHECK_EQ(trajectory_builders_.size(), all_trajectory_builder_options_.size());
168  return trajectory_id;
169 }
170 
172  const proto::TrajectoryBuilderOptionsWithSensorIds&
173  options_with_sensor_ids_proto) {
174  const int trajectory_id = trajectory_builders_.size();
175  trajectory_builders_.emplace_back();
176  all_trajectory_builder_options_.push_back(options_with_sensor_ids_proto);
177  CHECK_EQ(trajectory_builders_.size(), all_trajectory_builder_options_.size());
178  return trajectory_id;
179 }
180 
181 void MapBuilder::FinishTrajectory(const int trajectory_id) {
182  sensor_collator_->FinishTrajectory(trajectory_id);
183  pose_graph_->FinishTrajectory(trajectory_id);
184 }
185 
187  const SubmapId& submap_id, proto::SubmapQuery::Response* const response) {
188  if (submap_id.trajectory_id < 0 ||
189  submap_id.trajectory_id >= num_trajectory_builders()) {
190  return "Requested submap from trajectory " +
191  std::to_string(submap_id.trajectory_id) + " but there are only " +
192  std::to_string(num_trajectory_builders()) + " trajectories.";
193  }
194 
195  const auto submap_data = pose_graph_->GetSubmapData(submap_id);
196  if (submap_data.submap == nullptr) {
197  return "Requested submap " + std::to_string(submap_id.submap_index) +
198  " from trajectory " + std::to_string(submap_id.trajectory_id) +
199  " but it does not exist: maybe it has been trimmed.";
200  }
201  submap_data.submap->ToResponseProto(submap_data.pose, response);
202  return "";
203 }
204 
207 }
208 
210  bool load_frozen_state) {
211  io::ProtoStreamDeserializer deserializer(reader);
212 
213  // Create a copy of the pose_graph_proto, such that we can re-write the
214  // trajectory ids.
215  proto::PoseGraph pose_graph_proto = deserializer.pose_graph();
216  const auto& all_builder_options_proto =
217  deserializer.all_trajectory_builder_options();
218 
219  std::map<int, int> trajectory_remapping;
220  for (auto& trajectory_proto : *pose_graph_proto.mutable_trajectory()) {
221  const auto& options_with_sensor_ids_proto =
222  all_builder_options_proto.options_with_sensor_ids(
223  trajectory_proto.trajectory_id());
224  const int new_trajectory_id =
225  AddTrajectoryForDeserialization(options_with_sensor_ids_proto);
226  CHECK(trajectory_remapping
227  .emplace(trajectory_proto.trajectory_id(), new_trajectory_id)
228  .second)
229  << "Duplicate trajectory ID: " << trajectory_proto.trajectory_id();
230  trajectory_proto.set_trajectory_id(new_trajectory_id);
231  if (load_frozen_state) {
232  pose_graph_->FreezeTrajectory(new_trajectory_id);
233  }
234  }
235 
236  // Apply the calculated remapping to constraints in the pose graph proto.
237  for (auto& constraint_proto : *pose_graph_proto.mutable_constraint()) {
238  constraint_proto.mutable_submap_id()->set_trajectory_id(
239  trajectory_remapping.at(constraint_proto.submap_id().trajectory_id()));
240  constraint_proto.mutable_node_id()->set_trajectory_id(
241  trajectory_remapping.at(constraint_proto.node_id().trajectory_id()));
242  }
243 
245  for (const proto::Trajectory& trajectory_proto :
246  pose_graph_proto.trajectory()) {
247  for (const proto::Trajectory::Submap& submap_proto :
248  trajectory_proto.submap()) {
249  submap_poses.Insert(SubmapId{trajectory_proto.trajectory_id(),
250  submap_proto.submap_index()},
251  transform::ToRigid3(submap_proto.pose()));
252  }
253  }
254 
256  for (const proto::Trajectory& trajectory_proto :
257  pose_graph_proto.trajectory()) {
258  for (const proto::Trajectory::Node& node_proto : trajectory_proto.node()) {
259  node_poses.Insert(
260  NodeId{trajectory_proto.trajectory_id(), node_proto.node_index()},
261  transform::ToRigid3(node_proto.pose()));
262  }
263  }
264 
265  // Set global poses of landmarks.
266  for (const auto& landmark : pose_graph_proto.landmark_poses()) {
267  pose_graph_->SetLandmarkPose(landmark.landmark_id(),
268  transform::ToRigid3(landmark.global_pose()));
269  }
270 
271  SerializedData proto;
272  while (deserializer.ReadNextSerializedData(&proto)) {
273  switch (proto.data_case()) {
274  case SerializedData::kPoseGraph:
275  LOG(ERROR) << "Found multiple serialized `PoseGraph`. Serialized "
276  "stream likely corrupt!.";
277  break;
278  case SerializedData::kAllTrajectoryBuilderOptions:
279  LOG(ERROR) << "Found multiple serialized "
280  "`AllTrajectoryBuilderOptions`. Serialized stream likely "
281  "corrupt!.";
282  break;
283  case SerializedData::kSubmap: {
284  proto.mutable_submap()->mutable_submap_id()->set_trajectory_id(
285  trajectory_remapping.at(
286  proto.submap().submap_id().trajectory_id()));
287  const transform::Rigid3d& submap_pose = submap_poses.at(
288  SubmapId{proto.submap().submap_id().trajectory_id(),
289  proto.submap().submap_id().submap_index()});
290  pose_graph_->AddSubmapFromProto(submap_pose, proto.submap());
291  break;
292  }
293  case SerializedData::kNode: {
294  proto.mutable_node()->mutable_node_id()->set_trajectory_id(
295  trajectory_remapping.at(proto.node().node_id().trajectory_id()));
296  const transform::Rigid3d& node_pose =
297  node_poses.at(NodeId{proto.node().node_id().trajectory_id(),
298  proto.node().node_id().node_index()});
299  pose_graph_->AddNodeFromProto(node_pose, proto.node());
300  break;
301  }
302  case SerializedData::kTrajectoryData: {
303  proto.mutable_trajectory_data()->set_trajectory_id(
304  trajectory_remapping.at(proto.trajectory_data().trajectory_id()));
305  pose_graph_->SetTrajectoryDataFromProto(proto.trajectory_data());
306  break;
307  }
308  case SerializedData::kImuData: {
309  if (load_frozen_state) break;
310  pose_graph_->AddImuData(
311  trajectory_remapping.at(proto.imu_data().trajectory_id()),
312  sensor::FromProto(proto.imu_data().imu_data()));
313  break;
314  }
315  case SerializedData::kOdometryData: {
316  if (load_frozen_state) break;
317  pose_graph_->AddOdometryData(
318  trajectory_remapping.at(proto.odometry_data().trajectory_id()),
319  sensor::FromProto(proto.odometry_data().odometry_data()));
320  break;
321  }
322  case SerializedData::kFixedFramePoseData: {
323  if (load_frozen_state) break;
324  pose_graph_->AddFixedFramePoseData(
325  trajectory_remapping.at(
326  proto.fixed_frame_pose_data().trajectory_id()),
328  proto.fixed_frame_pose_data().fixed_frame_pose_data()));
329  break;
330  }
331  case SerializedData::kLandmarkData: {
332  if (load_frozen_state) break;
333  pose_graph_->AddLandmarkData(
334  trajectory_remapping.at(proto.landmark_data().trajectory_id()),
335  sensor::FromProto(proto.landmark_data().landmark_data()));
336  break;
337  }
338  default:
339  LOG(WARNING) << "Skipping unknown message type in stream: "
340  << proto.GetTypeName();
341  }
342  }
343 
344  if (load_frozen_state) {
345  // Add information about which nodes belong to which submap.
346  // Required for 3D pure localization.
347  for (const proto::PoseGraph::Constraint& constraint_proto :
348  pose_graph_proto.constraint()) {
349  if (constraint_proto.tag() !=
350  proto::PoseGraph::Constraint::INTRA_SUBMAP) {
351  continue;
352  }
353  pose_graph_->AddNodeToSubmap(
354  NodeId{constraint_proto.node_id().trajectory_id(),
355  constraint_proto.node_id().node_index()},
356  SubmapId{constraint_proto.submap_id().trajectory_id(),
357  constraint_proto.submap_id().submap_index()});
358  }
359  } else {
360  // When loading unfrozen trajectories, 'AddSerializedConstraints' will
361  // take care of adding information about which nodes belong to which
362  // submap.
363  pose_graph_->AddSerializedConstraints(
364  FromProto(pose_graph_proto.constraint()));
365  }
366  CHECK(reader->eof());
367 }
368 
369 } // namespace mapping
370 } // namespace cartographer
PoseGraph::Constraint::Tag FromProto(const proto::PoseGraph::Constraint::Tag &proto)
Definition: pose_graph.cc:38
std::unique_ptr< TrajectoryBuilderInterface > CreateGlobalTrajectoryBuilder2D(std::unique_ptr< LocalTrajectoryBuilder2D > local_trajectory_builder, const int trajectory_id, mapping::PoseGraph2D *const pose_graph, const TrajectoryBuilderInterface::LocalSlamResultCallback &local_slam_result_callback)
void SerializeState(io::ProtoStreamWriterInterface *writer) override
Definition: map_builder.cc:205
TrajectoryBuilderInterface::SensorId SensorId
constexpr T Pow2(T a)
Definition: math.h:50
void FinishTrajectory(int trajectory_id) override
Definition: map_builder.cc:181
std::vector< proto::TrajectoryBuilderOptionsWithSensorIds > all_trajectory_builder_options_
Definition: map_builder.h:92
TrajectoryBuilderInterface::LocalSlamResultCallback LocalSlamResultCallback
void WritePbStream(const mapping::PoseGraph &pose_graph, const std::vector< mapping::proto::TrajectoryBuilderOptionsWithSensorIds > &trajectory_builder_options, ProtoStreamWriterInterface *const writer)
const DataType & at(const IdType &id) const
Definition: id.h:311
int num_trajectory_builders() const override
Definition: map_builder.h:68
std::string SubmapToProto(const SubmapId &submap_id, proto::SubmapQuery::Response *response) override
Definition: map_builder.cc:186
void Insert(const IdType &id, const DataType &data)
Definition: id.h:280
FixedFramePoseData FromProto(const proto::FixedFramePoseData &proto)
transform::Rigid3d ToRigid3(const proto::Rigid3d &rigid)
Definition: transform.cc:71
bool ReadNextSerializedData(mapping::proto::SerializedData *data)
proto::MapBuilderOptions CreateMapBuilderOptions(common::LuaParameterDictionary *const parameter_dictionary)
Definition: map_builder.cc:57
FakeThreadPool thread_pool_
Definition: task_test.cc:70
Time FromUniversal(const int64 ticks)
Definition: time.cc:34
proto::ProbabilityGridRangeDataInserterOptions2D options_
const proto::MapBuilderOptions options_
Definition: map_builder.h:83
proto::PoseGraphOptions CreatePoseGraphOptions(common::LuaParameterDictionary *const parameter_dictionary)
Definition: pose_graph.cc:72
void LoadState(io::ProtoStreamReaderInterface *reader, bool load_frozen_state) override
Definition: map_builder.cc:209
std::unique_ptr< PoseGraph > pose_graph_
Definition: map_builder.h:86
std::vector< std::unique_ptr< mapping::TrajectoryBuilderInterface > > trajectory_builders_
Definition: map_builder.h:90
std::unique_ptr< TrajectoryBuilderInterface > CreateGlobalTrajectoryBuilder3D(std::unique_ptr< LocalTrajectoryBuilder3D > local_trajectory_builder, const int trajectory_id, mapping::PoseGraph3D *const pose_graph, const TrajectoryBuilderInterface::LocalSlamResultCallback &local_slam_result_callback)
std::unique_ptr< sensor::CollatorInterface > sensor_collator_
Definition: map_builder.h:88
common::ThreadPool thread_pool_
Definition: map_builder.h:84
const mapping::proto::AllTrajectoryBuilderOptions & all_trajectory_builder_options()
int AddTrajectoryBuilder(const std::set< SensorId > &expected_sensor_ids, const proto::TrajectoryBuilderOptions &trajectory_options, LocalSlamResultCallback local_slam_result_callback) override
Definition: map_builder.cc:98
int AddTrajectoryForDeserialization(const proto::TrajectoryBuilderOptionsWithSensorIds &options_with_sensor_ids_proto) override
Definition: map_builder.cc:171
std::unique_ptr< LuaParameterDictionary > GetDictionary(const std::string &key)
proto::MapLimits ToProto(const MapLimits &map_limits)
Definition: map_limits.h:92
MapBuilder(const proto::MapBuilderOptions &options)
Definition: map_builder.cc:73


cartographer
Author(s): The Cartographer Authors
autogenerated on Mon Feb 28 2022 22:00:58