DMP_BBO library
SpringDamperSystem.cpp
Go to the documentation of this file.
1 
25 #include <boost/serialization/export.hpp>
26 #include <boost/archive/text_iarchive.hpp>
27 #include <boost/archive/text_oarchive.hpp>
28 #include <boost/archive/xml_iarchive.hpp>
29 #include <boost/archive/xml_oarchive.hpp>
31 
34 
35 #include <cmath>
36 #include <iostream>
37 #include <eigen3/Eigen/Core>
38 
41 
42 using namespace std;
43 using namespace Eigen;
44 
45 namespace DmpBbo {
46 
47 SpringDamperSystem::SpringDamperSystem(double tau, Eigen::VectorXd y_init, Eigen::VectorXd y_attr, double damping_coefficient, double spring_constant, double mass, std::string name)
48  : DynamicalSystem(2, tau, y_init, y_attr, name),
49  damping_coefficient_(damping_coefficient),spring_constant_(spring_constant),mass_(mass)
50 {
51  if (spring_constant_==CRITICALLY_DAMPED)
52  spring_constant_ = damping_coefficient_*damping_coefficient_/4; // Critically damped
53 
54  y_ = VectorXd(dim_orig());
55  z_ = VectorXd(dim_orig());
56  yd_ = VectorXd(dim_orig());
57  zd_ = VectorXd(dim_orig());
58  y_attr_ = VectorXd(dim_orig());
59 
60 }
61 
63 {
64 }
65 
67 {
69  damping_coefficient_,spring_constant_,mass_,name());
70 }
71 
73  const Eigen::Ref<const Eigen::VectorXd>& x,
74  Eigen::Ref<Eigen::VectorXd> xd) const
75 {
76  ENTERING_REAL_TIME_CRITICAL_CODE
77 
78  // Spring-damper system was originally 2nd order, i.e. with [x xd xdd]
79  // After rewriting it as a 1st order system it becomes [y z yd zd], with yd = z;
80 
81  // Get 'y' and 'z' parts of the state in 'x'
82  // (These memory for these vectors has been initialized in the constructor to enable realtime.)
83  y_ = x.segment(0,dim_orig());
84  z_ = x.segment(dim_orig(),dim_orig());
85  attractor_state(y_attr_);
86  //y_attr_ = attractor_state*(.segment(0,dim_orig());
87 
88 
89  // Compute yd and zd
90  // See http://en.wikipedia.org/wiki/Damped_spring-mass_system#Example:mass_.E2.80.93spring.E2.80.93damper
91  // and equation 2.1 of http://www-clmc.usc.edu/publications/I/ijspeert-NC2013.pdf
92 
93  yd_ = z_/tau();
94 
95  zd_ = (-spring_constant_*(y_-y_attr_) - damping_coefficient_*z_)/(mass_*tau());
96 
97  xd.segment(0,dim()/2) = yd_;
98  xd.segment(dim()/2,dim()/2) = zd_;
99 
100  EXITING_REAL_TIME_CRITICAL_CODE
101 }
102 
103 void SpringDamperSystem::analyticalSolution(const VectorXd& ts, MatrixXd& xs, MatrixXd& xds) const
104 {
105  int T = ts.size();
106  assert(T>0);
107 
108  // Usually, we expect xs and xds to be of size T X dim(), so we resize to that. However, if the
109  // input matrices were of size dim() X T, we return the matrices of that size by doing a
110  // transposeInPlace at the end. That way, the user can also request dim() X T sized matrices.
111  bool caller_expects_transposed = (xs.rows()==dim() && xs.cols()==T);
112 
113  // Prepare output arguments to be of right size (Eigen does nothing if already the right size)
114  xs.resize(T,dim());
115  xds.resize(T,dim());
116 
117  VectorXd y_init = initial_state();
118  VectorXd y_attr = attractor_state();
119 
120  // Closed form solution to 2nd order canonical system
121  // This system behaves like a critically damped spring-damper system
122  // http://en.wikipedia.org/wiki/Damped_spring-mass_system
123  double omega_0 = sqrt(spring_constant_/mass_)/tau(); // natural frequency
124  double zeta = damping_coefficient_/(2*sqrt(mass_*spring_constant_)); // damping ratio
125  if (zeta!=1.0)
126  cout << "WARNING: Spring-damper system is not critically damped, zeta=" << zeta << endl;
127 
128  // Example
129  // _______________
130  // dim = 4
131  // _______
132  // dim2= 2
133  // [y_1 y_2 z_1 z_2 yd_1 yd_2 zd_1 zd_2]
134 
135  int dim2 = dim()/2;
136 
137  // The loop is slower, but more legible than fudging around with Eigen::replicate().
138  for (int i_dim=0; i_dim<dim2; i_dim++)
139  {
140  double y0 = y_init[i_dim] - y_attr[i_dim];
141  double yd0;
142  if (y_init.size()>=dim())
143  {
144  // Initial velocities also given
145  yd0 = y_init[dim2 + i_dim];
146  }
147  else
148  {
149  // Initial velocities not given: set to zero
150  yd0 = 0.0;
151  }
152 
153  double A = y0;
154  double B = yd0 + omega_0*y0;
155 
156  // Closed form solutions
157  // See http://en.wikipedia.org/wiki/Damped_spring-mass_system
158  VectorXd exp_term = -omega_0*ts;
159  exp_term = exp_term.array().exp();
160 
161  int Y = 0*dim2 + i_dim;
162  int Z = 1*dim2 + i_dim;
163 
164  VectorXd ABts = A + B*ts.array();
165 
166  // Closed form solutions
167  // See http://en.wikipedia.org/wiki/Damped_spring-mass_system
168  // If you find this illegible, I recommend to look at the Matlab code instead...
169  xs.col(Y) = y_attr(i_dim) + (( ABts.array()))*exp_term.array();
170 
171  // Derivative of the above (use product rule: (f*g)' = f'*g + f*g'
172  xds.col(Y) = ((B - omega_0* ABts.array()))*exp_term.array();
173 
174  // Derivative of the above (again use product rule: (f*g)' = f'*g + f*g'
175  VectorXd ydds = (-omega_0*(2*B - omega_0* ABts.array()))*exp_term.array();
176 
177  // This is how to compute the 'z' terms from the 'y' terms
178  xs.col(Z) = xds.col(Y)*tau();
179  xds.col(Z) = ydds*tau();
180  }
181 
182  if (caller_expects_transposed)
183  {
184  xs.transposeInPlace();
185  xds.transposeInPlace();
186  }
187 }
188 
190 {
191  RETURN_STRING_FROM_BOOST_SERIALIZATION_XML("SpringDamperSystem");
192 }
193 
194 
195 }
double tau(void) const
Accessor function for the time constant.
int dim_orig(void) const
Get the dimensionality of the dynamical system, i.e.
SpringDamperSystem class header file.
DynamicalSystem * clone(void) const
Return a pointer to a deep copy of the DynamicalSystem object.
void analyticalSolution(const Eigen::VectorXd &ts, Eigen::MatrixXd &xs, Eigen::MatrixXd &xds) const
Return analytical solution of the system at certain times.
Eigen::VectorXd initial_state(void) const
Accessor function for the initial state of the dynamical system.
int dim(void) const
Get the dimensionality of the dynamical system, i.e.
BOOST_CLASS_EXPORT_IMPLEMENT(DmpBbo::SpringDamperSystem)
For boost::serialization.
std::string toString(void) const
Returns a string representation of the object.
#define RETURN_STRING_FROM_BOOST_SERIALIZATION_XML(name)
Macro to convert the boost XML serialization of an object into a string.
std::string name(void) const
Accessor function for the name of the dynamical system.
void differentialEquation(const Eigen::Ref< const Eigen::VectorXd > &x, Eigen::Ref< Eigen::VectorXd > xd) const
The differential equation which defines the system.
Interface for implementing dynamical systems.
Eigen::VectorXd attractor_state(void) const
Accessor function for the attractor state of the dynamical system.
Header file to generate strings from boost serialized files.
Dynamical System modelling the evolution of a spring-damper system: .
double const CRITICALLY_DAMPED
Value indicating that the spring constant should be set such that the spring damper system is critica...
~SpringDamperSystem(void)
Destructor.
Header file for serialization of Eigen matrices.