Skip to content

Commit

Permalink
feat: implemented camera-lidar calibrator for the drs
Browse files Browse the repository at this point in the history
Signed-off-by: Kenzo Lobos-Tsunekawa <[email protected]>
  • Loading branch information
knzo25 committed Sep 17, 2024
1 parent 5a7f335 commit 399d9ed
Show file tree
Hide file tree
Showing 6 changed files with 407 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<arg name="base_frame" default="base_link"/>

<arg name="rviz" default="true"/>

<arg name="lost_frame_max_acceleration" default="10.0"/>
<arg name="calibration_skip_keyframes" default="7"/>
<arg name="mapping_registrator" default="ndt" description="ndt or gicp"/>
<arg name="mapping_min_range" default="5.0" description="minimum distance to use for mapping"/>
<arg name="mapping_max_range" default="80.0" description="maximum distance to use for mapping"/>

<let name="calibrate_base_frame" value="true"/>
<arg name="base_lidar_crop_box_min_x" default="-5.0"/>
<arg name="base_lidar_crop_box_min_y" default="-5.0"/>
<arg name="base_lidar_crop_box_min_z" default="-5.0"/>
<arg name="base_lidar_crop_box_max_x" default="10.0"/>
<arg name="base_lidar_crop_box_max_y" default="5.0"/>
<arg name="base_lidar_crop_box_max_z" default="5.0"/>
<arg name="base_lidar_min_plane_points_percentage" default="10.0"/>
<arg name="base_lidar_max_inlier_distance" default="0.03"/>
<arg name="base_lidar_min_plane_points" default="500"/>
<arg name="base_lidar_max_cos_distance" default="0.2"/>
<arg name="base_lidar_max_iterations" default="500"/>
<arg name="base_lidar_overwrite_xy_yaw" default="false"/>

<let name="calibration_camera_optical_link_frames" value="['']"/>

<let name="calibration_lidar_frames" value="['']"/>

<let name="mapping_lidar_frame" value="pandar_top"/>
<let name="mapping_pointcloud" value="/sensing/lidar/top/pointcloud_raw"/>
<let name="detected_objects" value="/perception/object_recognition/detection/objects"/>

<let name="calibration_camera_info_topics" value="['']"/>

<let name="calibration_image_topics" value="[
'']"/>

<let name="calibration_pointcloud_topics" value="['']"/>

<!-- mapping based calibrator -->
<include file="$(find-pkg-share mapping_based_calibrator)/launch/calibrator.launch.xml">
<arg name="ns" value=""/>
<arg name="calibration_service_name" value="calibrate_base_lidar"/>

<arg name="rviz" value="$(var rviz)"/>
<arg name="base_frame" value="$(var base_frame)"/>

<arg name="calibration_camera_optical_link_frames" value="$(var calibration_camera_optical_link_frames)"/>
<arg name="calibration_lidar_frames" value="$(var calibration_lidar_frames)"/>
<arg name="mapping_lidar_frame" value="$(var mapping_lidar_frame)"/>

<arg name="mapping_pointcloud" value="$(var mapping_pointcloud)"/>
<arg name="detected_objects" value="$(var detected_objects)"/>

<arg name="calibration_camera_info_topics" value="$(var calibration_camera_info_topics)"/>
<arg name="calibration_image_topics" value="$(var calibration_image_topics)"/>
<arg name="calibration_pointcloud_topics" value="$(var calibration_pointcloud_topics)"/>

<arg name="mapping_registrator" value="$(var mapping_registrator)"/>
<arg name="mapping_min_range" value="$(var mapping_min_range)"/>
<arg name="mapping_max_range" value="$(var mapping_max_range)"/>
<arg name="lost_frame_max_acceleration" value="$(var lost_frame_max_acceleration)"/>
<arg name="calibration_skip_keyframes" value="$(var calibration_skip_keyframes)"/>

<arg name="base_lidar_crop_box_min_x" value="$(var base_lidar_crop_box_min_x)"/>
<arg name="base_lidar_crop_box_min_y" value="$(var base_lidar_crop_box_min_y)"/>
<arg name="base_lidar_crop_box_min_z" value="$(var base_lidar_crop_box_min_z)"/>
<arg name="base_lidar_crop_box_max_x" value="$(var base_lidar_crop_box_max_x)"/>
<arg name="base_lidar_crop_box_max_y" value="$(var base_lidar_crop_box_max_y)"/>
<arg name="base_lidar_crop_box_max_z" value="$(var base_lidar_crop_box_max_z)"/>
<arg name="base_lidar_min_plane_points_percentage" value="$(var base_lidar_min_plane_points_percentage)"/>
<arg name="base_lidar_max_inlier_distance" value="$(var base_lidar_max_inlier_distance)"/>
<arg name="base_lidar_min_plane_points" value="$(var base_lidar_min_plane_points)"/>
<arg name="base_lidar_max_cos_distance" value="$(var base_lidar_max_cos_distance)"/>
<arg name="base_lidar_max_iterations" value="$(var base_lidar_max_iterations)"/>
<arg name="base_lidar_overwrite_xy_yaw" value="$(var base_lidar_overwrite_xy_yaw)"/>
</include>
</launch>
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<launch>
<arg name="camera_name" default="camera0">
<choice value="camera0"/>
<choice value="camera1"/>
<choice value="camera2"/>
<choice value="camera3"/>
<choice value="camera4"/>
<choice value="camera5"/>
<choice value="camera6"/>
<choice value="camera7"/>
</arg>

<arg name="view_only_ui" default="true" description="By default we use a minimal UI"/>
<arg name="calibration_pairs" default="14" description="Number of lidar-image pairs for the calibration to converge"/>
<arg name="calibration_pairs_min_distance" default="0.3" description="Minimum allowed between a new detection and current pairs"/>

<!-- we do not use the standard image_raw name to avoid naming conflicts -->
<let name="image_decompressed_topic" value="/sensing/camera/$(var camera_name)/image_raw/decompressed"/>
<let name="image_compressed_topic" value="/sensing/camera/$(var camera_name)/image_raw/compressed"/>

<let name="camera_info_topic" value="/sensing/camera/$(var camera_name)/camera_info"/>

<let name="lidar_frame" value="lidar_front" if="$(eval &quot;'$(var camera_name)' == 'camera0' &quot;)"/>
<let name="lidar_frame" value="lidar_front" if="$(eval &quot;'$(var camera_name)' == 'camera1' &quot;)"/>
<let name="lidar_frame" value="lidar_right" if="$(eval &quot;'$(var camera_name)' == 'camera2' &quot;)"/>
<let name="lidar_frame" value="lidar_right" if="$(eval &quot;'$(var camera_name)' == 'camera3' &quot;)"/>
<let name="lidar_frame" value="lidar_rear" if="$(eval &quot;'$(var camera_name)' == 'camera4' &quot;)"/>
<let name="lidar_frame" value="lidar_rear" if="$(eval &quot;'$(var camera_name)' == 'camera5' &quot;)"/>
<let name="lidar_frame" value="lidar_left" if="$(eval &quot;'$(var camera_name)' == 'camera6' &quot;)"/>
<let name="lidar_frame" value="lidar_left" if="$(eval &quot;'$(var camera_name)' == 'camera7' &quot;)"/>

<let name="pointcloud_topic" value="/sensing/lidar/front/nebula_points" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_front' &quot;)"/>
<let name="pointcloud_topic" value="/sensing/lidar/rear/nebula_points" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_rear' &quot;)"/>
<let name="pointcloud_topic" value="/sensing/lidar/left/nebula_points" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_left' &quot;)"/>
<let name="pointcloud_topic" value="/sensing/lidar/right/nebula_points" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_right' &quot;)"/>

<let name="camera_frame" value="$(var camera_name)/camera_link"/>
<let name="camera_optical_frame" value="$(var camera_name)/camera_optical_link"/>
<let name="rviz_profile" value="$(find-pkg-share tag_based_pnp_calibrator)/rviz/default_profile.rviz"/>

<let name="lidar_model" value="aeva_aeries2" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_front' &quot;)"/>
<let name="lidar_model" value="seyond_falcon" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_rear' &quot;)"/>
<let name="lidar_model" value="seyond_robin_w" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_left' &quot;)"/>
<let name="lidar_model" value="seyond_robin_w" if="$(eval &quot;'$(var lidar_frame)' == 'lidar_right' &quot;)"/>

