trajectory_optimization v1.4.0
Loading...
Searching...
No Matches
trajectory_optimization_ackermann.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
5
6#include <rclcpp_components/register_node_macro.hpp>
7
9
11
13 : TrajectoryOptimizationNode("TrajectoryOptimizationAckermannNode", options) {}
14
15void TrajectoryOptimizationAckermannNode::initializeTrajectory(trajectory_planning_msgs::msg::Trajectory& trajectory) {
16 trajectory_planning_msgs::trajectory_access::initializeTrajectory(trajectory, trajectory_planning_msgs::msg::DRIVABLE::TYPE_ID,
17 n_shots_ + 1);
18}
19
20std::vector<double> TrajectoryOptimizationAckermannNode::getBiLevelX0(const perception_msgs::msg::EgoData& ego_data) {
21 // transform latest trajectory to current base_link frame
22 trajectory_planning_msgs::msg::Trajectory tf_trajectory;
23 try {
24 tf_trajectory = tf2_buffer_->transform(latest_valid_trajectory_, vehicle_frame_id_, tf2_ros::fromMsg(ego_data.header.stamp),
25 fixed_over_time_frame_id_, tf2::durationFromSec(0.01));
26 } catch (tf2::TransformException& ex) {
27 RCLCPP_WARN(this->get_logger(), "Transformation is not available. Init high-level instead. Ex: %s", ex.what());
28 return getHighLevelX0(ego_data);
29 }
30
31 // fill vectors with state values from the transformed trajectory
32 std::vector<double> TIME, V, Y, A, THETA, DELTA;
33 for (int i = 0; i < trajectory_planning_msgs::trajectory_access::getSamplePointSize(tf_trajectory); i++) {
34 TIME.push_back(trajectory_planning_msgs::trajectory_access::getT(tf_trajectory, i));
35 Y.push_back(trajectory_planning_msgs::trajectory_access::getY(tf_trajectory, i));
36 V.push_back(trajectory_planning_msgs::trajectory_access::getV(tf_trajectory, i));
37 A.push_back(trajectory_planning_msgs::trajectory_access::getA(tf_trajectory, i));
38 THETA.push_back(trajectory_planning_msgs::trajectory_access::getTheta(tf_trajectory, i));
39 DELTA.push_back(trajectory_planning_msgs::trajectory_access::getDeltaAck(tf_trajectory, i));
40 }
41
42 // interpolate target states by time from the extracted vectors; if not successful, set to ego state (high-level initialization)
43 double v_tgt = 0.0, a_tgt = 0.0, y_tgt = 0.0, theta_tgt = 0.0, delta_tgt = 0.0;
44 double des_time = (rclcpp::Time(ego_data.header.stamp) - rclcpp::Time(tf_trajectory.header.stamp)).seconds();
45 if (!linearInterpolation(TIME, Y, des_time, y_tgt)) y_tgt = 0.0;
46 if (!linearInterpolation(TIME, V, des_time, v_tgt)) v_tgt = perception_msgs::object_access::getVelLon(ego_data);
47 if (!linearInterpolation(TIME, A, des_time, a_tgt)) a_tgt = perception_msgs::object_access::getAccLon(ego_data);
48 if (!linearInterpolation(TIME, THETA, des_time, theta_tgt, true)) theta_tgt = 0.0;
49 if (!linearInterpolation(TIME, DELTA, des_time, delta_tgt)) {
50 delta_tgt = perception_msgs::object_access::getSteeringAngleAck(ego_data);
51 }
52
53 RCLCPP_DEBUG(this->get_logger(), "y_tgt: %f, v_tgt: %f, a_tgt: %f, theta_tgt: %f, delta_tgt: %f", y_tgt, v_tgt, a_tgt,
54 theta_tgt, delta_tgt);
55
56 // handle thresholds for bi-level stabilization (which means, using ego state as initial state for the optimization)
57 // longitudinal reinits
58 if (fabs(v_tgt - perception_msgs::object_access::getVelLon(ego_data)) > bi_level_dV_) {
59 const auto ego_v = perception_msgs::object_access::getVelLon(ego_data);
60 const auto ego_a = perception_msgs::object_access::getAccLon(ego_data);
61 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);
62 v_tgt = ego_v;
63 a_tgt = ego_a;
64 }
65 // lateral reinits
66 if (fabs(y_tgt) > bi_level_dY_ || fabs(theta_tgt) > bi_level_dYaw_ * M_PI / 180.0) {
67 const auto ego_delta = perception_msgs::object_access::getSteeringAngleAck(ego_data);
68 RCLCPP_WARN(this->get_logger(),
69 "Lateral reinit: y_tgt: %f, theta_tgt: %f, delta_tgt: %f, ego_y: %f, ego_theta: %f, ego_delta: %f", y_tgt,
70 theta_tgt, delta_tgt, 0.0, 0.0, ego_delta);
71 y_tgt = 0.0;
72 theta_tgt = 0.0;
73 delta_tgt = ego_delta;
74 }
75
76 std::vector<double> x_init(*nlp_dims_->nx, 0.0);
77 x_init[0] = 0.0;
78 x_init[1] = y_tgt;
79 x_init[2] = 0.0;
80 x_init[3] = v_tgt;
81 x_init[4] = a_tgt;
82 x_init[5] = theta_tgt;
83 x_init[6] = delta_tgt;
84
85 return x_init;
86}
87
88std::vector<double> TrajectoryOptimizationAckermannNode::getHighLevelX0(const perception_msgs::msg::EgoData& ego_data) {
89 std::vector<double> x_init(*nlp_dims_->nx, 0.0);
90 x_init[3] = perception_msgs::object_access::getVelLon(ego_data);
91 x_init[4] = perception_msgs::object_access::getAccLon(ego_data);
92 x_init[6] = perception_msgs::object_access::getSteeringAngleAck(ego_data);
93
94 return x_init;
95}
96
97void TrajectoryOptimizationAckermannNode::convertToTrajectoryMsg(trajectory_planning_msgs::msg::Trajectory& trajectory) {
98 for (int i = 0; i <= n_shots_; ++i) {
99 trajectory_planning_msgs::trajectory_access::setX(trajectory, xtraj_[i * *nlp_dims_->nx + 0], i);
100 trajectory_planning_msgs::trajectory_access::setY(trajectory, xtraj_[i * *nlp_dims_->nx + 1], i);
101 trajectory_planning_msgs::trajectory_access::setS(trajectory, xtraj_[i * *nlp_dims_->nx + 2], i);
102 trajectory_planning_msgs::trajectory_access::setV(trajectory, xtraj_[i * *nlp_dims_->nx + 3], i);
103 trajectory_planning_msgs::trajectory_access::setA(trajectory, xtraj_[i * *nlp_dims_->nx + 4], i);
104 trajectory_planning_msgs::trajectory_access::setTheta(trajectory, xtraj_[i * *nlp_dims_->nx + 5], i);
105 trajectory_planning_msgs::trajectory_access::setDeltaAck(trajectory, xtraj_[i * *nlp_dims_->nx + 6], i);
106 }
107}
108
109} // namespace trajectory_optimization
void convertToTrajectoryMsg(trajectory_planning_msgs::msg::Trajectory &trajectory) override
Maps the optimized state trajectory into a trajectory message for a kinematic bicycle model with Acke...
std::vector< double > getBiLevelX0(const perception_msgs::msg::EgoData &ego_data) override
Computes the initial optimizer state using bi-level stabilizaion.
TrajectoryOptimizationAckermannNode(const rclcpp::NodeOptions &options)
Initializes the optimization node for a kinematic bicycle model with Ackermann steering.
void initializeTrajectory(trajectory_planning_msgs::msg::Trajectory &trajectory) override
Initializes a drivable trajectory message for a kinematic bicycle model with Ackermann steering.
std::vector< double > getHighLevelX0(const perception_msgs::msg::EgoData &ego_data) override
Computes the initial optimizer state using high-level stabilization.
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
Namespace for trajectory_optimization package.