Extract velocity estimation from poses into a function. (#435)
parent
a6d94c07cf
commit
b28bc3bc9e
|
@ -49,6 +49,7 @@ void PoseExtrapolator::AddPose(const common::Time time,
|
||||||
timed_pose_queue_[1].time <= time - pose_queue_duration_) {
|
timed_pose_queue_[1].time <= time - pose_queue_duration_) {
|
||||||
timed_pose_queue_.pop_front();
|
timed_pose_queue_.pop_front();
|
||||||
}
|
}
|
||||||
|
UpdateVelocitiesFromPoses();
|
||||||
TrimImuData();
|
TrimImuData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,36 +59,40 @@ void PoseExtrapolator::AddImuData(const sensor::ImuData& imu_data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
transform::Rigid3d PoseExtrapolator::ExtrapolatePose(const common::Time time) {
|
transform::Rigid3d PoseExtrapolator::ExtrapolatePose(const common::Time time) {
|
||||||
|
const TimedPose& newest_timed_pose = timed_pose_queue_.back();
|
||||||
|
CHECK(time >= newest_timed_pose.time);
|
||||||
|
const double extrapolation_delta =
|
||||||
|
common::ToSeconds(time - newest_timed_pose.time);
|
||||||
|
return transform::Rigid3d::Translation(extrapolation_delta *
|
||||||
|
linear_velocity_from_poses_) *
|
||||||
|
newest_timed_pose.pose *
|
||||||
|
transform::Rigid3d::Rotation(ExtrapolateRotation(time));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PoseExtrapolator::UpdateVelocitiesFromPoses() {
|
||||||
|
if (timed_pose_queue_.size() < 2) {
|
||||||
|
// We need two poses to estimate velocities.
|
||||||
|
return;
|
||||||
|
}
|
||||||
CHECK(!timed_pose_queue_.empty());
|
CHECK(!timed_pose_queue_.empty());
|
||||||
const TimedPose& newest_timed_pose = timed_pose_queue_.back();
|
const TimedPose& newest_timed_pose = timed_pose_queue_.back();
|
||||||
const auto newest_time = newest_timed_pose.time;
|
const auto newest_time = newest_timed_pose.time;
|
||||||
const transform::Rigid3d& newest_pose = newest_timed_pose.pose;
|
|
||||||
CHECK(time >= newest_time);
|
|
||||||
if (timed_pose_queue_.size() == 1) {
|
|
||||||
return newest_pose;
|
|
||||||
}
|
|
||||||
const TimedPose& oldest_timed_pose = timed_pose_queue_.front();
|
const TimedPose& oldest_timed_pose = timed_pose_queue_.front();
|
||||||
const auto oldest_time = oldest_timed_pose.time;
|
const auto oldest_time = oldest_timed_pose.time;
|
||||||
const transform::Rigid3d& oldest_pose = oldest_timed_pose.pose;
|
|
||||||
const double queue_delta = common::ToSeconds(newest_time - oldest_time);
|
const double queue_delta = common::ToSeconds(newest_time - oldest_time);
|
||||||
if (queue_delta < 0.001) { // 1 ms
|
if (queue_delta < 0.001) { // 1 ms
|
||||||
LOG(WARNING) << "Queue too short for extrapolation, returning most recent "
|
LOG(WARNING) << "Queue too short for velocity estimation. Queue duration: "
|
||||||
"pose. Queue duration: "
|
|
||||||
<< queue_delta << " ms";
|
<< queue_delta << " ms";
|
||||||
return newest_pose;
|
return;
|
||||||
}
|
}
|
||||||
const Eigen::Vector3d linear_velocity =
|
const transform::Rigid3d& newest_pose = newest_timed_pose.pose;
|
||||||
|
const transform::Rigid3d& oldest_pose = oldest_timed_pose.pose;
|
||||||
|
linear_velocity_from_poses_ =
|
||||||
(newest_pose.translation() - oldest_pose.translation()) / queue_delta;
|
(newest_pose.translation() - oldest_pose.translation()) / queue_delta;
|
||||||
const Eigen::Vector3d angular_velocity_from_pose =
|
angular_velocity_from_poses_ =
|
||||||
transform::RotationQuaternionToAngleAxisVector(
|
transform::RotationQuaternionToAngleAxisVector(
|
||||||
oldest_pose.rotation().inverse() * newest_pose.rotation()) /
|
oldest_pose.rotation().inverse() * newest_pose.rotation()) /
|
||||||
queue_delta;
|
queue_delta;
|
||||||
const double extrapolation_delta = common::ToSeconds(time - newest_time);
|
|
||||||
return transform::Rigid3d::Translation(extrapolation_delta *
|
|
||||||
linear_velocity) *
|
|
||||||
newest_pose *
|
|
||||||
transform::Rigid3d::Rotation(
|
|
||||||
ExtrapolateRotation(time, angular_velocity_from_pose));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoseExtrapolator::TrimImuData() {
|
void PoseExtrapolator::TrimImuData() {
|
||||||
|
@ -98,20 +103,19 @@ void PoseExtrapolator::TrimImuData() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Eigen::Quaterniond PoseExtrapolator::ExtrapolateRotation(
|
Eigen::Quaterniond PoseExtrapolator::ExtrapolateRotation(
|
||||||
const common::Time time,
|
const common::Time time) {
|
||||||
const Eigen::Vector3d& angular_velocity_from_pose) {
|
|
||||||
common::Time current = timed_pose_queue_.back().time;
|
common::Time current = timed_pose_queue_.back().time;
|
||||||
if (imu_data_.empty() || imu_data_.front().time >= time) {
|
if (imu_data_.empty() || imu_data_.front().time >= time) {
|
||||||
return RotationFromAngularVelocity(time - current,
|
return RotationFromAngularVelocity(time - current,
|
||||||
angular_velocity_from_pose);
|
angular_velocity_from_poses_);
|
||||||
}
|
}
|
||||||
// TODO(whess): Use the ImuTracker here?
|
// TODO(whess): Use the ImuTracker here?
|
||||||
// TODO(whess): Keep the last extrapolated pose.
|
// TODO(whess): Keep the last extrapolated pose.
|
||||||
Eigen::Quaterniond current_rotation;
|
Eigen::Quaterniond current_rotation;
|
||||||
auto imu_it = imu_data_.begin();
|
auto imu_it = imu_data_.begin();
|
||||||
if (imu_it->time > current) {
|
if (imu_it->time > current) {
|
||||||
current_rotation = RotationFromAngularVelocity(imu_it->time - current,
|
current_rotation = RotationFromAngularVelocity(
|
||||||
angular_velocity_from_pose);
|
imu_it->time - current, angular_velocity_from_poses_);
|
||||||
current = imu_it->time;
|
current = imu_it->time;
|
||||||
} else {
|
} else {
|
||||||
current_rotation = Eigen::Quaterniond::Identity();
|
current_rotation = Eigen::Quaterniond::Identity();
|
||||||
|
|
|
@ -27,10 +27,11 @@ namespace cartographer {
|
||||||
namespace mapping {
|
namespace mapping {
|
||||||
|
|
||||||
// Keeps poses for a certain duration to estimate linear and angular velocity,
|
// Keeps poses for a certain duration to estimate linear and angular velocity,
|
||||||
// and uses the velocities to extrapolate motion.
|
// and uses the velocities to extrapolate motion. Uses IMU data if available to
|
||||||
|
// improve the extrapolation of orientation.
|
||||||
//
|
//
|
||||||
// TODO(whess): Add IMU data and odometry and provide improved extrapolation
|
// TODO(whess): Add odometry and provide improved extrapolation models making
|
||||||
// models making use of all available data.
|
// use of all available data.
|
||||||
class PoseExtrapolator {
|
class PoseExtrapolator {
|
||||||
public:
|
public:
|
||||||
explicit PoseExtrapolator(common::Duration pose_queue_duration);
|
explicit PoseExtrapolator(common::Duration pose_queue_duration);
|
||||||
|
@ -47,9 +48,9 @@ class PoseExtrapolator {
|
||||||
transform::Rigid3d ExtrapolatePose(common::Time time);
|
transform::Rigid3d ExtrapolatePose(common::Time time);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void UpdateVelocitiesFromPoses();
|
||||||
void TrimImuData();
|
void TrimImuData();
|
||||||
Eigen::Quaterniond ExtrapolateRotation(
|
Eigen::Quaterniond ExtrapolateRotation(common::Time time);
|
||||||
common::Time time, const Eigen::Vector3d& angular_velocity_from_pose);
|
|
||||||
|
|
||||||
const common::Duration pose_queue_duration_;
|
const common::Duration pose_queue_duration_;
|
||||||
struct TimedPose {
|
struct TimedPose {
|
||||||
|
@ -57,6 +58,9 @@ class PoseExtrapolator {
|
||||||
transform::Rigid3d pose;
|
transform::Rigid3d pose;
|
||||||
};
|
};
|
||||||
std::deque<TimedPose> timed_pose_queue_;
|
std::deque<TimedPose> timed_pose_queue_;
|
||||||
|
Eigen::Vector3d linear_velocity_from_poses_ = Eigen::Vector3d::Zero();
|
||||||
|
Eigen::Vector3d angular_velocity_from_poses_ = Eigen::Vector3d::Zero();
|
||||||
|
|
||||||
std::deque<sensor::ImuData> imu_data_;
|
std::deque<sensor::ImuData> imu_data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue