| Directory: | ./ |
|---|---|
| File: | src/feature/feature-point6d.cpp |
| Date: | 2025-05-13 12:28:21 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 127 | 287 | 44.3% |
| Branches: | 123 | 510 | 24.1% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * Copyright 2010, 2011, 2012 | ||
| 3 | * François Bleibel, | ||
| 4 | * Olivier Stasse, | ||
| 5 | * Florent Lamiraux | ||
| 6 | * Nicolas Mansard | ||
| 7 | * | ||
| 8 | * CNRS/AIST | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | /* --------------------------------------------------------------------- */ | ||
| 13 | /* --- INCLUDE --------------------------------------------------------- */ | ||
| 14 | /* --------------------------------------------------------------------- */ | ||
| 15 | |||
| 16 | /* --- SOT --- */ | ||
| 17 | //#define VP_DEBUG | ||
| 18 | //#define VP_DEBUG_MODE 45 | ||
| 19 | #include <dynamic-graph/command-bind.h> | ||
| 20 | #include <dynamic-graph/command-getter.h> | ||
| 21 | #include <dynamic-graph/command-setter.h> | ||
| 22 | #include <dynamic-graph/command.h> | ||
| 23 | |||
| 24 | #include <Eigen/LU> | ||
| 25 | #include <sot/core/debug.hh> | ||
| 26 | #include <sot/core/exception-feature.hh> | ||
| 27 | #include <sot/core/feature-point6d.hh> | ||
| 28 | #include <sot/core/macros.hh> | ||
| 29 | |||
| 30 | using namespace std; | ||
| 31 | using namespace dynamicgraph; | ||
| 32 | using namespace dynamicgraph::sot; | ||
| 33 | |||
| 34 | #include <sot/core/factory.hh> | ||
| 35 | SOT_CORE_DISABLE_WARNING_PUSH | ||
| 36 | SOT_CORE_DISABLE_WARNING_DEPRECATED | ||
| 37 | ✗ | DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(FeaturePoint6d, "FeaturePoint6d"); | |
| 38 | SOT_CORE_DISABLE_WARNING_POP | ||
| 39 | |||
| 40 | /* --------------------------------------------------------------------- */ | ||
| 41 | /* --- CLASS ----------------------------------------------------------- */ | ||
| 42 | /* --------------------------------------------------------------------- */ | ||
| 43 | |||
| 44 | const FeaturePoint6d::ComputationFrameType | ||
| 45 | FeaturePoint6d::COMPUTATION_FRAME_DEFAULT = FRAME_DESIRED; | ||
| 46 | |||
| 47 | 2 | FeaturePoint6d::FeaturePoint6d(const string &pointName) | |
| 48 | : FeatureAbstract(pointName), | ||
| 49 | 2 | computationFrame_(COMPUTATION_FRAME_DEFAULT), | |
| 50 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | positionSIN( |
| 51 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
4 | NULL, "sotFeaturePoint6d(" + name + ")::input(matrixHomo)::position"), |
| 52 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | velocitySIN(NULL, |
| 53 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | "sotFeaturePoint6d(" + name + ")::input(vector)::velocity"), |
| 54 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | articularJacobianSIN( |
| 55 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | NULL, "sotFeaturePoint6d(" + name + ")::input(matrix)::Jq"), |
| 56 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | error_th_(), |
| 57 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | R_(), |
| 58 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Rref_(), |
| 59 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Rt_(), |
| 60 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Rreft_(), |
| 61 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | P_(3, 3), |
| 62 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | Pinv_(3, 3), |
| 63 |
8/16✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 2 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 2 times.
✗ Branch 25 not taken.
|
4 | accuracy_(1e-8) { |
| 64 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | jacobianSOUT.addDependency(positionSIN); |
| 65 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | jacobianSOUT.addDependency(articularJacobianSIN); |
| 66 | |||
| 67 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | errorSOUT.addDependency(positionSIN); |
| 68 | |||
| 69 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | signalRegistration(positionSIN << articularJacobianSIN); |
| 70 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | signalRegistration(errordotSOUT << velocitySIN); |
| 71 |
3/6✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
|
2 | errordotSOUT.setFunction( |
| 72 | boost::bind(&FeaturePoint6d::computeErrordot, this, _1, _2)); | ||
| 73 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | errordotSOUT.addDependency(velocitySIN); |
| 74 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | errordotSOUT.addDependency(positionSIN); |
| 75 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | errordotSOUT.addDependency(errorSOUT); |
| 76 | |||
| 77 | // Commands | ||
| 78 | // | ||
| 79 | { | ||
| 80 | using namespace dynamicgraph::command; | ||
| 81 | 2 | std::string docstring; | |
| 82 | // Set computation frame | ||
| 83 | docstring = | ||
| 84 | "Set computation frame\n" | ||
| 85 | "\n" | ||
| 86 | " Input:\n" | ||
| 87 | " a string: 'current' or 'desired'.\n" | ||
| 88 | " If 'current', the error is defined as the rotation " | ||
| 89 | "vector (VectorUTheta)\n" | ||
| 90 | " corresponding to the position of the reference in the " | ||
| 91 | "current frame:\n" | ||
| 92 | " -1 *\n" | ||
| 93 | " error = utheta (M M )\n" | ||
| 94 | " If 'desired', *-1\n" | ||
| 95 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | " error = utheta (M M)\n"; |
| 96 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | addCommand("frame", |
| 97 | new dynamicgraph::command::Setter<FeaturePoint6d, std::string>( | ||
| 98 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | *this, &FeaturePoint6d::computationFrame, docstring)); |
| 99 | docstring = | ||
| 100 | "Get frame of computation of the error\n" | ||
| 101 | "\n" | ||
| 102 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | " See command 'frame' for definition.\n"; |
| 103 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | addCommand("getFrame", |
| 104 | new dynamicgraph::command::Getter<FeaturePoint6d, std::string>( | ||
| 105 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | *this, &FeaturePoint6d::computationFrame, docstring)); |
| 106 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | addCommand( |
| 107 | "keep", | ||
| 108 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | makeCommandVoid0( |
| 109 | *this, &FeaturePoint6d::servoCurrentPosition, | ||
| 110 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
4 | docCommandVoid0( |
| 111 | "modify the desired position to servo at current pos."))); | ||
| 112 | 2 | } | |
| 113 | 2 | } | |
| 114 | |||
| 115 | 1 | void FeaturePoint6d::addDependenciesFromReference(void) { | |
| 116 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | assert(isReferenceSet()); |
| 117 | 1 | errorSOUT.addDependency(getReference()->positionSIN); | |
| 118 | 1 | jacobianSOUT.addDependency(getReference()->positionSIN); | |
| 119 | 1 | } | |
| 120 | |||
| 121 | ✗ | void FeaturePoint6d::removeDependenciesFromReference(void) { | |
| 122 | ✗ | assert(isReferenceSet()); | |
| 123 | ✗ | errorSOUT.removeDependency(getReference()->positionSIN); | |
| 124 | ✗ | jacobianSOUT.removeDependency(getReference()->positionSIN); | |
| 125 | } | ||
| 126 | |||
| 127 | /* --------------------------------------------------------------------- */ | ||
| 128 | /* --------------------------------------------------------------------- */ | ||
| 129 | /* --------------------------------------------------------------------- */ | ||
| 130 | 1 | void FeaturePoint6d::computationFrame(const std::string &inFrame) { | |
| 131 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (inFrame == "current") |
| 132 | ✗ | computationFrame_ = FRAME_CURRENT; | |
| 133 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | else if (inFrame == "desired") |
| 134 | 1 | computationFrame_ = FRAME_DESIRED; | |
| 135 | else { | ||
| 136 | ✗ | std::string msg("FeaturePoint6d::computationFrame: " + inFrame + | |
| 137 | ": invalid argument,\n" | ||
| 138 | ✗ | "expecting 'current' or 'desired'"); | |
| 139 | ✗ | throw ExceptionFeature(ExceptionFeature::GENERIC, msg); | |
| 140 | } | ||
| 141 | 1 | } | |
| 142 | |||
| 143 | /// \brief Get computation frame | ||
| 144 | ✗ | std::string FeaturePoint6d::computationFrame() const { | |
| 145 | ✗ | switch (computationFrame_) { | |
| 146 | ✗ | case FRAME_CURRENT: | |
| 147 | ✗ | return "current"; | |
| 148 | ✗ | case FRAME_DESIRED: | |
| 149 | ✗ | return "desired"; | |
| 150 | } | ||
| 151 | ✗ | assert(false && "Case not handled"); | |
| 152 | return "Case not handled"; | ||
| 153 | } | ||
| 154 | /* --------------------------------------------------------------------- */ | ||
| 155 | /* --------------------------------------------------------------------- */ | ||
| 156 | /* --------------------------------------------------------------------- */ | ||
| 157 | |||
| 158 | 1 | unsigned int &FeaturePoint6d::getDimension(unsigned int &dim, int time) { | |
| 159 | sotDEBUG(25) << "# In {" << endl; | ||
| 160 | |||
| 161 | 1 | const Flags &fl = selectionSIN.access(time); | |
| 162 | |||
| 163 | 1 | dim = 0; | |
| 164 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
|
7 | for (int i = 0; i < 6; ++i) |
| 165 |
2/4✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | if (fl(i)) dim++; |
| 166 | |||
| 167 | sotDEBUG(25) << "# Out }" << endl; | ||
| 168 | 1 | return dim; | |
| 169 | } | ||
| 170 | |||
| 171 | /** Compute the interaction matrix from a subset of | ||
| 172 | * the possible features. | ||
| 173 | */ | ||
| 174 | ✗ | Matrix &FeaturePoint6d::computeJacobian(Matrix &J, int time) { | |
| 175 | sotDEBUG(15) << "# In {" << endl; | ||
| 176 | |||
| 177 | ✗ | const Matrix &Jq = articularJacobianSIN(time); | |
| 178 | ✗ | const int &dim = dimensionSOUT(time); | |
| 179 | ✗ | const Flags &fl = selectionSIN(time); | |
| 180 | |||
| 181 | sotDEBUG(25) << "dim = " << dimensionSOUT(time) << " time:" << time << " " | ||
| 182 | << dimensionSOUT.getTime() << " " << dimensionSOUT.getReady() | ||
| 183 | << endl; | ||
| 184 | sotDEBUG(25) << "selec = " << selectionSIN(time) << " time:" << time << " " | ||
| 185 | << selectionSIN.getTime() << " " << selectionSIN.getReady() | ||
| 186 | << endl; | ||
| 187 | |||
| 188 | sotDEBUG(15) << "Dimension=" << dim << std::endl; | ||
| 189 | |||
| 190 | ✗ | const Matrix::Index cJ = Jq.cols(); | |
| 191 | ✗ | J.resize(dim, cJ); | |
| 192 | ✗ | Matrix LJq(6, cJ); | |
| 193 | |||
| 194 | ✗ | if (FRAME_CURRENT == computationFrame_) { | |
| 195 | /* The Jacobian on rotation is equal to Jr = - hdRh Jr6d. | ||
| 196 | * The Jacobian in translation is equalt to Jt = [hRw(wthd-wth)]x Jr - Jt. | ||
| 197 | */ | ||
| 198 | ✗ | const MatrixHomogeneous &wMh = positionSIN(time); | |
| 199 | ✗ | MatrixRotation wRh; | |
| 200 | ✗ | wRh = wMh.linear(); | |
| 201 | ✗ | MatrixRotation wRhd; | |
| 202 | ✗ | Vector hdth(3), Rhdth(3); | |
| 203 | |||
| 204 | ✗ | if (isReferenceSet()) { | |
| 205 | ✗ | const MatrixHomogeneous &wMhd = getReference()->positionSIN(time); | |
| 206 | ✗ | wRhd = wMhd.linear(); | |
| 207 | ✗ | for (unsigned int i = 0; i < 3; ++i) hdth(i) = wMhd(i, 3) - wMh(i, 3); | |
| 208 | } else { | ||
| 209 | ✗ | wRhd.setIdentity(); | |
| 210 | ✗ | for (unsigned int i = 0; i < 3; ++i) hdth(i) = -wMh(i, 3); | |
| 211 | } | ||
| 212 | ✗ | Rhdth = (wRh.inverse()) * hdth; | |
| 213 | ✗ | MatrixRotation hdRh; | |
| 214 | ✗ | hdRh = (wRhd.inverse()) * wRh; | |
| 215 | |||
| 216 | ✗ | Matrix Lx(6, 6); | |
| 217 | ✗ | for (unsigned int i = 0; i < 3; i++) { | |
| 218 | ✗ | for (unsigned int j = 0; j < 3; j++) { | |
| 219 | ✗ | if (i == j) { | |
| 220 | ✗ | Lx(i, j) = -1; | |
| 221 | } else { | ||
| 222 | ✗ | Lx(i, j) = 0; | |
| 223 | } | ||
| 224 | ✗ | Lx(i + 3, j) = 0; | |
| 225 | ✗ | Lx(i + 3, j + 3) = -hdRh(i, j); | |
| 226 | } | ||
| 227 | } | ||
| 228 | ✗ | const double &X = Rhdth(0), &Y = Rhdth(1), &Z = Rhdth(2); | |
| 229 | ✗ | Lx(0, 4) = -Z; | |
| 230 | ✗ | Lx(0, 5) = Y; | |
| 231 | ✗ | Lx(1, 3) = Z; | |
| 232 | ✗ | Lx(1, 5) = -X; | |
| 233 | ✗ | Lx(2, 3) = -Y; | |
| 234 | ✗ | Lx(2, 4) = X; | |
| 235 | ✗ | Lx(0, 3) = 0; | |
| 236 | ✗ | Lx(1, 4) = 0; | |
| 237 | ✗ | Lx(2, 5) = 0; | |
| 238 | sotDEBUG(15) << "Lx= " << Lx << endl; | ||
| 239 | |||
| 240 | ✗ | LJq = Lx * Jq; | |
| 241 | ✗ | } else { | |
| 242 | /* The Jacobian in rotation is equal to Jr = hdJ = hdRh Jr. | ||
| 243 | * The Jacobian in translation is equal to Jr = hdJ = hdRh Jr. */ | ||
| 244 | ✗ | const MatrixHomogeneous &wMh = positionSIN(time); | |
| 245 | ✗ | MatrixRotation wRh; | |
| 246 | ✗ | wRh = wMh.linear(); | |
| 247 | ✗ | MatrixRotation hdRh; | |
| 248 | |||
| 249 | ✗ | if (isReferenceSet()) { | |
| 250 | ✗ | const MatrixHomogeneous &wMhd = getReference()->positionSIN(time); | |
| 251 | ✗ | MatrixRotation wRhd; | |
| 252 | ✗ | wRhd = wMhd.linear(); | |
| 253 | ✗ | hdRh = (wRhd.inverse()) * wRh; | |
| 254 | } else { | ||
| 255 | ✗ | hdRh = wRh; | |
| 256 | } | ||
| 257 | |||
| 258 | ✗ | LJq.fill(0); | |
| 259 | ✗ | for (unsigned int i = 0; i < 3; i++) | |
| 260 | ✗ | for (unsigned int j = 0; j < cJ; j++) { | |
| 261 | ✗ | for (unsigned int k = 0; k < 3; k++) { | |
| 262 | ✗ | LJq(i, j) += hdRh(i, k) * Jq(k, j); | |
| 263 | ✗ | LJq(i + 3, j) += hdRh(i, k) * Jq(k + 3, j); | |
| 264 | } | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | /* Select the active line of Jq. */ | ||
| 269 | ✗ | unsigned int rJ = 0; | |
| 270 | ✗ | for (unsigned int r = 0; r < 6; ++r) | |
| 271 | ✗ | if (fl(r)) { | |
| 272 | ✗ | for (unsigned int c = 0; c < cJ; ++c) J(rJ, c) = LJq(r, c); | |
| 273 | ✗ | rJ++; | |
| 274 | } | ||
| 275 | |||
| 276 | sotDEBUG(15) << "# Out }" << endl; | ||
| 277 | ✗ | return J; | |
| 278 | } | ||
| 279 | |||
| 280 | #define SOT_COMPUTE_H1MH2(wMh, wMhd, hMhd) \ | ||
| 281 | { \ | ||
| 282 | MatrixHomogeneous hMw; \ | ||
| 283 | hMw = wMh.inverse(Eigen::Affine); \ | ||
| 284 | sotDEBUG(15) << "hMw = " << hMw << endl; \ | ||
| 285 | hMhd = hMw * wMhd; \ | ||
| 286 | sotDEBUG(15) << "hMhd = " << hMhd << endl; \ | ||
| 287 | } | ||
| 288 | |||
| 289 | /** Compute the error between two visual features from a subset | ||
| 290 | * a the possible features. | ||
| 291 | */ | ||
| 292 | 4 | Vector &FeaturePoint6d::computeError(Vector &error, int time) { | |
| 293 | sotDEBUGIN(15); | ||
| 294 | |||
| 295 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | const Flags &fl = selectionSIN(time); |
| 296 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | const MatrixHomogeneous &wMh = positionSIN(time); |
| 297 | sotDEBUG(15) << "wMh = " << wMh << endl; | ||
| 298 | |||
| 299 | /* Computing only translation: * | ||
| 300 | * trans( hMw wMhd ) = htw + hRw wthd * | ||
| 301 | * = -hRw wth + hrW wthd * | ||
| 302 | * = hRw ( wthd - wth ) * | ||
| 303 | * The second line is obtained by writting hMw as the inverse of wMh. */ | ||
| 304 | |||
| 305 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MatrixHomogeneous hMhd; |
| 306 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | if (isReferenceSet()) { |
| 307 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | const MatrixHomogeneous &wMhd = getReference()->positionSIN(time); |
| 308 | sotDEBUG(15) << "wMhd = " << wMhd << endl; | ||
| 309 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | switch (computationFrame_) { |
| 310 | ✗ | case FRAME_CURRENT: | |
| 311 | ✗ | SOT_COMPUTE_H1MH2(wMh, wMhd, hMhd); | |
| 312 | ✗ | break; | |
| 313 | 4 | case FRAME_DESIRED: | |
| 314 |
4/8✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
|
4 | SOT_COMPUTE_H1MH2(wMhd, wMh, hMhd); |
| 315 | 4 | break; // Compute hdMh indeed. | |
| 316 | }; | ||
| 317 | } else { | ||
| 318 | ✗ | switch (computationFrame_) { | |
| 319 | ✗ | case FRAME_CURRENT: | |
| 320 | ✗ | hMhd = wMh.inverse(); | |
| 321 | ✗ | break; | |
| 322 | ✗ | case FRAME_DESIRED: | |
| 323 | ✗ | hMhd = wMh; | |
| 324 | ✗ | break; // Compute hdMh indeed. | |
| 325 | }; | ||
| 326 | } | ||
| 327 | |||
| 328 | sotDEBUG(25) << "dim = " << dimensionSOUT(time) << " time:" << time << " " | ||
| 329 | << dimensionSOUT.getTime() << " " << dimensionSOUT.getReady() | ||
| 330 | << endl; | ||
| 331 | sotDEBUG(25) << "selec = " << selectionSIN(time) << " time:" << time << " " | ||
| 332 | << selectionSIN.getTime() << " " << selectionSIN.getReady() | ||
| 333 | << endl; | ||
| 334 | |||
| 335 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | error.resize(dimensionSOUT(time)); |
| 336 | 4 | unsigned int cursor = 0; | |
| 337 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | for (unsigned int i = 0; i < 3; ++i) { |
| 338 |
4/8✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
|
12 | if (fl(i)) error(cursor++) = hMhd(i, 3); |
| 339 | } | ||
| 340 | |||
| 341 |
3/14✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✗ Branch 16 not taken.
|
4 | if (fl(3) || fl(4) || fl(5)) { |
| 342 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | MatrixRotation hRhd; |
| 343 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | hRhd = hMhd.linear(); |
| 344 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | error_th_.fromRotationMatrix(hRhd); |
| 345 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | for (unsigned int i = 0; i < 3; ++i) { |
| 346 |
4/8✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 12 times.
✗ Branch 12 not taken.
|
12 | if (fl(i + 3)) error(cursor++) = error_th_.angle() * error_th_.axis()(i); |
| 347 | } | ||
| 348 | } | ||
| 349 | |||
| 350 | sotDEBUGOUT(15); | ||
| 351 | 4 | return error; | |
| 352 | } | ||
| 353 | |||
| 354 | 4 | void FeaturePoint6d::inverseJacobianRodrigues() { | |
| 355 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | const double &r1 = error_th_.angle() * error_th_.axis()(0); |
| 356 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | const double &r2 = error_th_.angle() * error_th_.axis()(1); |
| 357 |
1/2✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | const double &r3 = error_th_.angle() * error_th_.axis()(2); |
| 358 | 4 | double r1_2 = r1 * r1; | |
| 359 | 4 | double r2_2 = r2 * r2; | |
| 360 | 4 | double r3_2 = r3 * r3; | |
| 361 | 4 | double r1_3 = r1 * r1_2; | |
| 362 | 4 | double r2_3 = r2 * r2_2; | |
| 363 | 4 | double r3_3 = r3 * r3_2; | |
| 364 | 4 | double r1_4 = r1_2 * r1_2; | |
| 365 | 4 | double r2_4 = r2_2 * r2_2; | |
| 366 | 4 | double r3_4 = r3_2 * r3_2; | |
| 367 | 4 | double norm_2 = r3_2 + r2_2 + r1_2; | |
| 368 | |||
| 369 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (norm_2 < accuracy_) { |
| 370 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | P_.setIdentity(); |
| 371 | } else { | ||
| 372 | // This code has been generated by maxima software | ||
| 373 | ✗ | P_(0, 0) = | |
| 374 | ✗ | ((r3_2 + r2_2) * sqrt(norm_2) * sin(sqrt(norm_2)) + r1_2 * r3_2 + | |
| 375 | ✗ | r1_2 * r2_2 + r1_4) / | |
| 376 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 377 | ✗ | P_(0, 1) = | |
| 378 | ✗ | -(r1 * r2 * sqrt(norm_2) * sin(sqrt(norm_2)) + | |
| 379 | ✗ | (r3_3 + (r2_2 + r1_2) * r3) * cos(sqrt(norm_2)) - r3_3 - | |
| 380 | ✗ | r1 * r2 * r3_2 + (-r2_2 - r1_2) * r3 - r1 * r2_3 - r1_3 * r2) / | |
| 381 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 382 | ✗ | P_(0, 2) = | |
| 383 | ✗ | -(r1 * r3 * sqrt(norm_2) * sin(sqrt(norm_2)) + | |
| 384 | ✗ | (-r2 * r3_2 - r2_3 - r1_2 * r2) * cos(sqrt(norm_2)) - r1 * r3_3 + | |
| 385 | ✗ | r2 * r3_2 + (-r1 * r2_2 - r1_3) * r3 + r2_3 + r1_2 * r2) / | |
| 386 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 387 | ✗ | P_(1, 0) = | |
| 388 | ✗ | -(r1 * r2 * sqrt(norm_2) * sin(sqrt(norm_2)) + | |
| 389 | ✗ | ((-r2_2 - r1_2) * r3 - r3_3) * cos(sqrt(norm_2)) + r3_3 - | |
| 390 | ✗ | r1 * r2 * r3_2 + (r2_2 + r1_2) * r3 - r1 * r2_3 - r1_3 * r2) / | |
| 391 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 392 | ✗ | P_(1, 1) = | |
| 393 | ✗ | ((r3_2 + r1_2) * sqrt(norm_2) * sin(sqrt(norm_2)) + r2_2 * r3_2 + r2_4 + | |
| 394 | ✗ | r1_2 * r2_2) / | |
| 395 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 396 | ✗ | P_(1, 2) = | |
| 397 | ✗ | -(r2 * r3 * sqrt(norm_2) * sin(sqrt(norm_2)) + | |
| 398 | ✗ | (r1 * r3_2 + r1 * r2_2 + r1_3) * cos(sqrt(norm_2)) - r2 * r3_3 - | |
| 399 | ✗ | r1 * r3_2 + (-r2_3 - r1_2 * r2) * r3 - r1 * r2_2 - r1_3) / | |
| 400 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 401 | ✗ | P_(2, 0) = | |
| 402 | ✗ | -(r1 * r3 * sqrt(norm_2) * sin(sqrt(norm_2)) + | |
| 403 | ✗ | (r2 * r3_2 + r2_3 + r1_2 * r2) * cos(sqrt(norm_2)) - r1 * r3_3 - | |
| 404 | ✗ | r2 * r3_2 + (-r1 * r2_2 - r1_3) * r3 - r2_3 - r1_2 * r2) / | |
| 405 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 406 | ✗ | P_(2, 1) = | |
| 407 | ✗ | -(r2 * r3 * sqrt(norm_2) * sin(sqrt(norm_2)) + | |
| 408 | ✗ | (-r1 * r3_2 - r1 * r2_2 - r1_3) * cos(sqrt(norm_2)) - r2 * r3_3 + | |
| 409 | ✗ | r1 * r3_2 + (-r2_3 - r1_2 * r2) * r3 + r1 * r2_2 + r1_3) / | |
| 410 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 411 | ✗ | P_(2, 2) = | |
| 412 | ✗ | ((r2_2 + r1_2) * sqrt(norm_2) * sin(sqrt(norm_2)) + r3_4 + | |
| 413 | ✗ | (r2_2 + r1_2) * r3_2) / | |
| 414 | ✗ | (r3_4 + (2 * r2_2 + 2 * r1_2) * r3_2 + r2_4 + 2 * r1_2 * r2_2 + r1_4); | |
| 415 | } | ||
| 416 |
2/4✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | Pinv_ = P_.inverse(); |
| 417 | 4 | } | |
| 418 | |||
| 419 | 4 | Vector &FeaturePoint6d::computeErrordot(Vector &errordot, int time) { | |
| 420 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if (isReferenceSet()) { |
| 421 | 4 | const Vector &velocity = getReference()->velocitySIN(time); | |
| 422 | 4 | const MatrixHomogeneous &M = positionSIN(time); | |
| 423 | 4 | const MatrixHomogeneous &Mref = getReference()->positionSIN(time); | |
| 424 | // Linear velocity if the reference frame | ||
| 425 | 4 | v_(0) = velocity(0); | |
| 426 | 4 | v_(1) = velocity(1); | |
| 427 | 4 | v_(2) = velocity(2); | |
| 428 | // Angular velocity if the reference frame | ||
| 429 | 4 | omega_(0) = velocity(3); | |
| 430 | 4 | omega_(1) = velocity(4); | |
| 431 | 4 | omega_(2) = velocity(5); | |
| 432 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | R_ = M.linear(); |
| 433 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | t_ = M.translation(); |
| 434 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | Rt_ = R_.transpose(); |
| 435 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | Rref_ = Mref.linear(); |
| 436 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | tref_ = Mref.translation(); |
| 437 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | Rreft_ = Rref_.transpose(); |
| 438 | 4 | errorSOUT.recompute(time); | |
| 439 | 4 | inverseJacobianRodrigues(); | |
| 440 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | switch (computationFrame_) { |
| 441 | ✗ | case FRAME_CURRENT: | |
| 442 | // \dot{e}_{t} = R^{T} v | ||
| 443 | ✗ | errordot_t_ = Rt_ * v_; | |
| 444 | // \dot{e}_{\theta} = P^{-1}(e_{theta})R^{*T}\omega | ||
| 445 | ✗ | Rreftomega_ = Rreft_ * omega_; | |
| 446 | ✗ | errordot_th_ = Pinv_ * Rreftomega_; | |
| 447 | ✗ | break; | |
| 448 | 4 | case FRAME_DESIRED: | |
| 449 |
4/8✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 4 times.
✗ Branch 12 not taken.
|
4 | errordot_t_ = Rreft_ * (omega_.cross(tref_ - t_) - v_); |
| 450 |
3/6✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
|
4 | errordot_th_ = -Pinv_ * (Rt_ * omega_); |
| 451 | 4 | break; | |
| 452 | } | ||
| 453 | } else { | ||
| 454 | ✗ | errordot_t_.setZero(); | |
| 455 | ✗ | errordot_th_.setZero(); | |
| 456 | } | ||
| 457 | |||
| 458 | 4 | const Flags &fl = selectionSIN(time); | |
| 459 | 4 | errordot.resize(dimensionSOUT(time)); | |
| 460 | 4 | unsigned int cursor = 0; | |
| 461 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | for (unsigned int i = 0; i < 3; ++i) { |
| 462 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
|
12 | if (fl(i)) { |
| 463 | 12 | errordot(cursor++) = errordot_t_(i); | |
| 464 | } | ||
| 465 | } | ||
| 466 | |||
| 467 |
3/14✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 4 times.
✗ Branch 16 not taken.
|
4 | if (fl(3) || fl(4) || fl(5)) { |
| 468 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
|
16 | for (unsigned int i = 0; i < 3; ++i) { |
| 469 |
2/4✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
|
12 | if (fl(i + 3)) { |
| 470 | 12 | errordot(cursor++) = errordot_th_(i); | |
| 471 | } | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | 4 | return errordot; | |
| 476 | } | ||
| 477 | |||
| 478 | /* Modify the value of the reference (sdes) so that it corresponds | ||
| 479 | * to the current position. The effect on the servo is to maintain the | ||
| 480 | * current position and correct any drift. */ | ||
| 481 | ✗ | void FeaturePoint6d::servoCurrentPosition(void) { | |
| 482 | sotDEBUGIN(15); | ||
| 483 | |||
| 484 | ✗ | if (!isReferenceSet()) { | |
| 485 | ✗ | sotERROR << "The reference is not set, this function should not be called" | |
| 486 | ✗ | << std::endl; | |
| 487 | ✗ | throw ExceptionFeature( | |
| 488 | ✗ | ExceptionFeature::GENERIC, | |
| 489 | ✗ | "The reference is not set, this function should not be called"); | |
| 490 | } | ||
| 491 | ✗ | getReference()->positionSIN = positionSIN.accessCopy(); | |
| 492 | |||
| 493 | sotDEBUGOUT(15); | ||
| 494 | } | ||
| 495 | |||
| 496 | static const char *featureNames[] = {"X ", "Y ", "Z ", "RX", "RY", "RZ"}; | ||
| 497 | ✗ | void FeaturePoint6d::display(std::ostream &os) const { | |
| 498 | ✗ | os << "Point6d <" << name << ">: ("; | |
| 499 | |||
| 500 | try { | ||
| 501 | ✗ | const Flags &fl = selectionSIN.accessCopy(); | |
| 502 | ✗ | bool first = true; | |
| 503 | ✗ | for (int i = 0; i < 6; ++i) | |
| 504 | ✗ | if (fl(i)) { | |
| 505 | ✗ | if (first) { | |
| 506 | ✗ | first = false; | |
| 507 | } else { | ||
| 508 | ✗ | os << ","; | |
| 509 | } | ||
| 510 | ✗ | os << featureNames[i]; | |
| 511 | } | ||
| 512 | ✗ | os << ") "; | |
| 513 | ✗ | } catch (ExceptionAbstract e) { | |
| 514 | ✗ | os << " selectSIN not set."; | |
| 515 | } | ||
| 516 | } | ||
| 517 |