Galaxis Codebase  1.0.0
Team Galaxis software stack for the Carolo Cup 2023 - ROS2 based software
control.cpp
Go to the documentation of this file.
1 #include "control/control.hpp"
2 
3 #include "utils/logger.hpp"
4 #include "utils/poly.hpp"
5 #include "utils/clock.hpp"
6 #include "control/pose.hpp"
7 
8 #include <exception>
9 #include <memory>
10 #include <math.h>
11 #include <vector>
12 
13 #include <Eigen/Dense>
14 
15 using namespace galaxis;
16 using namespace galaxis::utils;
17 using namespace galaxis::control;
18 
19 TwoAndAHalfCarrots::TwoAndAHalfCarrots(std::shared_ptr<std::vector<float>> const p_yawStepsSPtr, float p_horizonStepTimeSec, int p_horizon, int p_errorAccuracyStepsPerHorizon, float p_carWheelbase, float p_errorIncraseFactor) :
20  m_yawStepsSPtr(p_yawStepsSPtr) {
21  this->set_horizon(p_horizon);
22 
23  assert(m_horizonStepTimeSec > 0);
24  m_horizonStepTimeSec = p_horizonStepTimeSec;
25 
26  assert(p_carWheelbase > 0);
27  m_carWheelbase = p_carWheelbase;
28  m_errorIncraseFactor = p_errorIncraseFactor;
29 
30  assert(p_errorAccuracyStepsPerHorizon > 0);
31  m_errorAccuracyStepsPerHorizon = p_errorAccuracyStepsPerHorizon;
32 
33  //log("TwoAndAHalfCarrots \n - HorizonTimeStep: ", m_horizonStepTimeSec, "\n - Horizon: ", m_horizon, "\n - ErrorAccuracy (StepsPerHorizon): ", m_errorAccuracyStepsPerHorizon, "\n - Wheelbase: ", m_carWheelbase, "");
34 }
35 
36 void TwoAndAHalfCarrots::set_horizon(int p_horizon) {
37  if(p_horizon < 1) {
38  log_error();
39  throw std::invalid_argument("Invalid Horizon! Horizon must be greater than 0!");
40  } else if(p_horizon != 2) {
41  log_warning("TwoAndAHalfCarrots only supports horizon 2 at the moment!");
42  }
43 
44  m_horizon = p_horizon;
45 }
46 
48  if (valueSec > 0) {
49  m_horizonStepTimeSec = valueSec;
50  return true;
51  }
52  else {
53  return false;
54  }
55 }
56 
58  m_errorIncraseFactor = factor;
59 }
60 
62  if (value > 0) {
64  return true;
65  }
66  else {
67  return false;
68  }
69 }
70 
71 // calulates the best drive trajectory compared with reference trajectory and returns yaw rate (bzw. lenkwinkel)
72 // -> all trajectories are relative to the car
73 // -> Velocity must be in m/s
74 // -> assuming yaw rate is steering angle
75 // TODO: implement other horizons
76 float TwoAndAHalfCarrots::calculate_best_yaw_rate(std::shared_ptr<PolySpline> p_referenceTrajectorySPtr,
77  std::shared_ptr<line_markings_reference_t> p_lineMarkings,
78  float p_currentVelocity, CarPose p_pose) { // currentYawRate?
79  if(p_currentVelocity < 0) {
80  log_warning("Velocity below 0! Return last Yaw Rate and skip calculation.");
81  return m_lastYawRate;
82  }
83 
84  m_currentVelocity = p_currentVelocity;
85  float coveredDistancePerHorizonStep = m_currentVelocity * m_horizonStepTimeSec;
86 
87  float bestYawRate = 0;
88  float bestError = 100000000; // TODO: maybe set maximum error here -> then yaw rate = 0
89 
90  std::shared_ptr<CarPose> currentPose = std::make_shared<CarPose>(p_pose);
91 
92  // debug track calculation time
94 
95  for(auto const& yawStepH1: *m_yawStepsSPtr) {
96  std::shared_ptr<CarPoseSeries> firstPoseSeries = get_pose_series(currentPose, coveredDistancePerHorizonStep, yawStepH1, m_errorAccuracyStepsPerHorizon);
97  for(auto const& yawStepH2: *m_yawStepsSPtr) {
98  // calculate point series
99  std::shared_ptr<CarPoseSeries> secondPoseSeries = get_pose_series(firstPoseSeries->at(firstPoseSeries->size() - 1), coveredDistancePerHorizonStep, yawStepH2, m_errorAccuracyStepsPerHorizon);
100 
101  // calculate error
102  float error = calculate_error_between_polyspline_poseseries(p_referenceTrajectorySPtr, firstPoseSeries, p_lineMarkings, m_crossAngleErrorWeight, m_crossLineMarkingErrorWeight) * m_errorIncraseFactor;
103  error += calculate_error_between_polyspline_poseseries(p_referenceTrajectorySPtr, secondPoseSeries, p_lineMarkings, m_crossAngleErrorWeight, m_crossLineMarkingErrorWeight);
104 
105  if(error < bestError) {
106  bestYawRate = yawStepH1;
107  bestError = error;
108 
109  m_lastFirstPoseSeries = firstPoseSeries;
110  m_lastSecondPoseSeries = secondPoseSeries;
111  }
112  }
113  }
114 
115  // debug print calculation time
116  long long time = m_debugStopwatch.get_time();
117  log("[CONTROL] Yaw Calculation Time [microsec]: ", time, "");
118 
119  m_lastYawRate = bestYawRate;
120  return bestYawRate;
121 }
122 
123 std::shared_ptr<CarPoseSeries> TwoAndAHalfCarrots::get_pose_series(std::shared_ptr<CarPose> const p_currentPoseSPtr, float p_distance, float p_yawRate, int p_steps) {
124  if(p_steps < 1) {
125  log_error("[CONTROL] Step Amount below 1.");
126  throw std::runtime_error("TwoAndAHalfCarrots::get_pose_series: Step amount below 1.");
127  }
128 
129  std::shared_ptr<CarPoseSeries> series = std::make_shared<CarPoseSeries>();
130  series->push_back(p_currentPoseSPtr); // start pose
131 
132  float step_distance = p_distance / static_cast<float>(p_steps);
133  for(int i = 0; i < p_steps; ++i) {
134  series->push_back(galaxis::control::get_new_pose(series->at(i), m_carWheelbase, step_distance, p_yawRate));
135  }
136 
137  return series;
138 }
139 
140 std::shared_ptr<CarPoseSeries const> TwoAndAHalfCarrots::get_last_first_poseseries() const {
141  if(m_lastFirstPoseSeries == nullptr) {
142  log_warning("LastFirstPoseSeries is nullptr");
143  }
144  return m_lastFirstPoseSeries;
145 }
146 
147 std::shared_ptr<CarPoseSeries const> TwoAndAHalfCarrots::get_last_second_poseseries() const {
148  if(m_lastSecondPoseSeries == nullptr) {
149  log_warning("LastSecondPoseSeries is nullptr");
150  }
151  return m_lastSecondPoseSeries;
152 }
153 
155  return m_lastYawRate;
156 }
157 
160 }
163 }
164 
165 // based on single-track model
166 // distance in m, yawrate in radians
167 // TODO: switch to millimeter
168 std::shared_ptr<CarPose> galaxis::control::get_new_pose(std::shared_ptr<CarPose> const p_currentPoseSPtr, float p_carWheelbase, float p_distance, float p_yawDiff) {
169  std::shared_ptr<CarPose> newPoseSPtr = std::make_shared<CarPose>();
170  newPoseSPtr->position = p_currentPoseSPtr->position;
171  newPoseSPtr->orientation = p_currentPoseSPtr->orientation;
172 
173  Eigen::Rotation2Df rotation(p_currentPoseSPtr->orientation);
174 
175  // filter edge case
176  if(std::sin(p_yawDiff) == 0) {
177  Eigen::Vector2f distance(p_distance, 0);
178  newPoseSPtr->position += rotation * distance;
179  return newPoseSPtr;
180  }
181 
182  // r = L/sin(steering_angle)
183  float radiusOfSteeringCircle = p_carWheelbase / std::sin(p_yawDiff);
184  // U = 2PI * r
185  float steeringCircumference = 2 * MATH_PI * radiusOfSteeringCircle;
186  // angle = distance / circumference * 2PI
187  float circleDrivenAngle = p_distance / steeringCircumference * 2 * MATH_PI;
188 
189  float directDistanceBetweenStartAndNewPose = 2 * std::sin(circleDrivenAngle / 2) * radiusOfSteeringCircle;
190 
191  Eigen::Vector2f position(0, 0);
192  position[0] = directDistanceBetweenStartAndNewPose * std::cos(circleDrivenAngle / 2);
193  position[1] = directDistanceBetweenStartAndNewPose * std::sin(circleDrivenAngle / 2);
194 
195  // Rotate new position with old orientation
196  position = rotation * position;
197 
198  newPoseSPtr->position += position;
199  newPoseSPtr->orientation += circleDrivenAngle;
200 
201  return newPoseSPtr;
202 }
galaxis::calculate_error_between_polyspline_poseseries
float calculate_error_between_polyspline_poseseries(shared_ptr< PolySpline > p_polySplineSPtr, shared_ptr< galaxis::control::CarPoseSeries > p_poseSeriesSPtr, shared_ptr< line_markings_reference_t > p_lineMarkings, float cross_angle_weight, float cross_line_weight)
Definition: poly.cpp:136
galaxis::control::TwoAndAHalfCarrots::m_currentVelocity
float m_currentVelocity
Definition: control.hpp:41
galaxis::utils::log_error
void log_error(const Args &... args)
Definition: logger.hpp:50
galaxis::control::TwoAndAHalfCarrots::m_carWheelbase
float m_carWheelbase
Definition: control.hpp:37
galaxis::control::TwoAndAHalfCarrots::m_lastFirstPoseSeries
std::shared_ptr< CarPoseSeries > m_lastFirstPoseSeries
Definition: control.hpp:46
galaxis::control::TwoAndAHalfCarrots::set_cross_line_marking_error_weight
void set_cross_line_marking_error_weight(float val)
Definition: control.cpp:161
galaxis::control::TwoAndAHalfCarrots::calculate_best_yaw_rate
float calculate_best_yaw_rate(std::shared_ptr< PolySpline > p_referenceTrajectorySPtr, std::shared_ptr< line_markings_reference_t > p_lineMarkings, float p_currentVelocity, CarPose p_pose=CarPose())
Definition: control.cpp:76
galaxis::control::TwoAndAHalfCarrots::set_error_factor_first_horizon
bool set_error_factor_first_horizon(float factor)
Definition: control.cpp:57
galaxis::utils::log_warning
void log_warning(const Args &... args)
Definition: logger.hpp:41
clock.hpp
galaxis::control::TwoAndAHalfCarrots::m_crossAngleErrorWeight
float m_crossAngleErrorWeight
Definition: control.hpp:34
pose.hpp
galaxis::control::TwoAndAHalfCarrots::get_last_first_poseseries
std::shared_ptr< CarPoseSeries const > get_last_first_poseseries() const
Definition: control.cpp:140
galaxis::control::TwoAndAHalfCarrots::m_lastSecondPoseSeries
std::shared_ptr< CarPoseSeries > m_lastSecondPoseSeries
Definition: control.hpp:47
galaxis::control::TwoAndAHalfCarrots::m_yawStepsSPtr
const std::shared_ptr< std::vector< float > > m_yawStepsSPtr
Definition: control.hpp:32
control.hpp
poly.hpp
galaxis::control::TwoAndAHalfCarrots::m_debugStopwatch
MicroStopwatch m_debugStopwatch
Definition: control.hpp:45
galaxis::utils::MicroStopwatch::start
void start()
Definition: clock.cpp:25
galaxis::utils::MicroStopwatch::get_time
long long get_time() const
Definition: clock.cpp:33
galaxis::control::TwoAndAHalfCarrots::get_last_second_poseseries
std::shared_ptr< CarPoseSeries const > get_last_second_poseseries() const
Definition: control.cpp:147
galaxis::control::TwoAndAHalfCarrots::m_errorAccuracyStepsPerHorizon
int m_errorAccuracyStepsPerHorizon
Definition: control.hpp:31
galaxis
Definition: MapClasses.hpp:10
galaxis::lina::Vector2f
Eigen::Vector2f Vector2f
Definition: linatypes.hpp:14
galaxis::control
Definition: control.hpp:24
galaxis::control::TwoAndAHalfCarrots::set_horizon
void set_horizon(int p_horizon)
Definition: control.cpp:36
galaxis::control::TwoAndAHalfCarrots::m_lastYawRate
float m_lastYawRate
Definition: control.hpp:40
galaxis::control::TwoAndAHalfCarrots::set_cross_angle_error_weight
void set_cross_angle_error_weight(float val)
Definition: control.cpp:158
logger.hpp
galaxis::control::TwoAndAHalfCarrots::set_error_accuracy_steps_per_horizon
bool set_error_accuracy_steps_per_horizon(int value)
Definition: control.cpp:61
galaxis::control::TwoAndAHalfCarrots::get_pose_series
std::shared_ptr< CarPoseSeries > get_pose_series(std::shared_ptr< CarPose > const p_currentPoseSPtr, float p_distance, float p_yawRate, int p_steps)
Definition: control.cpp:123
galaxis::utils
Definition: clock.hpp:5
galaxis::control::TwoAndAHalfCarrots::m_crossLineMarkingErrorWeight
float m_crossLineMarkingErrorWeight
Definition: control.hpp:35
galaxis::control::TwoAndAHalfCarrots::get_last_best_yaw_rate
float get_last_best_yaw_rate() const
Definition: control.cpp:154
galaxis::control::TwoAndAHalfCarrots::m_errorIncraseFactor
float m_errorIncraseFactor
Definition: control.hpp:38
galaxis::control::CarPose
Definition: pose.hpp:11
MATH_PI
constexpr float MATH_PI
Definition: control.hpp:16
galaxis::utils::log
void log(const Args &... args)
Definition: logger.hpp:33
galaxis::control::get_new_pose
std::shared_ptr< CarPose > get_new_pose(std::shared_ptr< CarPose > const p_currentPoseSPtr, float p_carWheelbase, float p_distance, float p_yawDiff)
Definition: control.cpp:168
galaxis::control::TwoAndAHalfCarrots::m_horizonStepTimeSec
float m_horizonStepTimeSec
Definition: control.hpp:42
galaxis::control::TwoAndAHalfCarrots::m_horizon
int m_horizon
Definition: control.hpp:30
galaxis::control::TwoAndAHalfCarrots::set_horizon_step_time
bool set_horizon_step_time(float valueSec)
Definition: control.cpp:47