00001 /* **-*-c++-*-************************************************************** 00002 Copyright (C)2002 David Jung <opensim@pobox.com> 00003 00004 This program/file is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. (http://www.gnu.org) 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 $Id: IKORFullSpaceSolver 1080 2004-07-28 19:51:26Z jungd $ 00019 $Revision: 1.8 $ 00020 $Date: 2004-07-28 15:51:26 -0400 (Wed, 28 Jul 2004) $ 00021 $Author: jungd $ 00022 00023 ****************************************************************************/ 00024 00025 #ifndef _ROBOT_CONTROL_KINEMATICS_IKORFULLSPACESOLVER_ 00026 #define _ROBOT_CONTROL_KINEMATICS_IKORFULLSPACESOLVER_ 00027 00028 #include <robot/control/kinematics/kinematics> 00029 00030 #include <robot/control/kinematics/FullSpaceSolver> 00031 00032 00033 namespace robot { 00034 namespace control { 00035 namespace kinematics { 00036 00037 00038 00039 /// Solver that finds the Full-space using the IKOR project method 00040 /// (refer to the OpenSim manual and references publications for detail) 00041 class IKORFullSpaceSolver : public FullSpaceSolver 00042 { 00043 public: 00044 IKORFullSpaceSolver(); 00045 00046 virtual String className() const { return String("IKORFullSpaceSolver"); } 00047 virtual Object& clone() const { return *NewObj IKORFullSpaceSolver(*this); } 00048 00049 /// Computes a set of vectors gi that can be used to find solutions to Ax=b for x 00050 /** 00051 * @param A_in NxM Matrix 00052 * @param b_in N-dim Vector 00053 * @param dependentRowsEliminated is filled out with the indices of rows of A_in 00054 * that are eliminated from the computation because they 00055 * are dependent (actually if Ai|bi is dependent. If only 00056 * Ai is dependent but bi conflicts an exception is throw 00057 * because solution is impossible) 00058 * @return returns the set of vector gis as columns of a Matrix 00059 * @exception std::invalid_argument if gis can't be found for the provided A & b 00060 */ 00061 virtual Matrix solve(const Matrix& A_in, const Vector& b_in, 00062 array<Int>& dependentRowsEliminated); 00063 00064 protected: 00065 IKORFullSpaceSolver(const IKORFullSpaceSolver& c) : FullSpaceSolver(c) {} 00066 00067 // Constants to indicate which rows/cols have been eliminated from A, any why. 00068 // used in solve()'s rowElim/colElim vectors 00069 // (NB: the actual values are the same as those used in IKORv2.0, for comparison) 00070 static const Int NotEleminated = 0; 00071 static const Int Eliminated_ZeroOrRestriction = 1; 00072 static const Int RowEliminated_Dependent = 2; 00073 static const Int RowEliminated_Special = 1; 00074 static const Int ColEliminated_SpecialCase1 = 2; 00075 static const Int ColEliminated_SpecialCase2 = 3; 00076 00077 inline static bool isSmall(Real a) { return Math::abs(a) < 5.0e-05; /*(=def. SMALL)*/ } 00078 00079 00080 /// Reduces the A matrix 00081 /** 00082 * This is what IKORv2.0 had to say (below). 00083 * Again; why a general solution method for Matrices is talking 00084 * about work spaces, joint etc. is a little concerning! 00085 * 00086 * Restricted work space motions can be 00087 * identified by rows of the A which only 00088 * have one nonzero element. Since the 00089 * corresponding column must be present in 00090 * all final joint space solutions, the 00091 * appropriate joint space motion will be 00092 * calculated before any redundancy 00093 * resolution is performed, and the 00094 * appropriate motions and joints will be 00095 * removed from the work space and A 00096 * respectively. Also such cases as 00097 * dependent rows, and SpecialCase1 must be 00098 * identified and dealt with. 00099 */ 00100 void reduceA(const Matrix& A, Matrix& Ared, 00101 const Vector& b, Vector& bred, 00102 const Int M, const Int N, 00103 Int& Mred, Int& Nred, 00104 base::IVector& colElim, base::IVector& rowElim, 00105 Matrix& specialg, Int& numSpecialgs); 00106 00107 00108 /// calculate a new g vector for a given square blocking pattern 00109 void blockColFindX(Vector& g, 00110 const base::IVector& tackon, const Vector& block, 00111 const Vector& b, const Matrix& A, 00112 const Int Mred, const Int Nred); 00113 00114 00115 /// Finds the remaining solution vectors after the first has been selected. 00116 /** It is recursive and thus calls itself when a 00117 * valid solution is found, if this solution 00118 * leads to a dead end, it will pop back to 00119 * last solution and build from there. This 00120 * insures that all possible combinations of 00121 * blocking patterns are available, given 00122 * first one, in pattern which follows the 00123 * algoritm presented in the article. 00124 */ 00125 void restOfSoln( const Int M, const Int N, const Int Mred, const Int Nred, 00126 Int nextToFind, 00127 Matrix& block, Matrix& g, 00128 const Vector& bred, const Matrix& Ared, 00129 const base::IVector& tackon, base::IVector& firstOK); 00130 00131 00132 /// returns true if the given two columns and dependent (used in special-case 1 detection) 00133 bool dependency(const Matrix& A, const base::IVector& slRow, Int Nred, Int first, Int second) const; 00134 00135 /// returns true if the original b is in the range of A 00136 bool checkRange(const Matrix& A, const Vector& b, const Matrix& g, const base::IVector& rowElim); 00137 00138 00139 /// rebuilds the g Matrix 00140 /** adds zeros in eliminated cols and tacks on the g vectors created 00141 * by special-case 1 00142 */ 00143 void rebuildgs(Matrix& g, 00144 const Int M, const Int N, const Int Mred, const Int Nred, 00145 const base::IVector& colElim, const base::IVector& rowElim, 00146 const Matrix& specialg, const Int numSpecialgs); 00147 00148 00149 bool systemComplete; 00150 00151 enum Status { Unknown=0, Restricted, Complete, NotComplete }; 00152 Status status; 00153 00154 }; 00155 00156 00157 } // namespace kinematics 00158 } // namespace control 00159 } // namespace robot 00160 00161 #endif