IMU ์ผ์ ์๊ฐ๊ณผ ROS ์๊ฐ์ด ์๋ก ๋ค๋ฅธ ์๊ฐ์ถ์ ์ฌ์ฉํด ๋ฐ์ํ LIO-SAM ๋๊ธฐํ ๋ฌธ์ ๋ฅผ,
IMU ์๊ฐ์ ์ฆ๊ฐ ์๋๋ฅผ ROS ์๊ฐ์ ๋ง์ถฐ ์ ํ ๋ณด์ ํ๊ณ ,
LiDAR์ IMU๋ฅผ ๋์ผํ ROS ์๊ฐ ๊ธฐ์ค์ผ๋ก ์ฌ์คํฌํํ์ฌ
ํ์์คํฌํ ์ค์ฐจ๋ฅผ 100ms ์ดํ๋ก ์์ ํํ๋ค.
LIO-SAM์ ๊ตฌ์กฐ์ ์ผ๋ก ๋ค์์ ์ ์ ๋ก ํ๋ค.
์ด ๋ ์๊ฐ์ด ๋์ผํ ์๊ฐ์ถ์ ์์ด์ผ ํ๋ค.
ํ์ง๋ง ์ค์ ํ๊ฒฝ์์๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
์ฆ, ์๋ก ๋ค๋ฅธ ์๊ณ๋ฅผ ์ฌ์ฉํ๋ ์ํ์๋ค.
๊ทธ ๊ฒฐ๊ณผ:
๐ ๋ฌธ์ ์ ๋ณธ์ง์
์ ๋ ์๊ฐ ์คํ์
+ ์๊ฐ ํ๋ฆ ์๋(Hz) ๋ถ์ผ์น์๋ค.
| ๋จ๊ณ | ์ฝ๋ | ์ญํ |
|---|---|---|
| 1 | imu_timestamp_fixer.py | IMU ์๊ฐ โ ROS ์๊ฐ์ผ๋ก ์ ํ ๋ณด์ |
| 2 | simple_sync.py | LiDAR & IMU๋ฅผ ๊ฐ์ ROS now ๊ธฐ์ค์ผ๋ก ํต์ผ |
| 3 | timestamp_check_synced.py | ์ค์ ์๊ฐ์ฐจ๊ฐ 100ms ์ดํ์ธ์ง ๊ฒ์ฆ |
imu_timestamp_fixer.py)์ด ๋จ๊ณ๊ฐ ์ ์ผํ๊ฒ โ์๊ฐ ๊ณ์ฐโ์ ์ํํ๋ ํต์ฌ ๋จ๊ณ๋ค.
IMU timestamp๋ฅผ ๊ทธ๋๋ก ์ฐ์ง ๋ง๊ณ ,
IMU ์๊ฐ์ ์ฆ๊ฐ ์๋ ์์ฒด๋ฅผ ROS ์๊ฐ์ ๋ง์ถ๋ค.
์ฒซ IMU ๋ฉ์์ง๊ฐ ๋ค์ด์จ ์๊ฐ์ ๊ธฐ์ค์ ์ผ๋ก ์ผ๋๋ค.
if self.first_sensor_time is None:
self.first_sensor_time = msg.header.stamp.to_sec()
self.first_ros_time = rospy.Time.now().to_sec()
return
first_sensor_time : IMU๊ฐ ๋งํ๋ โ์ฒซ ์๊ฐโfirst_ros_time : ๊ทธ ์๊ฐ์ ROS ์๊ฐ๐ โ๊ฐ์ ์๊ฐ์ ์๋ก ๋ค๋ฅธ ์๊ณ๋ก ๊ธฐ๋กํ ๊ธฐ์ค์ โ
์ดํ ๋ค์ด์ค๋ IMU ๋ฉ์์ง๋ง๋ค:
sensor_time = msg.header.stamp.to_sec()
ros_time = rospy.Time.now().to_sec()
sensor_elapsed = sensor_time - self.first_sensor_time
ros_elapsed = ros_time - self.first_ros_time
์ฆ,
[
\Delta t{sensor} = t{sensor} - t0_{sensor}
][
\Delta t_{ros} = t_{ros} - t0_{ros}
]
IMU ์๊ฐ๊ณผ ROS ์๊ฐ์ ์ฆ๊ฐ ์๋ ๋น์จ์ ๊ณ์ฐํ๋ค.
if sensor_elapsed > 0:
scale = ros_elapsed / sensor_elapsed
self.scale_factors.append(scale)
if len(self.scale_factors) < 100:
return
scaling_factor = sum(self.scale_factors) / len(self.scale_factors)
์์์ผ๋ก ํํํ๋ฉด:
[
s = \text{mean}\left(\frac{\Delta t{ros}}{\Delta t{sensor}}\right)
]
s > 1 โ IMU ์๊ฐ์ด ๋๋ฆฌ๊ฒ ํ๋ฆs < 1 โ IMU ์๊ฐ์ด ๋น ๋ฅด๊ฒ ํ๋ฆcorrected_elapsed = sensor_elapsed * scaling_factor
corrected_stamp = rospy.Time.from_sec(
self.first_ros_time + corrected_elapsed
)
msg.header.stamp = corrected_stamp
self.pub.publish(msg)
์ฆ,
[
t{imu}^{corrected}
= t0{ros}
๐ ๊ฒฐ๊ณผ:
simple_sync.py)์ด ๋จ๊ณ๋ ๊ณ์ฐ๋ณด๋ค๋ ์ ์ฑ ์ ์ ํ์ด๋ค.
def imu_callback(msg):
msg.header.stamp = rospy.Time.now()
imu_pub.publish(msg)
def lidar_callback(msg):
msg.header.stamp = rospy.Time.now()
msg.is_dense = True
points_pub.publish(msg)
๐ ์๋ฏธ:
โ์ผ์๊ฐ ์ธ์ ์ธก์ ํ๋์งโ๋ณด๋ค
โ์ง๊ธ ์ฒ๋ฆฌ๋๊ณ ์๋ ์๊ฐโ์ ๊ธฐ์ค์ผ๋ก ํต์ผ
์ฅ์
๋จ์
์ค์ ์ผ์ ์ธก์ ์๊ฐ์ด ์๋
โก ์ ํ๋๋ณด๋ค๋ ์์ ์ฑ์ ์ฐ์ ํ ๊ตฌ์กฐ
timestamp_check_synced.py)diff = abs(self.latest_imu_time - self.latest_lidar_time)
if diff < 0.1:
rospy.loginfo(f"Synced OK: diff={diff:.4f}s")
else:
rospy.logwarn(f"Time diff too large: {diff:.4f}s")
์์์ผ๋ก๋ ๋จ์ํ:
[
\text{diff} = |t{imu} - t{lidar}|
]
๐ ์ด ํ์ดํ๋ผ์ธ์ ๋ช
ํํ ๋ชฉํ๋
โLIO-SAM์ด ์๊ตฌํ๋ ์๊ฐ ์กฐ๊ฑด(โค100ms)โ ์ถฉ์กฑ
โก ์ผ๋ฐ์ ์ผ๋ก:
์ฆ,
โํญ์ 5ms ์ดํโ๋ ์๋์ง๋ง,
LIO-SAM์ด ์์ ์ ์ผ๋ก ๋์ํ๊ธฐ์ ์ถฉ๋ถํ ์์ ๋ฒ์๋ก ์๋ ดํ๋ค.
IMU ์ผ์ ์๊ฐ์ ํ๋ฆ์ ROS ์๊ฐ์ ์ ํ ๋งคํํด ๋๋ฆฌํํธ๋ฅผ ์ ๊ฑฐํ๊ณ ,
LiDAR์ IMU ๋ฉ์์ง๋ฅผ ๋์ผํ ROS ์๊ฐ ๊ธฐ์ค์ผ๋ก ์ฌ์คํฌํํจ์ผ๋ก์จ
LIO-SAM์์ ์๊ตฌํ๋ ํ์์คํฌํ ๋๊ธฐ ์กฐ๊ฑด(100ms ์ดํ)์ ๋ง์กฑ์์ผฐ๋ค.
simple_sync๋ ๋๊ธฐํ ์์ ์ฑ์ ์ํ ๊ฐ์ ์ ์ฑ
timestamp_check๋ ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ ์ซ์๋ก ์ฆ๋ช
ํ๋ ๋จ๊ณ