From 49059926bc5359547725ade2568cd18ab3775e1f Mon Sep 17 00:00:00 2001 From: Taekjin LEE <taekjin.lee@tier4.jp> Date: Wed, 13 Mar 2024 22:15:27 +0900 Subject: [PATCH 1/3] bugfix: mot multi-step prediction is not work as intended. back to one-step prediction. Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp> --- .../multi_object_tracker_core.hpp | 2 +- .../src/multi_object_tracker_core.cpp | 2 +- .../motion_model/motion_model_base.cpp | 57 ++++++++++++------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/perception/multi_object_tracker/include/multi_object_tracker/multi_object_tracker_core.hpp b/perception/multi_object_tracker/include/multi_object_tracker/multi_object_tracker_core.hpp index 95d33b78ff184..3b05af9601f1e 100644 --- a/perception/multi_object_tracker/include/multi_object_tracker/multi_object_tracker_core.hpp +++ b/perception/multi_object_tracker/include/multi_object_tracker/multi_object_tracker_core.hpp @@ -124,7 +124,7 @@ class MultiObjectTracker : public rclcpp::Node const autoware_auto_perception_msgs::msg::DetectedObject & object, const rclcpp::Time & time, const geometry_msgs::msg::Transform & self_transform) const; - void publish(const rclcpp::Time & time); + void publish(const rclcpp::Time & time) const; inline bool shouldTrackerPublish(const std::shared_ptr<const Tracker> tracker) const; }; diff --git a/perception/multi_object_tracker/src/multi_object_tracker_core.cpp b/perception/multi_object_tracker/src/multi_object_tracker_core.cpp index cc662768ce197..1e684e78fc45a 100644 --- a/perception/multi_object_tracker/src/multi_object_tracker_core.cpp +++ b/perception/multi_object_tracker/src/multi_object_tracker_core.cpp @@ -441,7 +441,7 @@ inline bool MultiObjectTracker::shouldTrackerPublish( return true; } -void MultiObjectTracker::publish(const rclcpp::Time & time) +void MultiObjectTracker::publish(const rclcpp::Time & time) const { const auto subscriber_count = tracked_objects_pub_->get_subscription_count() + tracked_objects_pub_->get_intra_process_subscription_count(); diff --git a/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp b/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp index b4af422fd2329..46834b80a5588 100644 --- a/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp +++ b/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp @@ -46,16 +46,28 @@ bool MotionModel::predictState(const rclcpp::Time & time) if (dt < 0.0) { return false; } - // if dt is too large, shorten dt and repeat prediction - const uint32_t repeat = std::ceil(dt / dt_max_); - const double dt_ = dt / repeat; - for (uint32_t i = 0; i < repeat; ++i) { - if (!predictStateStep(dt_, ekf_)) { - return false; - } - // add interval to last_update_time_ - last_update_time_ += rclcpp::Duration::from_seconds(dt_); + if (dt < 1e-6 /*1usec*/) { + return true; } + + // // if dt is too large, shorten dt and repeat prediction + // { + // const uint32_t repeat = std::floor(dt / dt_max_) + 1; + // const double dt_ = dt / repeat; + // for (uint32_t i = 0; i < repeat; ++i) { + // if (!predictStateStep(dt_, ekf_)) { + // return false; + // } + // // add interval to last_update_time_ + // last_update_time_ += rclcpp::Duration::from_seconds(dt_); + // } + // std::cout << "MotionModel::predictState predict dt: " << dt << ", dt_: " << dt_ << ", + // repeat: + // "<< repeat<< std::endl; + // } + + if (!predictStateStep(dt, ekf_)) return false; + // update last_update_time_ to the estimation time last_update_time_ = time; return true; @@ -76,17 +88,22 @@ bool MotionModel::getPredictedState( dt = 0.0; } - // predict only when dt is small enough - if (0.001 /*1msec*/ < dt) { - // if dt is too large, shorten dt and repeat prediction - const uint32_t repeat = std::ceil(dt / dt_max_); - const double dt_ = dt / repeat; - for (uint32_t i = 0; i < repeat; ++i) { - if (!predictStateStep(dt_, tmp_ekf_for_no_update)) { - return false; - } - } - } + // // predict only when dt is small enough + // if (1e-6 /*1usec*/ < dt) { + // // if dt is too large, shorten dt and repeat prediction + // const uint32_t repeat = std::floor(dt / dt_max_) + 1; + // const double dt_ = dt / repeat; + // for (uint32_t i = 0; i < repeat; ++i) { + // if (!predictStateStep(dt_, tmp_ekf_for_no_update)) { + // return false; + // } + // } + // std::cout << "MotionModel::getPredictedStateMatrix predict dt: " << dt << ", dt_: " << dt_ << + // ", repeat: "<< repeat<< std::endl; + // } + + if (!predictStateStep(dt, tmp_ekf_for_no_update)) return false; + tmp_ekf_for_no_update.getX(X); tmp_ekf_for_no_update.getP(P); return true; From d28afeaf556b2bae655e2fcebeb8185ee01c8df4 Mon Sep 17 00:00:00 2001 From: Taekjin LEE <taekjin.lee@tier4.jp> Date: Thu, 14 Mar 2024 08:43:30 +0900 Subject: [PATCH 2/3] fix: remove comment-out codes Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp> --- .../motion_model/motion_model_base.cpp | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp b/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp index 46834b80a5588..61763d9664ef9 100644 --- a/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp +++ b/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp @@ -50,25 +50,9 @@ bool MotionModel::predictState(const rclcpp::Time & time) return true; } - // // if dt is too large, shorten dt and repeat prediction - // { - // const uint32_t repeat = std::floor(dt / dt_max_) + 1; - // const double dt_ = dt / repeat; - // for (uint32_t i = 0; i < repeat; ++i) { - // if (!predictStateStep(dt_, ekf_)) { - // return false; - // } - // // add interval to last_update_time_ - // last_update_time_ += rclcpp::Duration::from_seconds(dt_); - // } - // std::cout << "MotionModel::predictState predict dt: " << dt << ", dt_: " << dt_ << ", - // repeat: - // "<< repeat<< std::endl; - // } - if (!predictStateStep(dt, ekf_)) return false; - // update last_update_time_ to the estimation time + // update last_update_time_ last_update_time_ = time; return true; } @@ -88,20 +72,6 @@ bool MotionModel::getPredictedState( dt = 0.0; } - // // predict only when dt is small enough - // if (1e-6 /*1usec*/ < dt) { - // // if dt is too large, shorten dt and repeat prediction - // const uint32_t repeat = std::floor(dt / dt_max_) + 1; - // const double dt_ = dt / repeat; - // for (uint32_t i = 0; i < repeat; ++i) { - // if (!predictStateStep(dt_, tmp_ekf_for_no_update)) { - // return false; - // } - // } - // std::cout << "MotionModel::getPredictedStateMatrix predict dt: " << dt << ", dt_: " << dt_ << - // ", repeat: "<< repeat<< std::endl; - // } - if (!predictStateStep(dt, tmp_ekf_for_no_update)) return false; tmp_ekf_for_no_update.getX(X); From c753924863eab655d0da1e6e6392c2ad019e79dd Mon Sep 17 00:00:00 2001 From: Taekjin LEE <taekjin.lee@tier4.jp> Date: Thu, 14 Mar 2024 11:45:52 +0900 Subject: [PATCH 3/3] fix: prediction to use variable kalman filter a bug was found on `predictStateStep` methods * intention: predict the future state of the variable kalman filter `ekf` * bug: using the member kalman filter `ekf_` * fix: get the state vector from the variable kalman filter `ekf` Signed-off-by: Taekjin LEE <taekjin.lee@tier4.jp> --- .../motion_model/bicycle_motion_model.cpp | 2 +- .../motion_model/ctrv_motion_model.cpp | 2 +- .../tracker/motion_model/cv_motion_model.cpp | 2 +- .../motion_model/motion_model_base.cpp | 34 +++++++++++++------ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/perception/multi_object_tracker/src/tracker/motion_model/bicycle_motion_model.cpp b/perception/multi_object_tracker/src/tracker/motion_model/bicycle_motion_model.cpp index d992ea926746e..a22fb0035f1ea 100644 --- a/perception/multi_object_tracker/src/tracker/motion_model/bicycle_motion_model.cpp +++ b/perception/multi_object_tracker/src/tracker/motion_model/bicycle_motion_model.cpp @@ -316,7 +316,7 @@ bool BicycleMotionModel::predictStateStep(const double dt, KalmanFilter & ekf) c // Current state vector X t Eigen::MatrixXd X_t(DIM, 1); - getStateVector(X_t); + ekf.getX(X_t); const double cos_yaw = std::cos(X_t(IDX::YAW) + X_t(IDX::SLIP)); const double sin_yaw = std::sin(X_t(IDX::YAW) + X_t(IDX::SLIP)); diff --git a/perception/multi_object_tracker/src/tracker/motion_model/ctrv_motion_model.cpp b/perception/multi_object_tracker/src/tracker/motion_model/ctrv_motion_model.cpp index b10fc70d1bba7..9e8327e381057 100644 --- a/perception/multi_object_tracker/src/tracker/motion_model/ctrv_motion_model.cpp +++ b/perception/multi_object_tracker/src/tracker/motion_model/ctrv_motion_model.cpp @@ -272,7 +272,7 @@ bool CTRVMotionModel::predictStateStep(const double dt, KalmanFilter & ekf) cons // Current state vector X t Eigen::MatrixXd X_t(DIM, 1); - getStateVector(X_t); + ekf.getX(X_t); const double cos_yaw = std::cos(X_t(IDX::YAW)); const double sin_yaw = std::sin(X_t(IDX::YAW)); diff --git a/perception/multi_object_tracker/src/tracker/motion_model/cv_motion_model.cpp b/perception/multi_object_tracker/src/tracker/motion_model/cv_motion_model.cpp index 28ba59f4f19f9..a9ad03e7875c5 100644 --- a/perception/multi_object_tracker/src/tracker/motion_model/cv_motion_model.cpp +++ b/perception/multi_object_tracker/src/tracker/motion_model/cv_motion_model.cpp @@ -209,7 +209,7 @@ bool CVMotionModel::predictStateStep(const double dt, KalmanFilter & ekf) const // Current state vector X t Eigen::MatrixXd X_t(DIM, 1); - getStateVector(X_t); + ekf.getX(X_t); // Predict state vector X t+1 Eigen::MatrixXd X_next_t(DIM, 1); // predicted state diff --git a/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp b/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp index 61763d9664ef9..4d51021de634b 100644 --- a/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp +++ b/perception/multi_object_tracker/src/tracker/motion_model/motion_model_base.cpp @@ -50,9 +50,15 @@ bool MotionModel::predictState(const rclcpp::Time & time) return true; } - if (!predictStateStep(dt, ekf_)) return false; - - // update last_update_time_ + // multi-step prediction + // if dt is too large, shorten dt and repeat prediction + const uint32_t repeat = std::floor(dt / dt_max_) + 1; + const double dt_ = dt / repeat; + for (uint32_t i = 0; i < repeat; ++i) { + if (!predictStateStep(dt_, ekf_)) return false; + last_update_time_ += rclcpp::Duration::from_seconds(dt_); + } + // reset the last_update_time_ to the prediction time last_update_time_ = time; return true; } @@ -63,17 +69,23 @@ bool MotionModel::getPredictedState( // check if the state is initialized if (!checkInitialized()) return false; + const double dt = getDeltaTime(time); + if (dt < 1e-6 /*1usec*/) { + // no prediction, return the current state + ekf_.getX(X); + ekf_.getP(P); + return true; + } + // copy the predicted state and covariance KalmanFilter tmp_ekf_for_no_update = ekf_; - - double dt = getDeltaTime(time); - if (dt < 0.0) { - // a naive way to handle the case when the required prediction time is in the past - dt = 0.0; + // multi-step prediction + // if dt is too large, shorten dt and repeat prediction + const uint32_t repeat = std::floor(dt / dt_max_) + 1; + const double dt_ = dt / repeat; + for (uint32_t i = 0; i < repeat; ++i) { + if (!predictStateStep(dt_, tmp_ekf_for_no_update)) return false; } - - if (!predictStateStep(dt, tmp_ekf_for_no_update)) return false; - tmp_ekf_for_no_update.getX(X); tmp_ekf_for_no_update.getP(P); return true;