Skip to content

Commit 7926ecb

Browse files
committed
(image_buffer) use forward list as buffer
1 parent f129130 commit 7926ecb

File tree

2 files changed

+79
-54
lines changed

2 files changed

+79
-54
lines changed

ed_sensor_integration/include/ed/kinect/image_buffer.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
#include <rgbd/types.h>
66
#include <geolib/datatypes.h>
77

8+
#include <forward_list>
89
#include <memory>
910
#include <mutex>
10-
#include <queue>
1111
#include <thread>
1212

1313
namespace rgbd
@@ -69,17 +69,29 @@ class ImageBuffer
6969

7070
std::unique_ptr<tf::TransformListener> tf_listener_;
7171

72-
std::queue<rgbd::ImageConstPtr> image_buffer_;
72+
/**
73+
* @brief Newer images should be pushed on the front. This will result in the front being the most recent and the back being the oldest
74+
*/
75+
std::forward_list<rgbd::ImageConstPtr> image_buffer_;
7376

7477
ros::CallbackQueue cb_queue_;
7578

7679
std::pair<rgbd::ImageConstPtr, geo::Pose3D> recent_image_;
77-
std::mutex recent_image_mutex_;
80+
std::mutex recent_image_mutex_; // For protecting ImageBuffer::recent_image_
7881
std::unique_ptr<std::thread> worker_thread_ptr_;
79-
bool shutdown_;
82+
bool shutdown_; // Trigger to kill the worker thread
8083

84+
/**
85+
* @brief Iterates over the buffer and tries to get TF for the most recent image. Deletes image and all older images when succesful
86+
* or when image is too old from the buffer
87+
* @return Indicates whether the most recent image has been updated
88+
*/
8189
bool getMostRecentImageTF();
8290

91+
/**
92+
* @brief Calls ImageBuffer::getMostRecentImageTF on the specified frequency
93+
* @param frequency Frequency for checking new images.
94+
*/
8395
void workerThreadFunc(const float frequency=20);
8496

8597
};

ed_sensor_integration/src/kinect/image_buffer.cpp

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -127,74 +127,86 @@ bool ImageBuffer::getMostRecentImageTF()
127127
// - - - - - - - - - - - - - - - - - -
128128
// Fetch kinect image and place in image buffer
129129

130-
rgbd::ImageConstPtr rgbd_image = kinect_client_->nextImage();
131-
if (!rgbd_image)
132130
{
133-
ROS_DEBUG("[IMAGE_BUFFER] No new image from the RGBD client");
134-
return false;
131+
rgbd::ImageConstPtr new_image = kinect_client_->nextImage();
132+
if (new_image)
133+
{
134+
image_buffer_.push_front(new_image);
135+
ROS_DEBUG_STREAM_NAMED("image_buffer", "[IMAGE_BUFFER] New image from the RGBD client with timestamp: " << new_image->getTimestamp());
136+
}
137+
else
138+
{
139+
ROS_DEBUG_NAMED("image_buffer", "[IMAGE_BUFFER] No new image from the RGBD client");
140+
}
135141
}
136142

137143
geo::Pose3D sensor_pose;
138144

