17 #ifndef POINT_CLOUD_MAPPING__POINT_CLOUD_MAPPER_HPP_
18 #define POINT_CLOUD_MAPPING__POINT_CLOUD_MAPPER_HPP_
22 #include <sensor_msgs/msg/point_cloud2.hpp>
24 #include <tf2_sensor_msgs/tf2_sensor_msgs.h>
29 #include <experimental/optional>
33 #include <type_traits>
39 namespace point_cloud_mapping
41 template<
typename MapIncrementT>
43 geometry_msgs::msg::PoseWithCovarianceStamped>;
48 template<
typename LocalizerSummaryT,
typename MapIncrementT>
84 template<
typename LocalizerT,
typename MapRepresentationT,
85 typename ObservationMsgT,
typename MapIncrementT,
typename RegistrationSummaryT,
86 class WriteTriggerPolicyT,
class PrefixGeneratorT>
89 ObservationMsgT, MapIncrementT, RegistrationSummaryT>
93 std::is_same<MapIncrementT, typename LocalizerT::MapMsg>::value,
94 "MapperBase and the utilized Relative Localizer must use the same map increment type");
96 std::is_same<ObservationMsgT, typename LocalizerT::InputMsg>::value,
97 "MapperBase and the utilized Relative Localizer must use the same observation type");
102 std::experimental::optional<typename LocalizerT::RegistrationSummary>;
107 RelativeLocalizerBase<ObservationMsgT, MapIncrementT, typename LocalizerT::RegistrationSummary>;
117 const std::string & map_filename_prefix,
118 MapRepresentationT && map,
120 const std::string map_frame_id)
121 : m_base_fn_prefix{map_filename_prefix},
122 m_map{std::forward<MapRepresentationT>(map)},
123 m_localizer_ptr{std::forward<LocalizerBasePtr>(localizer_ptr)},
124 m_frame_id{map_frame_id}
126 this->set_map_valid();
140 if (m_map.size() > 0U) {
141 if (!m_localizer_ptr->map_valid()) {
142 throw std::runtime_error(
143 "MapperBase: Map representation has data but "
144 "the localizer's map is at an invalid state.");
146 localization_summary =
147 m_localizer_ptr->register_measurement(msg, transform_initial, pose_out);
151 pose_out = get_identity(
get_stamp(msg), m_frame_id);
154 const auto & increment_ptr = get_map_increment(msg, pose_out);
156 const auto & update_summary = update_map(*increment_ptr, registered_pose);
158 if (m_trigger_policy.ready(m_map)) {
162 return make_summary(increment_ptr, update_summary, localization_summary);
173 insert_to_map_impl(msg);
176 std::chrono::system_clock::time_point
map_stamp() const noexcept
override
178 return m_current_stamp;
184 if (msg_frame != m_frame_id) {
185 throw std::runtime_error(
"MapperBase: Can't insert a map that is in a different frame.");
187 update_map(msg, get_identity(
get_stamp(msg), m_frame_id));
199 if (m_map.size() > 0U) {
200 m_map.write(m_fn_prefix_generator.get(m_base_fn_prefix));
206 m_trigger_policy = std::move(write_trigger);
211 m_fn_prefix_generator = std::move(prefix_generator);
215 builtin_interfaces::msg::Time stamp,
216 const std::string frame_id)
const noexcept
219 out.header.stamp = stamp;
220 out.header.frame_id = frame_id;
221 out.pose.pose.orientation.w = 1.0;
226 virtual RegistrationSummaryT make_summary(
227 const ConstMapIncrementPtrT & increment,
229 const MaybeLocalizerSummary & localization_summary)
const noexcept = 0;
237 const MapIncrementT & increment,
238 PoseWithCovarianceStamped pose)
240 const auto insert_summary = m_map.try_add_observation(increment, pose);
249 switch (insert_summary.update_type) {
251 m_localizer_ptr->set_map(increment);
254 m_localizer_ptr->insert_to_map(increment);
261 return insert_summary;
268 virtual ConstMapIncrementPtrT get_map_increment(
269 const ObservationMsgT & observation,
270 const PoseWithCovarianceStamped & registered_pose) = 0;
272 std::string m_base_fn_prefix;
273 MapRepresentationT m_map;
274 LocalizerBasePtr m_localizer_ptr;
275 WriteTriggerPolicyT m_trigger_policy;
276 PrefixGeneratorT m_fn_prefix_generator;
277 std::string m_frame_id;
278 std::chrono::system_clock::time_point m_current_stamp{
279 std::chrono::system_clock::time_point::min()};
282 using Cloud = sensor_msgs::msg::PointCloud2;
290 template<
typename LocalizerT,
typename MapRepresentationT,
291 class WriteTriggerPolicyT,
class FileNamePrefixGeneratorT>
293 sensor_msgs::msg::PointCloud2, sensor_msgs::msg::PointCloud2,
294 MapperRegistrationSummaryBase<typename LocalizerT::RegistrationSummary,
296 WriteTriggerPolicyT, FileNamePrefixGeneratorT>
303 sensor_msgs::msg::PointCloud2, sensor_msgs::msg::PointCloud2,
315 const std::string & map_filename_prefix,
317 const std::string & map_frame)
318 :
Base(map_filename_prefix, std::forward<MapRepresentationT>(map),
320 m_cached_increment_ptr{std::make_shared<Cloud>()}
332 const Cloud & observation,
335 reset_cached_msg(get_msg_size(observation));
338 tf.header.stamp = registered_pose.header.stamp;
339 tf.header.frame_id = registered_pose.header.frame_id;
340 tf.child_frame_id = observation.header.frame_id;
341 const auto & trans = registered_pose.pose.pose.position;
342 const auto & rot = registered_pose.pose.pose.orientation;
343 tf.transform.translation.set__x(trans.x).set__y(trans.y).set__z(trans.z);
344 tf.transform.rotation.set__x(rot.x).set__y(rot.y).set__z(rot.z).set__w(rot.w);
347 return m_cached_increment_ptr;
351 void reset_cached_msg(std::size_t size)
353 sensor_msgs::PointCloud2Modifier inc_modifier{*m_cached_increment_ptr};
354 inc_modifier.clear();
355 inc_modifier.resize(size);
357 std::size_t get_msg_size(
const Cloud & msg)
const
361 return (safe_indices.data_length == msg.data.size()) ?
362 msg.width : (safe_indices.data_length / safe_indices.point_step);
367 const MapUpdateSummary & map_update_summary,
380 #endif // POINT_CLOUD_MAPPING__POINT_CLOUD_MAPPER_HPP_