Skip to content

Commit df5509b

Browse files
committed
Merge branch 'feature-timesync'
2 parents 7095274 + 15aa372 commit df5509b

File tree

3 files changed

+116
-19
lines changed

3 files changed

+116
-19
lines changed

imu_vn_100/include/imu_vn_100/imu_vn_100.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@ class ImuVn100 {
114114

115115
void FixImuRate();
116116
void LoadParameters();
117+
118+
// used for clock synchronziation
119+
bool synchronize_time_;
120+
double hardware_clock_;
121+
uint64_t last_hardware_time_stamp_;
122+
double hardware_clock_adj_;
123+
const double adj_alpha_ = .01;
124+
uint64_t adj_count_;
125+
126+
ros::Time getSynchronizedTime(uint64_t time_stamp, const ros::Time &system_time);
117127
};
118128

119129
// Just don't like type that is ALL CAP

imu_vn_100/src/imu_vn_100.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,8 @@ void ImuVn100::Disconnect() {
420420

421421
void ImuVn100::PublishData(const VnDeviceCompositeData& data) {
422422
sensor_msgs::Imu imu_msg;
423-
imu_msg.header.stamp = ros::Time::now();
423+
// imu_msg.header.stamp = ros::Time::now();
424+
imu_msg.header.stamp = getSynchronizedTime(data.timeStartup, ros::Time::now());
424425
imu_msg.header.frame_id = frame_id_;
425426

426427
if (imu_compensated_) {
@@ -471,6 +472,45 @@ void ImuVn100::PublishData(const VnDeviceCompositeData& data) {
471472
// updater_.update();
472473
}
473474

475+
ros::Time ImuVn100::getSynchronizedTime(uint64_t time_stamp, const ros::Time &system_time)
476+
{
477+
ros::Time stamp = system_time;
478+
479+
double delta = (time_stamp - last_hardware_time_stamp_) * 1.0e-9;
480+
hardware_clock_ += delta;
481+
double cur_adj = stamp.toSec() - hardware_clock_;
482+
if (adj_count_ > 0)
483+
{
484+
hardware_clock_adj_ = adj_alpha_*cur_adj+(1.0-adj_alpha_)*hardware_clock_adj_;
485+
}
486+
else
487+
{
488+
// Initialize the EMA
489+
hardware_clock_adj_ = cur_adj;
490+
}
491+
adj_count_++;
492+
last_hardware_time_stamp_ = time_stamp;
493+
494+
// Once hardware clock is synchronized, use it. Otherwise just return the
495+
// input system_time_stamp as ros::Time.
496+
if (adj_count_ > 100)
497+
{
498+
stamp.fromSec(hardware_clock_+hardware_clock_adj_);
499+
// If the time error is large a clock warp has occurred.
500+
// Reset the EMA and use the system time.
501+
if (fabs((stamp-system_time).toSec()) > 0.1)
502+
{
503+
adj_count_ = 0;
504+
hardware_clock_ = 0.0;
505+
last_hardware_time_stamp_ = 0;
506+
stamp = system_time;
507+
ROS_INFO("%s: detected clock warp, reset EMA", __func__);
508+
}
509+
}
510+
return stamp;
511+
}
512+
513+
474514
void VnEnsure(const VnErrorCode& error_code) {
475515
if (error_code == VNERR_NO_ERROR) return;
476516

rti_dvl/scripts/rti_dvl_node.py

Lines changed: 65 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,66 @@
99

1010
SALINITY = {'fresh': 0, 'salt': 35}
1111

12-
def zeor_pressure(req):
13-
rospy.loginfo('Zero pressure sensor')
1412

15-
dvl.write('CPZ\r\n')
16-
return TriggerResponse(success=True)
13+
class SyncTime(object):
14+
"""Time translator
15+
- See https://github.com/ethz-asl/cuckoo_time_translator for more details.
16+
- Implement https://github.com/ros-drivers/urg_node/blob/d2722c60f1b4713bbe1d39f32849090dece0104d/src/urg_c_wrapper.cpp#L1052
17+
"""
18+
19+
def __init__(self):
20+
self.hardware_clock = 0.0
21+
self.last_hardware_time_stamp = 0.0
22+
self.hardware_clock_adj = 0.0
23+
self.adj_count = 0
24+
self.adj_alpha = 0.01
25+
26+
def sync(self, time_stamp, system_time_stamp):
27+
delta = time_stamp - self.last_hardware_time_stamp
28+
self.hardware_clock += delta
29+
cur_adj = system_time_stamp.to_sec() - self.hardware_clock
30+
if self.adj_count > 0:
31+
self.hardware_clock_adj = (
32+
self.adj_alpha * cur_adj
33+
+ (1.0 - self.adj_alpha) * self.hardware_clock_adj
34+
)
35+
else:
36+
self.hardware_clock_adj = cur_adj
1737

38+
self.adj_count += 1
39+
self.last_hardware_time_stamp = time_stamp
1840

19-
def toggle_status(req):
20-
global running
21-
if running:
22-
rospy.loginfo('Stop DVL')
23-
dvl.write('STOP\r\n')
24-
running = False
25-
return TriggerResponse(success=True, message='Stop')
26-
else:
27-
rospy.loginfo('Start DVL')
28-
dvl.write('START\r\n')
29-
running = True
30-
return TriggerResponse(success=True, message='Start')
41+
stamp = system_time_stamp
42+
if self.adj_count > 100:
43+
stamp = stamp.from_sec(self.hardware_clock + self.hardware_clock_adj)
44+
45+
if abs((stamp - system_time_stamp).to_sec()) > 0.1:
46+
self.adj_count = 0
47+
self.hardware_clock = 0.0
48+
self.last_hardware_time_stamp = 0.0
49+
self.stamp = system_time_stamp
50+
return stamp
51+
52+
53+
# def zeor_pressure(req):
54+
# rospy.loginfo('Zero pressure sensor')
55+
56+
# dvl.write('CPZ\r\n')
57+
# return TriggerResponse(success=True)
58+
59+
60+
# def toggle_status(req):
61+
# global running
62+
# if running:
63+
# rospy.loginfo('Stop DVL')
64+
# dvl.write('STOP\r\n')
65+
# running = False
66+
# return TriggerResponse(success=True, message='Stop')
67+
# else:
68+
# rospy.loginfo('Start DVL')
69+
# dvl.write('START\r\n')
70+
# running = True
71+
# return TriggerResponse(success=True, message='Start')
3172

3273

3374
if __name__ == '__main__':
@@ -40,6 +81,8 @@ def toggle_status(req):
4081
water = rospy.get_param('/water', 'fresh')
4182
salinity = SALINITY[water]
4283

84+
rospy.logwarn('Water is {}. Please set salinity in DVL.'.format(water))
85+
4386
# TODO
4487
# Change salinity here
4588

@@ -122,15 +165,19 @@ def toggle_status(req):
122165
dvl_pub = rospy.Publisher('/rti/body_velocity/raw', DVL, queue_size=100)
123166
reader = pynmea2.NMEAStreamReader(errors='ignore')
124167

168+
sync = SyncTime()
125169
while not rospy.is_shutdown():
126170
try:
127171
char = dvl.read()
128172
except serial.SerialException:
129173
break
130174
for msg in reader.next(char):
131-
if isinstance(msg, pynmea2.types.rti.RTI01) or isinstance(msg, pynmea2.types.rti.RTI03):
175+
if isinstance(msg, pynmea2.types.rti.RTI01) or isinstance(
176+
msg, pynmea2.types.rti.RTI03
177+
):
132178
d = DVL()
133-
d.header.stamp = rospy.Time.now()
179+
stamp = sync.sync(msg.time / 100.0, rospy.Time.now())
180+
d.header.stamp = stamp
134181
d.velocity.x = msg.x / 1000.0
135182
d.velocity.y = msg.y / 1000.0
136183
d.velocity.z = msg.z / 1000.0

0 commit comments

Comments
 (0)