139-
try
140-
{
141-
tf::StampedTransform t_sensor_pose;
142-
tf_listener_->lookupTransform(root_frame_, rgbd_image->getFrameId(), ros::Time(rgbd_image->getTimestamp()), t_sensor_pose);
143-
geo::convert(t_sensor_pose, sensor_pose);
144-
}
145-
catch(tf::ExtrapolationException& ex)
145+
for (std::forward_list<rgbd::ImageConstPtr>::iterator it = image_buffer_.begin(); it != image_buffer_.end(); ++it)
146146
{
147+
rgbd::ImageConstPtr& rgbd_image = *it;
147148
try
148149
{
149-
// Now we have to check if the error was an interpolation or extrapolation error (i.e., the image is too old or
150-
// to new, respectively). If it is too old, discard it.
151-
152-
tf::StampedTransform latest_sensor_pose;
153-
tf_listener_->lookupTransform(root_frame_, rgbd_image->getFrameId(), ros::Time(0), latest_sensor_pose);
154-
// If image time stamp is older than latest transform, throw it out
155-
if ( latest_sensor_pose.stamp_ > ros::Time(rgbd_image->getTimestamp()) )
156-
{
157-
ROS_ERROR_STREAM_DELAYED_THROTTLE(10, "[IMAGE_BUFFER] Image too old to look-up tf: image timestamp = " << std::fixed
158-
<< ros::Time(rgbd_image->getTimestamp()));
159-
ROS_WARN_STREAM("[IMAGE_BUFFER] Image too old to look-up tf: image timestamp = " << std::fixed
160-
<< ros::Time(rgbd_image->getTimestamp()));
161-
return false;
162-
}
163-
else
150+
tf::StampedTransform t_sensor_pose;
151+
tf_listener_->lookupTransform(root_frame_, rgbd_image->getFrameId(), ros::Time(rgbd_image->getTimestamp()), t_sensor_pose);
152+
geo::convert(t_sensor_pose, sensor_pose);
153+
}
154+
catch (tf::ExtrapolationException& ex)
155+
{
156+
try
164157
{
165-
if(!tf_listener_->waitForTransform(root_frame_, rgbd_image->getFrameId(), ros::Time(rgbd_image->getTimestamp()), ros::Duration(0.5)))
158+
// Now we have to check if the error was an interpolation or extrapolation error (i.e., the image is too old or
159+
// to new, respectively). If it is too old, discard it.
160+
tf::StampedTransform latest_sensor_pose;
161+
tf_listener_->lookupTransform(root_frame_, rgbd_image->getFrameId(), ros::Time(0), latest_sensor_pose);
162+
// If image time stamp is older than latest transform, the image is too old and the tf data is not available anymore
163+
if ( latest_sensor_pose.stamp_ > ros::Time(rgbd_image->getTimestamp()) )
166164
{
167-
ROS_ERROR_STREAM_DELAYED_THROTTLE(10, "[IMAGE_BUFFER] Image too new to look-up tf: image timestamp: " << ros::Time(rgbd_image->getTimestamp()) << ", what: " << ex.what());
168-
ROS_WARN_STREAM("[IMAGE_BUFFER] Image too new to look-up tf: image timestamp: " << ros::Time(rgbd_image->getTimestamp()) << ", what: " << ex.what());
165+
166+
ROS_DEBUG_STREAM_NAMED("image_buffer", "[IMAGE_BUFFER] Image too old to look-up tf. Deleting all images older than timestamp: " << std::fixed
167+
<< ros::Time(rgbd_image->getTimestamp()));
168+
// Deleting this image and all older images
169+
image_buffer_.erase_after(it, image_buffer_.end());
169170
return false;
170171
}
171-
tf::StampedTransform t_sensor_pose;
172-
tf_listener_->lookupTransform(root_frame_, rgbd_image->getFrameId(), ros::Time(rgbd_image->getTimestamp()), t_sensor_pose);
173-
geo::convert(t_sensor_pose, sensor_pose);
172+
else
173+
{
174+
// Image is too new; continue to next image, which is older
175+
ROS_DEBUG_STREAM_DELAYED_THROTTLE_NAMED(10, "image_buffer", "[IMAGE_BUFFER] Image too new to look-up tf: image timestamp: " << std::fixed << ros::Time(rgbd_image->getTimestamp()) << ", what: " << ex.what());
176+
continue;
177+
}
178+
}
179+
catch (tf::TransformException& ex)
180+
{
181+
ROS_ERROR_DELAYED_THROTTLE_NAMED(10, "image_buffer", "[IMAGE_BUFFER] Could not get latest sensor pose (probably because tf is still initializing): %s", ex.what());
182+
ROS_WARN_NAMED("image_buffer", "[IMAGE_BUFFER] Could not get latest sensor pose (probably because tf is still initializing): %s", ex.what());
183+
continue;
174184
}
175185
}
176-
catch(tf::TransformException& exc)
186+
catch (tf::TransformException& ex)
177187
{
178-
ROS_ERROR_DELAYED_THROTTLE(10, "[IMAGE_BUFFER] Could not get latest sensor pose (probably because tf is still initializing): %s", ex.what());
179-
ROS_WARN("[IMAGE_BUFFER] Could not get latest sensor pose (probably because tf is still initializing): %s", ex.what());
180-
return false;
188+
ROS_ERROR_DELAYED_THROTTLE_NAMED(10, "image_buffer", "[IMAGE_BUFFER] Could not get sensor pose: %s", ex.what());
189+
ROS_WARN_NAMED("image_buffer", "[IMAGE_BUFFER] Could not get sensor pose: %s", ex.what());
190+
continue;
181191
}
182-
}
183-
catch(tf::TransformException& ex)
184-
{
185-
ROS_ERROR_DELAYED_THROTTLE(10, "[IMAGE_BUFFER] Could not get sensor pose: %s", ex.what());
186-
ROS_WARN("[IMAGE_BUFFER] Could not get sensor pose: %s", ex.what());
187-
return false;
188-
}
189192

190-
// Convert from ROS coordinate frame to geolib coordinate frame
191-
sensor_pose.R = sensor_pose.R * geo::Matrix3(1, 0, 0, 0, -1, 0, 0, 0, -1);
193+
// Convert from ROS coordinate frame to geolib coordinate frame
194+
sensor_pose.R = sensor_pose.R * geo::Matrix3(1, 0, 0, 0, -1, 0, 0, 0, -1);
192195

193-
std::lock_guard<std::mutex> lg(recent_image_mutex_);
194-
recent_image_.first = rgbd_image;
195-
recent_image_.second = sensor_pose;
196+
{
197+
std::lock_guard<std::mutex> lg(recent_image_mutex_);
198+
recent_image_.first = rgbd_image;
199+
recent_image_.second = sensor_pose;
200+
}
196201

197-
return true;
202+
// Deleting this image and all older images
203+
image_buffer_.erase_after(it, image_buffer_.end());
204+
205+
return true;
206+
}
207+
208+
// Not been able to update the most recent image/TF combo
209+
return false;
198210
}
199211

200212
// ----------------------------------------------------------------------------------------------------
@@ -204,7 +216,8 @@ void ImageBuffer::workerThreadFunc(const float frequency)
204216
ros::Rate r(frequency);
205217
while(!shutdown_)
206218
{
207-
getMostRecentImageTF();
219+
if (!getMostRecentImageTF())
220+
ROS_ERROR_DELAYED_THROTTLE_NAMED(5, "image_buffer", "[IMAGE_BUFFER] Could not get a pose for any image in the buffer");
208221
r.sleep();
209222
}
210223
}

0 commit comments

Comments
 (0)