- 3.0.2 rigid body dynamics module.
SingleDOFTrajectoryGenerator.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich.
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 #pragma once
7 
8 #include "ct/core/core.h"
9 
10 namespace ct {
11 namespace rbd {
12 namespace tpl {
13 
29 template <typename SCALAR = double>
31 {
32 protected:
33  enum MODE
34  {
37  };
38 
39 public:
41  : operation_mode_(ACCELERATE_AND_DECELERATE),
42  x0_(SCALAR(0.0)),
43  x_t0n_(SCALAR(0)),
44  x_mid_(SCALAR(0)),
45  x_t1_(SCALAR(0)),
46  xT_(SCALAR(0.0)),
47  v_max_(SCALAR(0.0)),
48  a_max_(SCALAR(0.0)),
49  t0_(SCALAR(0.0)),
50  t0n_(SCALAR(0.0)),
51  t1_(SCALAR(0.0)),
52  T_(SCALAR(0.0))
53  {
54  }
55 
56 
57  SingleDOFTrajectoryGenerator(const SCALAR x0, const SCALAR xT, SCALAR abs_v_max, SCALAR abs_a_max)
59  {
60  setup(x0, xT, abs_v_max, abs_a_max);
61  }
62 
63 
74  SCALAR setup(const SCALAR x0, const SCALAR xT, SCALAR abs_v_max, SCALAR abs_a_max)
75  {
76  x0_ = x0;
77  xT_ = xT;
78  v_max_ = abs_v_max;
79  a_max_ = abs_a_max;
80 
81  // check if we in fact need negative acceleration and velocities
82  if (xT_ < x0_)
83  {
84  v_max_ = -v_max_;
85  a_max_ = -a_max_;
86  }
87 
88  // nominal time until the max velocity would be reached
89  t0n_ = v_max_ / a_max_;
90  // Distance which would be traveled during that time
91  SCALAR delta_x = 0.5 * a_max_ * t0n_ * t0n_;
92 
93  // If the distance traveled would surpass the total position difference, we choose
94  // ACCELERATE_AND_DECELERATE, otherwise we put a constant velocity hold segment in-between.
95  if (2 * fabs(delta_x) >= fabs(xT_ - x0_))
96  {
97  operation_mode_ = ACCELERATE_AND_DECELERATE;
98 
99  SCALAR delta_x_mid = 0.5 * (xT_ - x0_); // Half the distance between start and target
100  x_mid_ = 0.5 * (xT_ + x0_);
101  ; // The point exactly in the middle
102  t0_ = sqrt(delta_x_mid * 2 / a_max_); // The time passed when driving there with const. acceleration
103  v_max_ = a_max_ * t0_; // The velocity reached when arriving at x_mid - update v_max
104  T_ = 2 * t0_; // The total move time horizon
105  }
106  else
107  {
108  operation_mode_ = ACCELERATE_HOLD_DECELERATE;
109 
110  x_t0n_ = x0_ + 0.5 * a_max_ * t0n_ * t0n_; // The position reached after that time
111  x_t1_ = xT_ - delta_x; // The position where we start decelerating again after the constant vel. section
112  t1_ = t0n_ + (x_t1_ - x_t0n_) / v_max_; // The time when this happens, calculated from the const velocity.
113  T_ = t1_ + t0n_; // The total move time horizon
114  }
115 
116  return T_;
117  }
118 
126  void queryTrajectory(const SCALAR time, SCALAR& x_new, SCALAR& v_new)
127  {
128  if (time < SCALAR(0.0))
129  throw std::runtime_error("SingleAxisTrajGenerator: time cannot be negative!");
130 
131  if (operation_mode_ == ACCELERATE_AND_DECELERATE)
132  queryPlanAccADec(time, x_new, v_new);
133  else if (operation_mode_ == ACCELERATE_HOLD_DECELERATE)
134  queryPlanAccHDec(time, x_new, v_new);
135  else
136  throw std::runtime_error("SingleAxisTrajectoryGenerator: operation mode not available.");
137  }
138 
139 
140 private:
142  MODE operation_mode_;
143  SCALAR x0_, x_t0n_, x_mid_, x_t1_, xT_;
144  SCALAR v_max_, a_max_;
145  SCALAR t0_, t0n_, t1_, T_;
146 
147  void queryPlanAccADec(const SCALAR& time, SCALAR& x_new, SCALAR& v_new)
148  {
149  if (time <= t0_)
150  {
151  x_new = x0_ + 0.5 * a_max_ * time * time; // Quadratic function for x
152  v_new = a_max_ * time; // Linear function for vel
153  }
154  else if (time > t0_ && time <= 2 * t0_)
155  {
156  // Quadratic function for x
157  x_new = x_mid_ + v_max_ * (time - t0_) - 0.5 * a_max_ * (time - t0_) * (time - t0_);
158  // Linear function for vel
159  v_new = v_max_ - a_max_ * (time - t0_);
160  }
161  else if (time > 2 * t0_)
162  {
163  x_new = xT_; // Set to desired values if time horizon exceeded
164  v_new = 0.0;
165  }
166  else
167  {
168  throw std::runtime_error("SingleAxisTrajectoryGenerator: something is wrong with the time.");
169  }
170  }
171 
172  void queryPlanAccHDec(const SCALAR& time, SCALAR& x_new, SCALAR& v_new)
173  {
174  if (time <= t0n_)
175  {
176  x_new = 0.5 * a_max_ * time * time + x0_; // Quadratic function for x
177  v_new = a_max_ * time; // Linear function for vel
178  }
179  else if (time > t0n_ && time <= t1_)
180  {
181  x_new = x_t0n_ + v_max_ * (time - t0n_); // Position linearly increasing
182  v_new = v_max_; // Constant velocity
183  }
184  else if (time > t1_ && time <= T_)
185  {
186  // x quadratically decreasing
187  x_new = x_t1_ + v_max_ * (time - t1_) - 0.5 * a_max_ * ((time - t1_) * (time - t1_));
188  // linearly decreasing
189  v_new = v_max_ - ((time - t1_) * a_max_);
190  }
191  else if (time > T_)
192  {
193  x_new = xT_; // Set to desired values if time horizon exceeded
194  v_new = 0.0;
195  }
196  else
197  {
198  throw std::runtime_error("SingleAxisTrajectoryGenerator: something is wrong with the time.");
199  }
200  }
201 };
202 
203 
204 } // tpl
205 
207 
208 } // rbd
209 } // ct
void queryTrajectory(const SCALAR time, SCALAR &x_new, SCALAR &v_new)
Definition: SingleDOFTrajectoryGenerator.h:126
SCALAR setup(const SCALAR x0, const SCALAR xT, SCALAR abs_v_max, SCALAR abs_a_max)
Definition: SingleDOFTrajectoryGenerator.h:74
SingleDOFTrajectoryGenerator(const SCALAR x0, const SCALAR xT, SCALAR abs_v_max, SCALAR abs_a_max)
Definition: SingleDOFTrajectoryGenerator.h:57
Definition: SingleDOFTrajectoryGenerator.h:30
CppAD::AD< CppAD::cg::CG< double > > SCALAR
MODE
Definition: SingleDOFTrajectoryGenerator.h:33
SingleDOFTrajectoryGenerator()
Definition: SingleDOFTrajectoryGenerator.h:40