|
@@ -15,9 +15,9 @@
|
|
#include "mpc_lateral_controller/mpc.hpp"
|
|
#include "mpc_lateral_controller/mpc.hpp"
|
|
|
|
|
|
#include "interpolation/linear_interpolation.hpp"
|
|
#include "interpolation/linear_interpolation.hpp"
|
|
-#include "motion_utils/trajectory/trajectory.hpp"
|
|
|
|
|
|
+//#include "motion_utils/trajectory/trajectory.hpp"
|
|
#include "mpc_lateral_controller/mpc_utils.hpp"
|
|
#include "mpc_lateral_controller/mpc_utils.hpp"
|
|
-#include "tier4_autoware_utils/math/unit_conversion.hpp"
|
|
|
|
|
|
+//#include "tier4_autoware_utils/math/unit_conversion.hpp"
|
|
|
|
|
|
#include <algorithm>
|
|
#include <algorithm>
|
|
#include <limits>
|
|
#include <limits>
|
|
@@ -25,25 +25,107 @@
|
|
|
|
|
|
namespace autoware::motion::control::mpc_lateral_controller
|
|
namespace autoware::motion::control::mpc_lateral_controller
|
|
{
|
|
{
|
|
-using tier4_autoware_utils::calcDistance2d;
|
|
|
|
-using tier4_autoware_utils::normalizeRadian;
|
|
|
|
-using tier4_autoware_utils::rad2deg;
|
|
|
|
|
|
+//using tier4_autoware_utils::calcDistance2d;
|
|
|
|
+//using tier4_autoware_utils::normalizeRadian;
|
|
|
|
+//using tier4_autoware_utils::rad2deg;
|
|
|
|
+
|
|
|
|
+//bool MPC::calculateMPC(
|
|
|
|
+// const SteeringReport & current_steer, const Odometry & current_kinematics,
|
|
|
|
+// AckermannLateralCommand & ctrl_cmd, Trajectory & predicted_trajectory,
|
|
|
|
+// Float32MultiArrayStamped & diagnostic)
|
|
|
|
+//{
|
|
|
|
+// // since the reference trajectory does not take into account the current velocity of the ego
|
|
|
|
+// // vehicle, it needs to calculate the trajectory velocity considering the longitudinal dynamics.
|
|
|
|
+// const auto reference_trajectory =
|
|
|
|
+// applyVelocityDynamicsFilter(m_reference_trajectory, current_kinematics);
|
|
|
|
+
|
|
|
|
+// // get the necessary data
|
|
|
|
+// const auto [success_data, mpc_data] =
|
|
|
|
+// getData(reference_trajectory, current_steer, current_kinematics);
|
|
|
|
+// if (!success_data) {
|
|
|
|
+// return fail_warn_throttle("fail to get MPC Data. Stop MPC.");
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // calculate initial state of the error dynamics
|
|
|
|
+// const auto x0 = getInitialState(mpc_data);
|
|
|
|
+
|
|
|
|
+// // apply time delay compensation to the initial state
|
|
|
|
+// const auto [success_delay, x0_delayed] =
|
|
|
|
+// updateStateForDelayCompensation(reference_trajectory, mpc_data.nearest_time, x0);
|
|
|
|
+// if (!success_delay) {
|
|
|
|
+// return fail_warn_throttle("delay compensation failed. Stop MPC.");
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // resample reference trajectory with mpc sampling time
|
|
|
|
+// const double mpc_start_time = mpc_data.nearest_time + m_param.input_delay;
|
|
|
|
+// const double prediction_dt =
|
|
|
|
+// getPredictionDeltaTime(mpc_start_time, reference_trajectory, current_kinematics);
|
|
|
|
+
|
|
|
|
+// const auto [success_resample, mpc_resampled_ref_trajectory] =
|
|
|
|
+// resampleMPCTrajectoryByTime(mpc_start_time, prediction_dt, reference_trajectory);
|
|
|
|
+// if (!success_resample) {
|
|
|
|
+// return fail_warn_throttle("trajectory resampling failed. Stop MPC.");
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // generate mpc matrix : predict equation Xec = Aex * x0 + Bex * Uex + Wex
|
|
|
|
+// const auto mpc_matrix = generateMPCMatrix(mpc_resampled_ref_trajectory, prediction_dt);
|
|
|
|
+
|
|
|
|
+// // solve Optimization problem
|
|
|
|
+// const auto [success_opt, Uex] = executeOptimization(
|
|
|
|
+// mpc_matrix, x0_delayed, prediction_dt, mpc_resampled_ref_trajectory,
|
|
|
|
+// current_kinematics.twist.twist.linear.x);
|
|
|
|
+// if (!success_opt) {
|
|
|
|
+// return fail_warn_throttle("optimization failed. Stop MPC.");
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // apply filters for the input limitation and low pass filter
|
|
|
|
+// const double u_saturated = std::clamp(Uex(0), -m_steer_lim, m_steer_lim);
|
|
|
|
+// const double u_filtered = m_lpf_steering_cmd.filter(u_saturated);
|
|
|
|
+
|
|
|
|
+// // set control command
|
|
|
|
+// ctrl_cmd.steering_tire_angle = static_cast<float>(u_filtered);
|
|
|
|
+// ctrl_cmd.steering_tire_rotation_rate = static_cast<float>(calcDesiredSteeringRate(
|
|
|
|
+// mpc_matrix, x0_delayed, Uex, u_filtered, current_steer.steering_tire_angle, prediction_dt));
|
|
|
|
+
|
|
|
|
+// // save the control command for the steering prediction
|
|
|
|
+// m_steering_predictor->storeSteerCmd(u_filtered);
|
|
|
|
+
|
|
|
|
+// // save input to buffer for delay compensation
|
|
|
|
+// m_input_buffer.push_back(ctrl_cmd.steering_tire_angle);
|
|
|
|
+// m_input_buffer.pop_front();
|
|
|
|
+
|
|
|
|
+// // save previous input for the mpc rate limit
|
|
|
|
+// m_raw_steer_cmd_pprev = m_raw_steer_cmd_prev;
|
|
|
|
+// m_raw_steer_cmd_prev = Uex(0);
|
|
|
|
+
|
|
|
|
+// // calculate predicted trajectory
|
|
|
|
+// predicted_trajectory =
|
|
|
|
+// calcPredictedTrajectory(mpc_resampled_ref_trajectory, mpc_matrix, x0_delayed, Uex);
|
|
|
|
+
|
|
|
|
+// // prepare diagnostic message
|
|
|
|
+// diagnostic =
|
|
|
|
+// generateDiagData(reference_trajectory, mpc_data, mpc_matrix, ctrl_cmd, Uex, current_kinematics);
|
|
|
|
+
|
|
|
|
+// return true;
|
|
|
|
+//}
|
|
|
|
|
|
bool MPC::calculateMPC(
|
|
bool MPC::calculateMPC(
|
|
- const SteeringReport & current_steer, const Odometry & current_kinematics,
|
|
|
|
- AckermannLateralCommand & ctrl_cmd, Trajectory & predicted_trajectory,
|
|
|
|
- Float32MultiArrayStamped & diagnostic)
|
|
|
|
|
|
+ const iv::ADCSteeringReport & current_steer, const iv::ADCOdometry & current_kinematics,
|
|
|
|
+ ADCAckermannLateralCommand & ctrl_cmd, MPCTrajectory & predicted_trajectory
|
|
|
|
+ )
|
|
{
|
|
{
|
|
// since the reference trajectory does not take into account the current velocity of the ego
|
|
// since the reference trajectory does not take into account the current velocity of the ego
|
|
// vehicle, it needs to calculate the trajectory velocity considering the longitudinal dynamics.
|
|
// vehicle, it needs to calculate the trajectory velocity considering the longitudinal dynamics.
|
|
const auto reference_trajectory =
|
|
const auto reference_trajectory =
|
|
- applyVelocityDynamicsFilter(m_reference_trajectory, current_kinematics);
|
|
|
|
|
|
+ applyVelocityDynamicsFilter(m_reference_trajectory, current_kinematics);
|
|
|
|
|
|
// get the necessary data
|
|
// get the necessary data
|
|
const auto [success_data, mpc_data] =
|
|
const auto [success_data, mpc_data] =
|
|
- getData(reference_trajectory, current_steer, current_kinematics);
|
|
|
|
|
|
+ getData(reference_trajectory, current_steer, current_kinematics);
|
|
if (!success_data) {
|
|
if (!success_data) {
|
|
- return fail_warn_throttle("fail to get MPC Data. Stop MPC.");
|
|
|
|
|
|
+ std::cout<<"fail to get MPC Data. Stop MPC."<<std::endl;
|
|
|
|
+ return false;
|
|
|
|
+ // return fail_warn_throttle("fail to get MPC Data. Stop MPC.");
|
|
}
|
|
}
|
|
|
|
|
|
// calculate initial state of the error dynamics
|
|
// calculate initial state of the error dynamics
|
|
@@ -51,20 +133,24 @@ bool MPC::calculateMPC(
|
|
|
|
|
|
// apply time delay compensation to the initial state
|
|
// apply time delay compensation to the initial state
|
|
const auto [success_delay, x0_delayed] =
|
|
const auto [success_delay, x0_delayed] =
|
|
- updateStateForDelayCompensation(reference_trajectory, mpc_data.nearest_time, x0);
|
|
|
|
|
|
+ updateStateForDelayCompensation(reference_trajectory, mpc_data.nearest_time, x0);
|
|
if (!success_delay) {
|
|
if (!success_delay) {
|
|
- return fail_warn_throttle("delay compensation failed. Stop MPC.");
|
|
|
|
|
|
+ std::cout<<"delay compensation failed. Stop MPC."<<std::endl;
|
|
|
|
+ return false;
|
|
|
|
+// return fail_warn_throttle("delay compensation failed. Stop MPC.");
|
|
}
|
|
}
|
|
|
|
|
|
// resample reference trajectory with mpc sampling time
|
|
// resample reference trajectory with mpc sampling time
|
|
const double mpc_start_time = mpc_data.nearest_time + m_param.input_delay;
|
|
const double mpc_start_time = mpc_data.nearest_time + m_param.input_delay;
|
|
const double prediction_dt =
|
|
const double prediction_dt =
|
|
- getPredictionDeltaTime(mpc_start_time, reference_trajectory, current_kinematics);
|
|
|
|
|
|
+ getPredictionDeltaTime(mpc_start_time, reference_trajectory, current_kinematics);
|
|
|
|
|
|
const auto [success_resample, mpc_resampled_ref_trajectory] =
|
|
const auto [success_resample, mpc_resampled_ref_trajectory] =
|
|
- resampleMPCTrajectoryByTime(mpc_start_time, prediction_dt, reference_trajectory);
|
|
|
|
|
|
+ resampleMPCTrajectoryByTime(mpc_start_time, prediction_dt, reference_trajectory);
|
|
if (!success_resample) {
|
|
if (!success_resample) {
|
|
- return fail_warn_throttle("trajectory resampling failed. Stop MPC.");
|
|
|
|
|
|
+ std::cout<<"trajectory resampling failed. Stop MPC."<<std::endl;
|
|
|
|
+ return false;
|
|
|
|
+// return fail_warn_throttle("trajectory resampling failed. Stop MPC.");
|
|
}
|
|
}
|
|
|
|
|
|
// generate mpc matrix : predict equation Xec = Aex * x0 + Bex * Uex + Wex
|
|
// generate mpc matrix : predict equation Xec = Aex * x0 + Bex * Uex + Wex
|
|
@@ -72,10 +158,12 @@ bool MPC::calculateMPC(
|
|
|
|
|
|
// solve Optimization problem
|
|
// solve Optimization problem
|
|
const auto [success_opt, Uex] = executeOptimization(
|
|
const auto [success_opt, Uex] = executeOptimization(
|
|
- mpc_matrix, x0_delayed, prediction_dt, mpc_resampled_ref_trajectory,
|
|
|
|
- current_kinematics.twist.twist.linear.x);
|
|
|
|
|
|
+ mpc_matrix, x0_delayed, prediction_dt, mpc_resampled_ref_trajectory,
|
|
|
|
+ current_kinematics.twist.linear_x);
|
|
if (!success_opt) {
|
|
if (!success_opt) {
|
|
- return fail_warn_throttle("optimization failed. Stop MPC.");
|
|
|
|
|
|
+ std::cout<<"optimization failed. Stop MPC."<<std::endl;
|
|
|
|
+ return false;
|
|
|
|
+// return fail_warn_throttle("optimization failed. Stop MPC.");
|
|
}
|
|
}
|
|
|
|
|
|
// apply filters for the input limitation and low pass filter
|
|
// apply filters for the input limitation and low pass filter
|
|
@@ -85,7 +173,7 @@ bool MPC::calculateMPC(
|
|
// set control command
|
|
// set control command
|
|
ctrl_cmd.steering_tire_angle = static_cast<float>(u_filtered);
|
|
ctrl_cmd.steering_tire_angle = static_cast<float>(u_filtered);
|
|
ctrl_cmd.steering_tire_rotation_rate = static_cast<float>(calcDesiredSteeringRate(
|
|
ctrl_cmd.steering_tire_rotation_rate = static_cast<float>(calcDesiredSteeringRate(
|
|
- mpc_matrix, x0_delayed, Uex, u_filtered, current_steer.steering_tire_angle, prediction_dt));
|
|
|
|
|
|
+ mpc_matrix, x0_delayed, Uex, u_filtered, current_steer.steering_tire_angle, prediction_dt));
|
|
|
|
|
|
// save the control command for the steering prediction
|
|
// save the control command for the steering prediction
|
|
m_steering_predictor->storeSteerCmd(u_filtered);
|
|
m_steering_predictor->storeSteerCmd(u_filtered);
|
|
@@ -100,18 +188,42 @@ bool MPC::calculateMPC(
|
|
|
|
|
|
// calculate predicted trajectory
|
|
// calculate predicted trajectory
|
|
predicted_trajectory =
|
|
predicted_trajectory =
|
|
- calcPredictedTrajectory(mpc_resampled_ref_trajectory, mpc_matrix, x0_delayed, Uex);
|
|
|
|
|
|
+ calcPredictedTrajectory(mpc_resampled_ref_trajectory, mpc_matrix, x0_delayed, Uex);
|
|
|
|
|
|
// prepare diagnostic message
|
|
// prepare diagnostic message
|
|
- diagnostic =
|
|
|
|
- generateDiagData(reference_trajectory, mpc_data, mpc_matrix, ctrl_cmd, Uex, current_kinematics);
|
|
|
|
|
|
+// diagnostic =
|
|
|
|
+// generateDiagData(reference_trajectory, mpc_data, mpc_matrix, ctrl_cmd, Uex, current_kinematics);
|
|
|
|
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-Trajectory MPC::calcPredictedTrajectory(
|
|
|
|
- const MPCTrajectory & mpc_resampled_ref_trajectory, const MPCMatrix & mpc_matrix,
|
|
|
|
- const VectorXd & x0_delayed, const VectorXd & Uex) const
|
|
|
|
|
|
+//Trajectory MPC::calcPredictedTrajectory(
|
|
|
|
+// const MPCTrajectory & mpc_resampled_ref_trajectory, const MPCMatrix & mpc_matrix,
|
|
|
|
+// const VectorXd & x0_delayed, const VectorXd & Uex) const
|
|
|
|
+//{
|
|
|
|
+// const VectorXd Xex = mpc_matrix.Aex * x0_delayed + mpc_matrix.Bex * Uex + mpc_matrix.Wex;
|
|
|
|
+// MPCTrajectory mpc_predicted_traj;
|
|
|
|
+// const auto & traj = mpc_resampled_ref_trajectory;
|
|
|
|
+// for (int i = 0; i < m_param.prediction_horizon; ++i) {
|
|
|
|
+// const int DIM_X = m_vehicle_model_ptr->getDimX();
|
|
|
|
+// const double lat_error = Xex(i * DIM_X);
|
|
|
|
+// const double yaw_error = Xex(i * DIM_X + 1);
|
|
|
|
+// const double x = traj.x.at(i) - std::sin(traj.yaw.at(i)) * lat_error;
|
|
|
|
+// const double y = traj.y.at(i) + std::cos(traj.yaw.at(i)) * lat_error;
|
|
|
|
+// const double z = traj.z.at(i);
|
|
|
|
+// const double yaw = traj.yaw.at(i) + yaw_error;
|
|
|
|
+// const double vx = traj.vx.at(i);
|
|
|
|
+// const double k = traj.k.at(i);
|
|
|
|
+// const double smooth_k = traj.smooth_k.at(i);
|
|
|
|
+// const double relative_time = traj.relative_time.at(i);
|
|
|
|
+// mpc_predicted_traj.push_back(x, y, z, yaw, vx, k, smooth_k, relative_time);
|
|
|
|
+// }
|
|
|
|
+// return MPCUtils::convertToAutowareTrajectory(mpc_predicted_traj);
|
|
|
|
+//}
|
|
|
|
+
|
|
|
|
+MPCTrajectory MPC::calcPredictedTrajectory(
|
|
|
|
+ const MPCTrajectory & mpc_resampled_ref_trajectory, const MPCMatrix & mpc_matrix,
|
|
|
|
+ const VectorXd & x0_delayed, const VectorXd & Uex) const
|
|
{
|
|
{
|
|
const VectorXd Xex = mpc_matrix.Aex * x0_delayed + mpc_matrix.Bex * Uex + mpc_matrix.Wex;
|
|
const VectorXd Xex = mpc_matrix.Aex * x0_delayed + mpc_matrix.Bex * Uex + mpc_matrix.Wex;
|
|
MPCTrajectory mpc_predicted_traj;
|
|
MPCTrajectory mpc_predicted_traj;
|
|
@@ -130,89 +242,171 @@ Trajectory MPC::calcPredictedTrajectory(
|
|
const double relative_time = traj.relative_time.at(i);
|
|
const double relative_time = traj.relative_time.at(i);
|
|
mpc_predicted_traj.push_back(x, y, z, yaw, vx, k, smooth_k, relative_time);
|
|
mpc_predicted_traj.push_back(x, y, z, yaw, vx, k, smooth_k, relative_time);
|
|
}
|
|
}
|
|
- return MPCUtils::convertToAutowareTrajectory(mpc_predicted_traj);
|
|
|
|
|
|
+ return mpc_predicted_traj;
|
|
|
|
+ // return MPCUtils::convertToAutowareTrajectory(mpc_predicted_traj);
|
|
}
|
|
}
|
|
|
|
|
|
-Float32MultiArrayStamped MPC::generateDiagData(
|
|
|
|
- const MPCTrajectory & reference_trajectory, const MPCData & mpc_data,
|
|
|
|
- const MPCMatrix & mpc_matrix, const AckermannLateralCommand & ctrl_cmd, const VectorXd & Uex,
|
|
|
|
- const Odometry & current_kinematics) const
|
|
|
|
-{
|
|
|
|
- Float32MultiArrayStamped diagnostic;
|
|
|
|
|
|
+//Float32MultiArrayStamped MPC::generateDiagData(
|
|
|
|
+// const MPCTrajectory & reference_trajectory, const MPCData & mpc_data,
|
|
|
|
+// const MPCMatrix & mpc_matrix, const AckermannLateralCommand & ctrl_cmd, const VectorXd & Uex,
|
|
|
|
+// const Odometry & current_kinematics) const
|
|
|
|
+//{
|
|
|
|
+// Float32MultiArrayStamped diagnostic;
|
|
|
|
+
|
|
|
|
+// // prepare diagnostic message
|
|
|
|
+// const double nearest_k = reference_trajectory.k.at(mpc_data.nearest_idx);
|
|
|
|
+// const double nearest_smooth_k = reference_trajectory.smooth_k.at(mpc_data.nearest_idx);
|
|
|
|
+// const double wb = m_vehicle_model_ptr->getWheelbase();
|
|
|
|
+// const double current_velocity = current_kinematics.twist.twist.linear.x;
|
|
|
|
+// const double wz_predicted = current_velocity * std::tan(mpc_data.predicted_steer) / wb;
|
|
|
|
+// const double wz_measured = current_velocity * std::tan(mpc_data.steer) / wb;
|
|
|
|
+// const double wz_command = current_velocity * std::tan(ctrl_cmd.steering_tire_angle) / wb;
|
|
|
|
+
|
|
|
|
+// typedef decltype(diagnostic.data)::value_type DiagnosticValueType;
|
|
|
|
+// const auto append_diag = [&](const auto & val) -> void {
|
|
|
|
+// diagnostic.data.push_back(static_cast<DiagnosticValueType>(val));
|
|
|
|
+// };
|
|
|
|
+// append_diag(ctrl_cmd.steering_tire_angle); // [0] final steering command (MPC + LPF)
|
|
|
|
+// append_diag(Uex(0)); // [1] mpc calculation result
|
|
|
|
+// append_diag(mpc_matrix.Uref_ex(0)); // [2] feed-forward steering value
|
|
|
|
+// append_diag(std::atan(nearest_smooth_k * wb)); // [3] feed-forward steering value raw
|
|
|
|
+// append_diag(mpc_data.steer); // [4] current steering angle
|
|
|
|
+// append_diag(mpc_data.lateral_err); // [5] lateral error
|
|
|
|
+// append_diag(tf2::getYaw(current_kinematics.pose.pose.orientation)); // [6] current_pose yaw
|
|
|
|
+// append_diag(tf2::getYaw(mpc_data.nearest_pose.orientation)); // [7] nearest_pose yaw
|
|
|
|
+// append_diag(mpc_data.yaw_err); // [8] yaw error
|
|
|
|
+// append_diag(reference_trajectory.vx.at(mpc_data.nearest_idx)); // [9] reference velocity
|
|
|
|
+// append_diag(current_velocity); // [10] measured velocity
|
|
|
|
+// append_diag(wz_command); // [11] angular velocity from steer command
|
|
|
|
+// append_diag(wz_measured); // [12] angular velocity from measured steer
|
|
|
|
+// append_diag(current_velocity * nearest_smooth_k); // [13] angular velocity from path curvature
|
|
|
|
+// append_diag(nearest_smooth_k); // [14] nearest path curvature (used for feed-forward)
|
|
|
|
+// append_diag(nearest_k); // [15] nearest path curvature (not smoothed)
|
|
|
|
+// append_diag(mpc_data.predicted_steer); // [16] predicted steer
|
|
|
|
+// append_diag(wz_predicted); // [17] angular velocity from predicted steer
|
|
|
|
+
|
|
|
|
+// return diagnostic;
|
|
|
|
+//}
|
|
|
|
|
|
- // prepare diagnostic message
|
|
|
|
- const double nearest_k = reference_trajectory.k.at(mpc_data.nearest_idx);
|
|
|
|
- const double nearest_smooth_k = reference_trajectory.smooth_k.at(mpc_data.nearest_idx);
|
|
|
|
- const double wb = m_vehicle_model_ptr->getWheelbase();
|
|
|
|
- const double current_velocity = current_kinematics.twist.twist.linear.x;
|
|
|
|
- const double wz_predicted = current_velocity * std::tan(mpc_data.predicted_steer) / wb;
|
|
|
|
- const double wz_measured = current_velocity * std::tan(mpc_data.steer) / wb;
|
|
|
|
- const double wz_command = current_velocity * std::tan(ctrl_cmd.steering_tire_angle) / wb;
|
|
|
|
-
|
|
|
|
- typedef decltype(diagnostic.data)::value_type DiagnosticValueType;
|
|
|
|
- const auto append_diag = [&](const auto & val) -> void {
|
|
|
|
- diagnostic.data.push_back(static_cast<DiagnosticValueType>(val));
|
|
|
|
- };
|
|
|
|
- append_diag(ctrl_cmd.steering_tire_angle); // [0] final steering command (MPC + LPF)
|
|
|
|
- append_diag(Uex(0)); // [1] mpc calculation result
|
|
|
|
- append_diag(mpc_matrix.Uref_ex(0)); // [2] feed-forward steering value
|
|
|
|
- append_diag(std::atan(nearest_smooth_k * wb)); // [3] feed-forward steering value raw
|
|
|
|
- append_diag(mpc_data.steer); // [4] current steering angle
|
|
|
|
- append_diag(mpc_data.lateral_err); // [5] lateral error
|
|
|
|
- append_diag(tf2::getYaw(current_kinematics.pose.pose.orientation)); // [6] current_pose yaw
|
|
|
|
- append_diag(tf2::getYaw(mpc_data.nearest_pose.orientation)); // [7] nearest_pose yaw
|
|
|
|
- append_diag(mpc_data.yaw_err); // [8] yaw error
|
|
|
|
- append_diag(reference_trajectory.vx.at(mpc_data.nearest_idx)); // [9] reference velocity
|
|
|
|
- append_diag(current_velocity); // [10] measured velocity
|
|
|
|
- append_diag(wz_command); // [11] angular velocity from steer command
|
|
|
|
- append_diag(wz_measured); // [12] angular velocity from measured steer
|
|
|
|
- append_diag(current_velocity * nearest_smooth_k); // [13] angular velocity from path curvature
|
|
|
|
- append_diag(nearest_smooth_k); // [14] nearest path curvature (used for feed-forward)
|
|
|
|
- append_diag(nearest_k); // [15] nearest path curvature (not smoothed)
|
|
|
|
- append_diag(mpc_data.predicted_steer); // [16] predicted steer
|
|
|
|
- append_diag(wz_predicted); // [17] angular velocity from predicted steer
|
|
|
|
-
|
|
|
|
- return diagnostic;
|
|
|
|
-}
|
|
|
|
|
|
+//void MPC::setReferenceTrajectory(
|
|
|
|
+// const Trajectory & trajectory_msg, const TrajectoryFilteringParam & param,
|
|
|
|
+// const Odometry & current_kinematics)
|
|
|
|
+//{
|
|
|
|
+// const size_t nearest_seg_idx = motion_utils::findFirstNearestSegmentIndexWithSoftConstraints(
|
|
|
|
+// trajectory_msg.points, current_kinematics.pose.pose, ego_nearest_dist_threshold,
|
|
|
|
+// ego_nearest_yaw_threshold);
|
|
|
|
+// const double ego_offset_to_segment = motion_utils::calcLongitudinalOffsetToSegment(
|
|
|
|
+// trajectory_msg.points, nearest_seg_idx, current_kinematics.pose.pose.position);
|
|
|
|
+
|
|
|
|
+// const auto mpc_traj_raw = MPCUtils::convertToMPCTrajectory(trajectory_msg);
|
|
|
|
+
|
|
|
|
+// // resampling
|
|
|
|
+// const auto [success_resample, mpc_traj_resampled] = MPCUtils::resampleMPCTrajectoryByDistance(
|
|
|
|
+// mpc_traj_raw, param.traj_resample_dist, nearest_seg_idx, ego_offset_to_segment);
|
|
|
|
+// if (!success_resample) {
|
|
|
|
+// warn_throttle("[setReferenceTrajectory] spline error when resampling by distance");
|
|
|
|
+// return;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// const auto is_forward_shift =
|
|
|
|
+// motion_utils::isDrivingForward(mpc_traj_resampled.toTrajectoryPoints());
|
|
|
|
+
|
|
|
|
+// // if driving direction is unknown, use previous value
|
|
|
|
+// m_is_forward_shift = is_forward_shift ? is_forward_shift.get() : m_is_forward_shift;
|
|
|
|
+
|
|
|
|
+// // path smoothing
|
|
|
|
+// MPCTrajectory mpc_traj_smoothed = mpc_traj_resampled; // smooth filtered trajectory
|
|
|
|
+// const int mpc_traj_resampled_size = static_cast<int>(mpc_traj_resampled.size());
|
|
|
|
+// if (
|
|
|
|
+// param.enable_path_smoothing && mpc_traj_resampled_size > 2 * param.path_filter_moving_ave_num) {
|
|
|
|
+// using MoveAverageFilter::filt_vector;
|
|
|
|
+// if (
|
|
|
|
+// !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.x) ||
|
|
|
|
+// !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.y) ||
|
|
|
|
+// !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.yaw) ||
|
|
|
|
+// !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.vx)) {
|
|
|
|
+// RCLCPP_DEBUG(m_logger, "path callback: filtering error. stop filtering.");
|
|
|
|
+// mpc_traj_smoothed = mpc_traj_resampled;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// /*
|
|
|
|
+// * Extend terminal points
|
|
|
|
+// * Note: The current MPC does not properly take into account the attitude angle at the end of the
|
|
|
|
+// * path. By extending the end of the path in the attitude direction, the MPC can consider the
|
|
|
|
+// * attitude angle well, resulting in improved control performance. If the trajectory is
|
|
|
|
+// * well-defined considering the end point attitude angle, this feature is not necessary.
|
|
|
|
+// */
|
|
|
|
+// if (param.extend_trajectory_for_end_yaw_control) {
|
|
|
|
+// MPCUtils::extendTrajectoryInYawDirection(
|
|
|
|
+// mpc_traj_raw.yaw.back(), param.traj_resample_dist, m_is_forward_shift, mpc_traj_smoothed);
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// // calculate yaw angle
|
|
|
|
+// MPCUtils::calcTrajectoryYawFromXY(mpc_traj_smoothed, m_is_forward_shift);
|
|
|
|
+// MPCUtils::convertEulerAngleToMonotonic(mpc_traj_smoothed.yaw);
|
|
|
|
+
|
|
|
|
+// // calculate curvature
|
|
|
|
+// MPCUtils::calcTrajectoryCurvature(
|
|
|
|
+// param.curvature_smoothing_num_traj, param.curvature_smoothing_num_ref_steer, mpc_traj_smoothed);
|
|
|
|
+
|
|
|
|
+// // stop velocity at a terminal point
|
|
|
|
+// mpc_traj_smoothed.vx.back() = 0.0;
|
|
|
|
+
|
|
|
|
+// // add a extra point on back with extended time to make the mpc stable.
|
|
|
|
+// auto last_point = mpc_traj_smoothed.back();
|
|
|
|
+// last_point.relative_time += 100.0; // extra time to prevent mpc calc failure due to short time
|
|
|
|
+// last_point.vx = 0.0; // stop velocity at a terminal point
|
|
|
|
+// mpc_traj_smoothed.push_back(last_point);
|
|
|
|
+
|
|
|
|
+// if (!mpc_traj_smoothed.size()) {
|
|
|
|
+// RCLCPP_DEBUG(m_logger, "path callback: trajectory size is undesired.");
|
|
|
|
+// return;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// m_reference_trajectory = mpc_traj_smoothed;
|
|
|
|
+//}
|
|
|
|
|
|
void MPC::setReferenceTrajectory(
|
|
void MPC::setReferenceTrajectory(
|
|
- const Trajectory & trajectory_msg, const TrajectoryFilteringParam & param,
|
|
|
|
- const Odometry & current_kinematics)
|
|
|
|
|
|
+ const MPCTrajectory & trajectory_msg, const TrajectoryFilteringParam & param,
|
|
|
|
+ const iv::ADCOdometry & current_kinematics)
|
|
{
|
|
{
|
|
- const size_t nearest_seg_idx = motion_utils::findFirstNearestSegmentIndexWithSoftConstraints(
|
|
|
|
- trajectory_msg.points, current_kinematics.pose.pose, ego_nearest_dist_threshold,
|
|
|
|
- ego_nearest_yaw_threshold);
|
|
|
|
- const double ego_offset_to_segment = motion_utils::calcLongitudinalOffsetToSegment(
|
|
|
|
- trajectory_msg.points, nearest_seg_idx, current_kinematics.pose.pose.position);
|
|
|
|
|
|
+ const size_t nearest_seg_idx = MPCUtils::findFirstNearestSegmentIndexWithSoftConstraints(
|
|
|
|
+ trajectory_msg, current_kinematics.pose, ego_nearest_dist_threshold,
|
|
|
|
+ ego_nearest_yaw_threshold);
|
|
|
|
+ const double ego_offset_to_segment = MPCUtils::calcLongitudinalOffsetToSegment(
|
|
|
|
+ trajectory_msg, nearest_seg_idx, current_kinematics.pose.position);
|
|
|
|
|
|
- const auto mpc_traj_raw = MPCUtils::convertToMPCTrajectory(trajectory_msg);
|
|
|
|
|
|
+ const auto mpc_traj_raw = trajectory_msg;// MPCUtils::convertToMPCTrajectory(trajectory_msg);
|
|
|
|
|
|
// resampling
|
|
// resampling
|
|
const auto [success_resample, mpc_traj_resampled] = MPCUtils::resampleMPCTrajectoryByDistance(
|
|
const auto [success_resample, mpc_traj_resampled] = MPCUtils::resampleMPCTrajectoryByDistance(
|
|
- mpc_traj_raw, param.traj_resample_dist, nearest_seg_idx, ego_offset_to_segment);
|
|
|
|
|
|
+ mpc_traj_raw, param.traj_resample_dist, nearest_seg_idx, ego_offset_to_segment);
|
|
if (!success_resample) {
|
|
if (!success_resample) {
|
|
- warn_throttle("[setReferenceTrajectory] spline error when resampling by distance");
|
|
|
|
|
|
+ std::cout<<"[setReferenceTrajectory] spline error when resampling by distance"<<std::endl;
|
|
|
|
+// warn_throttle("[setReferenceTrajectory] spline error when resampling by distance");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
const auto is_forward_shift =
|
|
const auto is_forward_shift =
|
|
- motion_utils::isDrivingForward(mpc_traj_resampled.toTrajectoryPoints());
|
|
|
|
|
|
+ MPCUtils::isDrivingForward(mpc_traj_resampled);
|
|
|
|
|
|
// if driving direction is unknown, use previous value
|
|
// if driving direction is unknown, use previous value
|
|
- m_is_forward_shift = is_forward_shift ? is_forward_shift.get() : m_is_forward_shift;
|
|
|
|
|
|
+ m_is_forward_shift = is_forward_shift;// ? is_forward_shift.get() : m_is_forward_shift;
|
|
|
|
|
|
// path smoothing
|
|
// path smoothing
|
|
MPCTrajectory mpc_traj_smoothed = mpc_traj_resampled; // smooth filtered trajectory
|
|
MPCTrajectory mpc_traj_smoothed = mpc_traj_resampled; // smooth filtered trajectory
|
|
const int mpc_traj_resampled_size = static_cast<int>(mpc_traj_resampled.size());
|
|
const int mpc_traj_resampled_size = static_cast<int>(mpc_traj_resampled.size());
|
|
if (
|
|
if (
|
|
- param.enable_path_smoothing && mpc_traj_resampled_size > 2 * param.path_filter_moving_ave_num) {
|
|
|
|
|
|
+ param.enable_path_smoothing && mpc_traj_resampled_size > 2 * param.path_filter_moving_ave_num) {
|
|
using MoveAverageFilter::filt_vector;
|
|
using MoveAverageFilter::filt_vector;
|
|
if (
|
|
if (
|
|
- !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.x) ||
|
|
|
|
- !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.y) ||
|
|
|
|
- !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.yaw) ||
|
|
|
|
- !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.vx)) {
|
|
|
|
- RCLCPP_DEBUG(m_logger, "path callback: filtering error. stop filtering.");
|
|
|
|
|
|
+ !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.x) ||
|
|
|
|
+ !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.y) ||
|
|
|
|
+ !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.yaw) ||
|
|
|
|
+ !filt_vector(param.path_filter_moving_ave_num, mpc_traj_smoothed.vx)) {
|
|
|
|
+ std::cout<<"path callback: filtering error. stop filtering."<<std::endl;
|
|
|
|
+ // RCLCPP_DEBUG(m_logger, "path callback: filtering error. stop filtering.");
|
|
mpc_traj_smoothed = mpc_traj_resampled;
|
|
mpc_traj_smoothed = mpc_traj_resampled;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -226,7 +420,7 @@ void MPC::setReferenceTrajectory(
|
|
*/
|
|
*/
|
|
if (param.extend_trajectory_for_end_yaw_control) {
|
|
if (param.extend_trajectory_for_end_yaw_control) {
|
|
MPCUtils::extendTrajectoryInYawDirection(
|
|
MPCUtils::extendTrajectoryInYawDirection(
|
|
- mpc_traj_raw.yaw.back(), param.traj_resample_dist, m_is_forward_shift, mpc_traj_smoothed);
|
|
|
|
|
|
+ mpc_traj_raw.yaw.back(), param.traj_resample_dist, m_is_forward_shift, mpc_traj_smoothed);
|
|
}
|
|
}
|
|
|
|
|
|
// calculate yaw angle
|
|
// calculate yaw angle
|
|
@@ -235,7 +429,7 @@ void MPC::setReferenceTrajectory(
|
|
|
|
|
|
// calculate curvature
|
|
// calculate curvature
|
|
MPCUtils::calcTrajectoryCurvature(
|
|
MPCUtils::calcTrajectoryCurvature(
|
|
- param.curvature_smoothing_num_traj, param.curvature_smoothing_num_ref_steer, mpc_traj_smoothed);
|
|
|
|
|
|
+ param.curvature_smoothing_num_traj, param.curvature_smoothing_num_ref_steer, mpc_traj_smoothed);
|
|
|
|
|
|
// stop velocity at a terminal point
|
|
// stop velocity at a terminal point
|
|
mpc_traj_smoothed.vx.back() = 0.0;
|
|
mpc_traj_smoothed.vx.back() = 0.0;
|
|
@@ -247,18 +441,29 @@ void MPC::setReferenceTrajectory(
|
|
mpc_traj_smoothed.push_back(last_point);
|
|
mpc_traj_smoothed.push_back(last_point);
|
|
|
|
|
|
if (!mpc_traj_smoothed.size()) {
|
|
if (!mpc_traj_smoothed.size()) {
|
|
- RCLCPP_DEBUG(m_logger, "path callback: trajectory size is undesired.");
|
|
|
|
|
|
+ std::cout<<"path callback: trajectory size is undesired."<<std::endl;
|
|
|
|
+ // RCLCPP_DEBUG(m_logger, "path callback: trajectory size is undesired.");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
m_reference_trajectory = mpc_traj_smoothed;
|
|
m_reference_trajectory = mpc_traj_smoothed;
|
|
}
|
|
}
|
|
|
|
|
|
-void MPC::resetPrevResult(const SteeringReport & current_steer)
|
|
|
|
|
|
+//void MPC::resetPrevResult(const SteeringReport & current_steer)
|
|
|
|
+//{
|
|
|
|
+// // Consider limit. The prev value larger than limitation brakes the optimization constraint and
|
|
|
|
+// // results in optimization failure.
|
|
|
|
+// const float steer_lim_f = static_cast<float>(m_steer_lim);
|
|
|
|
+// m_raw_steer_cmd_prev = std::clamp(current_steer.steering_tire_angle, -steer_lim_f, steer_lim_f);
|
|
|
|
+// m_raw_steer_cmd_pprev = std::clamp(current_steer.steering_tire_angle, -steer_lim_f, steer_lim_f);
|
|
|
|
+//}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+void MPC::resetPrevResult(const iv::ADCSteeringReport & current_steer)
|
|
{
|
|
{
|
|
// Consider limit. The prev value larger than limitation brakes the optimization constraint and
|
|
// Consider limit. The prev value larger than limitation brakes the optimization constraint and
|
|
// results in optimization failure.
|
|
// results in optimization failure.
|
|
- const float steer_lim_f = static_cast<float>(m_steer_lim);
|
|
|
|
|
|
+ const float steer_lim_f = static_cast<float>(m_steer_lim); //
|
|
m_raw_steer_cmd_prev = std::clamp(current_steer.steering_tire_angle, -steer_lim_f, steer_lim_f);
|
|
m_raw_steer_cmd_prev = std::clamp(current_steer.steering_tire_angle, -steer_lim_f, steer_lim_f);
|
|
m_raw_steer_cmd_pprev = std::clamp(current_steer.steering_tire_angle, -steer_lim_f, steer_lim_f);
|
|
m_raw_steer_cmd_pprev = std::clamp(current_steer.steering_tire_angle, -steer_lim_f, steer_lim_f);
|
|
}
|
|
}
|
|
@@ -320,7 +525,8 @@ std::pair<bool, MPCData> MPC::getData(
|
|
if (!MPCUtils::calcNearestPoseInterp(
|
|
if (!MPCUtils::calcNearestPoseInterp(
|
|
traj, current_pose, &(data.nearest_pose), &(data.nearest_idx), &(data.nearest_time),
|
|
traj, current_pose, &(data.nearest_pose), &(data.nearest_idx), &(data.nearest_time),
|
|
ego_nearest_dist_threshold, ego_nearest_yaw_threshold)) {
|
|
ego_nearest_dist_threshold, ego_nearest_yaw_threshold)) {
|
|
- warn_throttle("calculateMPC: error in calculating nearest pose. stop mpc.");
|
|
|
|
|
|
+ std::cout<<"calculateMPC: error in calculating nearest pose. stop mpc."<<std::endl;
|
|
|
|
+// warn_throttle("calculateMPC: error in calculating nearest pose. stop mpc.");
|
|
return {false, MPCData{}};
|
|
return {false, MPCData{}};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -336,13 +542,15 @@ std::pair<bool, MPCData> MPC::getData(
|
|
// check error limit
|
|
// check error limit
|
|
const double dist_err = MPCUtils::ADCcalcDistance2d(current_pose.position, data.nearest_pose.position);
|
|
const double dist_err = MPCUtils::ADCcalcDistance2d(current_pose.position, data.nearest_pose.position);
|
|
if (dist_err > m_admissible_position_error) {
|
|
if (dist_err > m_admissible_position_error) {
|
|
- warn_throttle("Too large position error: %fm > %fm", dist_err, m_admissible_position_error);
|
|
|
|
|
|
+ printf("Too large position error: %fm > %fm", dist_err, m_admissible_position_error);
|
|
|
|
+ // warn_throttle("Too large position error: %fm > %fm", dist_err, m_admissible_position_error);
|
|
return {false, MPCData{}};
|
|
return {false, MPCData{}};
|
|
}
|
|
}
|
|
|
|
|
|
// check yaw error limit
|
|
// check yaw error limit
|
|
if (std::fabs(data.yaw_err) > m_admissible_yaw_error_rad) {
|
|
if (std::fabs(data.yaw_err) > m_admissible_yaw_error_rad) {
|
|
- warn_throttle("Too large yaw error: %f > %f", data.yaw_err, m_admissible_yaw_error_rad);
|
|
|
|
|
|
+ printf("Too large yaw error: %f > %f", data.yaw_err, m_admissible_yaw_error_rad);
|
|
|
|
+// warn_throttle("Too large yaw error: %f > %f", data.yaw_err, m_admissible_yaw_error_rad);
|
|
return {false, MPCData{}};
|
|
return {false, MPCData{}};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -351,7 +559,8 @@ std::pair<bool, MPCData> MPC::getData(
|
|
m_param.min_prediction_length / static_cast<double>(m_param.prediction_horizon - 1);
|
|
m_param.min_prediction_length / static_cast<double>(m_param.prediction_horizon - 1);
|
|
auto end_time = data.nearest_time + m_param.input_delay + m_ctrl_period + max_prediction_time;
|
|
auto end_time = data.nearest_time + m_param.input_delay + m_ctrl_period + max_prediction_time;
|
|
if (end_time > traj.relative_time.back()) {
|
|
if (end_time > traj.relative_time.back()) {
|
|
- warn_throttle("path is too short for prediction.");
|
|
|
|
|
|
+ printf("path is too short for prediction.");
|
|
|
|
+ // warn_throttle("path is too short for prediction.");
|
|
return {false, MPCData{}};
|
|
return {false, MPCData{}};
|
|
}
|
|
}
|
|
return {true, data};
|
|
return {true, data};
|
|
@@ -366,7 +575,8 @@ std::pair<bool, MPCTrajectory> MPC::resampleMPCTrajectoryByTime(
|
|
mpc_time_v.push_back(ts + i * prediction_dt);
|
|
mpc_time_v.push_back(ts + i * prediction_dt);
|
|
}
|
|
}
|
|
if (!MPCUtils::linearInterpMPCTrajectory(input.relative_time, input, mpc_time_v, output)) {
|
|
if (!MPCUtils::linearInterpMPCTrajectory(input.relative_time, input, mpc_time_v, output)) {
|
|
- warn_throttle("calculateMPC: mpc resample error. stop mpc calculation. check code!");
|
|
|
|
|
|
+ printf("calculateMPC: mpc resample error. stop mpc calculation. check code!");
|
|
|
|
+// warn_throttle("calculateMPC: mpc resample error. stop mpc calculation. check code!");
|
|
return {false, {}};
|
|
return {false, {}};
|
|
}
|
|
}
|
|
return {true, output};
|
|
return {true, output};
|
|
@@ -394,10 +604,13 @@ VectorXd MPC::getInitialState(const MPCData & data)
|
|
dlat = m_lpf_lateral_error.filter(dlat);
|
|
dlat = m_lpf_lateral_error.filter(dlat);
|
|
dyaw = m_lpf_yaw_error.filter(dyaw);
|
|
dyaw = m_lpf_yaw_error.filter(dyaw);
|
|
x0 << lat_err, dlat, yaw_err, dyaw;
|
|
x0 << lat_err, dlat, yaw_err, dyaw;
|
|
- RCLCPP_DEBUG(m_logger, "(before lpf) dot_lat_err = %f, dot_yaw_err = %f", dlat, dyaw);
|
|
|
|
- RCLCPP_DEBUG(m_logger, "(after lpf) dot_lat_err = %f, dot_yaw_err = %f", dlat, dyaw);
|
|
|
|
|
|
+ std::cout<<"(before lpf) dot_lat_err = "<<dlat<<", dot_yaw_err = "<<dyaw<<std::endl;
|
|
|
|
+ std::cout<<"(after lpf) dot_lat_err = "<<dlat<<", dot_yaw_err = "<<dyaw<<std::endl;
|
|
|
|
+// RCLCPP_DEBUG(m_logger, "(before lpf) dot_lat_err = %f, dot_yaw_err = %f", dlat, dyaw);
|
|
|
|
+// RCLCPP_DEBUG(m_logger, "(after lpf) dot_lat_err = %f, dot_yaw_err = %f", dlat, dyaw);
|
|
} else {
|
|
} else {
|
|
- RCLCPP_ERROR(m_logger, "vehicle_model_type is undefined");
|
|
|
|
|
|
+ std::cout<<"vehicle_model_type is undefined"<<std::endl;
|
|
|
|
+// RCLCPP_ERROR(m_logger, "vehicle_model_type is undefined");
|
|
}
|
|
}
|
|
return x0;
|
|
return x0;
|
|
}
|
|
}
|
|
@@ -422,7 +635,8 @@ std::pair<bool, VectorXd> MPC::updateStateForDelayCompensation(
|
|
k = interpolation::lerp(traj.relative_time, traj.k, mpc_curr_time);
|
|
k = interpolation::lerp(traj.relative_time, traj.k, mpc_curr_time);
|
|
v = interpolation::lerp(traj.relative_time, traj.vx, mpc_curr_time);
|
|
v = interpolation::lerp(traj.relative_time, traj.vx, mpc_curr_time);
|
|
} catch (const std::exception & e) {
|
|
} catch (const std::exception & e) {
|
|
- RCLCPP_ERROR(m_logger, "mpc resample failed at delay compensation, stop mpc: %s", e.what());
|
|
|
|
|
|
+ std::cout<<"mpc resample failed at delay compensation, stop mpc: "<<e.what()<<std::endl;
|
|
|
|
+ // RCLCPP_ERROR(m_logger, "mpc resample failed at delay compensation, stop mpc: %s", e.what());
|
|
return {false, {}};
|
|
return {false, {}};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -438,22 +652,46 @@ std::pair<bool, VectorXd> MPC::updateStateForDelayCompensation(
|
|
return {true, x_curr};
|
|
return {true, x_curr};
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+//MPCTrajectory MPC::applyVelocityDynamicsFilter(
|
|
|
|
+// const MPCTrajectory & input, const Odometry & current_kinematics) const
|
|
|
|
+//{
|
|
|
|
+// const auto autoware_traj = MPCUtils::convertToAutowareTrajectory(input);
|
|
|
|
+// if (autoware_traj.points.empty()) {
|
|
|
|
+// return input;
|
|
|
|
+// }
|
|
|
|
+
|
|
|
|
+// const size_t nearest_seg_idx = motion_utils::findFirstNearestSegmentIndexWithSoftConstraints(
|
|
|
|
+// autoware_traj.points, current_kinematics.pose.pose, ego_nearest_dist_threshold,
|
|
|
|
+// ego_nearest_yaw_threshold);
|
|
|
|
+
|
|
|
|
+// MPCTrajectory output = input;
|
|
|
|
+// MPCUtils::dynamicSmoothingVelocity(
|
|
|
|
+// nearest_seg_idx, current_kinematics.twist.twist.linear.x, m_param.acceleration_limit,
|
|
|
|
+// m_param.velocity_time_constant, output);
|
|
|
|
+
|
|
|
|
+// auto last_point = output.back();
|
|
|
|
+// last_point.relative_time += 100.0; // extra time to prevent mpc calc failure due to short time
|
|
|
|
+// last_point.vx = 0.0; // stop velocity at a terminal point
|
|
|
|
+// output.push_back(last_point);
|
|
|
|
+// return output;
|
|
|
|
+//}
|
|
|
|
+
|
|
MPCTrajectory MPC::applyVelocityDynamicsFilter(
|
|
MPCTrajectory MPC::applyVelocityDynamicsFilter(
|
|
- const MPCTrajectory & input, const Odometry & current_kinematics) const
|
|
|
|
|
|
+ const MPCTrajectory & trajectory, const iv::ADCOdometry & current_kinematics) const
|
|
{
|
|
{
|
|
- const auto autoware_traj = MPCUtils::convertToAutowareTrajectory(input);
|
|
|
|
- if (autoware_traj.points.empty()) {
|
|
|
|
- return input;
|
|
|
|
|
|
+ // const auto autoware_traj = MPCUtils::convertToAutowareTrajectory(input);
|
|
|
|
+ if (trajectory.size() == 0) {
|
|
|
|
+ return trajectory;
|
|
}
|
|
}
|
|
|
|
|
|
- const size_t nearest_seg_idx = motion_utils::findFirstNearestSegmentIndexWithSoftConstraints(
|
|
|
|
- autoware_traj.points, current_kinematics.pose.pose, ego_nearest_dist_threshold,
|
|
|
|
- ego_nearest_yaw_threshold);
|
|
|
|
|
|
+ const size_t nearest_seg_idx = MPCUtils::findFirstNearestSegmentIndexWithSoftConstraints(
|
|
|
|
+ trajectory, current_kinematics.pose, ego_nearest_dist_threshold,
|
|
|
|
+ ego_nearest_yaw_threshold);
|
|
|
|
|
|
- MPCTrajectory output = input;
|
|
|
|
|
|
+ MPCTrajectory output = trajectory;
|
|
MPCUtils::dynamicSmoothingVelocity(
|
|
MPCUtils::dynamicSmoothingVelocity(
|
|
- nearest_seg_idx, current_kinematics.twist.twist.linear.x, m_param.acceleration_limit,
|
|
|
|
- m_param.velocity_time_constant, output);
|
|
|
|
|
|
+ nearest_seg_idx, current_kinematics.twist.linear_x, m_param.acceleration_limit,
|
|
|
|
+ m_param.velocity_time_constant, output);
|
|
|
|
|
|
auto last_point = output.back();
|
|
auto last_point = output.back();
|
|
last_point.relative_time += 100.0; // extra time to prevent mpc calc failure due to short time
|
|
last_point.relative_time += 100.0; // extra time to prevent mpc calc failure due to short time
|
|
@@ -555,7 +793,7 @@ MPCMatrix MPC::generateMPCMatrix(
|
|
// get reference input (feed-forward)
|
|
// get reference input (feed-forward)
|
|
m_vehicle_model_ptr->setCurvature(ref_smooth_k);
|
|
m_vehicle_model_ptr->setCurvature(ref_smooth_k);
|
|
m_vehicle_model_ptr->calculateReferenceInput(Uref);
|
|
m_vehicle_model_ptr->calculateReferenceInput(Uref);
|
|
- if (std::fabs(Uref(0, 0)) < tier4_autoware_utils::deg2rad(m_param.zero_ff_steer_deg)) {
|
|
|
|
|
|
+ if (std::fabs(Uref(0, 0)) < MPCUtils::deg2rad(m_param.zero_ff_steer_deg)) {
|
|
Uref(0, 0) = 0.0; // ignore curvature noise
|
|
Uref(0, 0) = 0.0; // ignore curvature noise
|
|
}
|
|
}
|
|
m.Uref_ex.block(i * DIM_U, 0, DIM_U, 1) = Uref;
|
|
m.Uref_ex.block(i * DIM_U, 0, DIM_U, 1) = Uref;
|
|
@@ -604,7 +842,8 @@ std::pair<bool, VectorXd> MPC::executeOptimization(
|
|
VectorXd Uex;
|
|
VectorXd Uex;
|
|
|
|
|
|
if (!isValid(m)) {
|
|
if (!isValid(m)) {
|
|
- warn_throttle("model matrix is invalid. stop MPC.");
|
|
|
|
|
|
+ printf("model matrix is invalid. stop MPC.");
|
|
|
|
+// warn_throttle("model matrix is invalid. stop MPC.");
|
|
return {false, {}};
|
|
return {false, {}};
|
|
}
|
|
}
|
|
|
|
|
|
@@ -642,17 +881,20 @@ std::pair<bool, VectorXd> MPC::executeOptimization(
|
|
bool solve_result = m_qpsolver_ptr->solve(H, f.transpose(), A, lb, ub, lbA, ubA, Uex);
|
|
bool solve_result = m_qpsolver_ptr->solve(H, f.transpose(), A, lb, ub, lbA, ubA, Uex);
|
|
auto t_end = std::chrono::system_clock::now();
|
|
auto t_end = std::chrono::system_clock::now();
|
|
if (!solve_result) {
|
|
if (!solve_result) {
|
|
- warn_throttle("qp solver error");
|
|
|
|
|
|
+ printf("qp solver error");
|
|
|
|
+// warn_throttle("qp solver error");
|
|
return {false, {}};
|
|
return {false, {}};
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
{
|
|
auto t = std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start).count();
|
|
auto t = std::chrono::duration_cast<std::chrono::milliseconds>(t_end - t_start).count();
|
|
- RCLCPP_DEBUG(m_logger, "qp solver calculation time = %ld [ms]", t);
|
|
|
|
|
|
+ std::cout<<"qp solver calculation time = "<<t<<"[ms]";
|
|
|
|
+// RCLCPP_DEBUG(m_logger, "qp solver calculation time = %ld [ms]", t);
|
|
}
|
|
}
|
|
|
|
|
|
if (Uex.array().isNaN().any()) {
|
|
if (Uex.array().isNaN().any()) {
|
|
- warn_throttle("model Uex includes NaN, stop MPC.");
|
|
|
|
|
|
+ printf("model Uex includes NaN, stop MPC.");
|
|
|
|
+// warn_throttle("model Uex includes NaN, stop MPC.");
|
|
return {false, {}};
|
|
return {false, {}};
|
|
}
|
|
}
|
|
return {true, Uex};
|
|
return {true, Uex};
|
|
@@ -727,36 +969,71 @@ void MPC::addSteerWeightF(const double prediction_dt, MatrixXd & f) const
|
|
f(0, 1) += (2.0 * m_raw_steer_cmd_prev * steer_acc_r_cp1) * 0.5;
|
|
f(0, 1) += (2.0 * m_raw_steer_cmd_prev * steer_acc_r_cp1) * 0.5;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+//double MPC::getPredictionDeltaTime(
|
|
|
|
+// const double start_time, const MPCTrajectory & input, const Odometry & current_kinematics) const
|
|
|
|
+//{
|
|
|
|
+// // Calculate the time min_prediction_length ahead from current_pose
|
|
|
|
+// const auto autoware_traj = MPCUtils::convertToAutowareTrajectory(input);
|
|
|
|
+// const size_t nearest_idx = motion_utils::findFirstNearestIndexWithSoftConstraints(
|
|
|
|
+// autoware_traj.points, current_kinematics.pose.pose, ego_nearest_dist_threshold,
|
|
|
|
+// ego_nearest_yaw_threshold);
|
|
|
|
+// double sum_dist = 0;
|
|
|
|
+// const double target_time = [&]() {
|
|
|
|
+// const double t_ext = 100.0; // extra time to prevent mpc calculation failure due to short time
|
|
|
|
+// for (size_t i = nearest_idx + 1; i < input.relative_time.size(); i++) {
|
|
|
|
+// const double segment_dist = MPCUtils::calcDistance2d(input, i, i - 1);
|
|
|
|
+// sum_dist += segment_dist;
|
|
|
|
+// if (m_param.min_prediction_length < sum_dist) {
|
|
|
|
+// const double prev_sum_dist = sum_dist - segment_dist;
|
|
|
|
+// const double ratio = (m_param.min_prediction_length - prev_sum_dist) / segment_dist;
|
|
|
|
+// const double relative_time_at_i = i == input.relative_time.size() - 1
|
|
|
|
+// ? input.relative_time.at(i) - t_ext
|
|
|
|
+// : input.relative_time.at(i);
|
|
|
|
+// return input.relative_time.at(i - 1) +
|
|
|
|
+// (relative_time_at_i - input.relative_time.at(i - 1)) * ratio;
|
|
|
|
+// }
|
|
|
|
+// }
|
|
|
|
+// return input.relative_time.back() - t_ext;
|
|
|
|
+// }();
|
|
|
|
+
|
|
|
|
+// // Calculate delta time for min_prediction_length
|
|
|
|
+// const double dt =
|
|
|
|
+// (target_time - start_time) / static_cast<double>(m_param.prediction_horizon - 1);
|
|
|
|
+
|
|
|
|
+// return std::max(dt, m_param.prediction_dt);
|
|
|
|
+//}
|
|
|
|
+
|
|
double MPC::getPredictionDeltaTime(
|
|
double MPC::getPredictionDeltaTime(
|
|
- const double start_time, const MPCTrajectory & input, const Odometry & current_kinematics) const
|
|
|
|
|
|
+ const double start_time, const MPCTrajectory & input,
|
|
|
|
+ const iv::ADCOdometry & current_kinematics) const
|
|
{
|
|
{
|
|
// Calculate the time min_prediction_length ahead from current_pose
|
|
// Calculate the time min_prediction_length ahead from current_pose
|
|
- const auto autoware_traj = MPCUtils::convertToAutowareTrajectory(input);
|
|
|
|
- const size_t nearest_idx = motion_utils::findFirstNearestIndexWithSoftConstraints(
|
|
|
|
- autoware_traj.points, current_kinematics.pose.pose, ego_nearest_dist_threshold,
|
|
|
|
- ego_nearest_yaw_threshold);
|
|
|
|
|
|
+ const size_t nearest_idx = MPCUtils::findFirstNearestIndexWithSoftConstraints(
|
|
|
|
+ input, current_kinematics.pose, ego_nearest_dist_threshold,
|
|
|
|
+ ego_nearest_yaw_threshold);
|
|
|
|
+
|
|
double sum_dist = 0;
|
|
double sum_dist = 0;
|
|
const double target_time = [&]() {
|
|
const double target_time = [&]() {
|
|
- const double t_ext = 100.0; // extra time to prevent mpc calculation failure due to short time
|
|
|
|
- for (size_t i = nearest_idx + 1; i < input.relative_time.size(); i++) {
|
|
|
|
- const double segment_dist = MPCUtils::calcDistance2d(input, i, i - 1);
|
|
|
|
- sum_dist += segment_dist;
|
|
|
|
- if (m_param.min_prediction_length < sum_dist) {
|
|
|
|
- const double prev_sum_dist = sum_dist - segment_dist;
|
|
|
|
- const double ratio = (m_param.min_prediction_length - prev_sum_dist) / segment_dist;
|
|
|
|
- const double relative_time_at_i = i == input.relative_time.size() - 1
|
|
|
|
- ? input.relative_time.at(i) - t_ext
|
|
|
|
- : input.relative_time.at(i);
|
|
|
|
- return input.relative_time.at(i - 1) +
|
|
|
|
- (relative_time_at_i - input.relative_time.at(i - 1)) * ratio;
|
|
|
|
|
|
+ const double t_ext = 100.0; // extra time to prevent mpc calculation failure due to short time
|
|
|
|
+ for (size_t i = nearest_idx + 1; i < input.relative_time.size(); i++) {
|
|
|
|
+ const double segment_dist = MPCUtils::calcDistance2d(input, i, i - 1);
|
|
|
|
+ sum_dist += segment_dist;
|
|
|
|
+ if (m_param.min_prediction_length < sum_dist) {
|
|
|
|
+ const double prev_sum_dist = sum_dist - segment_dist;
|
|
|
|
+ const double ratio = (m_param.min_prediction_length - prev_sum_dist) / segment_dist;
|
|
|
|
+ const double relative_time_at_i = i == input.relative_time.size() - 1
|
|
|
|
+ ? input.relative_time.at(i) - t_ext
|
|
|
|
+ : input.relative_time.at(i);
|
|
|
|
+ return input.relative_time.at(i - 1) +
|
|
|
|
+ (relative_time_at_i - input.relative_time.at(i - 1)) * ratio;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }
|
|
|
|
- return input.relative_time.back() - t_ext;
|
|
|
|
|
|
+ return input.relative_time.back() - t_ext;
|
|
}();
|
|
}();
|
|
|
|
|
|
// Calculate delta time for min_prediction_length
|
|
// Calculate delta time for min_prediction_length
|
|
const double dt =
|
|
const double dt =
|
|
- (target_time - start_time) / static_cast<double>(m_param.prediction_horizon - 1);
|
|
|
|
|
|
+ (target_time - start_time) / static_cast<double>(m_param.prediction_horizon - 1);
|
|
|
|
|
|
return std::max(dt, m_param.prediction_dt);
|
|
return std::max(dt, m_param.prediction_dt);
|
|
}
|
|
}
|