Autoware.Auto
nlp_adapters.hpp
Go to the documentation of this file.
1 // Copyright 2020 Embotech AG, Zurich, Switzerland. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // This file contains some templated classes for interacting with the NLP, both
16 // at the time of problem formulation as well as for calling the solver after it
17 // has been generated. All the templates can be used with "symbolic" variables such as
18 // CasADi variable objects, but also with concrete numbers such as float and double.
19 //
20 // In fact, the adapters assemble_variable_vector and assemble_parameter_vector are
21 // used both when formulating the problem for code generation as well as afterwards
22 // for calling the generated solver. This ensures consistency of variable and parameter
23 // ordering because those orderings are defined just in one place - here.
24 
25 #ifndef PARKING_PLANNER__NLP_ADAPTERS_HPP_
26 #define PARKING_PLANNER__NLP_ADAPTERS_HPP_
27 
28 #include <common/types.hpp>
29 #include <vector>
30 #include <string>
31 
32 #include "configuration.hpp"
34 #include "bicycle_model.hpp"
35 #include "geometry.hpp"
36 
37 namespace autoware
38 {
39 
40 namespace motion
41 {
42 
43 namespace planning
44 {
45 
47 namespace parking_planner
48 {
49 
55 
62 constexpr auto ARTIFICIAL_DUAL_MULTIPLIER_BOUND = 1.0e4;
63 
64 // \brief Class to represent cost function weights used in the nonlinear
65 // optimization problem solve
66 template<typename T>
68 {
69 public:
71  T steering,
72  T throttle,
73  T goal
74  )
75  {
76  m_steering = steering;
77  m_throttle = throttle;
78  m_goal = goal;
79  }
80 
81  std::vector<T> serialize(void) const
82  {
83  return std::vector<T>({m_steering, m_throttle, m_goal});
84  }
85 
86  static NLPCostWeights deserialize(std::vector<T> serialized)
87  {
88  constexpr std::size_t expected_length = NLPCostWeights::get_serialized_length();
89  if (serialized.size() != expected_length) {
90  throw std::length_error {"Need a vector of length " + std::string{expected_length}};
91  }
92  NLPCostWeights weights(serialized[0], serialized[1], serialized[2]);
93  return weights;
94  }
95 
96  static constexpr std::size_t get_serialized_length() noexcept
97  {return internal_weights_number;}
98 
99  T get_steering_weight() const noexcept {return m_steering;}
100  T get_throttle_weight() const noexcept {return m_throttle;}
101  T get_goal_weight() const noexcept {return m_goal;}
102 
103 private:
104  static constexpr std::size_t internal_weights_number = 3;
106  T m_steering;
107 
109  T m_throttle;
110 
114  T m_goal;
115 };
116 
118 // stage for describing obstacle constraints
119 template<typename T>
121 {
122 public:
124  std::vector<T> lambda,
125  std::vector<T> mu
126  )
127  {
128  m_lambda = lambda;
129  m_mu = mu;
130  }
131 
133  std::vector<T> serialize(void) const
134  {
135  std::vector<T> serialized{};
136  serialized.reserve(internal_lambda_number + internal_mu_number);
137  serialized.insert(serialized.end(), m_lambda.begin(), m_lambda.end());
138  serialized.insert(serialized.end(), m_mu.begin(), m_mu.end());
139  return serialized;
140  }
141 
142  static constexpr std::size_t get_lambda_length() noexcept
143  {return internal_lambda_number;}
144 
145  static constexpr std::size_t get_mu_length() noexcept
146  {return internal_mu_number;}
147 
148  static constexpr std::size_t get_serialized_length() noexcept
149  {return internal_mu_number + internal_lambda_number;}
150 
151  static NLPObstacleStageVariables deserialize(std::vector<T> serialized)
152  {
153  static constexpr auto lambda_length = NLPObstacleStageVariables<float64_t>::get_lambda_length();
154  static constexpr auto mu_length = NLPObstacleStageVariables<float64_t>::get_mu_length();
155  static constexpr auto expected_length =
157  if (serialized.size() != expected_length) {
158  throw std::length_error {"Need a vector of length " + std::string{expected_length}};
159  }
160 
161  const auto start = serialized.begin();
163  std::vector<T>(start, start + lambda_length),
164  std::vector<T>(start + lambda_length, start + lambda_length + mu_length) );
165  }
166 
167  std::vector<T> get_lambda() const noexcept {return m_lambda;}
168  std::vector<T> get_mu() const noexcept {return m_mu;}
169 
170 private:
172  static constexpr std::size_t internal_lambda_number = MAX_HYPERPLANES_PER_OBSTACLE;
173 
175  static constexpr std::size_t internal_mu_number = MAX_EGO_HYPERPLANES;
176 
178  std::vector<T> m_lambda;
179 
181  std::vector<T> m_mu;
182 };
183 
184 
189 template<typename T>
191 {
192 public:
194  std::vector<NLPObstacleStageVariables<T>> stage_variables,
195  std::vector<Halfplane2D<T>> halfplanes) noexcept
196  {
197  m_stage_variables = stage_variables;
198  m_halfplanes = halfplanes;
199  }
200 
202  // a CasADi-interfaced solver
203  std::vector<T> serialize_variables(void) const
204  {
205  std::vector<T> serialized{};
206  serialized.reserve(m_stage_variables.size() * m_stage_variables[0].get_serialized_length() );
207  for (const auto & stage : m_stage_variables) {
208  const auto serialized_stage = stage.serialize();
209  serialized.insert(serialized.end(), serialized_stage.begin(), serialized_stage.end());
210  }
211  return serialized;
212  }
213 
215  // for use by a CasADi-interfaced solver
216  std::vector<T> serialize_parameters(void) const
217  {
218  std::vector<T> serialized{};
219  for (const auto & halfplane : m_halfplanes) {
220  const auto serialized_halfplane = halfplane.serialize();
221  serialized.insert(
222  serialized.end(), serialized_halfplane.begin(),
223  serialized_halfplane.end() );
224  }
225  return serialized;
226  }
227 
229  std::vector<Halfplane2D<T>> get_halfplanes() const noexcept
230  {return m_halfplanes;}
231 
233  std::vector<NLPObstacleStageVariables<T>> get_stage_variables() const noexcept
234  {return m_stage_variables;}
235 
237  // where the outer vector is the column and the inner vectors each contain
238  // a row.
239  std::vector<std::vector<T>> build_A() const
240  {
241  std::vector<std::vector<T>> A{};
242  for (const auto & halfplane : this->m_halfplanes) {
243  auto coordinates = halfplane.get_coefficients().get_coord();
244  A.push_back(std::vector<T>({coordinates.first, coordinates.second}) );
245  }
246  return A;
247  }
248 
250  std::vector<T> build_b() const
251  {
252  std::vector<T> b{};
253  for (const auto & halfplane : this->m_halfplanes) {
254  auto rhs = halfplane.get_right_hand_side();
255  b.push_back(rhs);
256  }
257  return b;
258  }
259 
260 private:
262  std::vector<Halfplane2D<T>> m_halfplanes;
263 
265  std::vector<NLPObstacleStageVariables<T>> m_stage_variables;
266 };
267 
268 
269 template<typename T>
271 {
272  std::vector<T> variables;
273  std::vector<float64_t> lower_bounds;
274  std::vector<float64_t> upper_bounds;
275 };
276 
277 
287 template<typename T>
289  const Trajectory<T> & trajectory,
290  const std::vector<NLPObstacle<T>> & obstacles,
291  const VehicleState<float64_t> & lower_state_bounds,
292  const VehicleState<float64_t> & upper_state_bounds,
293  const VehicleCommand<float64_t> & lower_command_bounds,
294  const VehicleCommand<float64_t> & upper_command_bounds
295 )
296 {
297  std::vector<T> assembled_variables{};
298  std::vector<float64_t> lower_bounds{};
299  std::vector<float64_t> upper_bounds{};
300  const auto serialized_state_lower = lower_state_bounds.serialize();
301  const auto serialized_state_upper = upper_state_bounds.serialize();
302  const auto serialized_command_lower = lower_command_bounds.serialize();
303  const auto serialized_command_upper = upper_command_bounds.serialize();
304  for (const auto & step : trajectory) {
305  // State and its bounds
306  const auto serialized_state = step.get_state().serialize();
307  assembled_variables.insert(
308  assembled_variables.end(),
309  serialized_state.begin(), serialized_state.end() );
310  lower_bounds.insert(
311  lower_bounds.end(),
312  serialized_state_lower.begin(), serialized_state_lower.end() );
313  upper_bounds.insert(
314  upper_bounds.end(),
315  serialized_state_upper.begin(), serialized_state_upper.end() );
316 
317  // Commands and their bounds
318  const auto serialized_command = step.get_command().serialize();
319  assembled_variables.insert(
320  assembled_variables.end(),
321  serialized_command.begin(), serialized_command.end() );
322  lower_bounds.insert(
323  lower_bounds.end(),
324  serialized_command_lower.begin(), serialized_command_lower.end() );
325  upper_bounds.insert(
326  upper_bounds.end(),
327  serialized_command_upper.begin(), serialized_command_upper.end() );
328  }
329 
330  // Obstacle variables and their bounds
331  for (const auto & obstacle : obstacles) {
332  const auto serialized = obstacle.serialize_variables();
333  assembled_variables.insert(
334  assembled_variables.end(),
335  serialized.begin(), serialized.end()
336  );
337  for (std::size_t k = {}; k < serialized.size(); k++) {
338  lower_bounds.push_back(0.0);
339  upper_bounds.push_back(ARTIFICIAL_DUAL_MULTIPLIER_BOUND);
340  }
341  }
342 
343  return SerializedVariables<T>{assembled_variables, lower_bounds, upper_bounds};
344 }
345 
346 
349 template<typename T>
351  const std::vector<T> & variable_vector,
352  const std::size_t horizon_length)
353 {
356 
357  Trajectory<float64_t> disassembled{};
358  disassembled.reserve(variable_vector.size());
359  auto vstart = variable_vector.begin();
360  for (std::size_t k = {}; k < horizon_length; k++) {
361  const auto state_k = VehicleState<T>::deserialize(std::vector<T>(vstart, vstart + Nstates));
362  vstart += Nstates;
363  const auto command_k = VehicleCommand<T>::deserialize(
364  std::vector<T>(vstart, vstart + Ncommands)
365  );
366  vstart += Ncommands;
367  disassembled.push_back(TrajectoryStep<T>(command_k, state_k));
368  }
369 
370  return disassembled;
371 }
372 
373 
376 template<typename T>
378  const VehicleState<T> & current_state,
379  const VehicleState<T> & goal_state,
380  const BicycleModelParameters<T> & model_parameters,
381  const std::vector<NLPObstacle<T>> & obstacles,
382  const NLPCostWeights<T> & cost_weights
383 )
384 {
385  std::vector<T> assembled{};
386  {
387  const auto serialized = current_state.serialize();
388  assembled.insert(assembled.end(), serialized.begin(), serialized.end() );
389  }
390  {
391  const auto serialized = goal_state.serialize();
392  assembled.insert(assembled.end(), serialized.begin(), serialized.end() );
393  }
394  {
395  const auto serialized = model_parameters.serialize();
396  assembled.insert(assembled.end(), serialized.begin(), serialized.end() );
397  }
398 
399  {
400  const auto serialized = cost_weights.serialize();
401  assembled.insert(assembled.end(), serialized.begin(), serialized.end() );
402  }
403 
404  for (const auto & obstacle : obstacles) {
405  const auto serialized = obstacle.serialize_parameters();
406  assembled.insert(assembled.end(), serialized.begin(), serialized.end() );
407  }
408 
409  return assembled;
410 }
411 
412 } // namespace parking_planner
413 } // namespace planning
414 } // namespace motion
415 } // namespace autoware
416 
417 #endif // PARKING_PLANNER__NLP_ADAPTERS_HPP_
std::vector< T > serialize(void) const
Definition: bicycle_model.hpp:59
std::vector< float64_t > lower_bounds
Definition: nlp_adapters.hpp:273
double float64_t
Definition: types.hpp:37
Class used to describe the additional dual variables required for each.
Definition: nlp_adapters.hpp:120
NLPCostWeights(T steering, T throttle, T goal)
Definition: nlp_adapters.hpp:70
std::vector< TrajectoryStep< T > > Trajectory
Class to represent a dynamic trajectory.
Definition: parking_planner_types.hpp:200
T
Definition: catr_diff.py:22
Class to represent the state of a vehicle.
Definition: parking_planner_types.hpp:37
static NLPCostWeights deserialize(std::vector< T > serialized)
Definition: nlp_adapters.hpp:86
NLPObstacleStageVariables(std::vector< T > lambda, std::vector< T > mu)
Definition: nlp_adapters.hpp:123
T get_steering_weight() const noexcept
Definition: nlp_adapters.hpp:99
std::vector< float64_t > upper_bounds
Definition: nlp_adapters.hpp:274
std::vector< T > serialize(void) const
Serialize the object into a vector of scalars.
Definition: nlp_adapters.hpp:133
std::vector< T > serialize(void) const
Turn the object into flat vector of doubles (for use with numerical code)
Definition: parking_planner_types.hpp:142
Class used to represent an obstacle with the relevant data and conversions for the NLP solver...
Definition: nlp_adapters.hpp:190
NLPObstacle(std::vector< NLPObstacleStageVariables< T >> stage_variables, std::vector< Halfplane2D< T >> halfplanes) noexcept
Definition: nlp_adapters.hpp:193
static constexpr std::size_t get_lambda_length() noexcept
Definition: nlp_adapters.hpp:142
static constexpr std::size_t get_serialized_length() noexcept
Get number of scalars a serialized version of this object has.
Definition: parking_planner_types.hpp:163
T get_goal_weight() const noexcept
Definition: nlp_adapters.hpp:101
constexpr auto Nstates
Definition: generate_nlp_planner_solver.cpp:80
constexpr std::size_t MAX_HYPERPLANES_PER_OBSTACLE
Maximum number of hyperplanes per obstacle supported by the NLP planner.
Definition: configuration.hpp:39
This file includes common type definition.
T get_throttle_weight() const noexcept
Definition: nlp_adapters.hpp:100
std::vector< T > serialize_parameters(void) const
Turn the obstacle parameter variables into a vector of scalars,.
Definition: nlp_adapters.hpp:216
std::vector< T > serialize(void) const
Definition: nlp_adapters.hpp:81
constexpr auto ARTIFICIAL_DUAL_MULTIPLIER_BOUND
Since we need upper and lower bounds in the constructs used here, but some variables do not have clea...
Definition: nlp_adapters.hpp:62
static VehicleState deserialize(std::vector< T > serialized_states)
Definition: parking_planner_types.hpp:61
std::vector< std::vector< T > > build_A() const
Assemble an A matrix from the halfplanes in form of a vector of vectors.
Definition: nlp_adapters.hpp:239
static constexpr std::size_t get_serialized_length() noexcept
Definition: nlp_adapters.hpp:96
Class for storing physical parameters of a bicycle model bicycle model.
Definition: bicycle_model.hpp:45
static VehicleCommand deserialize(std::vector< T > serialized_commands)
Turn a previously serialized command vector back into a VehicleCommand object.
Definition: parking_planner_types.hpp:146
std::vector< Halfplane2D< T > > get_halfplanes() const noexcept
Getter for the halfplanes.
Definition: nlp_adapters.hpp:229
Definition: controller_base.hpp:30
Class describing a halfplane in two-dimensional space.
Definition: geometry.hpp:163
std::vector< NLPObstacleStageVariables< T > > get_stage_variables() const noexcept
Getter for the stage variables.
Definition: nlp_adapters.hpp:233
std::vector< T > get_mu() const noexcept
Definition: nlp_adapters.hpp:168
static constexpr std::size_t get_serialized_length() noexcept
Definition: nlp_adapters.hpp:148
std::vector< T > variables
Definition: nlp_adapters.hpp:272
Trajectory< float64_t > disassemble_variable_vector(const std::vector< T > &variable_vector, const std::size_t horizon_length)
Helper function to turn a serialized variable vector into a structured Trajectory object...
Definition: nlp_adapters.hpp:350
Class to represent the inputs of a vehicle.
Definition: parking_planner_types.hpp:127
std::vector< T > serialize(void) const
Turn the object into flat vector of doubles (for use with numerical code)
Definition: parking_planner_types.hpp:55
std::vector< T > serialize_variables(void) const
Turn the obstacle variables into a vector of scalars, for use by.
Definition: nlp_adapters.hpp:203
Class to represent one timestep in a dynamic trajectory.
Definition: parking_planner_types.hpp:181
constexpr std::size_t MAX_EGO_HYPERPLANES
Maximum number of ego vehicle hyperplanes supported by the NLP planner.
Definition: configuration.hpp:42
std::vector< T > get_lambda() const noexcept
Definition: nlp_adapters.hpp:167
static constexpr std::size_t get_mu_length() noexcept
Definition: nlp_adapters.hpp:145
SerializedVariables< T > assemble_variable_vector_and_bounds(const Trajectory< T > &trajectory, const std::vector< NLPObstacle< T >> &obstacles, const VehicleState< float64_t > &lower_state_bounds, const VehicleState< float64_t > &upper_state_bounds, const VehicleCommand< float64_t > &lower_command_bounds, const VehicleCommand< float64_t > &upper_command_bounds)
Function to assemble the variable vector for the NLP from given states and commands. This is used in both the solver generation for specifying how the variables are ordered as well as when calling the solver because it will expect the initial guess in the same format. The adapter here serves as a single source of truth for how the serialization is to be done.
Definition: nlp_adapters.hpp:288
static NLPObstacleStageVariables deserialize(std::vector< T > serialized)
Definition: nlp_adapters.hpp:151
std::vector< T > assemble_parameter_vector(const VehicleState< T > &current_state, const VehicleState< T > &goal_state, const BicycleModelParameters< T > &model_parameters, const std::vector< NLPObstacle< T >> &obstacles, const NLPCostWeights< T > &cost_weights)
Helper function to turn the inputs to an NLP solve into a flat vector of scalars for use by the CasAD...
Definition: nlp_adapters.hpp:377
std::vector< T > build_b() const
Build the b matrix from the halfplanes of the obstacles.
Definition: nlp_adapters.hpp:250
static constexpr std::size_t get_serialized_length() noexcept
Get number of scalars a serialized version of this object has.
Definition: parking_planner_types.hpp:88
constexpr auto Ncommands
Definition: generate_nlp_planner_solver.cpp:81
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24