Skip to content

Commit 889c0cb

Browse files
Merge pull request #523 from mabelzhang/dashing-port-melodic-2017-12-07
Port to Dashing: Bug fixes from melodic-devel Dec 07 2017
2 parents a8ee797 + c672040 commit 889c0cb

File tree

7 files changed

+97
-39
lines changed

7 files changed

+97
-39
lines changed

include/robot_localization/ros_filter.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,12 @@ class RosFilter : public rclcpp::Node
625625
//!
626626
std::map<std::string, Eigen::MatrixXd> previous_measurement_covariances_;
627627

628+
//! @brief By default, the filter predicts and corrects up to the time of the
629+
//! latest measurement. If this is set to true, the filter does the same, but
630+
//! then also predicts up to the current time step.
631+
//!
632+
bool predict_to_current_time_;
633+
628634
//! @brief Store the last time set pose message was received
629635
//!
630636
//! If we receive a setPose message to reset the filter, we can get in

include/robot_localization/ros_filter_utilities.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ double getYaw(const tf2::Quaternion quat);
7171
//! @param[in] time - The time at which we want the transform
7272
//! @param[in] timeout - How long to block before falling back to last transform
7373
//! @param[out] targetFrameTrans - The resulting transform object
74+
//! @param[in] silent - Whether or not to print transform warnings
7475
//! @return Sets the value of @p targetFrameTrans and returns true if
7576
//! successful, false otherwise.
7677
//!
@@ -87,14 +88,16 @@ bool lookupTransformSafe(
8788
const std::string & source_frame,
8889
const rclcpp::Time & time,
8990
const rclcpp::Duration & timeout,
90-
tf2::Transform & target_frame_trans);
91+
tf2::Transform & target_frame_trans,
92+
const bool silent = false);
9193

9294
//! @brief Method for safely obtaining transforms.
9395
//! @param[in] buffer - tf buffer object to use for looking up the transform
9496
//! @param[in] targetFrame - The target frame of the desired transform
9597
//! @param[in] sourceFrame - The source frame of the desired transform
9698
//! @param[in] time - The time at which we want the transform
9799
//! @param[out] targetFrameTrans - The resulting transform object
100+
//! @param[in] silent - Whether or not to print transform warnings
98101
//! @return Sets the value of @p targetFrameTrans and returns true if
99102
//! successful, false otherwise.
100103
//!
@@ -110,7 +113,8 @@ bool lookupTransformSafe(
110113
const std::string & targetFrame,
111114
const std::string & sourceFrame,
112115
const rclcpp::Time & time,
113-
tf2::Transform & targetFrameTrans);
116+
tf2::Transform & targetFrameTrans,
117+
const bool silent = false);
114118

115119
//! @brief Utility method for converting quaternion to RPY
116120
//! @param[in] quat - The quaternion to convert

src/filter_base.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ void FilterBase::setProcessNoiseCovariance(
321321
const Eigen::MatrixXd & process_noise_covariance)
322322
{
323323
process_noise_covariance_ = process_noise_covariance;
324+
dynamic_process_noise_covariance_ = process_noise_covariance_;
324325
}
325326

326327
void FilterBase::setSensorTimeout(const rclcpp::Duration & sensor_timeout)

src/navsat_transform.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,11 @@ void NavSatTransform::getRobotOriginWorldPose(
395395
transform_timeout_, robot_orientation);
396396