<let name="use_rectified_image" value="false"/>

<group>
<!-- image decompressor -->
<node pkg="autoware_image_transport_decompressor" exec="image_transport_decompressor_node" name="decompressor" output="screen">
<remap from="decompressor/input/compressed_image" to="$(var image_compressed_topic)"/>
op
<remap from="decompressor/output/raw_image" to="$(var image_decompressed_topic)"/>

<param name="encoding" value="default"/>
</node>

<!-- tag based calibrator -->
<include file="$(find-pkg-share tag_based_pnp_calibrator)/launch/calibrator.launch.xml">
<arg name="image_topic" value="$(var image_decompressed_topic)"/>
<arg name="camera_info_topic" value="$(var camera_info_topic)"/>
<arg name="pointcloud_topic" value="$(var pointcloud_topic)"/>
<arg name="pointcloud_topic_ex" value="$(var camera_info_topic)"/>
<arg name="lidar_model" value="$(var lidar_model)"/>
<arg name="calibration_service_name" value="calibrate_camera_lidar"/>

<arg name="use_rectified_image" value="$(var use_rectified_image)"/>
<arg name="calibration_pairs" value="$(var calibration_pairs)"/>
<arg name="calibration_pairs_min_distance" value="$(var calibration_pairs_min_distance)"/>
</include>

<!-- interactive calibrator -->
<node pkg="interactive_camera_lidar_calibrator" exec="interactive_calibrator" name="interactive_calibrator" output="screen" if="$(eval &quot;'$(var view_only_ui)' == 'false' &quot;)">
<remap from="pointcloud" to="$(var pointcloud_topic)"/>
<remap from="image" to="$(var image_compressed_topic)"/>
<remap from="camera_info" to="$(var camera_info_topic)"/>
<remap from="calibration_points_input" to="calibration_points"/>

<param name="camera_frame" value="$(var camera_frame)"/>
<param name="use_calibration_api" value="false"/>
<param name="can_publish_tf" value="false"/>
</node>

<!-- camera view -->
<node pkg="tier4_calibration_views" exec="image_view_node.py" name="image_view_node_py" output="screen" if="$(eval &quot;'$(var view_only_ui)' == 'true' &quot;)">
<remap from="pointcloud" to="$(var pointcloud_topic)"/>
<remap from="image" to="$(var image_compressed_topic)"/>
<remap from="camera_info" to="$(var camera_info_topic)"/>
<remap from="calibration_points_input" to="calibration_points"/>
</node>

<!-- create a placeholder lidar frame to make the rviz profile generic -->
<node pkg="tf2_ros" exec="static_transform_publisher" name="tf_broadcaster" output="screen" args="0 0 0 0 0 0 $(var lidar_frame) lidar_frame"/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var lidar_frame) --child-frame-id base_link --x 0.0 --y 0.0 --z -2.0 --yaw 0.0 --roll 0.0 --pitch 0.0"
/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var lidar_frame) --child-frame-id $(var camera_frame) --x 0.0 --y 0.0 --z 0.0 --yaw 1.54 --roll 0.0 --pitch 0.0"
if="$(eval &quot;'$(var lidar_frame)' == 'lidar_front' &quot;)"
/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var lidar_frame) --child-frame-id $(var camera_frame) --x 0.0 --y 0.0 --z 0.0 --yaw 0.523599 --roll 0.0 --pitch 0.523599"
if="$(eval &quot;'$(var camera_name)' == 'camera2' &quot;)"
/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var lidar_frame) --child-frame-id $(var camera_frame) --x 0.0 --y 0.0 --z 0.0 --yaw -0.523599 --roll 0.0 --pitch 0.523599"
if="$(eval &quot;'$(var camera_name)' == 'camera3' &quot;)"
/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var lidar_frame) --child-frame-id $(var camera_frame) --x 0.0 --y 0.0 --z 0.0 --yaw 0.0 --roll 0.0 --pitch 0.0"
if="$(eval &quot;'$(var lidar_frame)' == 'lidar_rear' &quot;)"
/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var lidar_frame) --child-frame-id $(var camera_frame) --x 0.0 --y 0.0 --z 0.0 --yaw 0.523599 --roll 0.0 --pitch 0.523599"
if="$(eval &quot;'$(var camera_name)' == 'camera6' &quot;)"
/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var lidar_frame) --child-frame-id $(var camera_frame) --x 0.0 --y 0.0 --z 0.0 --yaw -0.523599 --roll 0.0 --pitch 0.523599"
if="$(eval &quot;'$(var camera_name)' == 'camera7' &quot;)"
/>
<node
pkg="tf2_ros"
exec="static_transform_publisher"
name="tf_broadcaster"
output="screen"
args="--frame-id $(var camera_frame) --child-frame-id $(var camera_optical_frame) --x 0.0 --y 0.0 --z 0.0 --qx 0.5 --qy -0.5 --qz 0.5 --qw -0.5"
/>

