Skip to content

Commit 0219d5c

Browse files
committed
Optionally publish a sim clock and use timestamps stored in svo in message headers rather than current wall time.
Sim clock appears to be working, may have some odd glitches, may mess up non svo-playback modes Adjusting some of the timestamps, not sure if all pubs are using good timestamps, some of the static frames are timestamp 0 (but that's okay for static frames?), need to figure out if faster than real time playback is possible- there must be an api that allows read frames quickly, but maybe ruled out here. Make a function to centralize getting of time from the image or current time, clean up some other stamp usage Not clear on use of timestamps CURRENT vs ros::Time::now()
1 parent a666d67 commit 0219d5c

File tree

4 files changed

+111
-40
lines changed

4 files changed

+111
-40
lines changed

zed_nodelets/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ find_package(catkin REQUIRED COMPONENTS
4242
roscpp
4343
image_transport
4444
rosconsole
45+
rosgraph_msgs
4546
sensor_msgs
4647
stereo_msgs
4748
std_msgs

zed_nodelets/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<depend>nav_msgs</depend>
1919
<depend>roscpp</depend>
2020
<depend>rosconsole</depend>
21+
<depend>rosgraph_msgs</depend>
2122
<depend>sensor_msgs</depend>
2223
<depend>stereo_msgs</depend>
2324
<depend>message_filters</depend>

zed_nodelets/src/zed_nodelet/include/zed_wrapper_nodelet.hpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <image_transport/image_transport.h>
3232
#include <nodelet/nodelet.h>
3333
#include <ros/ros.h>
34+
#include <rosgraph_msgs/Clock.h>
3435
#include <sensor_msgs/PointCloud2.h>
3536
#include <tf2/LinearMath/Transform.h>
3637
#include <tf2_ros/static_transform_broadcaster.h>
@@ -117,6 +118,21 @@ class ZEDWrapperNodelet : public nodelet::Nodelet
117118
*/
118119
void readParameters();
119120

121+
ros::WallTimer wall_timer_;
122+
ros::Time sim_clock_base_time;
123+
/*! \brief Publish the current time when use_sim_time is true
124+
* \param t : the ros::Time to send in the clock message
125+
*/
126+
void publishSimClock(const ros::Time& stamp);
127+
128+
/*! \brief sim clock update thread
129+
*/
130+
void sim_clock_update(const ros::WallTimerEvent& e);
131+
132+
/*! \brief get ZED image time or current time depending on params
133+
*/
134+
ros::Time getTimestamp();
135+
120136
/*! \brief ZED camera polling thread function
121137
*/
122138
void device_poll_thread_func();
@@ -156,7 +172,7 @@ class ZEDWrapperNodelet : public nodelet::Nodelet
156172
/*!
157173
* \brief Publish IMU frame once as static TF
158174
*/
159-
void publishStaticImuFrame();
175+
void publishStaticImuFrame(const ros::Time& t);
160176

161177
/*! \brief Publish a sl::Mat image with a ros Publisher
162178
* \param imgMsgPtr : the image message to publish
@@ -417,6 +433,8 @@ class ZEDWrapperNodelet : public nodelet::Nodelet
417433
image_transport::CameraPublisher mPubRightGray;
418434
image_transport::CameraPublisher mPubRawRightGray;
419435

436+
ros::Publisher mPubSimClock;
437+
420438
ros::Publisher mPubConfMap; //
421439
ros::Publisher mPubDisparity; //
422440
ros::Publisher mPubCloud;
@@ -610,6 +628,7 @@ class ZEDWrapperNodelet : public nodelet::Nodelet
610628
double mCamDepthResizeFactor = 1.0;
611629

612630
// flags
631+
bool mUseSimTime = false;
613632
bool mTriggerAutoExposure = true;
614633
bool mTriggerAutoWB = true;
615634
bool mComputeDepth;

zed_nodelets/src/zed_nodelet/src/zed_wrapper_nodelet.cpp

Lines changed: 89 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "zed_wrapper_nodelet.hpp"
2222

23+
#include <boost/date_time/posix_time/posix_time.hpp>
2324
#include <chrono>
2425
#include <csignal>
2526

@@ -472,6 +473,11 @@ void ZEDWrapperNodelet::onInit()
472473
mPubRawStereo = it_zed.advertise(stereo_raw_topic, 1);
473474
NODELET_INFO_STREAM("Advertised on topic " << mPubRawStereo.getTopic());
474475

476+
if (mUseSimTime)
477+
{
478+
mPubSimClock = mNhNs.advertise<rosgraph_msgs::Clock>("/clock", 2);
479+
}
480+
475481
// Confidence Map publisher
476482
mPubConfMap = mNhNs.advertise<sensor_msgs::Image>(conf_map_topic, 1); // confidence map
477483
NODELET_INFO_STREAM("Advertised on topic " << mPubConfMap.getTopic());
@@ -589,7 +595,8 @@ void ZEDWrapperNodelet::onInit()
589595

590596
if (!mSvoMode && !mSensTimestampSync)
591597
{
592-
mFrameTimestamp = ros::Time::now();
598+
// init so sensor callback will have a timestamp to work with on first publish
599+
mFrameTimestamp = getTimestamp();
593600
mImuTimer = mNhNs.createTimer(ros::Duration(1.0 / (mSensPubRate * 1.5)),
594601
&ZEDWrapperNodelet::callback_pubSensorsData, this);
595602
mSensPeriodMean_usec.reset(new sl_tools::CSmartMean(mSensPubRate / 2));
@@ -626,6 +633,11 @@ void ZEDWrapperNodelet::onInit()
626633
// Start pool thread
627634
mDevicePollThread = std::thread(&ZEDWrapperNodelet::device_poll_thread_func, this);
628635

636+
if (mUseSimTime) {
637+
// TODO(lucasw) 0.02-0.05 are probably fine
638+
wall_timer_ = mNhNs.createWallTimer(ros::WallDuration(0.01), &ZEDWrapperNodelet::sim_clock_update, this);
639+
}
640+
629641
// Start data publishing timer
630642
mVideoDepthTimer =
631643
mNhNs.createTimer(ros::Duration(1.0 / mVideoDepthFreq), &ZEDWrapperNodelet::callback_pubVideoDepth, this);
@@ -866,6 +878,9 @@ void ZEDWrapperNodelet::readParameters()
866878
mNhNs.param<std::string>("svo_file", mSvoFilepath, std::string());
867879
NODELET_INFO_STREAM(" * SVO input file: \t\t-> " << mSvoFilepath.c_str());
868880

881+
mNhNs.getParam("/use_sim_time", mUseSimTime);
882+
NODELET_INFO_STREAM(" * Use Sim Time\t\t\t-> " << mUseSimTime);
883+
869884
int svo_compr = 0;
870885
mNhNs.getParam("general/svo_compression", svo_compr);
871886

@@ -1776,7 +1791,7 @@ void ZEDWrapperNodelet::publishPose(ros::Time t)
17761791
}
17771792
}
17781793

1779-
void ZEDWrapperNodelet::publishStaticImuFrame()
1794+
void ZEDWrapperNodelet::publishStaticImuFrame(const ros::Time& stamp)
17801795
{
17811796
// Publish IMU TF as static TF
17821797
if (!mPublishImuTf)
@@ -1789,7 +1804,8 @@ void ZEDWrapperNodelet::publishStaticImuFrame()
17891804
return;
17901805
}
17911806

1792-
mStaticImuTransformStamped.header.stamp = ros::Time::now();
1807+
NODELET_WARN_STREAM_ONCE("static imu transform " << stamp);
1808+
mStaticImuTransformStamped.header.stamp = stamp;
17931809
mStaticImuTransformStamped.header.frame_id = mLeftCamFrameId;
17941810
mStaticImuTransformStamped.child_frame_id = mImuFrameId;
17951811
sl::Translation sl_tr = mSlCamImuTransf.getTranslation();
@@ -1805,7 +1821,7 @@ void ZEDWrapperNodelet::publishStaticImuFrame()
18051821
// Publish transformation
18061822
mStaticTransformImuBroadcaster.sendTransform(mStaticImuTransformStamped);
18071823

1808-
NODELET_INFO_STREAM("Published static transform '" << mImuFrameId << "' -> '" << mLeftCamFrameId << "'");
1824+
NODELET_INFO_STREAM("Published static transform '" << mImuFrameId << "' -> '" << mLeftCamFrameId << "' " << stamp);
18091825

18101826
mStaticImuFramePublished = true;
18111827
}
@@ -2700,8 +2716,10 @@ void ZEDWrapperNodelet::callback_pubVideoDepth(const ros::TimerEvent& e)
27002716
ros::Time stamp = sl_tools::slTime2Ros(grab_ts);
27012717
if (mSvoMode)
27022718
{
2703-
stamp = ros::Time::now();
2719+
// grab_ts is 0 when in svo playback mode
2720+
stamp = e.current_real;
27042721
}
2722+
NODELET_INFO_STREAM_ONCE("time " << stamp);
27052723
// <---- Data ROS timestamp
27062724

27072725
// ----> Publish sensor data if sync is required by user or SVO
@@ -2875,6 +2893,7 @@ void ZEDWrapperNodelet::callback_pubVideoDepth(const ros::TimerEvent& e)
28752893

28762894
void ZEDWrapperNodelet::callback_pubPath(const ros::TimerEvent& e)
28772895
{
2896+
NODELET_INFO_STREAM_ONCE("pub path " << e.current_real);
28782897
uint32_t mapPathSub = mPubMapPath.getNumSubscribers();
28792898
uint32_t odomPathSub = mPubOdomPath.getNumSubscribers();
28802899

@@ -3012,6 +3031,7 @@ void ZEDWrapperNodelet::publishSensData(ros::Time t)
30123031

30133032
sl::SensorsData sens_data;
30143033

3034+
// TODO(lucasw) is a mUseSimTime check needed in here?
30153035
if (mSvoMode || mSensTimestampSync)
30163036
{
30173037
if (mZed.getSensorsData(sens_data, sl::TIME_REFERENCE::IMAGE) != sl::ERROR_CODE::SUCCESS)
@@ -3041,6 +3061,7 @@ void ZEDWrapperNodelet::publishSensData(ros::Time t)
30413061
ts_baro = sl_tools::slTime2Ros(sens_data.barometer.timestamp);
30423062
ts_mag = sl_tools::slTime2Ros(sens_data.magnetometer.timestamp);
30433063
}
3064+
// TODO(lucasw) in svo mode the above timestamps need to be set to ros::Time::now()?
30443065

30453066
bool new_imu_data = ts_imu != lastTs_imu;
30463067
bool new_baro_data = ts_baro != lastTs_baro;
@@ -3066,7 +3087,7 @@ void ZEDWrapperNodelet::publishSensData(ros::Time t)
30663087

30673088
if (mPublishImuTf && !mStaticImuFramePublished)
30683089
{
3069-
publishStaticImuFrame();
3090+
publishStaticImuFrame(ts_imu);
30703091
}
30713092
}
30723093
// <---- Publish odometry tf only if enabled
@@ -3370,6 +3391,51 @@ void ZEDWrapperNodelet::publishSensData(ros::Time t)
33703391
// <---- Update Diagnostic
33713392
}
33723393

3394+
void ZEDWrapperNodelet::publishSimClock(const ros::Time& stamp)
3395+
{
3396+
{
3397+
boost::posix_time::ptime posix_time = stamp.toBoost();
3398+
const std::string iso_time_str = boost::posix_time::to_iso_extended_string(posix_time);
3399+
// NODELET_INFO_STREAM_THROTTLE(1.0, "time " << iso_time_str);
3400+
NODELET_INFO_STREAM_ONCE("time " << iso_time_str);
3401+
}
3402+
3403+
NODELET_WARN_STREAM_ONCE("using sim clock " << stamp);
3404+
rosgraph_msgs::Clock clock;
3405+
clock.clock = stamp;
3406+
mPubSimClock.publish(clock);
3407+
}
3408+
3409+
ros::Time ZEDWrapperNodelet::getTimestamp()
3410+
{
3411+
ros::Time stamp;
3412+
if (mSvoMode && !mUseSimTime)
3413+
{
3414+
// TODO(lucasw) does it matter which one?
3415+
stamp = ros::Time::now();
3416+
// mFrameTimestamp = sl_tools::slTime2Ros(mZed.getTimestamp(sl::TIME_REFERENCE::CURRENT));
3417+
NODELET_WARN_STREAM_ONCE("Using current time instead of image time " << stamp);
3418+
}
3419+
else
3420+
{
3421+
// TODO(lucasw) if no images have arrived yet, this is zero, or something else?
3422+
// In the svo file it appears to be something else, slightly in advance of the first
3423+
// frame.
3424+
stamp = sl_tools::slTime2Ros(mZed.getTimestamp(sl::TIME_REFERENCE::IMAGE));
3425+
NODELET_WARN_STREAM_ONCE("Using zed image time " << stamp);
3426+
}
3427+
return stamp;
3428+
}
3429+
3430+
void ZEDWrapperNodelet::sim_clock_update(const ros::WallTimerEvent& e)
3431+
{
3432+
// TODO(lucasw) mutex
3433+
publishSimClock(sim_clock_base_time);
3434+
// TODO(lucasw) have ability to roll forward faster than real time
3435+
sim_clock_base_time += ros::Duration(0.001);
3436+
std::this_thread::sleep_for(std::chrono::milliseconds(1));
3437+
}
3438+
33733439
void ZEDWrapperNodelet::device_poll_thread_func()
33743440
{
33753441
ros::Rate loop_rate(mCamFrameRate);
@@ -3383,14 +3449,10 @@ void ZEDWrapperNodelet::device_poll_thread_func()
33833449
mObjDetPeriodMean_msec.reset(new sl_tools::CSmartMean(mCamFrameRate));
33843450

33853451
// Timestamp initialization
3386-
if (mSvoMode)
3387-
{
3388-
mFrameTimestamp = ros::Time::now();
3389-
}
3390-
else
3391-
{
3392-
mFrameTimestamp = sl_tools::slTime2Ros(mZed.getTimestamp(sl::TIME_REFERENCE::CURRENT));
3393-
}
3452+
mFrameTimestamp = getTimestamp();
3453+
3454+
// TODO(lucasw) mutex
3455+
sim_clock_base_time = mFrameTimestamp;
33943456

33953457
mPrevFrameTimestamp = mFrameTimestamp;
33963458

@@ -3429,6 +3491,8 @@ void ZEDWrapperNodelet::device_poll_thread_func()
34293491
sl::RuntimeParameters runParams;
34303492
runParams.sensing_mode = static_cast<sl::SENSING_MODE>(mCamSensingMode);
34313493

3494+
// TODO(lucasw) is there a call to mZed in here that rolls it forward a frame in mSvoMode, or does it
3495+
// have a timer and keeps time independently, can only do real time?
34323496
// Main loop
34333497
while (mNhNs.ok())
34343498
{
@@ -3536,6 +3600,8 @@ void ZEDWrapperNodelet::device_poll_thread_func()
35363600
// the zed have been disconnected) and
35373601
// re-initialize the ZED
35383602

3603+
// TODO(lucasw) if the status is END OF SVO FILE REACHED then loop it optionally,
3604+
// or exit.
35393605
NODELET_INFO_STREAM_ONCE(toString(mGrabStatus));
35403606

35413607
std::this_thread::sleep_for(std::chrono::milliseconds(1));
@@ -3631,18 +3697,10 @@ void ZEDWrapperNodelet::device_poll_thread_func()
36313697
mGrabPeriodMean_usec->addValue(elapsed_usec);
36323698

36333699
// NODELET_INFO_STREAM("Grab time: " << elapsed_usec / 1000 << " msec");
3700+
mFrameTimestamp = getTimestamp();
36343701

3635-
// Timestamp
3636-
if (mSvoMode)
3637-
{
3638-
mFrameTimestamp = ros::Time::now();
3639-
}
3640-
else
3641-
{
3642-
mFrameTimestamp = sl_tools::slTime2Ros(mZed.getTimestamp(sl::TIME_REFERENCE::IMAGE));
3643-
}
3644-
3645-
ros::Time stamp = mFrameTimestamp; // Timestamp
3702+
const ros::Time stamp = mFrameTimestamp; // Timestamp
3703+
sim_clock_base_time = stamp;
36463704

36473705
// ----> Camera Settings
36483706
if (!mSvoMode && mFrameCount % 5 == 0)
@@ -3974,7 +4032,7 @@ void ZEDWrapperNodelet::device_poll_thread_func()
39744032
if (odomSubnumber > 0)
39754033
{
39764034
// Publish odometry message
3977-
publishOdom(mOdom2BaseTransf, mLastZedPose, mFrameTimestamp);
4035+
publishOdom(mOdom2BaseTransf, mLastZedPose, stamp);
39784036
}
39794037

39804038
mInitOdomWithPose = false;
@@ -4098,27 +4156,19 @@ void ZEDWrapperNodelet::device_poll_thread_func()
40984156
// Publish odometry tf only if enabled
40994157
if (mPublishTf)
41004158
{
4101-
ros::Time t;
4102-
4103-
if (mSvoMode)
4104-
{
4105-
t = ros::Time::now();
4106-
}
4107-
else
4108-
{
4109-
t = sl_tools::slTime2Ros(mZed.getTimestamp(sl::TIME_REFERENCE::CURRENT));
4110-
}
4159+
// TODO(lucasw) or just ust mFrameTimestamp?
4160+
const ros::Time t = getTimestamp();
41114161

4112-
publishOdomFrame(mOdom2BaseTransf, mFrameTimestamp); // publish the base Frame in odometry frame
4162+
publishOdomFrame(mOdom2BaseTransf, t); // publish the base Frame in odometry frame
41134163

41144164
if (mPublishMapTf)
41154165
{
4116-
publishPoseFrame(mMap2OdomTransf, mFrameTimestamp); // publish the odometry Frame in map frame
4166+
publishPoseFrame(mMap2OdomTransf, t); // publish the odometry Frame in map frame
41174167
}
41184168

41194169
if (mPublishImuTf && !mStaticImuFramePublished)
41204170
{
4121-
publishStaticImuFrame();
4171+
publishStaticImuFrame(t);
41224172
}
41234173
}
41244174
}

0 commit comments

Comments
 (0)