397397
if (can_transform) {
398+
// Zero out rotation because we don't care about the orientation of the
399+
// GPS receiver relative to base_link
398400
gps_offset_rotated.setOrigin(tf2::quatRotate(
399401
robot_orientation.getRotation(), gps_offset_rotated.getOrigin()));
402+
gps_offset_rotated.setRotation(tf2::Quaternion::getIdentity());
400403
robot_odom_pose = gps_offset_rotated.inverse() * gps_odom_pose;
401404
} else {
402405
RCLCPP_ERROR(

src/ros_filter.cpp

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,8 @@ void RosFilter<T>::integrateMeasurements(const rclcpp::Time & current_time)
536536
"\n" <<
537537
measurement_queue_.size() << " measurements in queue.\n");
538538

539+
bool predict_to_current_time = predict_to_current_time_;
540+
539541
// If we have any measurements in the queue, process them
540542
if (!measurement_queue_.empty()) {
541543
// Check if the first measurement we're going to process is older than the
@@ -558,8 +560,9 @@ void RosFilter<T>::integrateMeasurements(const rclcpp::Time & current_time)
558560
if (!revertTo(first_measurement->time_ - rclcpp::Duration(1))) {
559561
RF_DEBUG("ERROR: history interval is too small to revert to time " <<
560562
filter_utilities::toSec(first_measurement->time_) << "\n");
561-
// ROS_WARN_STREAM_THROTTLE(10.0, "Received old measurement for topic "
562-
// << first_measurement->topic_name_ <<
563+
// ROS_WARN_STREAM_DELAYED_THROTTLE(history_length_,
564+
// "Received old measurement for topic "
565+
// << first_measurement->topic_name_ <<
563566
// ", but history interval is insufficiently
564567
// sized to " "revert state and measurement
565568
// queue.");
@@ -624,23 +627,30 @@ void RosFilter<T>::integrateMeasurements(const rclcpp::Time & current_time)
624627

625628
// If we get a large delta, then continuously predict until
626629
if (last_update_delta >= filter_.getSensorTimeout()) {
630+
predict_to_current_time = true;
631+
627632
RF_DEBUG("Sensor timeout! Last measurement time was " <<
628633
filter_utilities::toSec(filter_.getLastMeasurementTime()) <<
629634
", current time is " << filter_utilities::toSec(current_time) <<
630635
", delta is " << filter_utilities::toSec(last_update_delta) <<
631636
"\n");
632-
633-
filter_.validateDelta(last_update_delta);
634-
filter_.predict(current_time, last_update_delta);
635-
636-
// Update the last measurement time and last update time
637-
filter_.setLastMeasurementTime(filter_.getLastMeasurementTime() +
638-
last_update_delta);
639637
}
640638
} else {
641639
RF_DEBUG("Filter not yet initialized.\n");
642640
}
643641

642+
if (filter_.getInitializedStatus() && predict_to_current_time) {
643+
rclcpp::Duration last_update_delta =
644+
current_time - filter_.getLastMeasurementTime();
645+
646+
filter_.validateDelta(last_update_delta);
647+
filter_.predict(current_time, last_update_delta);
648+
649+
// Update the last measurement time and last update time
650+
filter_.setLastMeasurementTime(filter_.getLastMeasurementTime() +
651+
last_update_delta);
652+
}
653+
644654
RF_DEBUG("\n----- /RosFilter<T>::integrateMeasurements ------\n");
645655
}
646656

@@ -1404,7 +1414,7 @@ void RosFilter<T>::loadParams()
14041414
differential, relative, pose_mahalanobis_thresh);
14051415
const CallbackData twist_callback_data(
14061416
imu_topic_name + "_twist", twist_update_vec, twist_update_sum,
1407-
differential, relative, pose_mahalanobis_thresh);
1417+
differential, relative, twist_mahalanobis_thresh);
14081418
const CallbackData accel_callback_data(
14091419
imu_topic_name + "_acceleration", accel_update_vec, accelUpdateSum,
14101420
differential, relative, accel_mahalanobis_thresh);
@@ -1919,9 +1929,12 @@ void RosFilter<T>::periodicUpdate()
19191929
clearExpiredHistory(filter_.getLastMeasurementTime() - history_length_);
19201930
}
19211931

1922-
if ((this->now() - cur_time).seconds() > 1. / frequency_) {
1932+
// Warn the user if the update took too long
1933+
const double loop_elapsed = (this->now() - cur_time).seconds();
1934+
if (loop_elapsed > 1. / frequency_) {
19231935
std::cerr <<
1924-
"Failed to meet update rate! Try decreasing the rate, limiting "
1936+
"Failed to meet update rate! Took " << std::setprecision(20) <<
1937+
loop_elapsed << "seconds. Try decreasing the rate, limiting "
19251938
"sensor output frequency, or limiting the number of sensors.\n";
19261939
}
19271940
}
@@ -2973,31 +2986,45 @@ bool RosFilter<T>::revertTo(const rclcpp::Time & time)
29732986

29742987
// Walk back through the queue until we reach a filter state whose time stamp
29752988
// is less than or equal to the requested time. Since every saved state after
2976-
// that time will be overwritten/corrected, we can pop from the queue.
2989+
// that time will be overwritten/corrected, we can pop from the queue. If the
2990+
// history is insufficiently short, we just take the oldest state we have.
2991+
FilterStatePtr last_history_state;
29772992
while (!filter_state_history_.empty() &&
29782993
filter_state_history_.back()->last_measurement_time_ > time)
29792994
{
2995+
last_history_state = filter_state_history_.back();
29802996
filter_state_history_.pop_back();
29812997
}
29822998