<!-- remap the pointcloud topic to make the rviz profile generic -->
<node pkg="rviz2" exec="rviz2" name="rviz2" output="screen" args="-d $(var rviz_profile)">
<remap from="pointcloud_topic_placeholder" to="$(var pointcloud_topic)"/>
</node>
</group>
</launch>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .default_project import * # noqa: F401, F403
from .drs import * # noqa: F401, F403
from .rdv import * # noqa: F401, F403
from .x1 import * # noqa: F401, F403
from .x2 import * # noqa: F401, F403
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .mapping_based_lidar_lidar_calibrator import MappingBasedLidarLidarCalibrator
from .tag_based_pnp_calibrator import TagBasedPNPCalibrator

__all__ = [
"MappingBasedLidarLidarCalibrator",
"TagBasedPNPCalibrator",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#!/usr/bin/env python3

# Copyright 2024 Tier IV, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Dict

import numpy as np

from sensor_calibration_manager.calibrator_base import CalibratorBase
from sensor_calibration_manager.calibrator_registry import CalibratorRegistry
from sensor_calibration_manager.ros_interface import RosInterface
from sensor_calibration_manager.types import FramePair


@CalibratorRegistry.register_calibrator(
project_name="drs", calibrator_name="mapping_based_lidar_lidar_calibrator"
)
class MappingBasedLidarLidarCalibrator(CalibratorBase):
required_frames = []

def __init__(self, ros_interface: RosInterface, **kwargs):
super().__init__(ros_interface)

self.sensor_kit_frame = "sensor_kit_base_link"
self.mapping_lidar_frame = "pandar_top"
self.calibration_lidar_frames = ["pandar_front", "pandar_left", "pandar_right"]
self.calibration_base_lidar_frames = [
"pandar_front_base_link",
"pandar_left_base_link",
"pandar_right_base_link",
]

self.required_frames.extend(
[
self.sensor_kit_frame,
self.mapping_lidar_frame,
*self.calibration_lidar_frames,
*self.calibration_base_lidar_frames,
]
)

self.add_calibrator(
service_name="calibrate_lidar_lidar",
expected_calibration_frames=[
FramePair(parent=self.mapping_lidar_frame, child=calibration_lidar_frame)
for calibration_lidar_frame in self.calibration_lidar_frames
],
)

def post_process(self, calibration_transforms: Dict[str, Dict[str, np.array]]):
sensor_kit_to_lidar_transform = self.get_transform_matrix(
self.sensor_kit_frame, self.mapping_lidar_frame
)

calibration_lidar_to_base_lidar_transforms = [
self.get_transform_matrix(calibration_lidar_frame, calibration_base_lidar_frame)
for calibration_lidar_frame, calibration_base_lidar_frame in zip(
self.calibration_lidar_frames, self.calibration_base_lidar_frames
)
]

sensor_kit_to_calibration_lidar_transforms = [
sensor_kit_to_lidar_transform
@ calibration_transforms[self.mapping_lidar_frame][calibration_lidar_frame]
@ calibration_lidar_to_base_lidar_transform
for calibration_lidar_frame, calibration_lidar_to_base_lidar_transform in zip(
self.calibration_lidar_frames, calibration_lidar_to_base_lidar_transforms
)
]

result = {
self.sensor_kit_frame: {
calibration_base_lidar_frame: transform
for calibration_base_lidar_frame, transform in zip(
self.calibration_base_lidar_frames, sensor_kit_to_calibration_lidar_transforms
)
}
}

return result
Loading

0 comments on commit 399d9ed

Please sign in to comment.