19 #include <sensor_msgs/LaserScan.h> 21 #include <boost/bind/bind.hpp> 22 #include <boost/format.hpp> 23 #include <boost/thread.hpp> 47 const boost::posix_time::ptime& time_read,
48 const std::string& echo_back,
49 const std::string& status,
51 const bool has_intensity)
70 const auto estimated_timestamp_lf =
76 t0_ = estimated_timestamp_lf;
79 const auto receive_time =
93 if (msg.header.stamp > time_read_ros)
96 << std::setprecision(6) << std::fixed
97 <<
"estimated future timestamp (read: " << time_read_ros.
toSec()
98 <<
", estimated: " << msg.header.stamp.toSec() << std::endl;
106 <<
"Size of the received scan data is wrong " 109 <<
", received: " << scan.
ranges_.size() <<
"); refreshing" << std::endl;
111 (has_intensity ?
"ME" :
"MD") +
117 msg.ranges.reserve(scan.
ranges_.size());
119 msg.ranges.push_back(r * 1e-3);
124 msg.intensities.push_back(r);
137 const boost::posix_time::ptime& time_read,
138 const std::string& echo_back,
139 const std::string& status,
150 <<
"Failed to enter the time synchronization mode, " 151 "even after receiving successful QT command response. " 152 "QT command may be ignored by the sensor firmware" 160 switch (echo_back[2])
197 sort(delays.begin(), delays.end());
198 sort(origins.begin(), origins.end());
215 <<
", device timestamp: " << walltime_device
216 <<
", device time origin: " << origins[
tm_iter_num_ / 2].toSec()
218 scip_->sendCommand(
"TM2");
248 const boost::posix_time::ptime& time_read,
249 const std::string& echo_back,
250 const std::string& status,
251 const std::map<std::string, std::string>& params)
260 const auto amin = params.find(
"AMIN");
261 const auto amax = params.find(
"AMAX");
262 const auto dmin = params.find(
"DMIN");
263 const auto dmax = params.find(
"DMAX");
264 const auto ares = params.find(
"ARES");
265 const auto afrt = params.find(
"AFRT");
266 const auto scan = params.find(
"SCAN");
267 if (amin == params.end() || amax == params.end() ||
268 dmin == params.end() || dmax == params.end() ||
269 ares == params.end() || afrt == params.end() ||
270 scan == params.end())
277 msg_base_.scan_time = 60.0 / std::stoi(scan->second);
278 msg_base_.angle_increment = 2.0 * M_PI / std::stoi(ares->second);
280 msg_base_.range_min = std::stoi(dmin->second) * 1e-3;
281 msg_base_.range_max = std::stoi(dmax->second) * 1e-3;
283 (std::stoi(amin->second) - std::stoi(afrt->second)) *
msg_base_.angle_increment;
285 (std::stoi(amax->second) - std::stoi(afrt->second)) *
msg_base_.angle_increment;
293 const boost::posix_time::ptime& time_read,
294 const std::string& echo_back,
295 const std::string& status,
296 const std::map<std::string, std::string>& params)
313 for (
const char* key : keys)
315 const auto kv = params.find(key);
316 if (kv == params.end())
331 const boost::posix_time::ptime& time_read,
332 const std::string& echo_back,
333 const std::string& status,
334 const std::map<std::string, std::string>& params)
343 const auto stat = params.find(
"STAT");
344 if (stat != params.end())
348 const auto mesm = params.find(
"MESM");
349 if (mesm != params.end())
356 if (mesm == params.end())
366 std::string state(mesm->second);
367 const auto tolower = [](
unsigned char c)
369 return std::tolower(c);
371 std::transform(state.begin(), state.end(), state.begin(), tolower);
372 if (state.find(
"idle") != std::string::npos || state.find(
"measuring") != std::string::npos)
376 scip2::logger::info() <<
"Sensor is idle, entering time synchronization mode" << std::endl;
398 if (delay.toSec() < 0.002)
400 const auto time = params.find(
"TIME");
401 if (time == params.end())
406 if (time->second.size() != 6 && time->second.size() != 4)
408 scip2::logger::debug() <<
"Timestamp in II is ill-formatted (" << time->second <<
")" << std::endl;
411 const uint32_t time_device =
412 time->second.size() == 6 ?
413 std::stoi(time->second,
nullptr, 16) :
435 (time_at_device_timestamp - origin).toSec();
436 const double exp_lpf_alpha =
438 const double updated_gain =
445 <<
"on scan delay: " << std::setprecision(6) << std::fixed << delay
446 <<
", device timestamp: " << walltime_device
447 <<
", device time origin: " << origin
448 <<
", gain: " << updated_gain << std::endl;
453 <<
"on scan delay (" << std::setprecision(6) << std::fixed << delay
454 <<
") is larger than expected; skipping" << std::endl;
459 const boost::posix_time::ptime& time_read,
460 const std::string& echo_back,
461 const std::string& status)
480 const boost::posix_time::ptime& time_read,
481 const std::string& echo_back,
482 const std::string& status)
487 scip_->sendCommand(
"RB");
490 else if (status ==
"00")
499 << echo_back <<
" errored with " << status << std::endl
500 <<
"Failed to reboot. Please power-off the sensor." << std::endl;
504 const boost::posix_time::ptime& time_read,
505 const std::string& echo_back,
506 const std::string& status)
511 << echo_back <<
" errored with " << status << std::endl
512 <<
"Failed to reset. Rebooting the sensor and exiting." << std::endl;
525 scip_->sendCommand(
"VV");
526 scip_->sendCommand(
"PP");
533 scip_->sendCommand(
"RS");
534 device_->startWatchdog(boost::posix_time::seconds(1));
540 <<
"internal state on failure: " 588 scip_->sendCommand(
"QT");
603 scip_->sendCommand(
"TM0");
607 scip_->sendCommand(
"TM2");
635 <<
"Error count exceeded limit, rebooting the sensor and exiting." 650 <<
"Error count exceeded limit, resetting the sensor and exiting." << std::endl;
656 <<
"Error count exceeded limit without successful time sync, " 657 "rebooting the sensor and exiting." 667 scip_->sendCommand(
"RS");
673 scip_->sendCommand(
"RB");
678 std::uniform_real_distribution<double> rnd(min, max);
683 const boost::posix_time::ptime& time_response,
684 const uint64_t& device_timestamp)
697 <<
"Device time origin jumped\n" 700 <<
", current origin: " << current_origin.
toSec()
702 <<
", device_timestamp: " << device_timestamp << std::endl;
723 std::random_device rd;
728 double sync_interval_min;
729 double sync_interval_max;
730 double delay_estim_interval;
732 pnh_.
param(
"ip_address", ip, std::string(
"192.168.0.10"));
736 pnh_.
param(
"sync_interval_min", sync_interval_min, 1.0);
737 pnh_.
param(
"sync_interval_max", sync_interval_max, 1.5);
738 sync_interval_ = std::uniform_real_distribution<double>(sync_interval_min, sync_interval_max);
739 pnh_.
param(
"delay_estim_interval", delay_estim_interval, 20.0);
743 double tm_interval, tm_timeout;
744 pnh_.
param(
"tm_interval", tm_interval, 0.06);
746 pnh_.
param(
"tm_timeout", tm_timeout, 10.0);
747 tm_try_max_ =
static_cast<int>(tm_timeout / tm_interval);
765 device_->registerCloseCallback(
767 device_->registerConnectCallback(
825 if (delay_estim_interval > 0.0)
834 boost::thread thread(
839 scip_->sendCommand(
"QT");
ros::Time update(const ros::Time &stamp)
void cbTM(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status, const scip2::Timestamp &time_device)
scip2::Protocol::Ptr scip_
scip2::Walltime< 24 > walltime_
ROSCONSOLE_DECL void notifyLoggerLevelsChanged()
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)
std::vector< int32_t > ranges_
double allowed_device_time_origin_diff_
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
bool detectDeviceTimeJump(const boost::posix_time::ptime &time_response, const uint64_t &device_timestamp)
void cbQT(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status)
FLT update(const FLT &in)
sensor_msgs::LaserScan msg_base_
void cbTMSend(const boost::posix_time::ptime &time_send)
void cbRS(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status)
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)
DelayEstimState delay_estim_state_
void cbRB(const boost::posix_time::ptime &time_read, const std::string &echo_back, const std::string &status)
void setInterval(const ros::Duration &interval)
ros::Time last_sync_time_
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)
std::uniform_real_distribution< double > sync_interval_
ResponseErrorCount error_count_
void retryTM(const ros::TimerEvent &event=ros::TimerEvent())
std::default_random_engine random_engine_
std::list< ros::Duration > communication_delays_
double communication_delay_filter_alpha_
std::list< ros::Time > device_time_origins_
ros::Duration tm_command_interval_
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void publish(const boost::shared_ptr< M > &message) const
uint64_t update(const uint32_t &time_device)
boost::posix_time::ptime time_ii_request
void setROSLogger(const std::string &prefix)
FirstOrderHPF< double > timestamp_hpf_
ros::Timer timer_retry_tm_
boost::posix_time::ptime time_tm_request
ros::Duration estimated_communication_delay_
ros::Time estimateOriginByAverage(const boost::posix_time::ptime &time_request, const boost::posix_time::ptime &time_response, const uint64_t &device_timestamp)
ros::Time update(const ros::Time &stamp)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool detectTimeJump(const ros::Time &last_device_time_origin, const ros::Time ¤t_device_time_origin, const double allowed_device_time_origin_diff)
std::vector< int32_t > intensities_
ros::Timer timer_delay_estim_
void timeSync(const ros::TimerEvent &event=ros::TimerEvent())
bool estimated_communication_delay_init_
std::string last_measurement_state_
void delayEstimation(const ros::TimerEvent &event=ros::TimerEvent())
device_time_origin::DriftedTime device_time_origin_
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)
ros::Time estimateOrigin(const boost::posix_time::ptime &time_response, const uint64_t &device_timestamp, const ros::Duration &communication_delay, ros::Time &time_at_device_timestamp)
Duration & fromNSec(int64_t t)
FirstOrderLPF< double > timestamp_lpf_
static Time fromBoost(const boost::posix_time::ptime &t)
ROSCPP_DECL void shutdown()
void sleepRandom(const double min, const double max)
ROSCONSOLE_DECL bool set_logger_level(const std::string &name, levels::Level level)
void cbIISend(const boost::posix_time::ptime &time_send)
void errorCountIncrement(const std::string &status="")
TimestampMovingAverage timestamp_moving_average_
void setInterval(const ros::Duration &interval)
TimestampOutlierRemover timestamp_outlier_removal_
#define ROSCONSOLE_DEFAULT_NAME
scip2::Connection::Ptr device_