trajectory_optimization v1.3.1
Loading...
Searching...
No Matches
trajectory_optimization_node.hpp
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#pragma once
5
6#include <tracetools/tracetools.h>
7#include <Eigen/Dense>
8#include <rclcpp/rclcpp.hpp>
9#include <std_msgs/msg/int32.hpp>
10#include <vector>
11#include <visualization_msgs/msg/marker_array.hpp>
12
13// definitions
14#include <perception_msgs/msg/ego_data.hpp>
15#include <perception_msgs/msg/object_list.hpp>
16#include <route_planning_msgs/msg/route.hpp>
17#include <trajectory_planning_msgs/msg/trajectory.hpp>
18
19// access functions
20#include <perception_msgs_utils/object_access.hpp>
21#include <route_planning_msgs_utils/route_access.hpp>
22#include <trajectory_planning_msgs_utils/trajectory_access.hpp>
23
24// tf2
25#include <tf2_ros/buffer.h>
26#include <tf2_ros/transform_listener.h>
27#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
28#include <tf2_perception_msgs/tf2_perception_msgs.hpp>
29#include <tf2_route_planning_msgs/tf2_route_planning_msgs.hpp>
30#include <tf2_trajectory_planning_msgs/tf2_trajectory_planning_msgs.hpp>
31
32// acados
35
37
38template <typename C>
39struct is_vector : std::false_type {};
40template <typename T, typename A>
41struct is_vector<std::vector<T, A>> : std::true_type {};
42template <typename C>
43inline constexpr bool is_vector_v = is_vector<C>::value;
44
45class TrajectoryOptimizationNode : public rclcpp::Node {
46 public:
53 explicit TrajectoryOptimizationNode(const std::string node_name, const rclcpp::NodeOptions& options);
54
59
64
71
76
83
84 protected:
86
88
104 template <typename T>
105 void declareAndLoadParameter(const std::string& name,
106 T& param,
107 const std::string& description,
108 const bool add_to_auto_reconfigurable_params = true,
109 const bool is_required = false,
110 const bool read_only = false,
111 const std::optional<double>& from_value = std::nullopt,
112 const std::optional<double>& to_value = std::nullopt,
113 const std::optional<double>& step_value = std::nullopt,
114 const std::string& additional_constraints = "");
115
122 rcl_interfaces::msg::SetParametersResult parametersCallback(const std::vector<rclcpp::Parameter>& parameters);
123
127 void setup();
128
132 void resetSolver();
133
141 bool setInitialGuess(const std::vector<double>& x_init, const rclcpp::Time& stamp);
142
146 void setupSolver();
147
151 void freeSolver();
152
158 void printSolution(const PerformanceMetrics& metrics);
159
165 void logPerformance(const PerformanceMetrics& metrics);
166
173 bool trajectory2outputFrame(trajectory_planning_msgs::msg::Trajectory& trajectory);
174
183 static double wrap_angle_rad(double angle_rad, double min_val = -M_PI, double max_val = M_PI);
184
195 bool linearInterpolation(const std::vector<double>& X,
196 const std::vector<double>& Y,
197 const double& desired_x,
198 double& output_y,
199 const bool wrap_angle = false);
200
206 void egoDataCallback(const perception_msgs::msg::EgoData::ConstSharedPtr msg);
207
213 void objectListCallback(const perception_msgs::msg::ObjectList::ConstSharedPtr msg);
214
220 void referenceTrajectoryCallback(const trajectory_planning_msgs::msg::Trajectory::ConstSharedPtr msg);
221
227 void routeCallback(const route_planning_msgs::msg::Route::ConstSharedPtr msg);
228
232 void planningCycle();
233
244 bool updateOcpInputs(const perception_msgs::msg::EgoData& ego_data,
245 const perception_msgs::msg::ObjectList& object_list,
246 const route_planning_msgs::msg::Route& route,
247 const trajectory_planning_msgs::msg::Trajectory& reference_trajectory,
248 const std::vector<double>& x_init);
249
257 void setOcpGlobalParameters(const std::vector<double>& cost_weights,
258 const trajectory_planning_msgs::msg::Trajectory& reference_trajectory,
259 const route_planning_msgs::msg::Route& route);
260
267 void setOcpParameters(const perception_msgs::msg::EgoData& ego_data, const perception_msgs::msg::ObjectList& object_list);
268
276 std::vector<std::pair<double, double>> normalBoundaryDistance(
277 const trajectory_planning_msgs::msg::Trajectory& reference_trajectory, const route_planning_msgs::msg::Route& route);
278
285 static void keepNClosestObjects(perception_msgs::msg::ObjectList& object_list, const int n_objects);
286
297 std::vector<double> discretizeBB2Circles(
298 const double x, const double y, const double yaw, const double length, const double width);
299
305 void vizCircles(const std::vector<double>& obstacles);
306
313 void vizEgoCircles(const std::vector<double>& x_trajectory, const std::string& model_name);
314
321 void vizBoundaryPoints(const std::vector<Eigen::Vector2d>& left_boundary_points,
322 const std::vector<Eigen::Vector2d>& right_boundary_points);
323
324 // virtual functions need to be implemented in derived classes
325
331 virtual void initializeTrajectory(trajectory_planning_msgs::msg::Trajectory& trajectory) = 0;
332
344 virtual std::vector<double> getBiLevelX0(const perception_msgs::msg::EgoData& ego_data) = 0;
345
355 virtual std::vector<double> getHighLevelX0(const perception_msgs::msg::EgoData& ego_data) = 0;
356
362 virtual void convertToTrajectoryMsg(trajectory_planning_msgs::msg::Trajectory& trajectory) = 0;
363
364 OnSetParametersCallbackHandle::SharedPtr parameters_callback_;
365
366 rclcpp::Subscription<perception_msgs::msg::EgoData>::SharedPtr ego_data_sub_;
367 rclcpp::Subscription<perception_msgs::msg::ObjectList>::SharedPtr object_list_sub_;
368 rclcpp::Subscription<route_planning_msgs::msg::Route>::SharedPtr route_sub_;
369 rclcpp::Subscription<trajectory_planning_msgs::msg::Trajectory>::SharedPtr reference_trajectory_sub_;
370
371 rclcpp::Publisher<trajectory_planning_msgs::msg::Trajectory>::SharedPtr trajectory_pub_;
372 rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr circles_pub_;
373 rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr ego_circles_pub_;
374 rclcpp::Publisher<visualization_msgs::msg::MarkerArray>::SharedPtr boundary_pub_;
375
376 rclcpp::TimerBase::SharedPtr planning_timer_;
377
378 std::unique_ptr<tf2_ros::Buffer> tf2_buffer_;
379 std::shared_ptr<tf2_ros::TransformListener> tf2_listener_;
380
381 // input data
382 perception_msgs::msg::EgoData ego_data_;
383 perception_msgs::msg::ObjectList object_list_;
384 route_planning_msgs::msg::Route route_;
385 trajectory_planning_msgs::msg::Trajectory reference_trajectory_;
386
387 // parameters
388 std::vector<std::tuple<std::string, std::function<void(const rclcpp::Parameter&)>>> auto_reconfigurable_params_;
389 std::string vehicle_frame_id_ = "base_link";
390 std::string trajectory_frame_id_ = "base_link";
391 std::string fixed_over_time_frame_id_ = "map";
392 std::string model_name_ = "karl";
393 double ego_data_timeout_ = 1.0;
394 double optimization_freq_ = 10.0;
395 int n_shots_ = 50;
397 bool verbose_ = false;
399 bool debug_viz_ = false;
402 bool add_x_init_to_ref_ = false;
405 bool run_as_callback_ = false;
406
407 // common bi-level thresholds
408 double bi_level_dV_ = 5.0;
409 double bi_level_dA_ = 2.0;
410 double bi_level_dY_ = 0.1;
411 double bi_level_dYaw_ = 5.0;
412
413 // latest valid trajectory
414 trajectory_planning_msgs::msg::Trajectory latest_valid_trajectory_;
415
416 // controls of the latest accepted solution; an empty vector denotes that no warm start is available
417 std::vector<double> control_guess_;
418 rclcpp::Time control_guess_stamp_{0, 0, RCL_ROS_TIME};
419
420 // visualization
421 std::vector<double> viz_circles_;
422
423 // cost weights
424 std::vector<double> cost_weights_ = std::vector<double>(12, 1.0);
425 double dynamic_weight_ = 1.0;
426 double thw_ = 2.0;
431
432 // ocp parameter vector structure
433 // attention: changes here must also be done in the OCP!
434 std::vector<int64_t> p_cost_weights_shape_ = {12, 1}; // nWeights x weightDim
435 std::vector<int64_t> p_ref_path_shape_ = {51, 6}; // nStates x [psi, x, y, v, d_bound_left, d_bound_right]
436 std::vector<int64_t> p_obstacle_circles_shape_ = {30, 3}; // nObstacleCircles x [x, y, radius]
437
438 // ocp variables
440 ocp_nlp_config* nlp_config_;
441 ocp_nlp_dims* nlp_dims_;
442 ocp_nlp_in* nlp_in_;
443 ocp_nlp_out* nlp_out_;
444 ocp_nlp_solver* nlp_solver_;
446
447 std::vector<double> xtraj_;
448 std::vector<double> utraj_;
449 uint64_t logging_cycle_ = 0;
450 std::unique_ptr<PerformanceLogger> performance_logger_;
451};
452
453} // namespace trajectory_optimization
static void keepNClosestObjects(perception_msgs::msg::ObjectList &object_list, const int n_objects)
Keeps the nearest forward objects and discards the remaining entries.
Definition utils.cpp:86
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr circles_pub_
TrajectoryOptimizationNode & operator=(const TrajectoryOptimizationNode &)=delete
Copy assignment is disabled because the node owns non-copyable runtime resources.
void printSolution(const PerformanceMetrics &metrics)
Logs solver status and optional debug statistics for the last optimization run.
Definition utils.cpp:441
void setupSolver()
Creates the acados solver instance and initializes its state buffers.
trajectory_planning_msgs::msg::Trajectory reference_trajectory_
void setup()
Creates ROS interfaces, initializes cached messages and prepares the solver.
TrajectoryOptimizationNode & operator=(TrajectoryOptimizationNode &&)=delete
Move assignment is disabled to keep solver and ROS handles bound to a single instance.
void routeCallback(const route_planning_msgs::msg::Route::ConstSharedPtr msg)
Stores the current route used for boundary constraints when enabled.
Definition callbacks.cpp:31
void freeSolver()
Frees the acados solver and clears cached optimization results.
trajectory_planning_msgs::msg::Trajectory latest_valid_trajectory_
void vizCircles(const std::vector< double > &obstacles)
Publishes visualization markers for the obstacle circles currently used by the optimizer.
Definition utils.cpp:338
TrajectoryOptimizationNode(const TrajectoryOptimizationNode &)=delete
Copy construction is disabled because the node owns non-copyable runtime resources.
virtual void initializeTrajectory(trajectory_planning_msgs::msg::Trajectory &trajectory)=0
Initializes an output trajectory message with the model-specific message type and size.
void logPerformance(const PerformanceMetrics &metrics)
Emits one machine-readable performance record when performance logging is enabled.
Definition utils.cpp:475
static double wrap_angle_rad(double angle_rad, double min_val=-M_PI, double max_val=M_PI)
Wraps an angle into a configured interval.
Definition utils.cpp:14
void setOcpParameters(const perception_msgs::msg::EgoData &ego_data, const perception_msgs::msg::ObjectList &object_list)
Writes stage-wise obstacle and dynamic weighting parameters into the OCP.
virtual void convertToTrajectoryMsg(trajectory_planning_msgs::msg::Trajectory &trajectory)=0
Maps the optimized state trajectory into the model-specific output message fields.
void objectListCallback(const perception_msgs::msg::ObjectList::ConstSharedPtr msg)
Stores the current object list when object handling is enabled.
Definition callbacks.cpp:12
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
bool updateOcpInputs(const perception_msgs::msg::EgoData &ego_data, const perception_msgs::msg::ObjectList &object_list, const route_planning_msgs::msg::Route &route, const trajectory_planning_msgs::msg::Trajectory &reference_trajectory, const std::vector< double > &x_init)
Transforms external inputs into the optimizer frame and writes them into the OCP.
void egoDataCallback(const perception_msgs::msg::EgoData::ConstSharedPtr msg)
Stores the latest ego state used by the optimizer.
Definition callbacks.cpp:7
void vizEgoCircles(const std::vector< double > &x_trajectory, const std::string &model_name)
Publishes the ego-vehicle circle approximation used by the selected OCP model.
Definition utils.cpp:361
void planningCycle()
Runs one full planning cycle from input preparation, over solver execution, to trajectory publication...
std::vector< std::tuple< std::string, std::function< void(const rclcpp::Parameter &)> > > auto_reconfigurable_params_
bool trajectory2outputFrame(trajectory_planning_msgs::msg::Trajectory &trajectory)
Transforms the planned trajectory into the configured output frame (trajectory_frame_id_) if required...
Definition utils.cpp:71
rclcpp::Subscription< route_planning_msgs::msg::Route >::SharedPtr route_sub_
rcl_interfaces::msg::SetParametersResult parametersCallback(const std::vector< rclcpp::Parameter > &parameters)
Applies parameter updates that can be reconfigured while the node is running.
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr boundary_pub_
std::vector< std::pair< double, double > > normalBoundaryDistance(const trajectory_planning_msgs::msg::Trajectory &reference_trajectory, const route_planning_msgs::msg::Route &route)
Computes minimum normal distances from the reference path to the active route boundaries.
Definition utils.cpp:154
virtual std::vector< double > getBiLevelX0(const perception_msgs::msg::EgoData &ego_data)=0
Computes the initial optimizer state using bi-level stabilizaion based on the model-specific EgoData ...
rclcpp::Subscription< perception_msgs::msg::EgoData >::SharedPtr ego_data_sub_
TrajectoryOptimizationNode(const std::string node_name, const rclcpp::NodeOptions &options)
Initializes the base node and loads the common optimizer configuration.
rclcpp::Publisher< visualization_msgs::msg::MarkerArray >::SharedPtr ego_circles_pub_
void vizBoundaryPoints(const std::vector< Eigen::Vector2d > &left_boundary_points, const std::vector< Eigen::Vector2d > &right_boundary_points)
Publishes the boundary intersections corresponding to the distances passed to the OCP.
Definition utils.cpp:301
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.
rclcpp::Subscription< perception_msgs::msg::ObjectList >::SharedPtr object_list_sub_
void referenceTrajectoryCallback(const trajectory_planning_msgs::msg::Trajectory::ConstSharedPtr msg)
Updates the reference trajectory and optionally triggers optimization immediately.
Definition callbacks.cpp:22
~TrajectoryOptimizationNode() override
Releases solver resources owned by the node.
rclcpp::Publisher< trajectory_planning_msgs::msg::Trajectory >::SharedPtr trajectory_pub_
std::shared_ptr< tf2_ros::TransformListener > tf2_listener_
TrajectoryOptimizationNode(TrajectoryOptimizationNode &&)=delete
Move construction is disabled to keep solver and ROS handles bound to a single instance.
std::vector< double > discretizeBB2Circles(const double x, const double y, const double yaw, const double length, const double width)
Approximates an oriented bounding box with a set of obstacle circles.
Definition utils.cpp:116
rclcpp::Subscription< trajectory_planning_msgs::msg::Trajectory >::SharedPtr reference_trajectory_sub_
void setOcpGlobalParameters(const std::vector< double > &cost_weights, const trajectory_planning_msgs::msg::Trajectory &reference_trajectory, const route_planning_msgs::msg::Route &route)
Writes stage-independent data into the OCP.
bool setInitialGuess(const std::vector< double > &x_init, const rclcpp::Time &stamp)
Builds and sets a dynamically consistent NLP initial guess from the current state and cached controls...
void resetSolver()
Resets the optimizer memory while retaining the generated solver instance.
virtual std::vector< double > getHighLevelX0(const perception_msgs::msg::EgoData &ego_data)=0
Computes the initial optimizer state using high-level stabilization based on the model-specific EgoDa...
Namespace for trajectory_optimization package.
std::variant< karl_solver_capsule *, shuttle_solver_capsule * > ocp_model_capsule_t