Rigid Body Dynamics Library
SegmentedQuinticBezierToolkit.h
Go to the documentation of this file.
1#ifndef SEGMENTEDQUINTICBEZIERTOOLKIT_H_
2#define SEGMENTEDQUINTICBEZIERTOOLKIT_H_
3/* -------------------------------------------------------------------------- *
4 * OpenSim: SegmentedQuinticBezierToolkit.h *
5 * -------------------------------------------------------------------------- *
6 * The OpenSim API is a toolkit for musculoskeletal modeling and simulation. *
7 * See http://opensim.stanford.edu and the NOTICE file for more information. *
8 * OpenSim is developed at Stanford University and supported by the US *
9 * National Institutes of Health (U54 GM072970, R24 HD065690) and by DARPA *
10 * through the Warrior Web program. *
11 * *
12 * Copyright (c) 2005-2012 Stanford University and the Authors *
13 * Author(s): Matthew Millard *
14 * *
15 * Licensed under the Apache License, Version 2.0 (the "License"); you may *
16 * not use this file except in compliance with the License. You may obtain a *
17 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
18 * *
19 * Unless required by applicable law or agreed to in writing, software *
20 * distributed under the License is distributed on an "AS IS" BASIS, *
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
22 * See the License for the specific language governing permissions and *
23 * limitations under the License. *
24 * -------------------------------------------------------------------------- */
25/*
26 Update:
27 This is a port of the original code so that it will work with
28 the multibody code RBDL written by Martin Felis.
29
30 Author:
31 Matthew Millard
32
33 Date:
34 Nov 2015
35
36*/
37#include <vector>
38#include <rbdl/rbdl_math.h>
39#include <rbdl/rbdl_config.h>
40#include "Function.h"
41
173namespace RigidBodyDynamics {
174 namespace Addons {
175 namespace Geometry{
176
177class RBDL_ADDON_DLLAPI SegmentedQuinticBezierToolkit
178{
179
180
181 public:
182
193 static double scaleCurviness(double curviness);
194
241 static double calcU(
242 double ax,
243 const RigidBodyDynamics::Math::VectorNd& bezierPtsX,
244 double tol,
245 int maxIter);
246
247
248
299 static int calcIndex(
300 double x,
301 const RigidBodyDynamics::Math::MatrixNd& bezierPtsX);
302
303 static int calcIndex(
304 double x,
305 const std::vector<RigidBodyDynamics::Math::VectorNd>& bezierPtsX);
306
307
308
309
310
376 double u,
378
446 double u,
448 int order);
449
523 double u,
526 int order);
527
528
595 double dydx0,
596 double x1, double y1,
597 double dydx1,
598 double curviness);
599
600 /*
601 This function numerically integrates the Bezier curve y(x).
602
603 @param vX Values of x to evaluate the integral of y(x)
604 @param ic0 The initial value of the integral
605 @param intAcc Accuracy of the integrated solution
606 @param uTol Tolerance on the calculation of the intermediate u term
607 @param uMaxIter Maximum number of iterations allowed for u to reach its
608 desired tolerance.
609 @param mX The 6xn matrix of Bezier control points for x(u)
610 @param mY The 6xn matrix of Bezier control points for y(u)
611
612 @param flag_intLeftToRight Setting this flag to true will evaluate the
613 integral from the left most point to the right most
614 point. Setting this flag to false will cause the
615 integral to be evaluated from right to left.
616 @param name Name of caller.
617 @return RigidBodyDynamics::Math::MatrixNd Col 0: X vector, Col 1: int(y(x))
618
619
620 This function numerically integrates the Bezier curve y(x), when really
621 both x and y are specified in terms of u. Evaluate the integral at the
622 locations specified in vX and return the result.
623
624 <B>Computational Costs</B>
625
626 This the expense of this function depends on the number of points in
627 vX, the points for which the integral y(x) must be calculated. The
628 integral is evaluated using a Runge Kutta 45 integrator, and so each
629 point requires 6 function evaluations.
630 (http://en.wikipedia.org/wiki/Dormand%E2%80%93Prince_method)
631
632 The cost of evaluating 1 Bezier curve y(x) scales with the number
633 of points in xVal:
634 \verbatim
635 ~1740 flops per point
636 \endverbatim
637
638 The example below is quite involved, but just so it can show you an
639 example of how to create the array of Spline objects that approximate
640 the function u(x). Although the example has been created for only 1
641 Bezier curve set, simply changing the size and entries of the matricies
642 _mX and _mY will allow multiple sets to be integrated.
643
644
645 <B>Example:</B>
646 @code
647 //Integrator and u tolerance settings
648 double INTTOL = 1e-12;
649 double UTOL = 1e-14;
650 int MAXITER= 10;
651
652 //Make up a Bezier curve - these happen to be the control points
653 //for a tendon curve
654 RigidBodyDynamics::Math::MatrixNd _mX(6,1), _mY(6,1);
655 _mX(0)= 1;
656 _mX(1)= 1.01164;
657 _mX(2)= 1.01164;
658 _mX(3)= 1.02364;
659 _mX(4)= 1.02364;
660 _mX(5)= 1.04;
661
662 _mY(0) = 0;
663 _mY(1) = 3.10862e-16;
664 _mY(2) = 3.10862e-16;
665 _mY(3) = 0.3;
666 _mY(4) = 0.3;
667 _mY(5) = 1;
668
669 _numBezierSections = 1;
670 bool _intx0x1 = true; //Says we're integrating from x0 to x1
672 //Generate the set of splines that approximate u(x)
674 RigidBodyDynamics::Math::VectorNd u(NUM_SAMPLE_PTS);
675 //Used for the approximate inverse
676 RigidBodyDynamics::Math::VectorNd x(NUM_SAMPLE_PTS);
677 //Used for the approximate inverse
678
679 //Used to generate the set of knot points of the integral of y(x)
680 RigidBodyDynamics::Math::VectorNd
681 xALL(NUM_SAMPLE_PTS*_numBezierSections-(_numBezierSections-1));
682 _arraySplineUX.resize(_numBezierSections);
683 int xidx = 0;
684
685 for(int s=0; s < _numBezierSections; s++){
686 //Sample the local set for u and x
687 for(int i=0;i<NUM_SAMPLE_PTS;i++){
688 u(i) = ( (double)i )/( (double)(NUM_SAMPLE_PTS-1) );
689 x(i) = SegmentedQuinticBezierToolkit::
690 calcQuinticBezierCurveVal(u(i),_mX(s),_name);
691 if(_numBezierSections > 1){
692 //Skip the last point of a set that has another set of points
693 //after it. Why? The last point and the starting point of the
694 //next set are identical in value.
695 if(i<(NUM_SAMPLE_PTS-1) || s == (_numBezierSections-1)){
696 xALL(xidx) = x(i);
697 xidx++;
698 }
699 }else{
700 xALL(xidx) = x(i);
701 xidx++;
702 }
703 }
704 //Create the array of approximate inverses for u(x)
705 _arraySplineUX[s] = SimTK::SplineFitter<double>::
706 fitForSmoothingParameter(3,x,u,0).getSpline();
707 }
708
709
711 //Compute the integral of y(x) and spline the result
713
714 RigidBodyDynamics::Math::VectorNd yInt = SegmentedQuinticBezierToolkit::
715 calcNumIntBezierYfcnX(xALL,0,INTTOL, UTOL, MAXITER,_mX, _mY,
716 _arraySplineUX,_name);
717
718 if(_intx0x1==false){
719 yInt = yInt*-1;
720 yInt = yInt - yInt(yInt.nelt()-1);
721 }
722
723 _splineYintX = SimTK::SplineFitter<double>::
724 fitForSmoothingParameter(3,xALL,yInt,0).getSpline();
725
726 @endcode
727
728
729 */
730
731//MM: Can't port this over to RBDL as RBDL doesn't have an error
732// controlled integrator. I could add this if a dependency
733// like Boost was allowed.
734//
735// static RigidBodyDynamics::Math::MatrixNd
736// calcNumIntBezierYfcnX(
737// const RigidBodyDynamics::Math::VectorNd& vX,
738// double ic0,
739// double intAcc,
740// double uTol,
741// int uMaxIter,
742// const RigidBodyDynamics::Math::MatrixNd& mX,
743// const RigidBodyDynamics::Math::MatrixNd& mY,
744// const SimTK::Array_<SimTK::Spline>& aSplineUX,
745// bool flag_intLeftToRight,const std::string& name);
746
747
748 private:
749
750
761 static void printMatrixToFile(
764 std::string& filename);
765
775 const Function_<double>& curveFit,
779 std::string& filename);
780
787 static double clampU(double u);
788
789
791
796class BezierData {
797 public:
804 //std::vector< std::vector<double> > _aArraySplineUX;
806 double _initalValue;
811 double _uTol;
815 int _uMaxIter;
819 //bool _flag_intLeftToRight;
821 //double _startValue;
822
825 std::string _name;
826};
828
829
830};
831
832}
833}
834}
835
836
837#endif
static double calcQuinticBezierCurveVal(double u, const RigidBodyDynamics::Math::VectorNd &pts)
static int calcIndex(double x, const RigidBodyDynamics::Math::MatrixNd &bezierPtsX)
static int calcIndex(double x, const std::vector< RigidBodyDynamics::Math::VectorNd > &bezierPtsX)
static double calcU(double ax, const RigidBodyDynamics::Math::VectorNd &bezierPtsX, double tol, int maxIter)
static void printBezierSplineFitCurves(const Function_< double > &curveFit, RigidBodyDynamics::Math::MatrixNd &ctrlPts, RigidBodyDynamics::Math::VectorNd &xVal, RigidBodyDynamics::Math::VectorNd &yVal, std::string &filename)
static void printMatrixToFile(const RigidBodyDynamics::Math::VectorNd &col0, const RigidBodyDynamics::Math::MatrixNd &data, std::string &filename)
static double calcQuinticBezierCurveDerivDYDX(double u, const RigidBodyDynamics::Math::VectorNd &xpts, const RigidBodyDynamics::Math::VectorNd &ypts, int order)
static RigidBodyDynamics::Math::MatrixNd calcQuinticBezierCornerControlPoints(double x0, double y0, double dydx0, double x1, double y1, double dydx1, double curviness)
static double calcQuinticBezierCurveDerivU(double u, const RigidBodyDynamics::Math::VectorNd &pts, int order)