18 #include <sensor_msgs/LaserScan.h> 20 #include <boost/bind/bind.hpp> 21 #include <boost/format.hpp> 22 #include <boost/thread.hpp> 100 const boost::posix_time::ptime &time_request,
101 const boost::posix_time::ptime &time_response,
102 const uint64_t &device_timestamp)
112 const boost::posix_time::ptime &time_response,
113 const uint64_t &device_timestamp,
116 time_at_device_timestamp =
ros::Time::fromBoost(time_response) - estimated_communication_delay_ * 0.5;
122 const boost::posix_time::ptime &time_read,
123 const std::string &echo_back,
124 const std::string &status,
126 const bool has_intensity)
130 const auto estimated_timestamp_lf =
136 t0_ = estimated_timestamp_lf;
138 const auto receive_time =
139 timestamp_outlier_removal_.
update(
141 estimated_communication_delay_ * 0.5 -
144 sensor_msgs::LaserScan msg(msg_base_);
146 timestamp_moving_average_.
update(
149 timestamp_lpf_.
update((estimated_timestamp_lf - t0_).toSec()) +
150 timestamp_hpf_.
update((receive_time - t0_).toSec())));
152 if (scan.
ranges_.size() != step_max_ - step_min_ + 1)
154 ROS_DEBUG(
"Size of the received scan data is wrong (expected: %d, received: %lu); refreshing",
155 step_max_ - step_min_ + 1, scan.
ranges_.size());
157 (has_intensity ?
"ME" :
"MD") +
158 (boost::format(
"%04d%04d") % step_min_ % step_max_).str() +
163 msg.ranges.reserve(scan.
ranges_.size());
165 msg.ranges.push_back(r * 1e-3);
170 msg.intensities.push_back(r);
175 void cbTMSend(
const boost::posix_time::ptime &time_send)
177 time_tm_request = time_send;
180 const boost::posix_time::ptime &time_read,
181 const std::string &echo_back,
182 const std::string &status,
188 timer_try_tm_.
stop();
189 switch (echo_back[2])
205 communication_delays_.push_back(delay);
207 communication_delays_.pop_front();
210 time_tm_request, time_read, walltime_device);
211 device_time_origins_.push_back(origin);
213 device_time_origins_.pop_front();
217 std::vector<ros::Duration> delays(communication_delays_.begin(), communication_delays_.end());
218 std::vector<ros::Time> origins(device_time_origins_.begin(), device_time_origins_.end());
219 sort(delays.begin(), delays.end());
220 sort(origins.begin(), origins.end());
222 if (!estimated_communication_delay_init_)
224 estimated_communication_delay_ = delays[tm_iter_num_ / 2];
225 device_time_origin_ =
DriftedTime(origins[tm_iter_num_ / 2], 1.0);
229 estimated_communication_delay_ =
231 delays[tm_iter_num_ / 2] * communication_delay_filter_alpha_;
233 estimated_communication_delay_init_ =
true;
234 ROS_DEBUG(
"delay: %0.6f, device timestamp: %ld, device time origin: %0.6f",
235 estimated_communication_delay_.
toSec(),
237 origins[tm_iter_num_ / 2].toSec());
238 scip_->sendCommand(
"TM2");
252 (publish_intensity_ ?
"ME" :
"MD") +
253 (boost::format(
"%04d%04d") % step_min_ % step_max_).str() +
256 timestamp_outlier_removal_.
reset();
257 timestamp_moving_average_.
reset();
264 const boost::posix_time::ptime &time_read,
265 const std::string &echo_back,
266 const std::string &status,
267 const std::map<std::string, std::string> ¶ms)
269 const auto amin = params.find(
"AMIN");
270 const auto amax = params.find(
"AMAX");
271 const auto dmin = params.find(
"DMIN");
272 const auto dmax = params.find(
"DMAX");
273 const auto ares = params.find(
"ARES");
274 const auto afrt = params.find(
"AFRT");
275 const auto scan = params.find(
"SCAN");
276 if (amin == params.end() || amax == params.end() ||
277 dmin == params.end() || dmax == params.end() ||
278 ares == params.end() || afrt == params.end() ||
279 scan == params.end())
281 ROS_ERROR(
"PP doesn't have required parameters");
284 step_min_ = std::stoi(amin->second);
285 step_max_ = std::stoi(amax->second);
286 msg_base_.scan_time = 60.0 / std::stoi(scan->second);
287 msg_base_.angle_increment = 2.0 * M_PI / std::stoi(ares->second);
288 msg_base_.time_increment = msg_base_.scan_time / std::stoi(ares->second);
289 msg_base_.range_min = std::stoi(dmin->second) * 1e-3;
290 msg_base_.range_max = std::stoi(dmax->second) * 1e-3;
291 msg_base_.angle_min =
292 (std::stoi(amin->second) - std::stoi(afrt->second)) * msg_base_.angle_increment;
293 msg_base_.angle_max =
294 (std::stoi(amax->second) - std::stoi(afrt->second)) * msg_base_.angle_increment;
301 const boost::posix_time::ptime &time_read,
302 const std::string &echo_back,
303 const std::string &status,
304 const std::map<std::string, std::string> ¶ms)
307 void cbIISend(
const boost::posix_time::ptime &time_send)
309 time_ii_request = time_send;
312 const boost::posix_time::ptime &time_read,
313 const std::string &echo_back,
314 const std::string &status,
315 const std::map<std::string, std::string> ¶ms)
321 if (delay.toSec() < 0.002)
323 const auto time = params.find(
"TIME");
324 if (time == params.end())
329 if (time->second.size() != 6 && time->second.size() != 4)
331 ROS_DEBUG(
"Timestamp in II is ill-formatted (%s)", time->second.c_str());
334 const uint32_t time_device =
335 time->second.size() == 6 ?
336 std::stoi(time->second,
nullptr, 16) :
339 const uint64_t walltime_device = walltime_.
update(time_device);
343 time_read, walltime_device, time_at_device_timestamp);
347 last_sync_time_ = now;
348 const double dt = std::min((now - last_sync_time_).toSec(), 10.0);
349 last_sync_time_ = now;
352 (time_at_device_timestamp - device_time_origin_.
origin_).toSec() /
353 (time_at_device_timestamp - origin).toSec();
354 const double exp_lpf_alpha =
356 const double updated_gain =
357 (1.0 - exp_lpf_alpha) * device_time_origin_.
gain_ + exp_lpf_alpha * gain;
358 device_time_origin_.
gain_ = updated_gain;
362 ROS_DEBUG(
"on scan delay: %0.6f, device timestamp: %ld, device time origin: %0.6f, gain: %0.6f",
370 ROS_DEBUG(
"on scan delay (%0.6f) is larger than expected; skipping",
375 const boost::posix_time::ptime &time_read,
376 const std::string &echo_back,
377 const std::string &status)
383 scip_->sendCommand(
"PP");
384 device_->startWatchdog(boost::posix_time::seconds(1));
399 ROS_INFO(
"Starting communication delay estimation");
400 scip_->sendCommand(
"QT");
407 scip_->sendCommand(
"QT");
408 scip_->sendCommand(
"TM0");
416 , tm_median_window_(35)
417 , estimated_communication_delay_init_(false)
418 , communication_delay_filter_alpha_(0.3)
422 , timestamp_outlier_removal_(
ros::Duration(0.001),
ros::Duration())
423 , timestamp_moving_average_(5,
ros::Duration())
427 double sync_interval_min;
428 double sync_interval_max;
429 double delay_estim_interval;
431 pnh_.
param(
"ip_address", ip, std::string(
"192.168.0.10"));
432 pnh_.
param(
"ip_port", port, 10940);
433 pnh_.
param(
"frame_id", msg_base_.header.frame_id, std::string(
"laser"));
434 pnh_.
param(
"publish_intensity", publish_intensity_,
true);
435 pnh_.
param(
"sync_interval_min", sync_interval_min, 1.0);
436 pnh_.
param(
"sync_interval_max", sync_interval_max, 1.5);
437 sync_interval_ = std::uniform_real_distribution<double>(sync_interval_min, sync_interval_max);
438 pnh_.
param(
"delay_estim_interval", delay_estim_interval, 20.0);
440 pub_scan_ = nh_.
advertise<sensor_msgs::LaserScan>(
"scan", 10);
444 device_->registerConnectCallback(
492 if (delay_estim_interval > 0.0)
500 boost::thread thread(
504 scip_->sendCommand(
"QT");
509 int main(
int argc,
char **argv)
scip2::Walltime< 24 > walltime_
DriftedTime(const ros::Time origin, const float gain)
std::shared_ptr< Connection > Ptr
void registerCallback(Callback cb)
void publish(const boost::shared_ptr< M > &message) const
std::vector< int32_t > ranges_
FirstOrderHPF< double > timestamp_hpf_
DriftedTime device_time_origin_
void cbVV(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status, const std::map< std::string, std::string > ¶ms)
int main(int argc, char **argv)
bool estimated_communication_delay_init_
ros::Time update(const ros::Time &stamp)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
std::list< ros::Duration > communication_delays_
void registerCallback(Callback cb)
FLT update(const FLT &in)
void delayEstimation(const ros::TimerEvent &event=ros::TimerEvent())
ros::Time calculateDeviceTimeOrigin(const boost::posix_time::ptime &time_response, const uint64_t &device_timestamp, ros::Time &time_at_device_timestamp)
ros::Timer timer_delay_estim_
void cbTMSend(const boost::posix_time::ptime &time_send)
void registerCallback(Callback cb)
void setInterval(const ros::Duration &interval)
scip2::Protocol::Ptr scip_
std::default_random_engine random_engine_
ros::Time update(const ros::Time &stamp)
void cbII(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status, const std::map< std::string, std::string > ¶ms)
boost::posix_time::ptime time_ii_request
uint64_t update(const uint32_t &time_device)
void cbM(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status, const scip2::ScanData &scan, const bool has_intensity)
scip2::Connection::Ptr device_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
ros::Time last_sync_time_
std::vector< ros::Duration > on_scan_communication_delays_
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
std::uniform_real_distribution< double > sync_interval_
TimestampMovingAverage timestamp_moving_average_
std::shared_ptr< Protocol > Ptr
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
TimestampOutlierRemover timestamp_outlier_removal_
sensor_msgs::LaserScan msg_base_
std::vector< int32_t > intensities_
void cbIISend(const boost::posix_time::ptime &time_send)
void cbQT(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status)
double communication_delay_filter_alpha_
void cbTM(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status, const scip2::Timestamp &time_device)
void setInterval(const ros::Duration &interval)
void tryTM(const ros::TimerEvent &event=ros::TimerEvent())
ros::Duration estimated_communication_delay_
Duration & fromNSec(int64_t t)
void timeSync(const ros::TimerEvent &event=ros::TimerEvent())
static Time fromBoost(const boost::posix_time::ptime &t)
ROSCPP_DECL void shutdown()
FirstOrderLPF< double > timestamp_lpf_
boost::posix_time::ptime time_tm_request
void cbPP(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status, const std::map< std::string, std::string > ¶ms)
std::list< ros::Time > device_time_origins_
ros::Time calculateDeviceTimeOriginByAverage(const boost::posix_time::ptime &time_request, const boost::posix_time::ptime &time_response, const uint64_t &device_timestamp)