Rigid Body Dynamics Library
Function.h
Go to the documentation of this file.
1#ifndef SimTK_SimTKCOMMON_FUNCTION_H_
2#define SimTK_SimTKCOMMON_FUNCTION_H_
3
4/* -------------------------------------------------------------------------- *
5 * Simbody(tm): SimTKcommon *
6 * -------------------------------------------------------------------------- *
7 * This is part of the SimTK biosimulation toolkit originating from *
8 * Simbios, the NIH National Center for Physics-Based Simulation of *
9 * Biological Structures at Stanford, funded under the NIH Roadmap for *
10 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11 * *
12 * Portions copyright (c) 2008-12 Stanford University and the Authors. *
13 * Authors: Peter Eastman *
14 * Contributors: Michael Sherman *
15 * *
16 * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17 * not use this file except in compliance with the License. You may obtain a *
18 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19 * *
20 * Unless required by applicable law or agreed to in writing, software *
21 * distributed under the License is distributed on an "AS IS" BASIS, *
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23 * See the License for the specific language governing permissions and *
24 * limitations under the License. *
25 * -------------------------------------------------------------------------- */
26
27// Note: this file was moved from Simmath to SimTKcommon 20100601; see the
28// Simmath repository for earlier history.
29
30//#include "SimTKcommon/basics.h"
31//#include "SimTKcommon/Simmatrix.h"
32/*
33 Update:
34 This is a port of the original code so that it will work with
35 the multibody code RBDL written by Martin Felis.
36
37 Author:
38 Matthew Millard
39
40 Date:
41 Nov 2015
42
43*/
44
45#include <cassert>
46#include <rbdl/rbdl_math.h>
47#include <vector>
48#include <cmath>
49#include <cstdio>
65namespace RigidBodyDynamics {
66 namespace Addons {
67 namespace Geometry{
68
69
70template <class T>
71class Function_ {
72public:
73 class Constant;
74 class Linear;
75 class Polynomial;
76 class Sinusoid;
77 class Step;
78 virtual ~Function_() {
79 }
86 virtual T calcValue(const RigidBodyDynamics::Math::VectorNd& x) const = 0;
107 virtual T calcDerivative(const std::vector<int>& derivComponents,
108 const RigidBodyDynamics::Math::VectorNd& x) const = 0;
109
112 /*
113 T calcDerivative(const std::vector<int>& derivComponents,
114 const RigidBodyDynamics::Math::VectorNd& x) const
115 { return calcDerivative(std::vector<int>(derivComponents),x); }
116 */
117
121 virtual int getArgumentSize() const = 0;
125 virtual int getMaxDerivativeOrder() const = 0;
126};
127
131
132
133
138template <class T>
139class Function_<T>::Constant : public Function_<T> {
140public:
148 explicit Constant(T value, int argumentSize=1)
149 : argumentSize(argumentSize), value(value) {
150 }
152 assert(x.size() == argumentSize);
153 return value;
154 }
155 T calcDerivative(const std::vector<int>& derivComponents,
156 const RigidBodyDynamics::Math::VectorNd& x) const {
157 return static_cast<T>(0);
158 }
159 virtual int getArgumentSize() const {
160 return argumentSize;
161 }
163 return std::numeric_limits<int>::max();
164 }
165
168 /*
169 T calcDerivative(const std::vector<int>& derivComponents,
170 const RigidBodyDynamics::Math::VectorNd& x) const
171 { return calcDerivative(std::vector<int>(derivComponents),x); }
172 */
173private:
174 const int argumentSize;
175 const T value;
176};
177
182template <class T>
183class Function_<T>::Linear : public Function_<T> {
184public:
195 explicit Linear(
196 const RigidBodyDynamics::Math::VectorNd& coefficients)
197 : coefficients(coefficients) {
198 }
200 assert(x.size() == coefficients.size()-1);
201 T value = static_cast<T>(0);
202 for (int i = 0; i < x.size(); ++i)
203 value += x[i]*coefficients[i];
204 value += coefficients[x.size()];
205 return value;
206 }
207 T calcDerivative(const std::vector<int>& derivComponents,
208 const RigidBodyDynamics::Math::VectorNd& x) const {
209 assert(x.size() == coefficients.size()-1);
210 assert(derivComponents.size() > 0);
211 if (derivComponents.size() == 1)
212 return coefficients[derivComponents[0]];
213 return static_cast<T>(0);
214 }
215 virtual int getArgumentSize() const {
216 return coefficients.size()-1;
217 }
219 return std::numeric_limits<int>::max();
220 }
221
224 /*
225 T calcDerivative(const std::vector<int>& derivComponents,
226 const RigidBodyDynamics::Math::VectorNd& x) const
227 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
228 */
229private:
231};
232
233
238template <class T>
239class Function_<T>::Polynomial : public Function_<T> {
240public:
248 : coefficients(coefficients) {
249 }
251 assert(x.size() == 1);
252 double arg = x[0];
253 T value = static_cast<T>(0);
254 for (int i = 0; i < coefficients.size(); ++i)
255 value = value*arg + coefficients[i];
256 return value;
257 }
258 T calcDerivative(const std::vector<int>& derivComponents,
259 const RigidBodyDynamics::Math::VectorNd& x) const {
260 assert(x.size() == 1);
261 assert(derivComponents.size() > 0);
262 double arg = x[0];
263 T value = static_cast<T>(0);
264 const int derivOrder = (int)derivComponents.size();
265 const int polyOrder = coefficients.size()-1;
266 for (int i = 0; i <= polyOrder-derivOrder; ++i) {
267 T coeff = coefficients[i];
268 for (int j = 0; j < derivOrder; ++j)
269 coeff *= polyOrder-i-j;
270 value = value*arg + coeff;
271 }
272 return value;
273 }
274 virtual int getArgumentSize() const {
275 return 1;
276 }
278 return std::numeric_limits<int>::max();
279 }
280
283 /*
284 T calcDerivative(const std::vector<int>& derivComponents,
285 const RigidBodyDynamics::Math::VectorNd& x) const
286 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
287 */
288private:
290};
291
292
300template <>
301class Function_<double>::Sinusoid : public Function_<double> {
302public:
310 Sinusoid(double amplitude, double frequency, double phase=0)
311 : a(amplitude), w(frequency), p(phase) {}
312
313 void setAmplitude(double amplitude) {a=amplitude;}
314 void setFrequency(double frequency) {w=frequency;}
315 void setPhase (double phase) {p=phase;}
316
317 double getAmplitude() const {return a;}
318 double getFrequency() const {return w;}
319 double getPhase () const {return p;}
320
321 // Implementation of Function_<T> virtuals.
322
323 virtual double calcValue(
324 const RigidBodyDynamics::Math::VectorNd& x) const {
325
326 const double t = x[0]; // we expect just one argument
327 return a*std::sin(w*t + p);
328 }
329
330 virtual double calcDerivative(
331 const std::vector<int>& derivComponents,
332 const RigidBodyDynamics::Math::VectorNd& x) const {
333
334 const double t = x[0]; // time is the only argument
335 const int order = derivComponents.size();
336 // The n'th derivative is
337 // sign * a * w^n * sc
338 // where sign is -1 if floor(order/2) is odd, else 1
339 // and sc is cos(w*t+p) if order is odd, else sin(w*t+p)
340 switch(order) {
341 case 0: return a* std::sin(w*t + p);
342 case 1: return a*w* std::cos(w*t + p);
343 case 2: return -a*w*w* std::sin(w*t + p);
344 case 3: return -a*w*w*w*std::cos(w*t + p);
345 default:
346 const double sign = double(((order/2) & 0x1) ? -1 : 1);
347 const double sc = (order & 0x1) ? std::cos(w*t+p) : std::sin(w*t+p);
348 const double wn = std::pow(w, order);
349 return sign*a*wn*sc;
350 }
351 }
352
353 virtual int getArgumentSize() const {return 1;} // just time
354 virtual int getMaxDerivativeOrder() const {
355 return std::numeric_limits<int>::max();
356 }
357
360 /*
361 double calcDerivative(const std::vector<int>& derivComponents,
362 const RigidBodyDynamics::Math::VectorNd& x) const
363 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
364 */
365private:
366 double a, w, p;
367};
368
376template <class T>
377class Function_<T>::Step : public Function_<T> {
378public:
396 Step(const T& y0, const T& y1, double x0, double x1)
397 : m_y0(y0), m_y1(y1), m_yr(y1-y0), m_zero(double(0)*y0),
398 m_x0(x0), m_x1(x1), m_ooxr(1/(x1-x0)), m_sign(copysign(1,m_ooxr))
399 {
400 /*
401 SimTK_ERRCHK1_ALWAYS(x0 != x1, "Function_<T>::Step::ctor()",
402 "A zero-length switching interval is illegal; both ends were %g.", x0);
403 */
404 assert(x0 != x1);
405 std::printf( "Function_<T>::Step::ctor():"
406 "A zero-length switching interval "
407 "is illegal; both ends were %g.", x0);
408
409 }
410
412 /*
413 SimTK_ERRCHK1_ALWAYS(xin.size() == 1,
414 "Function_<T>::Step::calcValue()",
415 "Expected just one input argument but got %d.", xin.size());
416 */
417 assert(xin.size() == 1);
418 std::printf( "Function_<T>::Step::calcValue() "
419 "Expected just one input argument but got %d.",
420 xin.size());
421
422
423 const double x = xin[0];
424 if ((x-m_x0)*m_sign <= 0) return m_y0;
425 if ((x-m_x1)*m_sign >= 0) return m_y1;
426 // f goes from 0 to 1 as x goes from x0 to x1.
427 const double f = step01(m_x0,m_ooxr, x);
428 return m_y0 + f*m_yr;
429 }
430
431 T calcDerivative(const std::vector<int>& derivComponents,
432 const RigidBodyDynamics::Math::VectorNd& xin) const {
433 /*
434 SimTK_ERRCHK1_ALWAYS(xin.size() == 1,
435 "Function_<T>::Step::calcDerivative()",
436 "Expected just one input argument but got %d.", xin.size());
437 */
438 assert(xin.size() == 1);
439 std::printf( "Function_<T>::Step::calcDerivative() "
440 "Expected just one input argument but got %d.",
441 xin.size());
442
443 const int derivOrder = (int)derivComponents.size();
444
445 /*
446 SimTK_ERRCHK1_ALWAYS(1 <= derivOrder && derivOrder <= 3,
447 "Function_<T>::Step::calcDerivative()",
448 "Only 1st, 2nd, and 3rd derivatives of the step are available,"
449 " but derivative %d was requested.", derivOrder);
450 */
451 assert(1 <= derivOrder && derivOrder <= 3);
452 std::printf("Function_<T>::Step::calcDerivative() "
453 "Only 1st, 2nd, and 3rd derivatives of the step are available,"
454 " but derivative %d was requested.", derivOrder);
455
456 const double x = xin[0];
457 if ((x-m_x0)*m_sign <= 0) return m_zero;
458 if ((x-m_x1)*m_sign >= 0) return m_zero;
459 switch(derivOrder) {
460 case 1: return dstep01(m_x0,m_ooxr, x) * m_yr;
461 case 2: return d2step01(m_x0,m_ooxr, x) * m_yr;
462 case 3: return d3step01(m_x0,m_ooxr, x) * m_yr;
463 default: assert(!"impossible derivOrder");
464 }
465 return NAN*m_yr; /*NOTREACHED*/
466 }
467
468 virtual int getArgumentSize() const {return 1;}
469 int getMaxDerivativeOrder() const {return 3;}
470
473 /*
474 T calcDerivative(const std::vector<int>& derivComponents,
475 const RigidBodyDynamics::Math::VectorNd& x) const
476 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
477 */
478private:
479 const T m_y0, m_y1, m_yr; // precalculate yr=(y1-y0)
480 const T m_zero; // precalculate T(0)
481 const double m_x0, m_x1, m_ooxr; // precalculate ooxr=1/(x1-x0)
482 const double m_sign; // sign(x1-x0) is 1 or -1
483
484 double step01(double x0, double x1, double x){
485 double u = (x-x0)/(x1-x0);
486 double u2 = u*u;
487 double u3 = u2*u;
488 return (3*u2 - 2*u3);
489 }
490
491 double dstep01(double x0, double x1, double x){
492 double u = (x-x0)/(x1-x0);
493 double du = (1)/(x1-x0);
494 double du2 = 2*u*du;
495 double du3 = 3*u*u*du;
496 return (3*du2 - 2*du3);
497 }
498
499 double d2step01(double x0, double x1, double x){
500 double u = (x-x0)/(x1-x0);
501 double du = (1)/(x1-x0);
502 //double ddu = 0;
503 double ddu2 = 2*du*du;// + 2*u*ddu since ddu=0;
504 double ddu3 = 3*du*u*du + 3*u*du*du;// + 3*u*u*du; ditto
505 return (3*ddu2 - 2*ddu3);
506 }
507
508 double d3step01(double x0, double x1, double x){
509 double u = (x-x0)/(x1-x0);
510 double du = (1)/(x1-x0);
511 //double ddu = 0;
512 //double dddu = 0;
513 double dddu2 = 0; //2*du*du;// since ddu=0;
514 double dddu3 = 3*du*du*du + 3*du*du*du;// ditto
515 return (3*dddu2 - 2*dddu3);
516 }
517};
518
519}
520}
521}
522
523#endif // SimTK_SimTKCOMMON_FUNCTION_H_
524
525
unsigned int size() const
T calcDerivative(const std::vector< int > &derivComponents, const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:155
T calcValue(const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:151
const RigidBodyDynamics::Math::VectorNd coefficients
Definition: Function.h:230
Linear(const RigidBodyDynamics::Math::VectorNd &coefficients)
Definition: Function.h:195
T calcDerivative(const std::vector< int > &derivComponents, const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:207
T calcValue(const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:199
const RigidBodyDynamics::Math::VectorNd coefficients
Definition: Function.h:289
T calcDerivative(const std::vector< int > &derivComponents, const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:258
T calcValue(const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:250
Polynomial(const RigidBodyDynamics::Math::VectorNd &coefficients)
Definition: Function.h:247
Sinusoid(double amplitude, double frequency, double phase=0)
Definition: Function.h:310
virtual double calcDerivative(const std::vector< int > &derivComponents, const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:330
virtual double calcValue(const RigidBodyDynamics::Math::VectorNd &x) const
Definition: Function.h:323
double step01(double x0, double x1, double x)
Definition: Function.h:484
double dstep01(double x0, double x1, double x)
Definition: Function.h:491
double d2step01(double x0, double x1, double x)
Definition: Function.h:499
T calcValue(const RigidBodyDynamics::Math::VectorNd &xin) const
Definition: Function.h:411
double d3step01(double x0, double x1, double x)
Definition: Function.h:508
T calcDerivative(const std::vector< int > &derivComponents, const RigidBodyDynamics::Math::VectorNd &xin) const
Definition: Function.h:431
Step(const T &y0, const T &y1, double x0, double x1)
Definition: Function.h:396
virtual T calcValue(const RigidBodyDynamics::Math::VectorNd &x) const =0
virtual T calcDerivative(const std::vector< int > &derivComponents, const RigidBodyDynamics::Math::VectorNd &x) const =0
Function_< double > Function
Definition: Function.h:130
MX_Xd_static< nrows, ncols > pow(const MX_Xd_static< nrows, ncols > &m, int exponent)
Definition: MX_Xd_utils.h:383
MX_Xd_scalar cos(const MX_Xd_scalar &x)
Definition: MX_Xd_utils.h:351
MX_Xd_scalar sin(const MX_Xd_scalar &x)
Definition: MX_Xd_utils.h:345