00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <robot/control/kinematics/IKORController>
00026
00027 #include <robot/control/kinematics/MPPseudoInvSolver>
00028 #include <robot/control/kinematics/LeastNormIKSolver>
00029 #include <robot/control/kinematics/FullSpaceSolver>
00030 #include <robot/control/kinematics/IKOR>
00031
00032
00033 using robot::control::kinematics::IKORController;
00034
00035 using base::Matrix;
00036 using base::Orient;
00037 using robot::ControlInterface;
00038 using robot::control::kinematics::LeastNormIKSolver;
00039 using robot::control::kinematics::IKOR;
00040
00041
00042
00043 IKORController::IKORController(IKMethod method, ref<robot::Robot> robot, Int manipulatorIndex,
00044 bool platformActive, bool orientationControl,
00045 base::Orient::Representation orientationRepresentation)
00046 : method(method), robot(robot),
00047 platformActive(platformActive), orientationControl(orientationControl),
00048 orientRep(orientationRepresentation),
00049 d(0.1)
00050 {
00051 ref<const RobotDescription> rd( robot->getRobotDescription() );
00052 if (!rd->platform()->isMobile() && platformActive)
00053 throw std::invalid_argument(Exception("A fixed Platform cannot be active"));
00054
00055 array<ref<const ManipulatorDescription> > manipulators( rd->manipulators() );
00056
00057 if (manipulators.size() == 0)
00058 throw std::invalid_argument(Exception("Robots without a manipulator not currently supported"));
00059
00060 if (manipulatorIndex >= manipulators.size())
00061 throw std::out_of_range(Exception("manipulatorIndex is invalid"));
00062
00063 ref<const ManipulatorDescription> manipulator( manipulators[manipulatorIndex] );
00064
00065 if (manipulator->type() != ManipulatorDescription::Serial)
00066 throw std::invalid_argument(Exception("Only serial manipulators are supported"));
00067
00068
00069 manipChain = manipulator->getKinematicChain();
00070
00071
00072
00073 try {
00074 proxInterface = robot->getControlInterface(String("manipulatorProximity")+base::intToString(manipulatorIndex+1));
00075 } catch (std::invalid_argument& e) {
00076 proxInterface = ref<ControlInterface>(0);
00077 }
00078
00079
00080 switch (method) {
00081
00082 case LeastNorm: {
00083 ikSolver = ref<InverseKinematicsSolver>(NewObj LeastNormIKSolver());
00084 optMethod = LeastNormIKSolver::DefaultMethod;
00085 optCriterion = LeastNormIKSolver::LeastNorm;
00086 optConstraints.set( LeastNormIKSolver::DefaultConstraints );
00087
00088 }
00089 break;
00090
00091 case FSPLagrangian: {
00092 ikSolver = ref<InverseKinematicsSolver>(NewObj IKOR(manipChain, Vector(), platformActive));
00093 optMethod = IKOR::Lagrangian;
00094 optCriterion = IKOR::LeastNorm;
00095 optConstraints.set(IKOR::JointLimits);
00096 if (proxInterface != 0)
00097 optConstraints.set(IKOR::ObstacleAvoidance);
00098 }
00099 break;
00100
00101 default:
00102 throw std::invalid_argument(Exception("unsupported/unknown IKMethod"));
00103 }
00104
00105
00106 inputName.at(0) = "x";
00107 inputName.at(1) = "y";
00108 inputName.at(2) = "z";
00109 for(Int o=0; o<9; o++)
00110 inputName.at(3+o) = "o"+base::intToString(o);
00111
00112 outputName.at(0) = "dx";
00113 outputName.at(1) = "dy";
00114 outputName.at(2) = "dz";
00115 for(Int o=0; o<9; o++)
00116 inputName.at(3+o) = "do"+base::intToString(o);
00117
00118 x.reset(zeroVector( 3+Orient(orientRep).size() ));
00119 tx.reset(zeroVector(orientationControl?x.size():3));
00120 }
00121
00122
00123
00124 void IKORController::setControlInterface(ref<ControlInterface> controlInterface)
00125 {
00126 if (controlInterface->getType() == "JointPositionControl") {
00127 manipulatorInterface = controlInterface;
00128
00129 calcEEPositionOrientation();
00130 tx = vectorRange(x,Range(0,tx.size()));
00131 }
00132 else {
00133 Logln("Ignoring useless interface - name:" << controlInterface->getName() << " type:" << controlInterface->getType());
00134 }
00135 }
00136
00137
00138 bool IKORController::iterate(const base::Time& time)
00139 {
00140 if (!isConnected()) return false;
00141 try {
00142 calcEEPositionOrientation();
00143 Vector x2(x);
00144 if (!orientationControl) {
00145 x2.resize(3);
00146 x2 = vectorRange(x,Range(0,3));
00147 }
00148
00149
00150
00151
00152
00153
00154 if (proxInterface != 0) {
00155 array<InverseKinematicsSolver::LinkProximityData> proxData( manipChain.dof() );
00156
00157
00158 Vector proximityInputs( proxInterface->getInputs() );
00159
00160
00161 for(Int v=0; v < manipChain.dof(); v++) {
00162 Int l = manipChain.linkIndexOfVariable(v);
00163 InverseKinematicsSolver::LinkProximityData& pd(proxData[v]);
00164
00165 pd.distance = proximityInputs[l*5];
00166 pd.direction.resize(3);
00167 pd.direction[0] = proximityInputs[l*5+1];
00168 pd.direction[1] = proximityInputs[l*5+2];
00169 pd.direction[2] = proximityInputs[l*5+3];
00170 pd.intercept = proximityInputs[l*5+4];
00171 }
00172
00173 ikSolver->setProximitySensorData(proxData, d);
00174
00175 }
00176
00177
00178
00179
00180 Vector dx = tx-x2;
00181 Matrix J( manipChain.getJacobian(q, orientationControl) );
00182 Vector dq( ikSolver->solve(dx, x2, q, J, optMethod, optCriterion, optConstraints, orientRep) );
00183
00184
00185 manipulatorInterface->setOutputs(q+dq);
00186
00187 } catch (std::exception& e) {
00188
00189 Logln("Warning: controller error:" << e.what());
00190 }
00191
00192 return false;
00193 }
00194
00195
00196 base::array<std::pair<String,String> > IKORController::controlInterfaces() const
00197 {
00198 array<std::pair<String, String> > a;
00199
00200 a.push_back(std::make_pair<String,String>("manipulatorEEPosition","EndEffectorPositionControl"));
00201 a.push_back(std::make_pair<String,String>("manipulatorLinkPositions","LinkOriginPositions"));
00202
00203 return a;
00204 }
00205
00206
00207 ref<ControlInterface> IKORController::getControlInterface(String interfaceName) throw(std::invalid_argument)
00208 {
00209 if (!isConnected())
00210 throw std::invalid_argument(Exception("unsupported interface (not yet connected)"));
00211
00212 if (interfaceName=="") interfaceName="manipulatorEEPosition";
00213
00214 if (interfaceName=="manipulatorEEPosition")
00215 return ref<ControlInterface>(NewObj EEPositionControlInterface(ref<IKORController>(this), "manipulatorEEPosition", "EndEffectorPositionControl"));
00216
00217 if (interfaceName=="manipulatorLinkPositions")
00218 return ref<ControlInterface>(NewObj LinkPositionsControlInterface(ref<IKORController>(this), "manipulatorLinkPositions","LinkOriginPositions"));
00219
00220 throw std::invalid_argument(Exception(String("unsupported interface name:")+interfaceName));
00221 }
00222
00223
00224 void IKORController::calcEEPositionOrientation()
00225 {
00226
00227 q.reset( manipulatorInterface->getInputs() );
00228 Matrix T( manipChain.getForwardKinematics(q) );
00229
00230
00231
00232
00233 Vector pos(3); pos = vectorRange(Vector(matrixColumn(T,3)), Range(0,3));
00234 Matrix rot(3,3); rot = matrixRange(T, Range(0,3), Range(0,3));
00235 Vector orient( Orient(rot).getVector(orientRep) );
00236 x.resize(3+Orient::size(orientRep));
00237 vectorRange(x, Range(0,3)) = pos;
00238 vectorRange(x, Range(3,x.size())) = orient;
00239 }
00240
00241
00242 base::array<base::String> IKORController::inputName;
00243 base::array<base::String> IKORController::outputName;
00244
00245
00246
00247
00248
00249 inline Int IKORController::EEPositionControlInterface::inputSize() const
00250 {
00251 return 3+Orient(c->orientRep).size();
00252 }
00253
00254 String IKORController::EEPositionControlInterface::inputName(Int i) const
00255 {
00256 if (i>=inputSize())
00257 throw std::out_of_range(Exception("index out of range"));
00258
00259 return c->inputName[i];
00260 }
00261
00262 Real IKORController::EEPositionControlInterface::getInput(Int i) const
00263 {
00264 if (i>=inputSize())
00265 throw std::out_of_range(Exception("index out of range"));
00266
00267 c->calcEEPositionOrientation();
00268 return c->x[i];
00269 }
00270
00271 const base::Vector& IKORController::EEPositionControlInterface::getInputs() const
00272 {
00273 c->calcEEPositionOrientation();
00274 return c->x;
00275 }
00276
00277 inline Int IKORController::EEPositionControlInterface::outputSize() const
00278 {
00279 return (c->orientationControl?inputSize():3);
00280 }
00281
00282 String IKORController::EEPositionControlInterface::outputName(Int i) const
00283 {
00284 if (i>=outputSize())
00285 throw std::out_of_range(Exception("index out of range"));
00286
00287 return c->inputName[i];
00288 }
00289
00290 void IKORController::EEPositionControlInterface::setOutput(Int i, Real value)
00291 {
00292 if (i>=outputSize())
00293 throw std::out_of_range(Exception("index out of range"));
00294
00295 c->calcEEPositionOrientation();
00296 c->tx[i] = value;
00297 }
00298
00299 void IKORController::EEPositionControlInterface::setOutputs(const Vector& values)
00300 {
00301 if (values.size() != outputSize())
00302 throw std::out_of_range(Exception("dimension not equal to output dimension"));
00303
00304 c->calcEEPositionOrientation();
00305 c->tx = values;
00306 }
00307
00308
00309
00310
00311
00312
00313 inline Int IKORController::LinkPositionsControlInterface::inputSize() const
00314 {
00315 return c->manipChain.dof()*3;
00316 }
00317
00318 String IKORController::LinkPositionsControlInterface::inputName(Int i) const
00319 {
00320 if (i>=inputSize())
00321 throw std::out_of_range(Exception("index out of range"));
00322
00323 Int j = i/3;
00324 Int c = i - (j*3);
00325 String coord( (c==0)?"x":((c==1)?"y":"z") );
00326 return coord+base::intToString(j);
00327 }
00328
00329 Real IKORController::LinkPositionsControlInterface::getInput(Int i) const
00330 {
00331 if (i>=inputSize())
00332 throw std::out_of_range(Exception("index out of range"));
00333
00334 const Vector& linkPositions( getInputs() );
00335 return linkPositions[i];
00336 }
00337
00338
00339
00340 const base::Vector& IKORController::LinkPositionsControlInterface::getInputs() const
00341 {
00342
00343
00344 c->q.reset( c->manipulatorInterface->getInputs() );
00345 array<Vector> jointPositions( c->manipChain.getLinkOrigins(c->q) );
00346 c->linkPositions.resize(jointPositions.size()*3);
00347 for(Int j=0; j<jointPositions.size(); j++) {
00348 c->linkPositions[3*j] = jointPositions[j][0];
00349 c->linkPositions[3*j+1] = jointPositions[j][1];
00350 c->linkPositions[3*j+2] = jointPositions[j][2];
00351 }
00352 return c->linkPositions;
00353 }
00354
00355 inline Int IKORController::LinkPositionsControlInterface::outputSize() const
00356 {
00357 return 0;
00358 }
00359
00360 String IKORController::LinkPositionsControlInterface::outputName(Int i) const
00361 {
00362 throw std::out_of_range(Exception("index out of range (interface has no outputs)"));
00363 }
00364
00365 void IKORController::LinkPositionsControlInterface::setOutput(Int i, Real value)
00366 {
00367 throw std::out_of_range(Exception("index out of range (interface has no outputs)"));
00368 }
00369
00370 void IKORController::LinkPositionsControlInterface::setOutputs(const Vector& values)
00371 {
00372 if (values.size() != 0)
00373 throw std::out_of_range(Exception("dimension not equal to output dimension (0 - no outputs)"));
00374 }