trajectory_optimization v1.4.0
Loading...
Searching...
No Matches
trajectory_optimization_rws.cpp
Go to the documentation of this file.
1// Copyright Institute for Automotive Engineering (ika), RWTH Aachen University
2// SPDX-License-Identifier: Apache-2.0
3
4#include <limits>
5
7
8#include <rclcpp_components/register_node_macro.hpp>
9
10RCLCPP_COMPONENTS_REGISTER_NODE(trajectory_optimization::TrajectoryOptimizationRWSNode)
11
14 : TrajectoryOptimizationNode("TrajectoryOptimizationRWSNode", options) {
15 this->declareAndLoadParameter("distance_front_axle", distance_front_axle_, "Distance from center of gravity to front axle [m]");
16 this->declareAndLoadParameter("distance_rear_axle", distance_rear_axle_, "Distance from center of gravity to rear axle [m]");
17}
18
19void TrajectoryOptimizationRWSNode::initializeTrajectory(trajectory_planning_msgs::msg::Trajectory& trajectory) {
20 trajectory_planning_msgs::trajectory_access::initializeTrajectory(
21 trajectory, trajectory_planning_msgs::msg::DRIVABLERWS::TYPE_ID, n_shots_ + 1);
22}
23
24std::vector<double> TrajectoryOptimizationRWSNode::getBiLevelX0(const perception_msgs::msg::EgoData& ego_data) {
25 // transform latest trajectory to current base_link frame
26 trajectory_planning_msgs::msg::Trajectory tf_trajectory;
27 try {
28 tf_trajectory = tf2_buffer_->transform(latest_valid_trajectory_, vehicle_frame_id_, tf2_ros::fromMsg(ego_data.header.stamp),
29 fixed_over_time_frame_id_, tf2::durationFromSec(0.01));
30 } catch (tf2::TransformException& ex) {
31 RCLCPP_WARN(this->get_logger(), "Transformation is not available. Init high-level instead. Ex: %s", ex.what());
32 return getHighLevelX0(ego_data);
33 }
34
35 // fill vectors with state values from the transformed trajectory
36 std::vector<double> TIME, V, Y, A, THETA, DELTA_FRONT, DELTA_REAR;
37 for (int i = 0; i < trajectory_planning_msgs::trajectory_access::getSamplePointSize(tf_trajectory); i++) {
38 TIME.push_back(trajectory_planning_msgs::trajectory_access::getT(tf_trajectory, i));
39 Y.push_back(trajectory_planning_msgs::trajectory_access::getY(tf_trajectory, i));
40 V.push_back(trajectory_planning_msgs::trajectory_access::getV(tf_trajectory, i));
41 A.push_back(trajectory_planning_msgs::trajectory_access::getA(tf_trajectory, i));
42 THETA.push_back(trajectory_planning_msgs::trajectory_access::getTheta(tf_trajectory, i));
43 DELTA_FRONT.push_back(trajectory_planning_msgs::trajectory_access::getDeltaFront(tf_trajectory, i));
44 DELTA_REAR.push_back(trajectory_planning_msgs::trajectory_access::getDeltaRear(tf_trajectory, i));
45 }
46
47 // interpolate target states by time from the extracted vectors; if not successful, set to ego state (high-level initialization)
48 double v_tgt = 0.0, a_tgt = 0.0, y_tgt = 0.0, theta_tgt = 0.0, delta_front_tgt = 0.0, delta_rear_tgt = 0.0;
49 double des_time = (rclcpp::Time(ego_data.header.stamp) - rclcpp::Time(tf_trajectory.header.stamp)).seconds();
50 if (!linearInterpolation(TIME, Y, des_time, y_tgt)) y_tgt = 0.0;
51 if (!linearInterpolation(TIME, THETA, des_time, theta_tgt, true)) theta_tgt = 0.0;
52 if (!linearInterpolation(TIME, V, des_time, v_tgt)) v_tgt = perception_msgs::object_access::getVelocityMagnitude(ego_data);
53 if (!linearInterpolation(TIME, A, des_time, a_tgt)) {
54 a_tgt = projectVectorAonV(perception_msgs::object_access::getAcceleration(ego_data),
55 perception_msgs::object_access::getVelocity(ego_data));
56 }
57 if (!linearInterpolation(TIME, DELTA_FRONT, des_time, delta_front_tgt)) {
58 delta_front_tgt = perception_msgs::object_access::getSteeringAngleFront(ego_data);
59 }
60 if (!linearInterpolation(TIME, DELTA_REAR, des_time, delta_rear_tgt)) {
61 delta_rear_tgt = perception_msgs::object_access::getSteeringAngleRear(ego_data);
62 }
63
64 RCLCPP_DEBUG(this->get_logger(), "y_tgt: %f, v_tgt: %f, a_tgt: %f, theta_tgt: %f, delta_front_tgt: %f, delta_rear_tgt: %f",
65 y_tgt, v_tgt, a_tgt, theta_tgt, delta_front_tgt, delta_rear_tgt);
66
67 // handle thresholds for bi-level stabilization (which means, using ego state as initial state for the optimization)
68 // longitudinal reinits
69 if (fabs(v_tgt - perception_msgs::object_access::getVelocityMagnitude(ego_data)) > bi_level_dV_) {
70 const auto ego_v = perception_msgs::object_access::getVelocityMagnitude(ego_data);
71 const auto ego_a = projectVectorAonV(perception_msgs::object_access::getAcceleration(ego_data),
72 perception_msgs::object_access::getVelocity(ego_data));
73 RCLCPP_WARN(this->get_logger(), "Velocity reinit: v_tgt: %f, a_tgt: %f, ego_v: %f, ego_a: %f", v_tgt, a_tgt, ego_v, ego_a);
74 v_tgt = ego_v;
75 a_tgt = ego_a;
76 }
77 // lateral reinits
78 if (fabs(y_tgt) > bi_level_dY_ || fabs(theta_tgt) > bi_level_dYaw_ * M_PI / 180.0) {
79 const auto ego_delta_front = perception_msgs::object_access::getSteeringAngleFront(ego_data);
80 const auto ego_delta_rear = perception_msgs::object_access::getSteeringAngleRear(ego_data);
81 RCLCPP_WARN(this->get_logger(),
82 "Lateral reinit: y_tgt: %f, theta_tgt: %f, delta_front_tgt: %f, delta_rear_tgt: %f, ego_y: %f, "
83 "ego_theta: %f, ego_delta_front: %f, ego_delta_rear: %f",
84 y_tgt, theta_tgt, delta_front_tgt, delta_rear_tgt, 0.0, 0.0, ego_delta_front, ego_delta_rear);
85 y_tgt = 0.0;
86 theta_tgt = 0.0;
87 delta_front_tgt = ego_delta_front;
88 delta_rear_tgt = ego_delta_rear;
89 }
90
91 std::vector<double> x_init(*nlp_dims_->nx, 0.0);
92 x_init[0] = 0.0;
93 x_init[1] = y_tgt;
94 x_init[2] = 0.0;
95 x_init[3] = v_tgt;
96 x_init[4] = a_tgt;
97 x_init[5] = theta_tgt;
98 x_init[6] = delta_front_tgt;
99 x_init[7] = delta_rear_tgt;
100
101 return x_init;
102}
103
104std::vector<double> TrajectoryOptimizationRWSNode::getHighLevelX0(const perception_msgs::msg::EgoData& ego_data) {
105 std::vector<double> x_init(*nlp_dims_->nx, 0.0);
106
107 x_init[3] = perception_msgs::object_access::getVelocityMagnitude(ego_data);
108 x_init[4] = projectVectorAonV(perception_msgs::object_access::getAcceleration(ego_data),
109 perception_msgs::object_access::getVelocity(ego_data));
110 x_init[6] = perception_msgs::object_access::getSteeringAngleFront(ego_data);
111 x_init[7] = perception_msgs::object_access::getSteeringAngleRear(ego_data);
112
113 return x_init;
114}
115
116void TrajectoryOptimizationRWSNode::convertToTrajectoryMsg(trajectory_planning_msgs::msg::Trajectory& trajectory) {
117 for (int i = 0; i <= n_shots_; ++i) {
118 trajectory_planning_msgs::trajectory_access::setX(trajectory, xtraj_[i * *nlp_dims_->nx + 0], i);
119 trajectory_planning_msgs::trajectory_access::setY(trajectory, xtraj_[i * *nlp_dims_->nx + 1], i);
120 trajectory_planning_msgs::trajectory_access::setS(trajectory, xtraj_[i * *nlp_dims_->nx + 2], i);
121 trajectory_planning_msgs::trajectory_access::setV(trajectory, xtraj_[i * *nlp_dims_->nx + 3], i);
122 trajectory_planning_msgs::trajectory_access::setA(trajectory, xtraj_[i * *nlp_dims_->nx + 4], i);
123 trajectory_planning_msgs::trajectory_access::setTheta(trajectory, xtraj_[i * *nlp_dims_->nx + 5], i);
124 trajectory_planning_msgs::trajectory_access::setDeltaFront(trajectory, xtraj_[i * *nlp_dims_->nx + 6], i);
125 trajectory_planning_msgs::trajectory_access::setDeltaRear(trajectory, xtraj_[i * *nlp_dims_->nx + 7], i);
126 trajectory_planning_msgs::trajectory_access::setBeta(
127 trajectory, xtraj_[i * *nlp_dims_->nx + 6], xtraj_[i * *nlp_dims_->nx + 7], distance_front_axle_, distance_rear_axle_, i);
128 }
129}
130
131double TrajectoryOptimizationRWSNode::computeVehicleSlipAngle(const double& delta_front, const double& delta_rear) const {
132 double wheel_base = distance_front_axle_ + distance_rear_axle_;
133 double slip_angle =
134 atan(distance_rear_axle_ / wheel_base * tan(delta_front) + distance_front_axle_ / wheel_base * tan(delta_rear));
135 return slip_angle;
136}
137
138double TrajectoryOptimizationRWSNode::projectVectorAonV(const geometry_msgs::msg::Vector3& a,
139 const geometry_msgs::msg::Vector3& v) {
140 double v_magnitude_squared = v.x * v.x + v.y * v.y;
141 if (v_magnitude_squared < std::numeric_limits<double>::epsilon()) {
142 return 0.0;
143 }
144 double scale = (a.x * v.x + a.y * v.y) / v_magnitude_squared;
145 return scale * std::sqrt(v_magnitude_squared);
146}
147
148} // namespace trajectory_optimization
trajectory_planning_msgs::msg::Trajectory latest_valid_trajectory_
bool linearInterpolation(const std::vector< double > &X, const std::vector< double > &Y, const double &desired_x, double &output_y, const bool wrap_angle=false)
Interpolates a value from sampled data and optionally handles angle wrap-around.
Definition utils.cpp:21
void declareAndLoadParameter(const std::string &name, T &param, const std::string &description, const bool add_to_auto_reconfigurable_params=true, const bool is_required=false, const bool read_only=false, const std::optional< double > &from_value=std::nullopt, const std::optional< double > &to_value=std::nullopt, const std::optional< double > &step_value=std::nullopt, const std::string &additional_constraints="")
Declares a ROS parameter, loads its value and optionally registers it for runtime updates.
void convertToTrajectoryMsg(trajectory_planning_msgs::msg::Trajectory &trajectory) override
Maps the optimized state trajectory into a trajectory message for a kinematic bicycle model with rear...
std::vector< double > getHighLevelX0(const perception_msgs::msg::EgoData &ego_data) override
Computes the initial optimizer state using high-level stabilization.
std::vector< double > getBiLevelX0(const perception_msgs::msg::EgoData &ego_data) override
Computes the initial optimizer state using bi-level stabilizaion.
static double projectVectorAonV(const geometry_msgs::msg::Vector3 &a, const geometry_msgs::msg::Vector3 &v)
Projects the acceleration vector onto the current direction of motion.
double computeVehicleSlipAngle(const double &delta_front, const double &delta_rear) const
Computes the kinematic vehicle slip angle from front and rear steering angles.
TrajectoryOptimizationRWSNode(const rclcpp::NodeOptions &options)
Initializes the optimization node for a kinematic bicycle model with rear wheel steering.
void initializeTrajectory(trajectory_planning_msgs::msg::Trajectory &trajectory) override
Initializes a drivable trajectory message for a kinematic bicycle model with rear wheel steering.
Namespace for trajectory_optimization package.