mirror of
https://github.com/introlab/rtabmap_ros.git
synced 2026-10-04 16:57:46 +08:00
Updated README with examples of usage of the MIT stata center dataset based on jfr2018 paper. #1350
This commit is contained in:
@@ -1,7 +1,191 @@
|
||||
|
||||
**TODO: currently committed here for backup, though a comprehensive step-by-step procedure would be required so that anyone could reproduce the results**
|
||||
|
||||
This is the raw files used to generate results for MIT Stata Center dataset of this paper (for KITTI, EuRoC and TUM datasets, see this [page](https://github.com/introlab/rtabmap/tree/master/docker/jfr2018)):
|
||||
* M. Labbé and F. Michaud, “RTAB-Map as an Open-Source Lidar and Visual SLAM Library for Large-Scale and Long-Term Online Operation,” in Journal of Field Robotics, accepted, 2018. ([pdf](https://introlab.3it.usherbrooke.ca/mediawiki-introlab/images/7/7a/Labbe18JFR_preprint.pdf)) ([Wiley](https://doi.org/10.1002/rob.21831))
|
||||
|
||||
Manual instructions are in [launch_lidar](https://github.com/introlab/rtabmap_ros/blob/master/rtabmap_legacy/launch/jfr2018/launch_lidar), [launch_stereo](https://github.com/introlab/rtabmap_ros/blob/master/rtabmap_legacy/launch/jfr2018/launch_stereo) and [launch_rgbd](https://github.com/introlab/rtabmap_ros/blob/master/rtabmap_legacy/launch/jfr2018/launch_rgbd) files depending on the sensor configuration. Refer also to explanations in the paper.
|
||||
Manual instructions are in [launch_lidar](https://github.com/introlab/rtabmap_ros/blob/master/rtabmap_legacy/launch/jfr2018/launch_lidar), [launch_stereo](https://github.com/introlab/rtabmap_ros/blob/master/rtabmap_legacy/launch/jfr2018/launch_stereo) and [launch_rgbd](https://github.com/introlab/rtabmap_ros/blob/master/rtabmap_legacy/launch/jfr2018/launch_rgbd) files depending on the sensor configuration. Refer also to explanations in the paper. Below are some examples of usage per sensor type.
|
||||
|
||||
# Long-Range LiDAR with WheelIMU→S2M odometry
|
||||
|
||||
1. Launch rtabmap following config "Long-Range LiDAR with WheelIMU→S2M odometry"
|
||||
```
|
||||
roslaunch rtabmap_launch rtabmap.launch \
|
||||
args:="\
|
||||
-d \
|
||||
--Rtabmap/PublishRAMUsage true \
|
||||
--Rtabmap/StartNewMapOnLoopClosure true \
|
||||
--Reg/Force3DoF false \
|
||||
--RGBD/ProximityPathMaxNeighbors 0 \
|
||||
--Mem/STMSize 15 \
|
||||
--Mem/BinDataKept true \
|
||||
--Kp/FlannRebalancingFactor 1.0 \
|
||||
--RGBD/LinearUpdate 0 \
|
||||
--RGBD/ProximityBySpace true \
|
||||
--RGBD/OptimizeMaxError 3 \
|
||||
--FAST/Threshold 7" \
|
||||
odom_args:="\
|
||||
--Odom/Strategy 0 \
|
||||
--Vis/CorType 0 \
|
||||
--Odom/KeyFrameThr 0.3 \
|
||||
--OdomF2M/MaxSize 2000 \
|
||||
--uwarn" \
|
||||
rgbd_sync:=true \
|
||||
depth_scale:=1.043 \
|
||||
frame_id:=base_footprint \
|
||||
ground_truth_frame_id:=world \
|
||||
ground_truth_base_frame_id:=scan_gt \
|
||||
use_sim_time:=true \
|
||||
odom_topic:=odom \
|
||||
rgb_topic:=/camera/rgb/image_raw \
|
||||
depth_topic:=/camera/depth/image_raw \
|
||||
camera_info_topic:=/camera/rgb/camera_info \
|
||||
approx_sync:=false \
|
||||
odom_guess_frame_id:=odom_combined \
|
||||
odom_always_process_most_recent_frame:=false
|
||||
```
|
||||
|
||||
2. Publish the ground truth in TF
|
||||
```
|
||||
python3 gt_tf_broadcaster.py \
|
||||
_file:=2012-01-25-12-33-29_part1_floor2.gt.laser.poses \
|
||||
_frame_id:=scan_gt \
|
||||
_fixed_frame_id:=world \
|
||||
_offset_time:=82.2 \
|
||||
_offset_x:=-0.275
|
||||
```
|
||||
|
||||
3. Launch the rosbag. Make sure you are running the rosbag on a SSD directly connected inside the computer (not USB SSD) to limit the lags. Note that in contrast to visual odometry approaches below, the lags seem affecting less lidar odometry, so we are still using the original rosbag here.
|
||||
```
|
||||
rosbag play --clock --pause 2012-01-25-12-33-29.bag
|
||||
```
|
||||
|
||||
# RGB-D Camera with F2M odometry
|
||||
1. To avoid lags when replaying the original rosbag, just extract the RGB-D data into another rosbag. With the script in this folder, do:
|
||||
```
|
||||
python3 extract_rgbd.py 2012-01-25-12-33-29
|
||||
```
|
||||
This will create a new rosbag called `2012-01-25-12-33-29_rgbd.bag`.
|
||||
|
||||
2. Launch rtabmap following config "RGB-D Camera with F2M odometry"
|
||||
```
|
||||
roslaunch rtabmap_launch rtabmap.launch \
|
||||
args:="-d \
|
||||
--Rtabmap/PublishRAMUsage true \
|
||||
--Rtabmap/StartNewMapOnLoopClosure true \
|
||||
--Reg/Force3DoF false \
|
||||
--RGBD/ProximityPathMaxNeighbors 0 \
|
||||
--Mem/STMSize 15 \
|
||||
--Mem/BinDataKept true \
|
||||
--Kp/FlannRebalancingFactor 1.0 \
|
||||
--RGBD/LinearUpdate 0 \
|
||||
--RGBD/ProximityBySpace true \
|
||||
--RGBD/OptimizeMaxError 3 \
|
||||
--GFTT/QualityLevel 0.01 \
|
||||
--Vis/MinInliers 10" \
|
||||
odom_args:="\
|
||||
--Odom/Strategy 0 \
|
||||
--Vis/CorType 0 \
|
||||
--Odom/KeyFrameThr 0.3 \
|
||||
--OdomF2M/MaxSize 2000 \
|
||||
--uwarn" \
|
||||
rgbd_sync:=true \
|
||||
depth_scale:=1.043 \
|
||||
frame_id:=base_footprint \
|
||||
ground_truth_frame_id:=world \
|
||||
ground_truth_base_frame_id:=scan_gt \
|
||||
use_sim_time:=true \
|
||||
odom_topic:=odom \
|
||||
rgb_topic:=/camera/rgb/image_raw \
|
||||
depth_topic:=/camera/depth/image_raw \
|
||||
camera_info_topic:=/camera/rgb/camera_info \
|
||||
approx_sync:=false \
|
||||
approx_sync_max_interval:=0.015 \
|
||||
odom_guess_frame_id:=odom_combined \
|
||||
odom_always_process_most_recent_frame:=false
|
||||
```
|
||||
3. Publish the ground truth in TF
|
||||
```
|
||||
python3 gt_tf_broadcaster.py \
|
||||
_file:=2012-01-25-12-33-29_part1_floor2.gt.laser.poses \
|
||||
_frame_id:=scan_gt \
|
||||
_fixed_frame_id:=world \
|
||||
_offset_time:=82.2 \
|
||||
_offset_x:=-0.275
|
||||
```
|
||||
|
||||
4. Launch the rosbag. Make sure you are running the rosbag on a SSD directly connected inside the computer (not USB SSD) to limit the lags.
|
||||
```
|
||||
rosbag play --clock --pause 2012-01-25-12-33-29_rgbd.bag
|
||||
```
|
||||
|
||||
# Stereo Camera with F2M odometry
|
||||
1. To avoid lags when replaying the original rosbag, just extract the stereo data into another rosbag. With the script in this folder, do:
|
||||
```
|
||||
python3 extract_stereo.py 2012-01-25-12-33-29
|
||||
```
|
||||
This will create a new rosbag called `2012-01-25-12-33-29_stereo.bag`.
|
||||
|
||||
2. Launch rtabmap following config "Stereo Camera with F2M odometry"
|
||||
```
|
||||
roslaunch rtabmap_launch rtabmap.launch \
|
||||
args:="-d \
|
||||
--Rtabmap/PublishRAMUsage true \
|
||||
--Rtabmap/StartNewMapOnLoopClosure true \
|
||||
--Reg/Force3DoF false \
|
||||
--RGBD/ProximityPathMaxNeighbors 0 \
|
||||
--Mem/STMSize 15 \
|
||||
--Mem/BinDataKept true \
|
||||
--Kp/FlannRebalancingFactor 1.0 \
|
||||
--RGBD/LinearUpdate 0 \
|
||||
--RGBD/ProximityBySpace true \
|
||||
--Odom/KeyFrameThr 0.3 \
|
||||
--Odom/Strategy 0 \
|
||||
--OdomF2M/MaxSize 2000 \
|
||||
--RGBD/OptimizeMaxError 3 \
|
||||
--GFTT/QualityLevel 0.01 \
|
||||
--Vis/MinInliers 10" \
|
||||
odom_args:="--Vis/CorType 0 --uwarn" \
|
||||
frame_id:=base_footprint \
|
||||
ground_truth_frame_id:=world \
|
||||
ground_truth_base_frame_id:=scan_gt \
|
||||
use_sim_time:=true \
|
||||
stereo:=true \
|
||||
stereo_namespace:=/wide_stereo \
|
||||
left_camera_info_topic:=/wide_stereo/left/camera_info \
|
||||
right_camera_info_topic:=/wide_stereo/right/camera_info_scaled \
|
||||
odom_topic:=odom \
|
||||
approx_sync:=false \
|
||||
odom_guess_frame_id:=odom_combined \
|
||||
odom_always_process_most_recent_frame:=false
|
||||
```
|
||||
3. Publish the ground truth in TF
|
||||
```
|
||||
python3 gt_tf_broadcaster.py \
|
||||
_file:=2012-01-25-12-33-29_part1_floor2.gt.laser.poses \
|
||||
_frame_id:=scan_gt \
|
||||
_fixed_frame_id:=world \
|
||||
_offset_time:=82.2 \
|
||||
_offset_x:=-0.275
|
||||
```
|
||||
|
||||
4. Republish the stereo camera calibration with baseline correctly scaled
|
||||
```
|
||||
python3 republish_camera_info.py \
|
||||
camera_info_in:=/wide_stereo/right/camera_info \
|
||||
camera_info_out:=/wide_stereo/right/camera_info_scaled
|
||||
```
|
||||
|
||||
5. Rectify the raw stereo images
|
||||
```
|
||||
export ROS_NAMESPACE=wide_stereo
|
||||
rosrun stereo_image_proc stereo_image_proc \
|
||||
left/image_raw:=left/image_raw \
|
||||
right/image_raw:=right/image_raw \
|
||||
left/camera_info:=left/camera_info \
|
||||
right/camera_info:=right/camera_info_scaled
|
||||
```
|
||||
|
||||
6. Launch the rosbag. Make sure you are running the rosbag on a SSD directly connected inside the computer (not USB SSD) to limit the lags.
|
||||
```
|
||||
rosbag play --clock --pause 2012-01-25-12-33-29_stereo.bag
|
||||
```
|
||||
|
||||
@@ -4,13 +4,13 @@ import sys
|
||||
from tf.msg import tfMessage
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print 'Usage: $ python extract_rgbd.py "2012-01-25-12-14-25"'
|
||||
print('Usage: $ python extract_rgbd.py "2012-01-25-12-14-25"')
|
||||
sys.exit(0)
|
||||
|
||||
bagName = sys.argv[1]
|
||||
with rosbag.Bag(bagName + '_rgbd.bag', 'w') as outbag:
|
||||
print 'Processing ' + bagName + '.bag...'
|
||||
print(f'Processing {bagName}.bag...')
|
||||
for topic, msg, t in rosbag.Bag(bagName + '.bag').read_messages():
|
||||
if topic == "/tf" or topic == "/camera/depth/image_raw" or topic == "/camera/rgb/camera_info" or topic == "/camera/rgb/image_raw":
|
||||
outbag.write(topic, msg, t)
|
||||
print 'Output: ' + bagName + '_out.bag'
|
||||
print(f'Output: {bagName}_rgbd.bag')
|
||||
|
||||
@@ -4,34 +4,22 @@ import sys
|
||||
from tf.msg import tfMessage
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print 'Usage: $ python extract_stereo.py "2012-01-25-12-14-25"'
|
||||
print('Usage: $ python extract_stereo.py "2012-01-25-12-14-25"')
|
||||
sys.exit(0)
|
||||
|
||||
bagName = sys.argv[1]
|
||||
with rosbag.Bag(bagName + '_stereo.bag', 'w') as outbag:
|
||||
print 'Processing ' + bagName + '.bag...'
|
||||
leftCamInfoStatus = True
|
||||
leftImageStatus = True
|
||||
rightCamInfoStatus = True
|
||||
rightImageStatus = True
|
||||
print(f'Processing {bagName}.bag...')
|
||||
for topic, msg, t in rosbag.Bag(bagName + '.bag').read_messages():
|
||||
if topic == "/tf":
|
||||
outbag.write(topic, msg, t)
|
||||
elif topic == "/wide_stereo/left/camera_info":
|
||||
if leftCamInfoStatus:
|
||||
outbag.write(topic, msg, t)
|
||||
leftCamInfoStatus = not leftCamInfoStatus
|
||||
outbag.write(topic, msg, t)
|
||||
elif topic == "/wide_stereo/right/camera_info":
|
||||
if rightCamInfoStatus:
|
||||
outbag.write(topic, msg, t)
|
||||
rightCamInfoStatus = not rightCamInfoStatus
|
||||
outbag.write(topic, msg, t)
|
||||
elif topic == "/wide_stereo/left/image_raw":
|
||||
if leftImageStatus:
|
||||
outbag.write(topic, msg, t)
|
||||
leftImageStatus = not leftImageStatus
|
||||
outbag.write(topic, msg, t)
|
||||
elif topic == "/wide_stereo/right/image_raw":
|
||||
if rightImageStatus:
|
||||
outbag.write(topic, msg, t)
|
||||
rightImageStatus = not rightImageStatus
|
||||
outbag.write(topic, msg, t)
|
||||
|
||||
print 'Output: ' + bagName + '_out.bag'
|
||||
print(f'Output: {bagName}_stereo.bag')
|
||||
|
||||
@@ -3,21 +3,20 @@
|
||||
<launch>
|
||||
<param name="use_sim_time" value="true"/>
|
||||
<group ns="/wide_stereo" >
|
||||
<node pkg="nodelet" type="nodelet" name="stereo_throttle" args="standalone rtabmap_ros/stereo_throttle">
|
||||
<node pkg="nodelet" type="nodelet" name="stereo_throttle" args="standalone rtabmap_legacy/stereo_throttle">
|
||||
<remap from="left/image" to="left/image_raw"/>
|
||||
<remap from="right/image" to="right/image_raw"/>
|
||||
<remap from="left/camera_info" to="left/camera_info"/>
|
||||
<remap from="right/camera_info" to="right/camera_info"/>
|
||||
|
||||
<param name="queue_size" type="int" value="10"/>
|
||||
<param name="queue_size" type="int" value="100"/>
|
||||
<param name="rate" type="double" value="15"/>
|
||||
<param name="expected_input_rate" type="double" value="30"/>
|
||||
</node>
|
||||
</group>
|
||||
|
||||
<group ns="camera">
|
||||
<node pkg="nodelet" type="nodelet" name="data_throttle" args="standalone rtabmap_ros/data_throttle">
|
||||
<param name="rate" type="double" value="15.0"/>
|
||||
|
||||
<node pkg="nodelet" type="nodelet" name="data_throttle" args="standalone rtabmap_legacy/data_throttle">
|
||||
<remap from="rgb/image_in" to="rgb/image_raw"/>
|
||||
<remap from="depth/image_in" to="depth/image_raw"/>
|
||||
<remap from="rgb/camera_info_in" to="rgb/camera_info"/>
|
||||
@@ -25,6 +24,10 @@
|
||||
<remap from="rgb/image_out" to="rgb/image_raw_throttle"/>
|
||||
<remap from="depth/image_out" to="depth/image_raw_throttle"/>
|
||||
<remap from="rgb/camera_info_out" to="rgb/camera_info_throttle"/>
|
||||
|
||||
<param name="queue_size" type="int" value="100"/>
|
||||
<param name="rate" type="double" value="15.0"/>
|
||||
<param name="expected_input_rate" type="double" value="30"/>
|
||||
</node>
|
||||
</group>
|
||||
</launch>
|
||||
|
||||
@@ -51,7 +51,7 @@ class DataThrottleNodelet : public nodelet::Nodelet
|
||||
public:
|
||||
//Constructor
|
||||
DataThrottleNodelet():
|
||||
rate_(0),
|
||||
period_(0),
|
||||
approxSync_(0),
|
||||
exactSync_(0),
|
||||
decimation_(1)
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
|
||||
private:
|
||||
ros::Time last_update_;
|
||||
double rate_;
|
||||
double period_;
|
||||
virtual void onInit()
|
||||
{
|
||||
ros::NodeHandle& nh = getNodeHandle();
|
||||
@@ -90,22 +90,33 @@ private:
|
||||
int queueSize = 10;
|
||||
bool approxSync = true;
|
||||
double approxSyncMaxInterval = 0.0;
|
||||
if(private_nh.getParam("max_rate", rate_))
|
||||
double rate = 0.0;
|
||||
double expectedInputRate = 0.0;
|
||||
if(private_nh.getParam("max_rate", rate))
|
||||
{
|
||||
NODELET_WARN("\"max_rate\" is now known as \"rate\".");
|
||||
}
|
||||
private_nh.param("rate", rate_, rate_);
|
||||
private_nh.param("rate", rate, rate);
|
||||
private_nh.param("expected_input_rate", expectedInputRate, expectedInputRate);
|
||||
private_nh.param("queue_size", queueSize, queueSize);
|
||||
private_nh.param("approx_sync", approxSync, approxSync);
|
||||
private_nh.param("approx_sync_max_interval", approxSyncMaxInterval, approxSyncMaxInterval);
|
||||
private_nh.param("decimation", decimation_, decimation_);
|
||||
ROS_ASSERT(decimation_ >= 1);
|
||||
NODELET_INFO("rate=%f Hz", rate_);
|
||||
NODELET_INFO("rate=%f Hz", rate);
|
||||
NODELET_INFO("expected_input_rate=%f Hz", expectedInputRate);
|
||||
NODELET_INFO("decimation=%d", decimation_);
|
||||
NODELET_INFO("approx_sync = %s", approxSync?"true":"false");
|
||||
if(approxSync)
|
||||
NODELET_INFO("approx_sync_max_interval = %f", approxSyncMaxInterval);
|
||||
|
||||
if(rate>0){
|
||||
period_ = 1.0/rate;
|
||||
}
|
||||
if(expectedInputRate > 0 && expectedInputRate >= rate) {
|
||||
period_ -= (1.0/expectedInputRate)/2.0;
|
||||
}
|
||||
|
||||
if(approxSync)
|
||||
{
|
||||
approxSync_ = new message_filters::Synchronizer<MyApproxSyncPolicy>(MyApproxSyncPolicy(queueSize), image_sub_, image_depth_sub_, info_sub_);
|
||||
@@ -132,19 +143,19 @@ private:
|
||||
const sensor_msgs::ImageConstPtr& imageDepth,
|
||||
const sensor_msgs::CameraInfoConstPtr& camInfo)
|
||||
{
|
||||
if (rate_ > 0.0)
|
||||
if (period_ > 0.0)
|
||||
{
|
||||
NODELET_DEBUG("update set to %f", rate_);
|
||||
if ( last_update_ + ros::Duration(1.0/rate_) > ros::Time::now())
|
||||
if (last_update_ != ros::Time() && (image->header.stamp - last_update_).toSec() < period_)
|
||||
{
|
||||
NODELET_DEBUG("throttle last update at %f skipping", last_update_.toSec());
|
||||
NODELET_DEBUG("throttle last update at %f skipping (ref=%f)", image->header.stamp.toSec(), last_update_.toSec());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
NODELET_DEBUG("rate unset continuing");
|
||||
}
|
||||
|
||||
last_update_ = ros::Time::now();
|
||||
last_update_ = image->header.stamp;
|
||||
|
||||
double rgbStamp = image->header.stamp.toSec();
|
||||
double depthStamp = imageDepth->header.stamp.toSec();
|
||||
|
||||
@@ -50,7 +50,7 @@ class StereoThrottleNodelet : public nodelet::Nodelet
|
||||
public:
|
||||
//Constructor
|
||||
StereoThrottleNodelet():
|
||||
rate_(0),
|
||||
period_(0),
|
||||
approxSync_(0),
|
||||
exactSync_(0),
|
||||
decimation_(1)
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
|
||||
private:
|
||||
ros::Time last_update_;
|
||||
double rate_;
|
||||
double period_;
|
||||
virtual void onInit()
|
||||
{
|
||||
ros::NodeHandle& nh = getNodeHandle();
|
||||
@@ -89,18 +89,29 @@ private:
|
||||
int queueSize = 5;
|
||||
bool approxSync = false;
|
||||
double approxSyncMaxInterval = 0.0;
|
||||
double rate = 0.0;
|
||||
double expectedInputRate = 0.0;
|
||||
pnh.param("approx_sync", approxSync, approxSync);
|
||||
pnh.param("approx_sync_max_interval", approxSyncMaxInterval, approxSyncMaxInterval);
|
||||
pnh.param("rate", rate_, rate_);
|
||||
pnh.param("rate", rate, rate);
|
||||
pnh.param("expected_input_rate", expectedInputRate, expectedInputRate);
|
||||
pnh.param("queue_size", queueSize, queueSize);
|
||||
pnh.param("decimation", decimation_, decimation_);
|
||||
ROS_ASSERT(decimation_ >= 1);
|
||||
NODELET_INFO("rate=%f Hz", rate_);
|
||||
NODELET_INFO("rate=%f Hz", rate);
|
||||
NODELET_INFO("expected_input_rate=%f Hz", expectedInputRate);
|
||||
NODELET_INFO("decimation=%d", decimation_);
|
||||
NODELET_INFO("approx_sync = %s", approxSync?"true":"false");
|
||||
if(approxSync)
|
||||
NODELET_INFO("approx_sync_max_interval = %f", approxSyncMaxInterval);
|
||||
|
||||
if(rate>0){
|
||||
period_ = 1.0/rate;
|
||||
}
|
||||
if(expectedInputRate > 0 && expectedInputRate >= rate) {
|
||||
period_ -= (1.0/expectedInputRate)/2.0;
|
||||
}
|
||||
|
||||
if(approxSync)
|
||||
{
|
||||
approxSync_ = new message_filters::Synchronizer<MyApproxSyncPolicy>(MyApproxSyncPolicy(queueSize), imageLeft_, imageRight_, cameraInfoLeft_, cameraInfoRight_);
|
||||
@@ -130,20 +141,21 @@ private:
|
||||
const sensor_msgs::CameraInfoConstPtr& camInfoLeft,
|
||||
const sensor_msgs::CameraInfoConstPtr& camInfoRight)
|
||||
{
|
||||
if (rate_ > 0.0)
|
||||
if (period_ > 0.0)
|
||||
{
|
||||
NODELET_DEBUG("update set to %f", rate_);
|
||||
if ( last_update_ + ros::Duration(1.0/rate_) > ros::Time::now())
|
||||
if (last_update_ != ros::Time() && (imageLeft->header.stamp - last_update_).toSec() < period_)
|
||||
{
|
||||
NODELET_DEBUG("throttle last update at %f skipping", last_update_.toSec());
|
||||
NODELET_DEBUG("throttle last update at %f skipping (ref=%f)", imageLeft->header.stamp.toSec(), last_update_.toSec());
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
NODELET_DEBUG("rate unset continuing");
|
||||
}
|
||||
|
||||
last_update_ = ros::Time::now();
|
||||
last_update_ = imageLeft->header.stamp;
|
||||
|
||||
|
||||
double leftStamp = imageLeft->header.stamp.toSec();
|
||||
double rightStamp = imageRight->header.stamp.toSec();
|
||||
double leftInfoStamp = camInfoLeft->header.stamp.toSec();
|
||||
|
||||
Reference in New Issue
Block a user