35 template <
typename T,
int NX,
int NU>
38 template <
typename T,
int NX,
int NU>
41 template <
typename T,
int NX,
int NU>
45 DynamicsSolverInitializer dynamics_solver_initializer = DynamicsSolverInitializer(init);
46 this->SetDt(dynamics_solver_initializer.dt);
47 this->SetIntegrator(dynamics_solver_initializer.Integrator);
51 raw_control_limits_low_ = dynamics_solver_initializer.ControlLimitsLow;
52 raw_control_limits_high_ = dynamics_solver_initializer.ControlLimitsHigh;
54 if (debug_)
INFO_NAMED(object_name_,
"Initialized DynamicsSolver of type " << GetObjectName() <<
" with dt=" << dynamics_solver_initializer.dt <<
" and integrator=" << dynamics_solver_initializer.Integrator);
57 template <
typename T,
int NX,
int NU>
62 template <
typename T,
int NX,
int NU>
66 return SimulateOneStep(x, u);
69 template <
typename T,
int NX,
int NU>
72 if (dt_in < 0.0001)
ThrowPretty(
"dt needs to be strictly greater than 0. Provided: " << dt_in);
76 template <
typename T,
int NX,
int NU>
87 Integrate(x, xdot, dt_, xout);
121 template <
typename T,
int NX,
int NU>
124 assert(num_positions_ == num_velocities_);
125 assert(x.size() == get_num_state());
126 assert(dx.size() == get_num_state_derivative());
127 assert(xout.size() == get_num_state());
128 if (dt < 1e-6)
ThrowPretty(
"dt needs to be positive!");
135 xout.noalias() = x + dt * dx;
143 dx_new.head(num_positions_) = dt * x.tail(num_velocities_) + (dt * dt) * dx.tail(num_velocities_);
144 dx_new.tail(num_velocities_) = dt * dx.tail(num_velocities_);
145 xout.noalias() = x + dx_new;
158 template <
typename T,
int NX,
int NU>
161 const int num_timesteps =
static_cast<int>(t / dt_);
163 for (
int i = 0; i < num_timesteps; ++i)
165 x_t_plus_1 = SimulateOneStep(x_t_plus_1, u);
170 template <
typename T,
int NX,
int NU>
173 assert(x_in.size() == get_num_state());
174 return x_in.head(num_positions_).eval();
177 template <
typename T,
int NX,
int NU>
180 return num_controls_;
183 template <
typename T,
int NX,
int NU>
186 return num_positions_;
189 template <
typename T,
int NX,
int NU>
192 return num_velocities_;
195 template <
typename T,
int NX,
int NU>
198 if (num_state_ == -1)
199 return num_positions_ + num_velocities_;
204 template <
typename T,
int NX,
int NU>
207 if (num_state_derivative_ == -1)
208 return 2 * num_velocities_;
210 return num_state_derivative_;
213 template <
typename T,
int NX,
int NU>
219 template <
typename T,
int NX,
int NU>
225 template <
typename T,
int NX,
int NU>
228 integrator_ = integrator_in;
231 template <
typename T,
int NX,
int NU>
234 if (integrator_in ==
"RK1")
236 else if (integrator_in ==
"SymplecticEuler")
238 else if (integrator_in ==
"RK2")
240 else if (integrator_in ==
"RK4")
243 ThrowPretty(
"Unknown integrator: " << integrator_in);
246 template <
typename T,
int NX,
int NU>
249 if (!control_limits_initialized_)
250 set_control_limits(raw_control_limits_low_, raw_control_limits_high_);
251 return control_limits_;
254 template <
typename T,
int NX,
int NU>
257 if (num_controls_ == -1)
258 ThrowPretty(
"Attempting to set control limits before num_controls is set.");
260 control_limits_initialized_ =
true;
261 control_limits_ = Eigen::MatrixXd(num_controls_, 2);
263 if (control_limits_low.size() == num_controls_)
264 control_limits_.col(0) = control_limits_low;
265 else if (control_limits_low.size() == 1)
266 control_limits_.col(0) = Eigen::VectorXd::Constant(num_controls_, control_limits_low(0));
268 ThrowPretty(
"Wrong control limits (low) size. Should either be 1 or " << num_controls_);
270 if (control_limits_high.size() == num_controls_)
271 control_limits_.col(1) = control_limits_high;
272 else if (control_limits_high.size() == 1)
273 control_limits_.col(1) = Eigen::VectorXd::Constant(num_controls_, control_limits_high(0));
275 ThrowPretty(
"Wrong control limits (high) size. Should either be 1 or " << num_controls_);
278 template <
typename T,
int NX,
int NU>
281 if (!has_state_limits_)
ThrowPretty(
"No StateLimits!");
282 if (state_in.size() != get_num_state())
ThrowPretty(
"Wrong size state passed in!");
283 assert(state_in.size() == state_limits_lower_.size());
284 assert(state_limits_lower_.size() == state_limits_upper_.size());
286 state_in = state_in.cwiseMax(state_limits_lower_).cwiseMin(state_limits_upper_);
289 template <
typename T,
int NX,
int NU>
292 if (second_order_derivatives_initialized_)
295 const int ndx = get_num_state_derivative();
297 fxx_default_ = Eigen::Tensor<T, 3>(ndx, ndx, ndx);
298 fxx_default_.setZero();
300 fuu_default_ = Eigen::Tensor<T, 3>(ndx, num_controls_, num_controls_);
301 fuu_default_.setZero();
303 fxu_default_ = Eigen::Tensor<T, 3>(ndx, ndx, num_controls_);
304 fxu_default_.setZero();
306 dStateDelta_.setIdentity(get_num_state_derivative(), get_num_state_derivative());
307 ddStateDelta_.setConstant(get_num_state_derivative(), Eigen::MatrixXd::Zero(get_num_state_derivative(), get_num_state_derivative()));
309 second_order_derivatives_initialized_ =
true;
312 template <
typename T,
int NX,
int NU>
315 if (!second_order_derivatives_initialized_) InitializeSecondOrderDerivatives();
319 template <
typename T,
int NX,
int NU>
322 if (!second_order_derivatives_initialized_) InitializeSecondOrderDerivatives();
326 template <
typename T,
int NX,
int NU>
329 if (!second_order_derivatives_initialized_) InitializeSecondOrderDerivatives();
333 template <
typename T,
int NX,
int NU>
336 ThrowPretty(
"This dynamics solver does not support inverse dynamics!");
339 template <
typename T,
int NX,
int NU>
342 const int nx = get_num_state();
343 const int ndx = get_num_state_derivative();
352 Eigen::MatrixXd fx_fd(ndx, ndx);
353 constexpr
double eps = 1e-6;
354 Eigen::VectorXd x_low(nx), x_high(nx), xdiff(ndx);
355 for (
int i = 0; i < ndx; ++i)
358 xdiff(i) = eps / 2.0;
360 Integrate(x, -xdiff, 1., x_low);
361 Integrate(x, xdiff, 1., x_high);
363 fx_fd.col(i) = (
f(x_high, u) -
f(x_low, u)) / eps;
367 integrator_ = previous_integrator;
372 template <
typename T,
int NX,
int NU>
378 template <
typename T,
int NX,
int NU>
381 const int ndx = get_num_state_derivative();
384 constexpr
double eps = 1e-6;
385 Eigen::MatrixXd fu_fd(ndx, num_controls_);
386 Eigen::VectorXd u_low(num_controls_), u_high(num_controls_);
387 for (
int i = 0; i < num_controls_; ++i)
391 u_low(i) -= eps / 2.0;
392 u_high(i) += eps / 2.0;
394 fu_fd.col(i) = (
f(x, u_high) -
f(x, u_low)) / eps;
400 template <
typename T,
int NX,
int NU>
406 template <
typename T,
int NX,
int NU>
415 Eigen::Block<Eigen::MatrixXd> da_dx = fx_.block(num_velocities_, 0, num_velocities_, get_num_state_derivative());
416 Eigen::Block<Eigen::MatrixXd> da_du = fu_.block(num_velocities_, 0, num_velocities_, num_controls_);
419 Fx_.setZero(get_num_state_derivative(), get_num_state_derivative());
420 Fu_.setZero(get_num_state_derivative(), get_num_controls());
427 Fx_.topRightCorner(num_velocities_, num_velocities_).diagonal().array() = dt_;
428 Fx_.bottomRows(num_velocities_).noalias() = dt_ * da_dx;
429 Fx_.diagonal().array() += 1.0;
431 Fu_.bottomRows(num_velocities_).noalias() = da_du * dt_;
437 Fx_.topRows(num_velocities_).noalias() = da_dx * dt_ * dt_;
438 Fx_.bottomRows(num_velocities_).noalias() = da_dx * dt_;
439 Fx_.topRightCorner(num_velocities_, num_velocities_).diagonal().array() += dt_;
440 Fx_.diagonal().array() += 1.0;
442 Fu_.topRows(num_velocities_).noalias() = da_du * dt_ * dt_;
443 Fu_.bottomRows(num_velocities_).noalias() = da_du * dt_;
451 template <
typename T,
int NX,
int NU>
457 template <
typename T,
int NX,
int NU>
463 template <
typename T,
int NX,
int NU>
469 template <
typename T,
int NX,
int NU>
void set_control_limits(Eigen::VectorXdRefConst control_limits_low, Eigen::VectorXdRefConst control_limits_high)
Sets the control limits.
const StateDerivative & get_Fx() const
Returns derivative Fx computed by ComputeDerivatives.
void InstantiateObject(const Initializer &init)
StateVector Simulate(const StateVector &x, const ControlVector &u, T t)
Simulates the dynamic system from starting state x using control u for t seconds. ...
const ControlDerivative & get_Fu() const
Returns derivative Fu computed by ComputeDerivatives.
int get_num_velocities() const
Returns number of velocities.
virtual StateVector F(const StateVector &x, const ControlVector &u)
State transition function. This internally computes the differential dynamics and applies the chosen ...
virtual ControlVector InverseDynamics(const StateVector &state)
Returns a control vector corresponding to the state vector assuming zero acceleration.
virtual StateVector SimulateOneStep(const StateVector &x, const ControlVector &u)
Integrates the dynamic system from state x with controls u applied for one timestep dt using the sele...
T get_dt() const
Returns integration timestep dt.
Integrator get_integrator() const
Returns used integration scheme.
int get_num_positions() const
Returns number of positions.
int get_num_controls() const
Returns number of controls.
int get_num_state() const
Returns size of state space (nx)
const Eigen::MatrixXd & get_control_limits()
Returns the control limits vector.
virtual void SetDt(double dt_in)
Sets the timestep dt to be used for integration.
virtual Eigen::Matrix< T, Eigen::Dynamic, 1 > GetPosition(Eigen::VectorXdRefConst x_in)
Returns the position-part of the state vector to update the scene. For types including SE(3) and rota...
virtual void Integrate(const StateVector &x, const StateVector &dx, const double dt, StateVector &xout)
Integrates without performing dynamics.
virtual void ComputeDerivatives(const StateVector &x, const ControlVector &u)
Computes derivatives fx, fu, Fx, Fu [single call for efficiency, derivatives can be retrieved with ge...
virtual ~AbstractDynamicsSolver()
Eigen::Matrix< T, NU, 1 > ControlVector
Convenience definition for a ControlVector (dimension NU x 1)
virtual void AssignScene(std::shared_ptr< Scene > scene_in)
Passes the Scene of the PlanningProblem to the DynamicsSolver.
virtual void InstantiateBase(const Initializer &init)
Instantiates the base properties of the DynamicsSolver.
const Eigen::Ref< const Eigen::VectorXd > & VectorXdRefConst
Convenience wrapper for storing references to sub-matrices/vectors.
#define INFO_NAMED(name, x)
const StateDerivative & get_fx() const
Returns derivative fx computed by ComputeDerivatives.
void SetIntegrator(const std::string &integrator_in)
Sets integrator type based on request string.
void InitializeSecondOrderDerivatives()
virtual Eigen::Tensor< T, 3 > fxu(const StateVector &x, const ControlVector &u)
const ControlDerivative & get_fu() const
Returns derivative fu computed by ComputeDerivatives.
virtual StateDerivative fx(const StateVector &x, const ControlVector &u)
Derivative of the forward dynamics w.r.t. the state.
void set_integrator(Integrator integrator_in)
Sets integrator type.
int get_num_state_derivative() const
Returns size of derivative vector of state space (ndx)
ControlDerivative fu_fd(const StateVector &x, const ControlVector &u)
Derivative of the forward dynamics w.r.t. the control [finite differencing].
virtual Eigen::Tensor< T, 3 > fuu(const StateVector &x, const ControlVector &u)
void ClampToStateLimits(Eigen::Ref< Eigen::VectorXd > state_in)
Clamps the passed in state to the state limits.
virtual Eigen::Tensor< T, 3 > fxx(const StateVector &x, const ControlVector &u)
StateDerivative fx_fd(const StateVector &x, const ControlVector &u)
Derivative of the forward dynamics w.r.t. the state [finite differencing].
virtual ControlDerivative fu(const StateVector &x, const ControlVector &u)
Derivative of the forward dynamics w.r.t. the control.
Eigen::Matrix< T, NX, 1 > StateVector
Convenience definition for a StateVector containing both position and velocity (dimension NX x 1) ...