ADORe
ADORe is a modular open source software library and toolkit for decision making, planning, control and simulation of automated vehicles
tactical_planner.h
Go to the documentation of this file.
1 /********************************************************************************
2  * Copyright (C) 2017-2020 German Aerospace Center (DLR).
3  * Eclipse ADORe, Automated Driving Open Research https://eclipse.org/adore
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License 2.0 which is available at
7  * http://www.eclipse.org/legal/epl-2.0.
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  * Thomas Lobig - initial implementation
13  * Daniel Heß - added automatic control/reset logic, indicators, propositions
14  * - selection via parametrizable weighted sum
15  * - integrated dispatcher
16  ********************************************************************************/
17 
18 #pragma once
19 
20 #include <adore/env/afactory.h>
22 #include <adore/env/afactory.h>
25 #include <adore/fun/afactory.h>
27 #include <adore/params/afactory.h>
28 #include <adore/view/alane.h>
29 
38 #include <adore/fun/turnstate.h>
39 
40 namespace adore
41 {
42  namespace apps
43  {
48  {
61  uint64_t iteration_;
65  double last_time_;
66  double cost_bound_;
68  // TODO compound the following into a user input observer object
73  std::string cost_bound_name_;
80 
81  public:
83 
88  TacticalPlanner(double iteration_time_length)
89  {
90  iteration_time_length_ = iteration_time_length;
91  iteration_ = 0u;
95  request_writer_ = adore::fun::FunFactoryInstance::get()->getPlanningRequestWriter();
96  result_reader_ = adore::fun::FunFactoryInstance::get()->getPlanningResultFeed();
97  select_writer_ = adore::fun::FunFactoryInstance::get()->getPlanningSelectWriter();
102  langechange_suppression_reader_ = adore::fun::FunFactoryInstance::get()->getLanechangeSuppressionReader();
103  force_langechange_left_reader_ = adore::fun::FunFactoryInstance::get()->getForceLanechangeLeftReader();
104  force_langechange_right_reader_ = adore::fun::FunFactoryInstance::get()->getForceLanechangeRightReader();
105  force_slow_maneuvers_reader_ = adore::fun::FunFactoryInstance::get()->getForceSlowManeuversReader();
106 
107  last_time_ = 0.0;
109  cost_bound_guard_ = 1.e99;
111  cost_bound_name_ = "MinimumNavigationCostOnLane";//@TODO HeD 20210917: replace with parameter
112  }
113 
115  {
116  delete pTrajectoryGeneration_;
117  delete request_writer_;
118  delete result_reader_;
119  delete vehicle_state_reader_;
120  delete proposition_writer_;
121  }
122 
127  void run()
128  {
129  //update current vehicle state
130  if(!vehicle_state_reader_->hasData())return;
133  if(x.getTime()==last_time_)
134  {
135  return;
136  }
137  //else
138  last_time_ = x.getTime();
139 
140  if (x.getvx()<pTacticalPlanner_->getLVResetVelocity())
141  {
143  }
144 
145 
146  //retrieve planning results received before current iteration
147  adore::fun::PlanningResultMap valid_results;
148  std::vector<adore::fun::PlanningResult> available_results;
149  adore::fun::Turnstate turnstate;
150  turnstate = adore::fun::Turnstate::off;
152  {
153  turnstate = adore::fun::Turnstate::right;
154  }
156  {
157  turnstate = adore::fun::Turnstate::left;
158  }
159 
160  // handle signal to suppress lanechanges
161  bool suppress_lanechanges = false;
163  {
164  // if (x.getTime() > lanechange_supression_timeout_)
165  // {
166  langechange_suppression_reader_->getData(suppress_lanechanges);
167  if (suppress_lanechanges) // should always be true, but just to be sure check this
168  {
172  }
173  // }
174  // else
175  // {
176  // std::cout << "Ignored Lanechange Suppression Signal due to timeout"
177  // }
178  }
179  if (x.getTime() < lanechange_supression_timeout_)
180  {
181  // if the time is before the timeout, suppression is still true
182  suppress_lanechanges = true;
183  }
184 
185  bool force_lanechange_left = false;
187  {
188  force_langechange_left_reader_->getData(force_lanechange_left);
189  if (force_lanechange_left) // should always be true, but just to be sure check this
190  {
192  }
193  }
194  if (x.getTime() < force_langechange_left_timeout_)
195  {
196  force_lanechange_left = true;
197  }
198 
199  bool force_lanechange_right = false;
201  {
202  force_langechange_right_reader_->getData(force_lanechange_right);
203  if (force_lanechange_right) // should always be true, but just to be sure check this
204  {
207  }
208  }
209  if (x.getTime() < force_langechange_right_timeout_)
210  {
211  force_lanechange_right = true;
212  }
213 
214  bool force_slow_maneuvers = false;
216  {
217  force_slow_maneuvers_reader_->getData(force_slow_maneuvers);
218  if (force_slow_maneuvers) // should always be true, but just to be sure check this
219  {
222  }
223  }
224  if (x.getTime() < force_slow_maneuver_timeout_)
225  {
226  force_slow_maneuvers = true;
227  }
228 
229  // if (turn_signal_observer_.newManualLeftIndicatorOnEvent() || turn_signal_observer_.newManualRightIndicatorOnEvent())
230  // {
231  // lane_view_reset_writer_->write(true);
232  // }
233 
234  while(result_reader_->hasNext())
235  {
237  result_reader_->getNext(result);
238  bool valid = true;
239  bool isLCL = false;
240  bool isLCR = false;
241 
242 
243 
244  if(result.iteration != iteration_)
245  {
246  result.status_string = "wrong iteration; "+result.status_string;
247  valid = false;
248  }
249  if(!result.combined_maneuver_valid)
250  {
251  valid = false;
252  }
253  if(!(result.getObjectiveValue(cost_bound_name_,cost_bound_guard_)<=cost_bound_))//expr. !(.<=.) is used to filter nan values
254  {
255  result.status_string = "cost bound exceeded; "+result.status_string;
256  valid = false;
257  }
258 
259  if(result.name.find("lcr") != std::string::npos)
260  {
261  isLCR = true;
262  }
263  else if(result.name.find("lcl") != std::string::npos)
264  {
265  isLCL = true;
266  }
267 
268  if(suppress_lanechanges && (isLCL || isLCR))
269  {
270  valid = false;
271  result.status_string = "suppressed lc maneuver; "+result.status_string;
272  }
273  else
274  {
275  // if(turnstate == adore::fun::Turnstate::left && result.name.find("lcl") == std::string::npos)
276  if(force_lanechange_left && result.name.find("lcl") == std::string::npos)
277  {
278  valid = false;
279  result.status_string = "non-lcl maneuver; "+result.status_string;
280  }
281  // if(turnstate == adore::fun::Turnstate::right && result.name.find("lcr") == std::string::npos)
282  if(force_lanechange_right && result.name.find("lcr") == std::string::npos)
283  {
284  valid = false;
285  result.status_string = "non-lcr maneuver; "+result.status_string;
286  }
287  }
288 
289  available_results.push_back(result);
290  if(valid)valid_results.insert({result.id,result});
291  }
292 
293 
294  //decide which planning result to execute
295  static_cast<adore::fun::EvaluatorWeightedSum>(evaluator_).setTurnState(turnstate);
296  int best_id = evaluator_.evaluateToBest(valid_results);
297  if(valid_results.size()>0 && best_id>=0)
298  {
299  best_planning_result_ = valid_results[best_id];
303  adore::env::Proposition prop("VALID_MANEUVER_AVAILABLE",true);
304  proposition_writer_->write(prop);
305 
307  {
309  + pNavigation_->getLaneChangePenalty() * 0.5; //add 1/2 lane change penalty for robustness in cost fluctuation
310  }
311  }
312  else
313  {
314  adore::env::Proposition prop("VALID_MANEUVER_AVAILABLE",false);
315  proposition_writer_->write(prop);
316  }
318 
319 
320  //status output: planning result overview
321  std::cout<<std::endl<<"--------------------------------------------------------------------------------"<<std::endl;
322  if(valid_results.size()==0)std::cout << "No valid plans\n";
323  std::cout<<"Current cost bound ("<<cost_bound_name_<<"): "<<cost_bound_<<std::endl;
324  std::sort(std::begin(available_results),
325  std::end(available_results),
326  [](auto& a, auto& b) {return a.id < b.id; });
327  for(auto& result:available_results)
328  {
329  std::cout<<((result.id==best_planning_result_.id && result.iteration==best_planning_result_.iteration)?"*":" ");
330  std::cout<<result.name<<" ("<<result.nominal_maneuver_valid<<","<<result.combined_maneuver_valid<<") ";
331  std::cout<<"c="<<evaluator_.getCost(result.id)<<" ";
332  std::cout<<"c_ttc_nom="<<result.getObjectiveValue("TTC_nom",0.0)<<" ";
333  std::cout<<result.status_string<<std::endl;
334  }
335 
336  //compute initial state and formulate request, to be evaluated in next iteration
338  bool x0_available = spr_dispatcher_.getInitialState(x0);
339  if(spr_dispatcher_.getStatus()!="")std::cout<<spr_dispatcher_.getStatus()<<std::endl;
340  if(!x0_available) return;//not able to formulate request in this iteration
342  req.iteration = ++iteration_;
344  if(req.initial_state.x0ref.getvx()<0.1 && req.initial_state.x0ref.getAx()<0.0)req.initial_state.x0ref.setAx(0.0);
345  req.initial_state.x0ref.setDAx(0.0);
346  req.initial_state.x0ref.setDDelta(0.0);
347  req.initial_state.tStart = x0.getTime();
350  req.t_planning_start = req.initial_state.tStart; // TODO is "now" a good time?
351  req.t_planning_end = req.t_planning_start + iteration_time_length_ * 0.95; // TODO should there be a better parametrization? magic numbers warning
352  request_writer_->write(req);
353 
354  //update navigation cost -> if received, reset cost_bound_
356  {
358  navigation_goal_reader_->getData( goal );//the goal itself is not important, just reset
360  }
361 
363 
364  }
365  };
366  } // namespace apps
367 } // namespace adore
Decision making and maneuver planning.
Definition: tactical_planner.h:48
adore::fun::AFactory::TPlanningRequestWriter * request_writer_
Definition: tactical_planner.h:53
adore::params::APTacticalPlanner * pTacticalPlanner_
Definition: tactical_planner.h:51
adore::fun::AFactory::TForceSlowManeuversReader * force_slow_maneuvers_reader_
Definition: tactical_planner.h:79
uint64_t iteration_
Definition: tactical_planner.h:61
double force_slow_maneuver_timeout_
Definition: tactical_planner.h:72
virtual ~TacticalPlanner()
Definition: tactical_planner.h:114
double iteration_time_length_
Definition: tactical_planner.h:64
adore::fun::AFactory::TMotionStateReader * vehicle_state_reader_
Definition: tactical_planner.h:52
adore::fun::EvaluatorWeightedSum * getEvaluator()
Definition: tactical_planner.h:82
adore::fun::AFactory::TForceLanechangeLeftReader * force_langechange_left_reader_
Definition: tactical_planner.h:77
double lanechange_supression_timeout_
Definition: tactical_planner.h:69
double last_time_
Definition: tactical_planner.h:65
adore::env::AFactory::TPropositionWriter * proposition_writer_
Definition: tactical_planner.h:56
double force_langechange_left_timeout_
Definition: tactical_planner.h:70
adore::fun::SetPointRequestDispatcher spr_dispatcher_
Definition: tactical_planner.h:57
double force_langechange_right_timeout_
Definition: tactical_planner.h:71
std::string cost_bound_name_
Definition: tactical_planner.h:73
adore::params::APNavigation * pNavigation_
Definition: tactical_planner.h:49
void run()
retrieve planning results, dispatch and formulate new planning request
Definition: tactical_planner.h:127
adore::fun::AFactory::TForceLanechangeRightReader * force_langechange_right_reader_
Definition: tactical_planner.h:78
adore::fun::AFactory::TPlanningResultWriter * select_writer_
Definition: tactical_planner.h:55
adore::fun::AFactory::TLanechangeSuppressionReader * langechange_suppression_reader_
Definition: tactical_planner.h:76
adore::fun::PlanningResult best_planning_result_
Definition: tactical_planner.h:63
adore::params::APTrajectoryGeneration * pTrajectoryGeneration_
Definition: tactical_planner.h:50
adore::fun::IndicatorDispatcher indicator_dispatcher_
Definition: tactical_planner.h:58
double cost_bound_guard_
Definition: tactical_planner.h:67
adore::fun::EvaluatorWeightedSum evaluator_
Definition: tactical_planner.h:62
fun::TurnSignalObserver turn_signal_observer_
Definition: tactical_planner.h:74
double cost_bound_
Definition: tactical_planner.h:66
adore::env::AFactory::TNavigationGoalReader * navigation_goal_reader_
Definition: tactical_planner.h:59
TacticalPlanner(double iteration_time_length)
constructur
Definition: tactical_planner.h:88
fun::UserInputObserver user_input_observer_
Definition: tactical_planner.h:75
adore::fun::AFactory::TPlanningResultFeed * result_reader_
Definition: tactical_planner.h:54
adore::env::AFactory::TResetLaneMatchingWriter * lane_view_reset_writer_
Definition: tactical_planner.h:60
virtual TPropositionWriter * getPropositionWriter()=0
virtual TNavigationGoalReader * getNavigationGoalReader()=0
virtual TVehicleMotionStateReader * getVehicleMotionStateReader()=0
virtual TResetLaneMatchingWriter * getResetLaneMatchingWriter()=0
static adore::env::AFactory * get()
Definition: afactory.h:236
Definition: evaluator_weighted_sum.h:31
int evaluateToBest(const PlanningResultMap &planning_results) override
Definition: evaluator_weighted_sum.h:83
double getCost(int id)
Definition: evaluator_weighted_sum.h:63
static adore::fun::AFactory * get()
Definition: afactory.h:170
Dispatches indicator command for maneuver, which is currently executed.
Definition: indicator_dispatcher.h:25
void setIndicators(const PlanningResult &selected_maneuver)
Definition: indicator_dispatcher.h:40
class helps to dispatch SetPointRequest to controller SetPointRequestDispatcher handles selection of ...
Definition: setpointrequest_dispatcher.h:29
std::string getStatus()
Definition: setpointrequest_dispatcher.h:218
bool getInitialState(VehicleMotionState9d &result)
compute and return initial state for next planning iteration The according initial state in odometry ...
Definition: setpointrequest_dispatcher.h:191
void dispatch(SetPointRequest &combined_trajectory, SetPointRequest &nominal_trajectory)
dispatch SetPointRequests computed in localization coordinates The combined trajectory will be conver...
Definition: setpointrequest_dispatcher.h:208
PlanarVehicleState10d x0ref
Definition: setpoint.h:32
double tStart
Definition: setpoint.h:34
double tEnd
Definition: setpoint.h:35
Definition: turn_signal_observer.h:22
bool rightIndicatorTurnedOnManuallyWithinLastSecond(double current_time, double max_delay=1.0)
Definition: turn_signal_observer.h:106
void update(double t)
Definition: turn_signal_observer.h:63
bool leftIndicatorTurnedOnManuallyWithinLastSecond(double current_time, double max_delay=1.0)
Definition: turn_signal_observer.h:110
Definition: user_input_observer.h:22
Definition: com_patterns.h:29
virtual void getNext(T &value)=0
virtual bool hasNext() const =0
Definition: com_patterns.h:68
virtual void getData(T &value)=0
virtual bool hasData() const =0
virtual bool hasUpdate() const =0
Definition: com_patterns.h:97
virtual void write(const T &value)=0
virtual APTacticalPlanner * getTacticalPlanner() const =0
virtual APTrajectoryGeneration * getTrajectoryGeneration() const =0
virtual APNavigation * getNavigation() const =0
abstract class containing parameters which configure navigation behaviour
Definition: ap_navigation.h:25
virtual double getLaneChangePenalty() const =0
abstract classs containing parameters to configure aspects and constraints of the tactical planner
Definition: ap_tactical_planner.h:25
virtual double getLVResetVelocity() const =0
virtual bool getEnforceMonotonousNavigationCost() const =0
virtual double getTimeoutForLangechangeSuppression() const =0
virtual double getTimeoutForPreferredLCAfterManuallySetIndicator() const =0
abstract class containing parameters to configure the behaviour of trajectory generation
Definition: ap_trajectory_generation.h:26
virtual double getEmergencyManeuverDelay() const =0
time after which emergency maneuver kicks in
static adore::params::AFactory * get()
Definition: afactory.h:103
@ right
Definition: indicator_hint.h:36
@ left
Definition: indicator_hint.h:35
Turnstate
Definition: turnstate.h:21
@ off
Definition: turnstate.h:22
std::unordered_map< int, adore::fun::PlanningResult > PlanningResultMap
Definition: atrajectory_evaluator.h:29
x0
Definition: adore_set_goal.py:25
x
Definition: adore_set_goal.py:30
Definition: areaofeffectconverter.h:20
A logical proposition, with a possible timeout for the information.
Definition: proposition.h:27
This struct holds the motion state of the vehicle in 9d.
Definition: vehiclemotionstate9d.h:39
Definition: navigationgoal.h:26
Definition: planarvehiclestate10d.h:41
double getvx() const
Definition: planarvehiclestate10d.h:65
void setDDelta(double value)
Definition: planarvehiclestate10d.h:82
void setDAx(double value)
Definition: planarvehiclestate10d.h:81
double getAx() const
Definition: planarvehiclestate10d.h:68
void setAx(double value)
Definition: planarvehiclestate10d.h:79
Definition: planning_request.h:22
double t_planning_start
Definition: planning_request.h:24
double t_emergency_start
Definition: planning_request.h:26
double t_planning_end
Definition: planning_request.h:25
SetPoint initial_state
Definition: planning_request.h:27
long long int iteration
Definition: planning_request.h:23
Definition: planning_result.h:29
bool combined_maneuver_valid
Definition: planning_result.h:64
std::string name
Definition: planning_result.h:32
double getObjectiveValue(std::string name, double bound)
Definition: planning_result.h:89
std::string status_string
Definition: planning_result.h:65
int id
Definition: planning_result.h:30
int iteration
Definition: planning_result.h:31
SetPointRequest nominal_maneuver
Definition: planning_result.h:33
SetPointRequest combined_maneuver
Definition: planning_result.h:35