2983-
// The state and measurement histories are stored at the same time, so if we
2984-
// have insufficient state history, we will also have insufficient measurement
2985-
// history.
2986-
if (filter_state_history_.empty()) {
2999+
// If the state history is not empty at this point, it means that our history
3000+
// was large enough, and we should revert to the state at the back of the
3001+
// history deque.
3002+
bool ret_val = false;
3003+
if (!filter_state_history_.empty()) {
3004+
ret_val = true;
3005+
last_history_state = filter_state_history_.back();
3006+
} else {
29873007
RF_DEBUG("Insufficient history to revert to time " <<
29883008
filter_utilities::toSec(time) << "\n");
29893009

2990-
return false;
3010+
if (last_history_state.get() != NULL) {
3011+
RF_DEBUG("Will revert to oldest state at " <<
3012+
filter_utilities::toSec(last_history_state->latest_control_time_) <<
3013+
".\n");
3014+
}
29913015
}
29923016

2993-
// Reset filter to the latest state from the queue.
2994-
const FilterStatePtr & state = filter_state_history_.back();
2995-
filter_.setState(state->state_);
2996-
filter_.setEstimateErrorCovariance(state->estimate_error_covariance_);
2997-
filter_.setLastMeasurementTime(state->last_measurement_time_);
3017+
// If we have a valid reversion state, revert
3018+
if (last_history_state.get() != NULL) {
3019+
// Reset filter to the latest state from the queue.
3020+
const FilterStatePtr & state = filter_state_history_.back();
3021+
filter_.setState(state->state_);
3022+
filter_.setEstimateErrorCovariance(state->estimate_error_covariance_);
3023+
filter_.setLastMeasurementTime(state->last_measurement_time_);
29983024

2999-
RF_DEBUG("Reverted to state with time " <<
3000-
filter_utilities::toSec(state->last_measurement_time_) << "\n");
3025+
RF_DEBUG("Reverted to state with time " <<
3026+
filter_utilities::toSec(state->last_measurement_time_) << "\n");
3027+
}
30013028

30023029
// Repeat for measurements, but push every measurement onto the measurement
30033030
// queue as we go
@@ -3014,7 +3041,7 @@ bool RosFilter<T>::revertTo(const rclcpp::Time & time)
30143041

30153042
RF_DEBUG("\n----- /RosFilter<T>::revertTo\n");
30163043

3017-
return true;
3044+
return ret_val;
30183045
}
30193046

30203047
template<typename T>

src/ros_filter_utilities.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@
4141
#include <string>
4242
#include <vector>
4343

44+
#define THROTTLE(clock, duration, thing) do { \
45+
static rclcpp::Time _last_output_time ## __LINE__(0, 0, (clock)->get_clock_type()); \
46+
auto _now = (clock)->now(); \
47+
if (_now - _last_output_time ## __LINE__ > (duration)) { \
48+
_last_output_time ## __LINE__ = _now; \
49+
thing; \
50+
} \
51+
} while (0)
52+
4453
std::ostream & operator<<(std::ostream & os, const tf2::Vector3 & vec)
4554
{
4655
os << "(" << std::setprecision(20) << vec.getX() << " " << vec.getY() << " " <<
@@ -117,7 +126,8 @@ bool lookupTransformSafe(
117126
const std::string & source_frame,
118127
const rclcpp::Time & time,
119128
const rclcpp::Duration & duration,
120-
tf2::Transform & target_frame_trans)
129+
tf2::Transform & target_frame_trans,
130+
const bool silent)
121131
{
122132
bool retVal = true;
123133
tf2::TimePoint time_tf = tf2::timeFromSec(filter_utilities::toSec(time));
@@ -140,15 +150,19 @@ bool lookupTransformSafe(
140150
.transform,
141151
target_frame_trans);
142152

143-
// ROS_WARN_STREAM_THROTTLE(2.0, "Transform from " << source_frame << " to
144-
// " << target_frame <<
145-
// " was unavailable for the time requested.
146-
// Using latest instead.\n");
153+
if (!silent) {
154+
// ROS_WARN_STREAM_THROTTLE(2.0, "Transform from " << source_frame <<
155+
// " to " << target_frame <<
156+
// " was unavailable for the time
157+
// requested. Using latest instead.\n");
158+
}
147159
} catch (tf2::TransformException & ex) {
148-
// ROS_WARN_STREAM_THROTTLE(2.0, "Could not obtain transform from " <<
149-
// source_frame <<
150-
// " to " << target_frame << ". Error was "
151-
// << ex.what() << "\n");
160+
if (!silent) {
161+
// ROS_WARN_STREAM_THROTTLE(2.0, "Could not obtain transform from " <<
162+
// source_frame <<
163+
// " to " << target_frame << ". Error was "
164+
// << ex.what() << "\n");
165+
}
152166

153167
retVal = false;
154168
}
@@ -172,10 +186,11 @@ bool lookupTransformSafe(
172186
const std::string & target_frame,
173187
const std::string & source_frame,
174188
const rclcpp::Time & time,
175-
tf2::Transform & target_frame_trans)
189+
tf2::Transform & target_frame_trans,
190+
const bool silent)
176191
{
177192
return lookupTransformSafe(buffer, target_frame, source_frame, time,
178-
rclcpp::Duration(0), target_frame_trans);
193+
rclcpp::Duration(0), target_frame_trans, silent);
179194
}
180195

181196
void quatToRPY(

test/test_ukf.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ TEST(UkfTest, Measurements) {
6363

6464
filter->getFilter().setEstimateErrorCovariance(initialCovar);
6565

66+
EXPECT_EQ(filter->getFilter().getEstimateErrorCovariance(), initialCovar);
67+
6668
Eigen::VectorXd measurement(STATE_SIZE);
6769
measurement.setIdentity();
6870

0 commit comments

Comments
 (0)