min_time_via_points_cost.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement
4  *
5  * Copyright (c) 2020, Christoph Rösmann, All rights reserved.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  *
20  * Authors: Christoph Rösmann
21  *********************************************************************/
22 
24 
27 
28 #include <cmath>
29 #include <memory>
30 
31 namespace mpc_local_planner {
32 
34 {
35  assert(k < _vp_association.size());
36  assert(_vp_association[k].first.size() == _vp_association[k].second);
37  return (int)_vp_association[k].second;
38 }
39 
41  corbo::ReferenceTrajectoryInterface* /*sref*/, bool single_dt, const Eigen::VectorXd& x0,
42  corbo::StagePreprocessor::Ptr /*stage_preprocessor*/, const std::vector<double>& /*dts*/,
44 {
45  if (!_via_points)
46  {
47  PRINT_WARNING("MinTimeViaPointsCost::update(): no via_point container specified");
48  return !_vp_association.empty();
49  }
50 
51  // setup minimum time cost
52  _single_dt = single_dt;
53  if (single_dt)
54  _time_weight = n - 1;
55  else
56  _time_weight = 1.0;
57 
58  // Setup via points
59 
60  // we currently require a full discretization grid as we want to have fast access to
61  // individual states without requiring any new simulation.
62  // Alternatively, other grids could be used in combination with method getStateAndControlTimeSeries()
63  const FullDiscretizationGridBaseSE2* fd_grid = static_cast<const FullDiscretizationGridBaseSE2*>(grid);
64 
65  assert(n == fd_grid->getN());
66 
67  bool new_structure = (n != _vp_association.size());
68  if (new_structure)
69  {
70  _vp_association.resize(n, std::make_pair<std::vector<const teb_local_planner::PoseSE2*>, std::size_t>({}, 0));
71  }
72 
73  // clear previous association
74  for (auto& item : _vp_association)
75  {
76  item.first.clear();
77  }
78 
79  int start_pose_idx = 0;
80 
81  for (const teb_local_planner::PoseSE2& pose : *_via_points)
82  {
83  int idx = fd_grid->findClosestPose(pose.x(), pose.y(), start_pose_idx);
84 
85  if (_via_points_ordered) start_pose_idx = idx + 2; // skip a point to have a DOF inbetween for further via-points
86 
87  // check if point coincides with final state or is located behind it
88  if (idx > n - 2) idx = n - 2; // set to a pose before the goal, since it is never fixed
89 
90  // check if point coincides with start or is located before it
91  if (idx < 1)
92  {
94  idx = 1; // try to connect the via point with the second pose. Grid adaptation might add new poses inbetween later if enabled.
95  else
96  {
97  PRINT_DEBUG("TebOptimalPlanner::AddEdgesViaPoints(): skipping a via-point that is close or behind the current robot pose.");
98  continue; // skip via points really close or behind the current robot pose
99  }
100  }
101 
102  _vp_association[idx].first.push_back(&pose);
103  }
104 
105  // check for structure changes
106  for (auto& item : _vp_association)
107  {
108  if (item.first.size() != item.second)
109  {
110  item.second = item.first.size();
111  new_structure = true;
112  // but continue until end for next time
113  }
114  }
115 
116  // return true if structure requires a changed
117  return new_structure;
118 }
119 
121 {
122  if (!_single_dt || k == 0)
123  cost[0] = _time_weight * dt;
124  else
125  {
126  PRINT_DEBUG_NAMED("this method should not be called in single_dt mode and k>0");
127  }
128 }
129 
131 {
132  assert(_via_points);
133  assert(k < _vp_association.size());
134  assert(cost.size() == _vp_association[k].first.size());
135  assert(_vp_association[k].second == _vp_association[k].first.size());
136 
137  for (int i = 0; i < (int)_vp_association[k].second; ++i)
138  {
139  cost[i] = _vp_position_weight * (_vp_association[k].first[i]->position() - x_k.head(2)).squaredNorm();
140  if (_vp_orientation_weight > 0)
141  {
142  cost[i] += _vp_orientation_weight * normalize_theta(_vp_association[k].first[i]->theta() - x_k[2]);
143  }
144  }
145 }
146 
147 } // namespace mpc_local_planner
int findClosestPose(double x_ref, double y_ref, int start_idx=0, double *distance=nullptr) const
Find the closest pose (first part of the state vector) on the grid w.r.t. to a provided reference poi...
#define PRINT_DEBUG(msg)
return int(ret)+1
#define PRINT_WARNING(msg)
std::vector< std::pair< std::vector< const teb_local_planner::PoseSE2 * >, std::size_t > > _vp_association
#define PRINT_DEBUG_NAMED(msg)
int getN() const override
get current horizon length
int getNonIntegralStateTermDimension(int k) const override
void computeNonIntegralDtTerm(int k, double dt, Eigen::Ref< Eigen::VectorXd > cost) const override
Full discretization grid specialization for SE2.
double normalize_theta(double theta)
normalize angle to interval [-pi, pi)
Definition: math_utils.h:81
std::shared_ptr< StagePreprocessor > Ptr
bool update(int n, double, corbo::ReferenceTrajectoryInterface &, corbo::ReferenceTrajectoryInterface &, corbo::ReferenceTrajectoryInterface *, bool single_dt, const Eigen::VectorXd &x0, corbo::StagePreprocessor::Ptr, const std::vector< double > &, const corbo::DiscretizationGridInterface *grid) override
void computeNonIntegralStateTerm(int k, const Eigen::Ref< const Eigen::VectorXd > &x_k, Eigen::Ref< Eigen::VectorXd > cost) const override


mpc_local_planner
Author(s): Christoph Rösmann
autogenerated on Mon Feb 28 2022 22:53:18