map_builder_bridge.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 
20 #include "cartographer_ros/color.h"
23 #include "cartographer_ros_msgs/TrajectorySubmapList.h"
24 
25 namespace cartographer_ros {
26 
27 constexpr double kTrajectoryLineStripMarkerScale = 0.07;
28 
30  tf2_ros::Buffer* const tf_buffer)
31  : node_options_(node_options),
32  map_builder_(node_options.map_builder_options),
33  tf_buffer_(tf_buffer) {}
34 
36  const std::unordered_set<string>& expected_sensor_ids,
37  const TrajectoryOptions& trajectory_options) {
38  const int trajectory_id = map_builder_.AddTrajectoryBuilder(
39  expected_sensor_ids, trajectory_options.trajectory_builder_options);
40  LOG(INFO) << "Added trajectory with ID '" << trajectory_id << "'.";
41 
42  CHECK_EQ(sensor_bridges_.count(trajectory_id), 0);
43  sensor_bridges_[trajectory_id] =
44  cartographer::common::make_unique<SensorBridge>(
45  trajectory_options.tracking_frame,
47  map_builder_.GetTrajectoryBuilder(trajectory_id));
48  auto emplace_result =
49  trajectory_options_.emplace(trajectory_id, trajectory_options);
50  CHECK(emplace_result.second == true);
51  return trajectory_id;
52 }
53 
54 void MapBuilderBridge::FinishTrajectory(const int trajectory_id) {
55  LOG(INFO) << "Finishing trajectory with ID '" << trajectory_id << "'...";
56 
57  CHECK_EQ(sensor_bridges_.count(trajectory_id), 1);
58  map_builder_.FinishTrajectory(trajectory_id);
60  sensor_bridges_.erase(trajectory_id);
61 }
62 
63 void MapBuilderBridge::SerializeState(const std::string& stem) {
64  std::ofstream proto_file(stem + ".pb",
65  std::ios_base::out | std::ios_base::binary);
66  CHECK(map_builder_.sparse_pose_graph()->ToProto().SerializeToOstream(
67  &proto_file))
68  << "Could not serialize pose graph.";
69  proto_file.close();
70  CHECK(proto_file) << "Could not write pose graph.";
71 }
72 
73 void MapBuilderBridge::WriteAssets(const string& stem) {
74  const auto all_trajectory_nodes =
76  // TODO(yutakaoka): Add multi-trajectory support.
77  CHECK_EQ(trajectory_options_.count(0), 1);
78  CHECK_EQ(all_trajectory_nodes.size(), 1);
79  if (all_trajectory_nodes[0].empty()) {
80  LOG(WARNING) << "No data was collected and no assets will be written.";
81  } else {
82  LOG(INFO) << "Writing assets with stem '" << stem << "'...";
83  if (node_options_.map_builder_options.use_trajectory_builder_2d()) {
85  all_trajectory_nodes[0], node_options_.map_frame,
87  .trajectory_builder_options.trajectory_builder_2d_options()
88  .submaps_options(),
89  stem);
90  }
91 
92  if (node_options_.map_builder_options.use_trajectory_builder_3d()) {
94  all_trajectory_nodes[0],
96  .trajectory_builder_options.trajectory_builder_3d_options()
97  .submaps_options()
98  .high_resolution(),
99  stem);
100  }
101  }
102 }
103 
105  cartographer_ros_msgs::SubmapQuery::Request& request,
106  cartographer_ros_msgs::SubmapQuery::Response& response) {
107  cartographer::mapping::proto::SubmapQuery::Response response_proto;
108  const std::string error = map_builder_.SubmapToProto(
109  request.trajectory_id, request.submap_index, &response_proto);
110  if (!error.empty()) {
111  LOG(ERROR) << error;
112  return false;
113  }
114 
115  response.submap_version = response_proto.submap_version();
116  response.cells.insert(response.cells.begin(), response_proto.cells().begin(),
117  response_proto.cells().end());
118  response.width = response_proto.width();
119  response.height = response_proto.height();
120  response.resolution = response_proto.resolution();
121  response.slice_pose = ToGeometryMsgPose(
122  cartographer::transform::ToRigid3(response_proto.slice_pose()));
123  return true;
124 }
125 
126 cartographer_ros_msgs::SubmapList MapBuilderBridge::GetSubmapList() {
127  cartographer_ros_msgs::SubmapList submap_list;
128  submap_list.header.stamp = ::ros::Time::now();
129  submap_list.header.frame_id = node_options_.map_frame;
130  for (int trajectory_id = 0;
131  trajectory_id < map_builder_.num_trajectory_builders();
132  ++trajectory_id) {
133  auto* const trajectory_builder =
134  map_builder_.GetTrajectoryBuilder(trajectory_id);
135  const int num_submaps = trajectory_builder->num_submaps();
136  cartographer_ros_msgs::TrajectorySubmapList trajectory_submap_list;
137  for (int submap_index = 0; submap_index != num_submaps; ++submap_index) {
138  cartographer_ros_msgs::SubmapEntry submap_entry;
139  const auto submap_data = trajectory_builder->GetSubmapData(submap_index);
140  submap_entry.submap_version = submap_data.submap->num_range_data();
141  submap_entry.pose = ToGeometryMsgPose(submap_data.pose);
142  trajectory_submap_list.submap.push_back(submap_entry);
143  }
144  submap_list.trajectory.push_back(trajectory_submap_list);
145  }
146  return submap_list;
147 }
148 
149 std::unique_ptr<nav_msgs::OccupancyGrid>
151  CHECK(node_options_.map_builder_options.use_trajectory_builder_2d())
152  << "Publishing OccupancyGrids for 3D data is not yet supported";
153  std::vector<::cartographer::mapping::TrajectoryNode> flat_trajectory_nodes;
154  for (const auto& single_trajectory_nodes :
156  flat_trajectory_nodes.insert(flat_trajectory_nodes.end(),
157  single_trajectory_nodes.begin(),
158  single_trajectory_nodes.end());
159  }
160  std::unique_ptr<nav_msgs::OccupancyGrid> occupancy_grid;
161  if (!flat_trajectory_nodes.empty()) {
162  occupancy_grid =
163  cartographer::common::make_unique<nav_msgs::OccupancyGrid>();
164  CHECK_EQ(trajectory_options_.count(0), 1);
166  flat_trajectory_nodes, node_options_.map_frame,
168  .trajectory_builder_options.trajectory_builder_2d_options()
169  .submaps_options(),
170  occupancy_grid.get());
171  }
172  return occupancy_grid;
173 }
174 
175 std::unordered_map<int, MapBuilderBridge::TrajectoryState>
177  std::unordered_map<int, TrajectoryState> trajectory_states;
178  for (const auto& entry : sensor_bridges_) {
179  const int trajectory_id = entry.first;
180  const SensorBridge& sensor_bridge = *entry.second;
181 
182  const cartographer::mapping::TrajectoryBuilder* const trajectory_builder =
183  map_builder_.GetTrajectoryBuilder(trajectory_id);
185  trajectory_builder->pose_estimate();
186  if (cartographer::common::ToUniversal(pose_estimate.time) < 0) {
187  continue;
188  }
189 
190  CHECK_EQ(trajectory_options_.count(trajectory_id), 1);
191  trajectory_states[trajectory_id] = {
192  pose_estimate,
194  trajectory_id),
195  sensor_bridge.tf_bridge().LookupToTracking(
196  pose_estimate.time,
197  trajectory_options_[trajectory_id].published_frame),
198  trajectory_options_[trajectory_id]};
199  }
200  return trajectory_states;
201 }
202 
203 visualization_msgs::MarkerArray MapBuilderBridge::GetTrajectoryNodesList() {
204  visualization_msgs::MarkerArray trajectory_nodes_list;
205  const auto all_trajectory_nodes =
207  int marker_id = 0;
208  for (int trajectory_id = 0;
209  trajectory_id < static_cast<int>(all_trajectory_nodes.size());
210  ++trajectory_id) {
211  const auto& single_trajectory_nodes = all_trajectory_nodes[trajectory_id];
212  visualization_msgs::Marker marker;
213  marker.id = marker_id++;
214  marker.type = visualization_msgs::Marker::LINE_STRIP;
215  marker.header.stamp = ::ros::Time::now();
216  marker.header.frame_id = node_options_.map_frame;
217  marker.color = GetColor(trajectory_id);
218  marker.scale.x = kTrajectoryLineStripMarkerScale;
219  marker.pose.orientation.w = 1.0;
220  for (const auto& node : single_trajectory_nodes) {
221  if (node.trimmed()) {
222  continue;
223  }
224  const ::geometry_msgs::Point node_point = ToGeometryMsgPoint(
225  (node.pose * node.constant_data->tracking_to_pose).translation());
226  marker.points.push_back(node_point);
227  // Work around the 16384 point limit in rviz by splitting the
228  // trajectory into multiple markers.
229  if (marker.points.size() == 16384) {
230  trajectory_nodes_list.markers.push_back(marker);
231  marker.id = marker_id++;
232  marker.points.clear();
233  // Push back the last point, so the two markers appear connected.
234  marker.points.push_back(node_point);
235  }
236  }
237  trajectory_nodes_list.markers.push_back(marker);
238  }
239  return trajectory_nodes_list;
240 }
241 
243  return sensor_bridges_.at(trajectory_id).get();
244 }
245 
246 } // namespace cartographer_ros
void Write3DAssets(const std::vector<::cartographer::mapping::TrajectoryNode > &trajectory_nodes, const double voxel_size, const std::string &stem)
int AddTrajectoryBuilder(const std::unordered_set< string > &expected_sensor_ids, const proto::TrajectoryBuilderOptions &trajectory_options)
::cartographer::mapping::proto::MapBuilderOptions map_builder_options
Definition: node_options.h:30
mapping::SparsePoseGraph * sparse_pose_graph()
geometry_msgs::Pose ToGeometryMsgPose(const Rigid3d &rigid3d)
geometry_msgs::Point ToGeometryMsgPoint(const Eigen::Vector3d &vector3d)
std::unique_ptr<::cartographer::transform::Rigid3d > LookupToTracking(::cartographer::common::Time time, const string &frame_id) const
Definition: tf_bridge.cc:31
void WriteAssets(const string &stem)
const TfBridge & tf_bridge() const
virtual std::vector< std::vector< TrajectoryNode > > GetTrajectoryNodes()=0
void Write2DAssets(const std::vector<::cartographer::mapping::TrajectoryNode > &trajectory_nodes, const string &map_frame, const ::cartographer::mapping_2d::proto::SubmapsOptions &submaps_options, const std::string &stem)
SensorBridge * sensor_bridge(int trajectory_id)
transform::Rigid3d ToRigid3(const proto::Rigid3d &rigid)
::std_msgs::ColorRGBA GetColor(int id)
Definition: color.cc:70
void FinishTrajectory(int trajectory_id)
void BuildOccupancyGrid2D(const std::vector<::cartographer::mapping::TrajectoryNode > &trajectory_nodes, const string &map_frame, const ::cartographer::mapping_2d::proto::SubmapsOptions &submaps_options,::nav_msgs::OccupancyGrid *const occupancy_grid)
virtual const PoseEstimate & pose_estimate() const =0
cartographer::mapping::MapBuilder map_builder_
constexpr double kTrajectoryLineStripMarkerScale
visualization_msgs::MarkerArray GetTrajectoryNodesList()
mapping::TrajectoryBuilder * GetTrajectoryBuilder(int trajectory_id) const
cartographer_ros_msgs::SubmapList GetSubmapList()
void SerializeState(const string &stem)
void FinishTrajectory(int trajectory_id)
proto::SparsePoseGraph ToProto()
int64 ToUniversal(const Time time)
::cartographer::mapping::proto::TrajectoryBuilderOptions trajectory_builder_options
string SubmapToProto(int trajectory_id, int submap_index, proto::SubmapQuery::Response *response)
MapBuilderBridge(const NodeOptions &node_options, tf2_ros::Buffer *tf_buffer)
bool HandleSubmapQuery(cartographer_ros_msgs::SubmapQuery::Request &request, cartographer_ros_msgs::SubmapQuery::Response &response)
std::unordered_map< int, TrajectoryOptions > trajectory_options_
static Time now()
virtual transform::Rigid3d GetLocalToGlobalTransform(int trajectory_id)=0
std::unordered_map< int, TrajectoryState > GetTrajectoryStates()
int AddTrajectory(const std::unordered_set< string > &expected_sensor_ids, const TrajectoryOptions &trajectory_options)
std::unique_ptr< nav_msgs::OccupancyGrid > BuildOccupancyGrid()
std::unordered_map< int, std::unique_ptr< SensorBridge > > sensor_bridges_


cartographer_ros
Author(s):
autogenerated on Wed Jun 5 2019 22:35:56