Galaxis Codebase  1.0.0
Team Galaxis software stack for the Carolo Cup 2023 - ROS2 based software
DecisionStateMachine.cpp
Go to the documentation of this file.
2 
4 
5 #include "utils/logger.hpp"
6 using namespace galaxis::utils;
7 
8 Decision::Decision(rclcpp::Node* nodePtr) {
9  m_startDriving = false;
10 
11  // initial state
12  m_state.drivingLane = true;
13  m_state.indicatorLeft = false;
14  m_state.indicatorRight = false;
15  m_state.velocity = 0.f;
16  m_state.velocityOfWheelFeedback = 0.f;
17  m_state.timeLeftLaneBlocked = 0;
18  m_state.timeRightLaneBlocked = 0;
19  m_state.stopLineDistance = -1;
20 
21  m_nodePtr = nodePtr;
22 }
23 
24 void Decision::set_velocity_reference(float velocityReference) {
25  std::unique_lock<std::mutex> lock(m_mtx);
26  m_velocityReference = velocityReference;
27  m_state.velocity = m_velocityReference;
28 }
29 void Decision::set_velocity_reference_parking(float velocityReference) {
30  std::unique_lock<std::mutex> lock(m_mtx);
31  m_velocityAtParkingZone = velocityReference;
32 }
34  m_distanceAfterSwitchBackToLaneMeter = valueM;
35 }
37  m_criticalObstacleDistanceForLaneChangingCM = valueCM;
38 }
39 // void Decision::set_default_driving_lane(bool value) { // false = left, true = right
40 // if(value == false) log_warning("[Decision] default_driving_lane: This mode only works properly in free driving mode (without obstacles).");
41 // m_defaultDrivingLane = value;
42 // }
44  m_startDriving = true;
45 }
46 
47 
48 void Decision::update(std::shared_ptr<PositionTimepoint> positionTimepoint, std::tuple<float, float, float, float> laneBlocked) {
49  std::unique_lock<std::mutex> lock(m_mtx);
50 
51  DrivingState newState = m_state;
52  newState.timestamp = m_nodePtr->get_clock()->now().nanoseconds(); // warning: DO NOT use positionTimepoint timestamp
53  newState.velocityOfWheelFeedback = positionTimepoint->speed;
54 
55  // transition functions
56  auto toNormalDrive = [&]() {
57  log_cout("[Decision] toNormalDrive");
59  newState.drivingLane = true; // right lane
60  newState.velocity = m_velocityReference; // velocityReference
61  };
62  auto toObstacleEvasion = [&]() {
63  log_cout("[Decision] toObstacleEvasion");
65  newState.velocity = m_velocityReference * 0.75f;
66  };
67  auto toIntersection = [&]() {
68  if((newState.timestamp - newState.intersectionLastExitTime) < 3e9) {
69  newState.stopLineDistance = -1.f;
70  return;
71  }
72 
73  log_cout("[Decision] toIntersection");
75  newState.velocity = m_velocityReference;
76  newState.timeStopLineDetected = newState.timestamp;
77  };
78  auto toParkingZone = [&]() {
79  if((newState.timestamp - newState.timeStartTargetLineDetected) < 10e9 // prevent stopline detection 8 sec after last detected
80  || (newState.timestamp - newState.timeLastParkingDone) < 10e9 ) { // prevent 3sec from parking after parked
81  newState.startTargetDistance = -1.f;
82  return;
83  }
84 
85  log_cout("[Decision] toParkingZone");
87  newState.startTargetDistance = -1.f;
88  };
89  auto toParking = [&]() {
90  log_cout("[Decision] toParking");
92  newState.velocity = 1.6f; // TODO: increase velocity in parking mode
93  };
94 
95  bool cannotDriveOnLefLane = std::get<0>(laneBlocked) >= 0 && std::get<0>(laneBlocked) < m_criticalObstacleDistanceForLaneChangingCM;
96  bool cannotDriveOnRigLane = std::get<1>(laneBlocked) >= 0 && std::get<1>(laneBlocked) < m_criticalObstacleDistanceForLaneChangingCM;
97 
98  this->update_lanes(newState, cannotDriveOnLefLane, cannotDriveOnRigLane);
99 
100  // driving state properties and transistions
101  if(m_state.situationState == SituationState::WaitForStart) {
102  log_debug("[Decision] WaitForStart");
103  newState.velocity = 0.f;
104  if(m_startDriving) {
105  toNormalDrive();
106  }
107  }
108  else if (m_state.situationState == SituationState::NormalDrive) {
109  log_debug("[Decision] NormalDrive");
110  if(cannotDriveOnRigLane) {
111  toObstacleEvasion();
112  }
113  if(m_state.stopLineDistance >= 0 && m_state.stopLineDistance <= 1.f) { // stop line detected
114  toIntersection();
115  }
116  if(m_state.startTargetDistance >= 0 && m_state.startTargetDistance <= 1.f) { // start stop line detected
117  // if(m_state.parkingState == ParkingState::Idle) { // parking node is in idle // moved to parkingzone
118  toParkingZone();
119  // }
120  // else {
121  m_state.startTargetDistance = -1.f;
122  // }
123  }
124  }
125  else if (m_state.situationState == SituationState::ObstacleEvasion) {
126  log_debug("[Decision] ObstacleEvasion");
127  if(cannotDriveOnRigLane) { // right blocked -> drive on left
128  newState.velocity = m_velocityReference * 0.8f;
129  newState.drivingLane = false;
130 
131  if(cannotDriveOnLefLane) { // both lanes blocked -> drive very slow
132  if(std::get<0>(laneBlocked) < std::get<1>(laneBlocked)) {
133  newState.drivingLane = true;
134  }
135 
136  // if(std::get<0>(laneBlocked) < 0.4f && std::get<1>(laneBlocked) < 0.4f) {
137  // // newState.velocity = 0.f;
138  // }
139  // else {
140  // newState.velocity = m_velocityReference * 0.75f;
141  // }
142 
143  }
144 
145  this->switch_lane_if_possible(newState); // TODO maybe reenable
146  }
147  // else if (m_state.tofRightValue > 0.f && m_state.tofRightValue < 0.35f && m_state.drivingLane == false) { // right lane blocked detected by tof (not 3d cam)
148  // newState.drivingLane = false; // stay on left
149  // }
150  else { // back to normal mode
151  newState.drivingLane = true;
152  this->switch_lane_if_possible(newState); // sets driving lane to false if switch not possible
153  if(newState.drivingLane == true) {
154  toNormalDrive();
155  }
156  }
157  }
158  else if (m_state.situationState == SituationState::Intersection) {
159  log_debug("[Decision] Intersection");
160  log_cout("[Decision] Intersection\n - RightLaneObjectDistance: ", std::get<1>(laneBlocked), "\n - IntersectionRightBeforeLeftDistance: ", std::get<2>(laneBlocked));
161 
162  newState.velocity = 0.f; // always brake at intersection
163 
164  if((std::get<2>(laneBlocked) >= 0.f && std::get<2>(laneBlocked) <= 85.f)
165  || (std::get<0>(laneBlocked) >= 0 && std::get<0>(laneBlocked) <= 0.6f)
166  || (std::get<1>(laneBlocked) >= 0 && std::get<1>(laneBlocked) <= 0.6f)) {
167  newState.velocity = 0.f; // brake
168  }
169  else if (std::get<2>(laneBlocked) < 0.f && !cannotDriveOnRigLane && (std::get<3>(laneBlocked) < 0.f || std::get<3>(laneBlocked) > 0.5f)) {
170  if(newState.timestamp - m_state.timeInSituationState > 3e9) { // wait minimum 3s in state
171  newState.stopLineDistance = -1;
172  newState.intersectionLastExitTime = newState.timestamp;
173  toNormalDrive(); // TODO maybe state for: only straight driving within intersection
174  }
175  }
176  // if(newState.timestamp - newState.timeStopLineDetected > 3e9) { // timeout
177  // newState.stopLineDistance = -1;
178  // toNormalDrive();
179  // }
180  }
181  else if (m_state.situationState == SituationState::ParkingZone) {
182  log_debug("[Decision] ParkingZone");
183  if((m_state.parkingState == ParkingState::Idle || m_state.parkingState == ParkingState::Searching) && get_velocity_reference() > m_velocityAtParkingZone) {
184  newState.velocity = m_velocityAtParkingZone;
185  }
186  else {
187  newState.velocity = get_velocity_reference();
188  }
189 
190  if(m_stopAtStartLine && (newState.timestamp - m_state.timeInSituationState) < 1e9) {
191  newState.velocity = 0.f;
192  }
193 
194  if(newState.parkingState == ParkingState::InParking) {
195  toParking();
196  newState.startTargetDistance = -1.f;
197  }
198  if(newState.timestamp - m_state.timeInSituationState > 4e9) { // timeout
199  log_cout(std::to_string(newState.timestamp - m_state.timeInSituationState));
200  log_cout("[Decision] Parking: Searching TIMEOUT");
201  newState.parkingState = ParkingState::Off;
202  newState.startTargetDistance = -1.f;
203  toNormalDrive();
204  }
205  }
206  else if (m_state.situationState == SituationState::Parking) {
207  log_debug("[Decision] Parking");
208  if(newState.parkingState == ParkingState::Done) {
209  newState.parkingState = ParkingState::Off;
210  m_parkingTries++;
211  toNormalDrive();
212  }
213  // TODO: reenable timeout if parking place not found
214  if(newState.timestamp - m_state.timeInSituationState > 8e9) { // timeout
215  log_cout(std::to_string(newState.timestamp - m_state.timeInSituationState));
216  log_cout("[Decision] Parking: Parking TIMEOUT");
217  newState.parkingState = ParkingState::Off;
218  newState.timeLastParkingDone = newState.timestamp;
219  toNormalDrive();
220  }
221  }
222 
223  // set indicators based on new state (and last)
224  this->set_indicators(newState); // reference to state
225 
226  if(m_state.situationState != newState.situationState) {
227  newState.timeInSituationState = m_nodePtr->get_clock()->now().nanoseconds();
228  }
229 
230  // make persistent
231  m_state = newState;
232 }
233 
234 void Decision::update_stopline(float value) {
235  std::unique_lock<std::mutex> lock(m_mtx);
236  m_state.stopLineDistance = value;
237 }
238 
240  std::unique_lock<std::mutex> lock(m_mtx);
241  m_state.startTargetDistance = value;
242 }
243 
245  std::unique_lock<std::mutex> lock(m_mtx);
246  if(state == ParkingState::Searching && m_state.situationState == SituationState::ParkingZone && m_state.parkingState == ParkingState::Idle) {
247  m_state.parkingState = ParkingState::Searching;
248  }
249  else if(state == ParkingState::InParking && m_state.situationState == SituationState::ParkingZone && m_state.parkingState == ParkingState::Searching) {
250  m_state.parkingState = ParkingState::InParking;
251  }
252  else if(state == ParkingState::Done && m_state.situationState == SituationState::Parking) {
253  m_state.parkingState = state;
254  }
255  else if(state == ParkingState::Idle && m_state.situationState != SituationState::Parking) {
256  m_state.parkingState = state;
257  }
258  else {
259  // other states are handled via update function
260  log_warning("[Decision] Can NOT set this parking state: ", state);
261  }
262 }
263 
264 void Decision::update_tof(float right, float rear) {
265  std::unique_lock<std::mutex> lock(m_mtx);
266  m_state.tofRightValue = right;
267  m_state.tofRearValue = rear;
268 }
269 
270 void Decision::update_lanes(DrivingState& newState, bool leftLaneBlocked, bool rightLaneBlocked) {
271  if(leftLaneBlocked) newState.timeLeftLaneBlocked = newState.timestamp;
272  if(rightLaneBlocked) newState.timeRightLaneBlocked = newState.timestamp;
273 }
274 
276  if(m_state.drivingLane == false && newState.drivingLane == true) { // switch from left lane to right -> enable left indicator
277  newState.indicatorRight = true;
278  newState.timeIndicatorSet = newState.timestamp;
279 
280  newState.indicatorLeft = false;
281  }
282  if(m_state.drivingLane == true && newState.drivingLane == false) { // switch from left lane to right -> enable left indicator
283  newState.indicatorLeft = true;
284  newState.timeIndicatorSet = newState.timestamp;
285 
286  newState.indicatorRight = false;
287  }
288 
289  // disable indicators
290  // rclcpp::Duration keepIndicatorOnDuration(1, 500000000); // 1.5 sec
291  if(m_state.indicatorLeft == true || m_state.indicatorRight == true) {
292  if((newState.timestamp - newState.timeIndicatorSet) > 1500000000) { // 2.5sec
293  newState.indicatorLeft = false;
294  newState.indicatorRight = false;
295  }
296  }
297 }
298 
300  if(newState.drivingLane != m_state.drivingLane) {
301  if(newState.drivingLane == false) { // new lane is left
302  // log_cout("## LEFT");
303  // log_cout("Time [ns]",(newState.timestamp - m_state.timeLeftLaneBlocked));
304  // log_cout("Time [ns] / 1000: ", ((newState.timestamp - m_state.timeLeftLaneBlocked) / 1000000000.f));
305  // log_cout("CurrVelo [m/s]: ", (m_state.velocityOfWheelFeedback / 1000.f));
306  // log_cout("FINAL: ", ((newState.timestamp - m_state.timeLeftLaneBlocked) / 1000000000.f) * (m_state.velocityOfWheelFeedback / 1000.f));
307  if(((newState.timestamp - m_state.timeLeftLaneBlocked) / 1000000000.f) * (m_state.velocityOfWheelFeedback / 1000.f) < m_distanceAfterSwitchBackToLaneMeter) { // ns -> s (1e9) mm-> m (1000)
308  newState.drivingLane = m_state.drivingLane; // stay on right
309  }
310  }
311  else { // new lane is right
312  // log_cout("## RIGHT");
313  // log_cout("Time [ns]",(newState.timestamp - m_state.timeRightLaneBlocked));
314  // log_cout("Time [ns] / 1000: ", ((newState.timestamp - m_state.timeRightLaneBlocked) / 1000000000.f));
315  // log_cout("CurrVelo [m/s]: ", (m_state.velocityOfWheelFeedback / 1000.f));
316  // log_cout("FINAL: ", ((newState.timestamp - m_state.timeRightLaneBlocked) / 1000000000.f) * (m_state.velocityOfWheelFeedback / 1000.f));
317  if(((newState.timestamp - m_state.timeRightLaneBlocked) / 1000000000.f) * (m_state.velocityOfWheelFeedback / 1000.f) < m_distanceAfterSwitchBackToLaneMeter) { // ns -> s (1e9) mm-> m (1000)
318  newState.drivingLane = m_state.drivingLane; // stay on left
319  }
320  }
321  }
322 }
323 
325  return m_state.indicatorLeft;
326 }
328  return m_state.indicatorRight;
329 }
331  return m_state.drivingLane;
332 }
334  return m_state.velocity;
335 }
337  return m_state.velocity == 0.f;
338 }
340  std::unique_lock<std::mutex> lock(m_mtx);
341  return m_state.situationState;
342 }
Decision::update_lanes
void update_lanes(DrivingState &newState, bool leftLaneBlocked, bool rightLaneBlocked)
Definition: DecisionStateMachine.cpp:270
NormalDrive
@ NormalDrive
Definition: Decision.hpp:12
Decision::get_current_situationstate
SituationState get_current_situationstate()
Definition: DecisionStateMachine.cpp:339
Decision::Decision
Decision(rclcpp::Node *nodePtr)
Definition: DecisionStateMachine.cpp:8
Decision::start_driving
void start_driving()
Definition: DecisionStateMachine.cpp:43
Decision::get_velocity_reference
float get_velocity_reference() const
Definition: DecisionStateMachine.cpp:333
ParkingState
ParkingState
Definition: Decision.hpp:19
Decision::update_stopline
void update_stopline(float value)
Definition: DecisionStateMachine.cpp:234
Decision::set_indicators
void set_indicators(DrivingState &newState)
Definition: DecisionStateMachine.cpp:275
Decision::get_chosen_lane
bool get_chosen_lane() const
Definition: DecisionStateMachine.cpp:330
DrivingState::timeStopLineDetected
uint64_t timeStopLineDetected
Definition: Decision.hpp:44
galaxis::utils::log_warning
void log_warning(const Args &... args)
Definition: logger.hpp:41
Decision::update
void update(std::shared_ptr< PositionTimepoint > positionTimepoint, std::tuple< float, float, float, float > laneBlocked)
Definition: DecisionStateMachine.cpp:48
DrivingState::timeLastParkingDone
uint64_t timeLastParkingDone
Definition: Decision.hpp:50
Decision::get_indicator_right
bool get_indicator_right() const
Definition: DecisionStateMachine.cpp:327
DrivingState::stopLineDistance
float stopLineDistance
Definition: Decision.hpp:43
InParking
@ InParking
Definition: Decision.hpp:23
DrivingState::timeRightLaneBlocked
uint64_t timeRightLaneBlocked
Definition: Decision.hpp:37
DrivingState::indicatorRight
bool indicatorRight
Definition: Decision.hpp:40
DrivingState::timestamp
uint64_t timestamp
Definition: Decision.hpp:28
Decision::set_critical_obstacle_distance_for_lane_changing
void set_critical_obstacle_distance_for_lane_changing(int valueCM)
Definition: DecisionStateMachine.cpp:36
ParkingZone
@ ParkingZone
Definition: Decision.hpp:15
DrivingState::timeStartTargetLineDetected
uint64_t timeStartTargetLineDetected
Definition: Decision.hpp:48
Decision::get_indicator_left
bool get_indicator_left() const
Definition: DecisionStateMachine.cpp:324
Parking
@ Parking
Definition: Decision.hpp:16
DrivingState::timeInSituationState
uint64_t timeInSituationState
Definition: Decision.hpp:30
DrivingState::intersectionLastExitTime
uint64_t intersectionLastExitTime
Definition: Decision.hpp:45
DrivingState::velocity
float velocity
Definition: Decision.hpp:32
Decision::switch_lane_if_possible
void switch_lane_if_possible(DrivingState &newState)
Definition: DecisionStateMachine.cpp:299
DrivingState
Definition: Decision.hpp:27
Done
@ Done
Definition: Decision.hpp:24
Decision::set_velocity_reference
void set_velocity_reference(float velocityReference)
Definition: DecisionStateMachine.cpp:24
galaxis::utils::log_cout
void log_cout(const Args &... args)
Definition: logger.hpp:25
DrivingState::startTargetDistance
float startTargetDistance
Definition: Decision.hpp:47
ObstacleEvasion
@ ObstacleEvasion
Definition: Decision.hpp:13
Intersection
@ Intersection
Definition: Decision.hpp:14
DrivingState::drivingLane
bool drivingLane
Definition: Decision.hpp:35
DecisionStateMachine.hpp
Decision::set_velocity_reference_parking
void set_velocity_reference_parking(float velocityReference)
Definition: DecisionStateMachine.cpp:29
DrivingState::timeLeftLaneBlocked
uint64_t timeLeftLaneBlocked
Definition: Decision.hpp:36
DrivingState::parkingState
ParkingState parkingState
Definition: Decision.hpp:49
WaitForStart
@ WaitForStart
Definition: Decision.hpp:11
SituationState
SituationState
Definition: Decision.hpp:10
logger.hpp
Idle
@ Idle
Definition: Decision.hpp:21
galaxis::utils
Definition: clock.hpp:5
Searching
@ Searching
Definition: Decision.hpp:22
Decision::update_tof
void update_tof(float right, float rear)
Definition: DecisionStateMachine.cpp:264
Decision::get_brakes_enable
bool get_brakes_enable() const
Definition: DecisionStateMachine.cpp:336
Decision::update_starttargetline
void update_starttargetline(float value)
Definition: DecisionStateMachine.cpp:239
DrivingState::indicatorLeft
bool indicatorLeft
Definition: Decision.hpp:39
galaxis::utils::log_debug
void log_debug(const Args &... args)
Definition: logger.hpp:62
Decision::set_distance_after_switch_back_lane
void set_distance_after_switch_back_lane(float valueM)
Definition: DecisionStateMachine.cpp:33
Off
@ Off
Definition: Decision.hpp:20
AutopilotSettings.hpp
Decision::set_parking_state
void set_parking_state(ParkingState state)
Definition: DecisionStateMachine.cpp:244
DrivingState::timeIndicatorSet
uint64_t timeIndicatorSet
Definition: Decision.hpp:41
DrivingState::velocityOfWheelFeedback
float velocityOfWheelFeedback
Definition: Decision.hpp:33
DrivingState::situationState
SituationState situationState
Definition: Decision.hpp:29