3 from message_filters 
import ApproximateTimeSynchronizer, Subscriber
 
    4 from sensor_msgs.msg 
import PointCloud2, PointField, NavSatFix
 
    5 from nav_msgs.msg 
import Odometry
 
    6 from cslam_common_interfaces.msg 
import KeyframeOdom, KeyframePointCloud
 
    7 from cslam_common_interfaces.msg 
import LocalDescriptorsRequest, LocalPointCloudDescriptors, InterRobotLoopClosure, IntraRobotLoopClosure, LocalKeyframeMatch
 
    8 from cslam_common_interfaces.msg 
import VizPointCloud
 
    9 import cslam.lidar_pr.icp_utils 
as icp_utils
 
   11 from rclpy.node 
import Node
 
   12 from rclpy.clock 
import Clock
 
   13 from rclpy.qos 
import QoSProfile, ReliabilityPolicy, HistoryPolicy, DurabilityPolicy
 
   14 from diagnostic_msgs.msg 
import KeyValue
 
   17     """Front-End data handler for lidar data 
   23         qos_profile = QoSProfile(
 
   24             reliability=ReliabilityPolicy.BEST_EFFORT,
 
   25             history=HistoryPolicy.KEEP_LAST,
 
   29         tss = ApproximateTimeSynchronizer( [ Subscriber(self.
nodenode, PointCloud2, self.
paramsparams[
"frontend.pointcloud_topic"], qos_profile=qos_profile),
 
   30                                   Subscriber(self.
nodenode, Odometry, self.
paramsparams[
"frontend.odom_topic"])], 100, self.
paramsparams[
"frontend.pointcloud_odom_approx_time_sync_s"] )
 
   53         period_ms = self.
paramsparams[
"frontend.map_manager_process_period_ms"]
 
   62         if self.
paramsparams[
"evaluation.enable_logs"]:
 
   64                 KeyValue, 
'log_info', 100)
 
   67         if self.
paramsparams[
"evaluation.enable_gps_recording"]:
 
   73         """Sensor data callback 
   76             pc_msg (sensor_msgs/Pointcloud2): point cloud 
   77             odom_msg (nav_msgs/Odometry): odometry estimate 
   79         if (odom_msg.pose.covariance[0] > 1000):
 
   80             self.
nodenode.get_logger().warn(
"Odom tracking failed, skipping frame")
 
   83         if self.
paramsparams[
"evaluation.enable_gps_recording"]:
 
   92         """Callback for local descriptors request 
   94         out_msg = LocalPointCloudDescriptors()
 
   96         out_msg.keyframe_id = request.keyframe_id
 
   97         out_msg.robot_id = self.
paramsparams[
"robot_id"]
 
   98         out_msg.matches_robot_id = request.matches_robot_id
 
   99         out_msg.matches_keyframe_id = request.matches_keyframe_id
 
  102         if self.
paramsparams[
"evaluation.enable_logs"]:
 
  107         """Callback for local descriptors from other robots 
  110         for i 
in range(len(msg.matches_robot_id)):
 
  111             if msg.matches_robot_id[i] == self.
paramsparams[
"robot_id"]:
 
  112                 frame_ids.append(msg.matches_keyframe_id[i])
 
  113         for frame_id 
in frame_ids:
 
  116             out_msg = InterRobotLoopClosure()
 
  117             out_msg.robot0_id = self.
paramsparams[
"robot_id"]
 
  118             out_msg.robot0_keyframe_id = frame_id
 
  119             out_msg.robot1_id = msg.robot_id
 
  120             out_msg.robot1_keyframe_id = msg.keyframe_id
 
  122                 out_msg.success = 
True 
  123                 out_msg.transform = transform
 
  125                 out_msg.success = 
False 
  129         """Callback for local keyframe match for intra-robot loop closures 
  134         out_msg = IntraRobotLoopClosure()
 
  135         out_msg.keyframe0_id = msg.keyframe0_id
 
  136         out_msg.keyframe1_id = msg.keyframe1_id
 
  138             out_msg.success = 
True 
  139             out_msg.transform = transform
 
  141             out_msg.success = 
False 
  145         """Compute the squared distance between two odometry messages 
  147         return (odom0.pose.pose.position.x - odom1.pose.pose.position.x)**2 + (odom0.pose.pose.position.y - odom1.pose.pose.position.y)**2 + (odom0.pose.pose.position.z - odom1.pose.pose.position.z)**2
 
  150         """Check if we should generate a new keyframe 
  153             msg (nav_msgs/Odometry): odometry msg 
  156             bool: flag indicating if a new keyframe should be created. 
  162         if dist > self.
paramsparams[
"frontend.keyframe_generation_ratio_distance"]**2:
 
  169         """ Process new sensor data 
  175             if self.
paramsparams[
"evaluation.enable_gps_recording"]:
 
  181                 except Exception 
as e:
 
  183                     self.
nodenode.get_logger().info(
"Failure to downsample point cloud to voxel size {}. {}".format(self.
paramsparams[
"frontend.voxel_size"], e))
 
  186                 msg_pointcloud = KeyframePointCloud()
 
  191                 msg_odom = KeyframeOdom()
 
  193                 msg_odom.odom = data[1]
 
  194                 if self.
paramsparams[
"evaluation.enable_gps_recording"]:
 
  197                 if self.
paramsparams[
"visualization.enable"]:
 
  198                     viz_msg = VizPointCloud()
 
  199                     viz_msg.robot_id = self.
paramsparams[
"robot_id"]
 
  201                     viz_msg.pointcloud = msg_pointcloud.pointcloud
 
  205 if __name__ == 
'__main__':
 
  207     rclpy.init(args=
None)
 
  208     node = Node(
"map_manager")
 
  209     node.declare_parameters(
 
  211             parameters=[(
'frontend.pointcloud_topic', 
'pointcloud'),
 
  212                         (
'frontend.odom_topic', 
'odom'),
 
  213                         (
'frontend.map_manager_process_period_ms', 100),
 
  214                         (
'frontend.voxel_size', 0.5),
 
  215                         (
'frontend.registration_min_inliers', 60),
 
  216                         (
'frontend.keyframe_generation_ratio_distance', 0.5),
 
  217                         (
'frontend.pointcloud_odom_approx_time_sync_s', 0.1),
 
  219                         (
'evaluation.enable_logs', 
False),  
 
  220                         (
'evaluation.enable_gps_recording', 
False), 
 
  221                         (
'evaluation.gps_topic', 
""),            
 
  222                         (
'evaluation.gps_topic', 
""),        
 
  223                         (
'visualization.enable', 
False),
 
  226     params[
'frontend.pointcloud_topic'] = node.get_parameter(
 
  227         'frontend.pointcloud_topic').value 
 
  228     params[
'frontend.odom_topic'] = node.get_parameter(
 
  229         'frontend.odom_topic').value
 
  230     params[
'frontend.map_manager_process_period_ms'] = node.get_parameter(
 
  231         'frontend.map_manager_process_period_ms').value
 
  232     params[
'frontend.voxel_size'] = node.get_parameter(
 
  233         'frontend.voxel_size').value
 
  234     params[
'frontend.registration_min_inliers'] = node.get_parameter(
 
  235         'frontend.registration_min_inliers').value 
 
  236     params[
'frontend.keyframe_generation_ratio_distance'] = node.get_parameter(
 
  237         'frontend.keyframe_generation_ratio_distance').value
 
  238     params[
'frontend.pointcloud_odom_approx_time_sync_s'] = node.get_parameter(
 
  239         'frontend.pointcloud_odom_approx_time_sync_s').value
 
  240     params[
'robot_id'] = node.get_parameter(
 
  242     params[
"evaluation.enable_logs"] = node.get_parameter(
 
  243             'evaluation.enable_logs').value
 
  244     params[
"evaluation.enable_gps_recording"] = node.get_parameter(
 
  245             'evaluation.enable_gps_recording').value
 
  246     params[
"evaluation.gps_topic"] = node.get_parameter(
 
  247             'evaluation.gps_topic').value
 
  248     params[
"visualization.enable"] = node.get_parameter(
 
  249             'visualization.enable').value
 
  251     node.get_logger().info(
'Initialization done.')
 
def odom_distance_squared(self, odom0, odom1)
def gps_callback(self, gps_msg)
def generate_new_keyframe(self, msg)
log_local_descriptors_cumulative_communication
keyframe_pointcloud_publisher
pointcloud_descriptors_publisher
def receive_local_descriptors(self, msg)
inter_robot_loop_closure_publisher
send_local_descriptors_subscriber
def send_local_descriptors_request(self, request)
intra_robot_loop_closure_publisher
def __init__(self, node, params)
local_keyframe_match_subscriber
def receive_local_keyframe_match(self, msg)
def lidar_callback(self, pc_msg, odom_msg)
def process_new_sensor_data(self)
pointcloud_descriptors_subscriber
def downsample_ros_pointcloud(pc_msg, voxel_size)
def open3d_to_ros(open3d_cloud)
def compute_transform(src, dst, voxel_size, min_inliers)