33 #include <visp3/ustk_needle_modeling/usNeedleInsertionModelRayleighRitzSpline.h>
35 #include <visp3/ustk_core/usGeometryTools.h>
37 #include <visp3/core/vpConfig.h>
38 #ifdef VISP_HAVE_EIGEN3
39 #include <eigen3/Eigen/SparseCore>
40 #include <eigen3/Eigen/SparseLU>
43 #include <visp3/core/vpMatrix.h>
44 #include <visp3/core/vpPoseVector.h>
45 #include <visp3/core/vpRGBa.h>
46 #include <visp3/core/vpRotationMatrix.h>
47 #include <visp3/core/vpTranslationVector.h>
48 #include <visp3/gui/vpDisplayX.h>
54 m_pathUpdateType(
PathUpdateType::NoUpdate), m_pathUpdateLengthThreshold(0.001), m_pathUpdateMixCoefficient(0.5),
64 : m_needle(model.m_needle), m_needleTip(model.m_needleTip->clone()), m_needleTipType(model.m_needleTipType),
65 m_tissue(model.m_tissue), m_stiffnessPerUnitLength(model.m_stiffnessPerUnitLength),
66 m_layerLength(model.m_layerLength),
68 m_pathUpdateType(model.m_pathUpdateType), m_pathUpdateLengthThreshold(model.m_pathUpdateLengthThreshold),
69 m_pathUpdateMixCoefficient(model.m_pathUpdateMixCoefficient),
71 m_solvingMethod(model.m_solvingMethod), m_restDilatationFactor(model.m_restDilatationFactor)
139 t->
setLength(d / 2 / tan(M_PI / 180 * 30 / 2));
161 t->
setLength(d / tan(M_PI / 180 * 32.09));
291 if (K <= 0 || l <= 0)
369 if (param !=
nullptr)
394 if (param !=
nullptr)
399 if (param !=
nullptr)
406 if (param !=
nullptr)
423 throw vpException(vpException::fatalError,
424 "usNeedleInsertionModelRayleighRitzSpline::getNeedleInsertionPoint: needle is not inserted");
432 throw vpException(vpException::fatalError,
433 "usNeedleInsertionModelRayleighRitzSpline::getTissueInsertionPoint: needle was not inserted");
439 double &correspondingRestParam)
const
441 correspondingRestIndex = -1;
442 correspondingRestParam = -1;
446 int needleIndex = -1;
447 double needleParam = -1;
449 if (l < freeLength || needleIndex < 0 || needleParam < 0)
452 double insertionLength = l - freeLength;
453 double currentNeedleInsertedLength = 0;
455 double currentRestParam = 0;
456 double currentRestLength = 0;
458 while (currentNeedleInsertedLength < insertionLength) {
467 currentNeedleInsertedLength = insertionLength;
474 currentNeedleInsertedLength) {
477 currentRestParam = 0;
481 currentRestParam += (currentNeedleInsertedLength - currentRestLength) /
m_restDilatationFactor.at(needleIndex);
482 currentRestLength = currentNeedleInsertedLength;
486 correspondingRestIndex = restIndex;
487 correspondingRestParam = currentRestParam;
499 double layerIndex = 0;
500 double currentDepth = 0;
504 for (
int i = 1; i < nbSeg; i++) {
510 double dl = length / 50;
513 double restParameter = -1;
514 vpColVector Pn = segment.
getPoint(l);
529 while (layerIndex + 1 <
m_layerLength.size() && currentDepth > nextDepth) {
576 double totalLength = freeLength - l;
582 double dl = (length - l) / 50;
585 double restParameter = -1;
596 maxL = totalLength + l;
611 maxL = totalLength + l;
616 totalLength += length;
639 double totalLength = freeLength - l;
647 double dl = (length - l) / 50;
650 double restParameter = -1;
651 vpColVector Pn = segment.
getPoint(l);
675 totalLength += length;
679 mean /= (totalLength - freeLength);
689 vpColVector position(pose.getTranslationVector());
707 for (
int i = 0; i < 3; i++)
715 throw vpException(vpException::dimensionError,
716 "usNeedleInsertionModelRayleighRitzSpline::cutPathToPoint: invalid vector dimension");
720 vpColVector lastPoint(3);
721 vpColVector lastDirection(3);
732 std::cout <<
"Warning usNeedleInsertionModelRayleighRitzSpline::cutPathToPoint: cut point is inconsistent with "
733 "current needle state"
740 M.insert(lastPoint, 0, 0);
741 M.insert((P - lastPoint).normalize(), 0, 1);
752 #ifdef VISP_HAVE_EIGEN3
754 double trueFreeLength = 0;
757 double freeLength = -1;
763 for (
int i = 0; i < seg; i++) {
769 for (
int i = 0; i < 3; i++)
772 for (
int i = 0; i < 3; i++)
775 if (cosTheta > std::numeric_limits<double>::epsilon())
785 vpMatrix M(3, seg.
getOrder() + 1, 0);
786 for (
int dim = 0; dim < 3; dim++) {
800 double segDefaultLength = 0.01;
809 for (
int i = 1; i < nbSegments - 1; i++)
815 for (
int i = 0; i < nbSegments; i++)
818 typedef Eigen::Triplet<double> T;
823 int nbConstraints = 2;
824 for (
int i = 0; i < nbSegments - 1; i++) {
827 int order = std::max(order1, order2);
828 nbConstraints += std::min(3, order);
831 L.reserve((nbConstraints + nbcoef) * (nbConstraints + nbcoef) / 10);
833 Eigen::MatrixX3d A = Eigen::MatrixX3d::Zero(nbConstraints + nbcoef, 3);
834 Eigen::MatrixX3d B = Eigen::MatrixX3d::Zero(nbConstraints + nbcoef, 3);
840 for (
int dim = 0; dim < 3; dim++)
842 L.push_back(T(line, 0, 1));
843 L.push_back(T(0, line, -1));
845 for (
int dim = 0; dim < 3; dim++)
847 L.push_back(T(line, 1, 1));
848 L.push_back(T(1, line, -1));
853 for (
int i = 0; i < nbSegments - 1; i++) {
857 int order = std::max(order1, order2);
862 double *tmp =
new double[nbSegCoef];
867 for (
int j = 1; j < nbSegCoef; j++)
868 tmp[j] = segLength * tmp[j - 1];
870 for (
int j = 0; j < nbSegCoef; j++) {
871 L.push_back(T(line, startIndex + j, tmp[j]));
872 L.push_back(T(startIndex + j, line, -tmp[j]));
874 L.push_back(T(line, startIndex + nbSegCoef, -1));
875 L.push_back(T(startIndex + nbSegCoef, line, 1));
882 for (
int j = 2; j < nbSegCoef; j++)
883 tmp[j] = segLength * tmp[j - 1];
884 for (
int j = 1; j < nbSegCoef; j++)
887 for (
int j = 1; j < nbSegCoef; j++) {
888 L.push_back(T(line, startIndex + j, tmp[j]));
889 L.push_back(T(startIndex + j, line, -tmp[j]));
891 L.push_back(T(line, startIndex + nbSegCoef + 1, -1));
892 L.push_back(T(startIndex + nbSegCoef + 1, line, 1));
900 for (
int j = 3; j < nbSegCoef; j++)
901 tmp[j] = segLength * tmp[j - 1];
902 for (
int j = 2; j < nbSegCoef; j++)
903 tmp[j] *= j * (j - 1);
905 for (
int j = 2; j < nbSegCoef; j++) {
906 L.push_back(T(line, startIndex + j, tmp[j]));
907 L.push_back(T(startIndex + j, line, -tmp[j]));
909 L.push_back(T(line, startIndex + nbSegCoef + 2, -2));
910 L.push_back(T(startIndex + nbSegCoef + 2, line, 2));
914 startIndex += nbSegCoef;
922 int nbSegEq = nbSegCoef;
924 for (
int j = 0; j < nbSegEq; j++) {
926 for (
int k = 2; k < nbSegCoef; k++) {
928 L.push_back(T(line, k, EI * pow(segLength, j + k - 3) * j * (j - 1) * k * (k - 1) / (j + k - 3)));
933 startIndex = nbSegCoef;
935 double currentRestParam = 0;
937 double currentDepth = 0;
939 for (
int i = 1; i < nbSegments; i++) {
946 double LsegMax = segLength;
947 while (lseg < segLength) {
950 if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (
int)
m_layerLength.size()) {
951 LsegMax = nextLayerDepth - currentDepth;
954 for (
int j = 0; j < nbSegEq; j++) {
955 for (
int k = 0; k < nbSegCoef; k++) {
959 c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
962 c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
964 L.push_back(T(line + j, startIndex + k, c));
969 while (l < LsegMax) {
975 int nbRestSegCoef = p.
getOrder() + 1;
986 currentRestParam = 0;
991 for (
int j = 0; j < nbSegEq; j++) {
992 for (
int k = 0; k < nbRestSegCoef; k++) {
993 double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
994 for (
int dim = 0; dim < 3; dim++) {
995 B(line + j, dim) += c * coefP[dim][k];
1001 if (LsegMax < segLength) {
1004 lseg += LsegMax - LsegMin;
1008 currentDepth += LsegMax - LsegMin;
1010 LsegMax = segLength;
1014 startIndex += nbSegCoef;
1017 Eigen::SparseMatrix<double> M(nbConstraints + nbcoef, nbConstraints + nbcoef);
1018 M.setFromTriplets(L.begin(), L.end());
1020 Eigen::SparseLU<Eigen::SparseMatrix<double> > solver;
1023 A = solver.solve(B);
1027 for (
int i = 0; i < nbSegments; i++) {
1029 vpMatrix m(3, order + 1);
1030 for (
int j = 0; j < order + 1; j++) {
1031 for (
int dim = 0; dim < 3; dim++) {
1032 m[dim][j] = A(startIndex + j, dim);
1036 startIndex += order + 1;
1040 vpException::functionNotImplementedError,
1041 "usNeedleInsertionModelRayleighRitzSpline::solveSegmentsParametersSparseEigen: not implemented without Eigen3");
1047 #ifdef VISP_HAVE_EIGEN3
1051 vpMatrix M(3, seg.
getOrder() + 1, 0);
1052 for (
int dim = 0; dim < 3; dim++) {
1064 double trueFreeLength = 0;
1067 double freeLength = -1;
1073 for (
int i = 0; i < seg; i++) {
1079 for (
int i = 0; i < 3; i++)
1082 for (
int i = 0; i < 3; i++)
1085 if (cosTheta > std::numeric_limits<double>::epsilon())
1095 vpMatrix M(3, seg.
getOrder() + 1, 0);
1096 for (
int dim = 0; dim < 3; dim++) {
1110 double segDefaultLength = 0.01;
1123 for (
int i = 1; i < nbSegments - 1; i++)
1128 segDefaultLength * (nbSegments - 2));
1131 for (
int i = 0; i < nbSegments; i++)
1134 typedef Eigen::Triplet<double> T;
1139 int nbConstraints = 2;
1140 for (
int i = 0; i < nbSegments - 1; i++) {
1143 int order = std::max(order1, order2);
1144 nbConstraints += std::min(3, order);
1147 int nbMatrixLine = 3 * (nbConstraints + nbcoef);
1149 L.reserve(nbMatrixLine * nbMatrixLine / 10);
1151 Eigen::VectorXd A = Eigen::VectorXd::Zero(nbMatrixLine);
1152 Eigen::VectorXd B = Eigen::VectorXd::Zero(nbMatrixLine);
1157 int line = 3 * nbcoef;
1158 for (
int dim = 0; dim < 3; dim++) {
1160 L.push_back(T(line, dim, 1));
1161 L.push_back(T(dim, line, -1));
1164 for (
int dim = 0; dim < 3; dim++) {
1166 L.push_back(T(line, 3 + dim, 1));
1167 L.push_back(T(3 + dim, line, -1));
1173 for (
int i = 0; i < nbSegments - 1; i++) {
1177 int order = std::max(order1, order2);
1182 double *tmp =
new double[nbSegCoef];
1186 for (
int j = 1; j < nbSegCoef; j++)
1187 tmp[j] = segLength * tmp[j - 1];
1189 for (
int dim = 0; dim < 3; dim++) {
1190 for (
int j = 0; j < nbSegCoef; j++) {
1191 L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1192 L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1194 L.push_back(T(line, startIndex + 3 * nbSegCoef + dim, -1));
1195 L.push_back(T(startIndex + 3 * nbSegCoef + dim, line, 1));
1203 for (
int j = 2; j < nbSegCoef; j++)
1204 tmp[j] = segLength * tmp[j - 1];
1205 for (
int j = 1; j < nbSegCoef; j++)
1208 for (
int dim = 0; dim < 3; dim++) {
1209 for (
int j = 1; j < nbSegCoef; j++) {
1210 L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1211 L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1213 L.push_back(T(line, startIndex + 3 * (nbSegCoef + 1) + dim, -1));
1214 L.push_back(T(startIndex + 3 * (nbSegCoef + 1) + dim, line, 1));
1223 for (
int j = 3; j < nbSegCoef; j++)
1224 tmp[j] = segLength * tmp[j - 1];
1225 for (
int j = 2; j < nbSegCoef; j++)
1226 tmp[j] *= j * (j - 1);
1228 for (
int dim = 0; dim < 3; dim++) {
1229 for (
int j = 2; j < nbSegCoef; j++) {
1230 L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1231 L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1233 L.push_back(T(line, startIndex + 3 * (nbSegCoef + 2) + dim, -2));
1234 L.push_back(T(startIndex + 3 * (nbSegCoef + 2) + dim, line, 2));
1239 startIndex += 3 * nbSegCoef;
1247 int nbSegEq = nbSegCoef;
1250 for (
int j = 0; j < nbSegEq; j++) {
1252 for (
int k = 2; k < nbSegCoef; k++) {
1254 for (
int dim = 0; dim < 3; dim++)
1256 T(line + dim, 3 * k + dim, EI * pow(segLength, j + k - 3) * j * (j - 1) * k * (k - 1) / (j + k - 3)));
1261 startIndex = 3 * nbSegCoef;
1263 double currentRestParam = 0;
1265 double currentDepth = 0;
1267 for (
int i = 1; i < nbSegments; i++) {
1269 nbSegEq = nbSegCoef;
1274 double LsegMax = segLength;
1275 while (lseg < segLength) {
1278 if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (
int)
m_layerLength.size()) {
1279 LsegMax = nextLayerDepth - currentDepth;
1282 for (
int j = 0; j < nbSegEq; j++) {
1283 for (
int k = 0; k < nbSegCoef; k++) {
1287 c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
1289 c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
1291 for (
int dim = 0; dim < 3; dim++)
1292 L.push_back(T(line + 3 * j + dim, startIndex + 3 * k + dim, c));
1297 while (l < LsegMax) {
1303 int nbRestSegCoef = p.
getOrder() + 1;
1314 currentRestParam = 0;
1319 for (
int j = 0; j < nbSegEq; j++) {
1320 for (
int k = 0; k < nbRestSegCoef; k++) {
1321 double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
1322 for (
int dim = 0; dim < 3; dim++) {
1323 B(line + 3 * j + dim) += c * coefP[dim][k];
1329 if (LsegMax < segLength) {
1332 lseg += LsegMax - LsegMin;
1336 currentDepth += LsegMax - LsegMin;
1338 LsegMax = segLength;
1341 line += 3 * nbSegEq;
1342 startIndex += 3 * nbSegCoef;
1352 vpRotationMatrix R(0, 0, 0);
1355 double bevLength = bevelSegment.frobeniusNorm();
1356 bevelSegment.normalize();
1358 R.buildFrom(p[0], p[1], p[2]);
1362 if (currentDepth == 0) {
1364 if (cosTheta > std::numeric_limits<double>::epsilon())
1369 LbevMin = bevLength;
1371 double lbev = LbevMin;
1372 double LbevMax = bevLength;
1373 while (lbev < bevLength) {
1376 if (currentDepth - lbev + bevLength > nextLayerDepth && layerIndex + 1 < (
int)
m_layerLength.size()) {
1377 LbevMax = nextLayerDepth - currentDepth;
1380 for (
int j = 0; j < nbSegEq; j++) {
1381 for (
int k = 0; k < nbSegCoef; k++) {
1387 c0 = pow(segLength, j + k) * (LbevMax - LbevMin);
1389 c1 = j * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1391 c2 = k * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1393 c3 = (j * k) * pow(segLength, j + k - 2) * (pow(LbevMax, 3) - pow(LbevMin, 3)) / 3;
1395 vpMatrix coefMat = stiffnessPerUnitLength * (c0 * I + c1 * R.t() + c2 * R + c3 * R.t() * R);
1397 for (
int dimj = 0; dimj < 3; dimj++)
1398 for (
int dimk = 0; dimk < 3; dimk++)
1399 L.push_back(T(line + 3 * j + dimj, startIndex + 3 * k + dimk, coefMat[dimj][dimk]));
1404 while (l < LbevMax) {
1410 int nbRestSegCoef = p.
getOrder() + 1;
1416 currentRestParam += LbevMax - l;
1421 currentRestParam = 0;
1426 for (
int j = 0; j < nbSegEq; j++) {
1427 vpColVector b0(3, 0);
1428 vpColVector b1(3, 0);
1429 for (
int k = 0; k < nbRestSegCoef; k++) {
1430 b0 += pow(segLength, j) * (pow(Lmax, k + 1) - pow(Lmin, k + 1)) / (k + 1) * coefP.getCol(k);
1433 for (
int k = 0; k < nbRestSegCoef; k++) {
1434 b1 += j * pow(segLength, j - 1) * (pow(Lmax, k + 2) - pow(Lmin, k + 2)) / (k + 2) * coefP.getCol(k);
1436 vpColVector coef = stiffnessPerUnitLength * (b0 + R.t() * b1);
1438 for (
int dim = 0; dim < 3; dim++)
1439 B(line + 3 * j + dim) += coef[dim];
1443 if (LbevMax < bevLength) {
1446 lbev += LbevMax - LbevMin;
1450 currentDepth += LbevMax - LbevMin;
1452 LbevMax = bevLength;
1456 Eigen::SparseMatrix<double> M(nbMatrixLine, nbMatrixLine);
1457 M.setFromTriplets(L.begin(), L.end());
1459 Eigen::SparseLU<Eigen::SparseMatrix<double> > solver;
1462 A = solver.solve(B);
1466 for (
int i = 0; i < nbSegments; i++) {
1468 vpMatrix m(3, order + 1);
1469 for (
int j = 0; j < order + 1; j++) {
1470 for (
int dim = 0; dim < 3; dim++) {
1471 m[dim][j] = A(startIndex + 3 * j + dim);
1475 startIndex += 3 * (order + 1);
1478 throw vpException(vpException::functionNotImplementedError,
"usNeedleInsertionModelRayleighRitzSpline::"
1479 "solveSegmentsParametersFullSparseEigen: not implemented "
1486 #ifdef VISP_HAVE_EIGEN3
1491 vpMatrix M(3, seg.
getOrder() + 1, 0);
1492 for (
int dim = 0; dim < 3; dim++) {
1504 double trueFreeLength = 0;
1507 double freeLength = -1;
1513 for (
int i = 0; i < seg; i++) {
1519 for (
int i = 0; i < 3; i++)
1522 for (
int i = 0; i < 3; i++)
1525 if (cosTheta > std::numeric_limits<double>::epsilon())
1535 vpMatrix M(3, seg.
getOrder() + 1, 0);
1536 for (
int dim = 0; dim < 3; dim++) {
1548 double segDefaultLength = 0.01;
1558 for (
int i = 0; i < nbSegments - 1; i++)
1560 if (nbSegments > 1) {
1562 if (l > std::numeric_limits<double>::epsilon())
1570 for (
int i = 0; i < nbSegments; i++)
1573 typedef Eigen::Triplet<double> T;
1578 int nbConstraints = 2;
1579 for (
int i = 0; i < nbSegments - 1; i++) {
1582 int order = std::max(order1, order2);
1583 nbConstraints += std::min(3, order);
1586 int nbMatrixLine = 3 * (nbConstraints + nbcoef);
1588 L.reserve(nbMatrixLine * nbMatrixLine / 10);
1590 Eigen::VectorXd A = Eigen::VectorXd::Zero(nbMatrixLine);
1591 Eigen::VectorXd B = Eigen::VectorXd::Zero(nbMatrixLine);
1596 int line = 3 * nbcoef;
1597 for (
int dim = 0; dim < 3; dim++) {
1599 L.push_back(T(line, dim, 1));
1600 L.push_back(T(dim, line, -1));
1603 for (
int dim = 0; dim < 3; dim++) {
1605 L.push_back(T(line, 3 + dim, 1));
1606 L.push_back(T(3 + dim, line, -1));
1612 for (
int i = 0; i < nbSegments - 1; i++) {
1616 int order = std::max(order1, order2);
1621 double *tmp =
new double[nbSegCoef];
1626 for (
int j = 1; j < nbSegCoef; j++)
1627 tmp[j] = segLength * tmp[j - 1];
1629 for (
int dim = 0; dim < 3; dim++) {
1630 for (
int j = 0; j < nbSegCoef; j++) {
1631 L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1632 L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1634 L.push_back(T(line, startIndex + 3 * nbSegCoef + dim, -1));
1635 L.push_back(T(startIndex + 3 * nbSegCoef + dim, line, 1));
1643 for (
int j = 2; j < nbSegCoef; j++)
1644 tmp[j] = segLength * tmp[j - 1];
1645 for (
int j = 1; j < nbSegCoef; j++)
1648 for (
int dim = 0; dim < 3; dim++) {
1649 for (
int j = 1; j < nbSegCoef; j++) {
1650 L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1651 L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1653 L.push_back(T(line, startIndex + 3 * (nbSegCoef + 1) + dim, -1));
1654 L.push_back(T(startIndex + 3 * (nbSegCoef + 1) + dim, line, 1));
1663 for (
int j = 3; j < nbSegCoef; j++)
1664 tmp[j] = segLength * tmp[j - 1];
1665 for (
int j = 2; j < nbSegCoef; j++)
1666 tmp[j] *= j * (j - 1);
1668 for (
int dim = 0; dim < 3; dim++) {
1669 for (
int j = 2; j < nbSegCoef; j++) {
1670 L.push_back(T(line, startIndex + 3 * j + dim, tmp[j]));
1671 L.push_back(T(startIndex + 3 * j + dim, line, -tmp[j]));
1673 L.push_back(T(line, startIndex + 3 * (nbSegCoef + 2) + dim, -2));
1674 L.push_back(T(startIndex + 3 * (nbSegCoef + 2) + dim, line, 2));
1679 startIndex += 3 * nbSegCoef;
1687 int nbSegEq = nbSegCoef;
1692 double currentRestParam = 0;
1693 int layerIndex = -1;
1694 double currentDepth = -trueFreeLength;
1695 double nextLayerDepth = 0;
1696 for (
int i = 0; i < nbSegments; i++) {
1698 nbSegEq = nbSegCoef;
1703 double LsegMax = segLength;
1704 while (lseg < segLength) {
1705 double stiffnessPerUnitLength = 0;
1706 if (layerIndex >= 0)
1709 if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (
int)
m_layerLength.size()) {
1710 LsegMax = nextLayerDepth - currentDepth;
1713 for (
int j = 0; j < nbSegEq; j++) {
1714 for (
int k = 0; k < nbSegCoef; k++) {
1718 c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
1721 c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
1723 for (
int dim = 0; dim < 3; dim++)
1724 L.push_back(T(line + 3 * j + dim, startIndex + 3 * k + dim, c));
1728 if (layerIndex >= 0) {
1731 while (l < LsegMax) {
1737 int nbRestSegCoef = p.
getOrder() + 1;
1743 currentRestParam += (LsegMax - l) / factor;
1748 currentRestParam = 0;
1753 for (
int j = 0; j < nbSegEq; j++) {
1754 for (
int k = 0; k < nbRestSegCoef; k++) {
1755 double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
1756 for (
int dim = 0; dim < 3; dim++) {
1757 B(line + 3 * j + dim) += c * coefP[dim][k];
1764 if (LsegMax < segLength) {
1767 lseg += LsegMax - LsegMin;
1771 currentDepth += LsegMax - LsegMin;
1773 LsegMax = segLength;
1776 line += 3 * nbSegEq;
1777 startIndex += 3 * nbSegCoef;
1785 if (layerIndex < 0) {
1791 vpRotationMatrix R(0, 0, 0);
1794 double bevLength = bevelSegment.frobeniusNorm();
1795 bevelSegment.normalize();
1797 R.buildFrom(p[0], p[1], p[2]);
1801 if (currentDepth == 0) {
1803 if (cosTheta > std::numeric_limits<double>::epsilon())
1808 LbevMin = bevLength;
1810 double lbev = LbevMin;
1811 double LbevMax = bevLength;
1812 while (lbev < bevLength) {
1815 if (currentDepth - lbev + bevLength > nextLayerDepth && layerIndex + 1 < (
int)
m_layerLength.size()) {
1816 LbevMax = nextLayerDepth - currentDepth;
1819 for (
int j = 0; j < nbSegEq; j++) {
1820 for (
int k = 0; k < nbSegCoef; k++) {
1826 c0 = pow(segLength, j + k) * (LbevMax - LbevMin);
1828 c1 = j * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1830 c2 = k * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
1832 c3 = (j * k) * pow(segLength, j + k - 2) * (pow(LbevMax, 3) - pow(LbevMin, 3)) / 3;
1834 vpMatrix coefMat = stiffnessPerUnitLength * (c0 * I + c1 * R.t() + c2 * R + c3 * R.t() * R);
1836 for (
int dimj = 0; dimj < 3; dimj++)
1837 for (
int dimk = 0; dimk < 3; dimk++)
1838 L.push_back(T(line + 3 * j + dimj, startIndex + 3 * k + dimk, coefMat[dimj][dimk]));
1843 while (l < LbevMax) {
1849 int nbRestSegCoef = p.
getOrder() + 1;
1855 currentRestParam += LbevMax - l;
1860 currentRestParam = 0;
1865 for (
int j = 0; j < nbSegEq; j++) {
1866 vpColVector b0(3, 0);
1867 vpColVector b1(3, 0);
1868 for (
int k = 0; k < nbRestSegCoef; k++) {
1869 b0 += pow(segLength, j) * (pow(Lmax, k + 1) - pow(Lmin, k + 1)) / (k + 1) * coefP.getCol(k);
1872 for (
int k = 0; k < nbRestSegCoef; k++) {
1873 b1 += j * pow(segLength, j - 1) * (pow(Lmax, k + 2) - pow(Lmin, k + 2)) / (k + 2) * coefP.getCol(k);
1875 vpColVector coef = stiffnessPerUnitLength * (b0 + R.t() * b1);
1877 for (
int dim = 0; dim < 3; dim++)
1878 B(line + 3 * j + dim) += coef[dim];
1882 if (LbevMax < bevLength) {
1885 lbev += LbevMax - LbevMin;
1889 currentDepth += LbevMax - LbevMin;
1891 LbevMax = bevLength;
1895 Eigen::SparseMatrix<double> M(nbMatrixLine, nbMatrixLine);
1896 M.setFromTriplets(L.begin(), L.end());
1898 Eigen::SparseLU<Eigen::SparseMatrix<double> > solver;
1901 A = solver.solve(B);
1905 for (
int i = 0; i < nbSegments; i++) {
1907 vpMatrix m(3, order + 1);
1908 for (
int j = 0; j < order + 1; j++) {
1909 for (
int dim = 0; dim < 3; dim++) {
1910 m[dim][j] = A(startIndex + 3 * j + dim);
1914 startIndex += 3 * (order + 1);
1917 throw vpException(vpException::functionNotImplementedError,
"usNeedleInsertionModelRayleighRitzSpline::"
1918 "solveSegmentsParametersFullSparseEigenFixedLength: not "
1919 "implemented without Eigen3");
1929 vpMatrix M(3, seg.
getOrder() + 1, 0);
1930 for (
int dim = 0; dim < 3; dim++) {
1942 double trueFreeLength = 0;
1945 double freeLength = -1;
1951 for (
int i = 0; i < seg; i++) {
1957 for (
int i = 0; i < 3; i++)
1960 for (
int i = 0; i < 3; i++)
1963 if (cosTheta > std::numeric_limits<double>::epsilon())
1973 vpMatrix M(3, seg.
getOrder() + 1, 0);
1974 for (
int dim = 0; dim < 3; dim++) {
1986 double segDefaultLength = 0.01;
1996 for (
int i = 0; i < nbSegments - 1; i++)
1998 if (nbSegments > 1) {
2000 if (l > std::numeric_limits<double>::epsilon())
2008 for (
int i = 0; i < nbSegments; i++)
2013 int nbConstraints = 2;
2014 for (
int i = 0; i < nbSegments - 1; i++) {
2017 int order = std::max(order1, order2);
2018 nbConstraints += std::min(3, order);
2021 int nbMatrixLine = 3 * (nbConstraints + nbcoef);
2023 vpMatrix M(nbMatrixLine, nbMatrixLine, 0);
2025 vpColVector A(nbMatrixLine, 0);
2026 vpColVector B(nbMatrixLine, 0);
2031 int line = 3 * nbcoef;
2032 for (
int dim = 0; dim < 3; dim++) {
2038 for (
int dim = 0; dim < 3; dim++) {
2040 M[line][3 + dim] = 1;
2041 M[3 + dim][line] = -1;
2047 for (
int i = 0; i < nbSegments - 1; i++) {
2051 int order = std::max(order1, order2);
2056 double *tmp =
new double[nbSegCoef];
2060 for (
int j = 1; j < nbSegCoef; j++)
2061 tmp[j] = segLength * tmp[j - 1];
2063 for (
int dim = 0; dim < 3; dim++) {
2064 for (
int j = 0; j < nbSegCoef; j++) {
2065 M[line][startIndex + 3 * j + dim] = tmp[j];
2066 M[startIndex + 3 * j + dim][line] = -tmp[j];
2068 M[line][startIndex + 3 * nbSegCoef + dim] = -1;
2069 M[startIndex + 3 * nbSegCoef + dim][line] = 1;
2077 for (
int j = 2; j < nbSegCoef; j++)
2078 tmp[j] = segLength * tmp[j - 1];
2079 for (
int j = 1; j < nbSegCoef; j++)
2082 for (
int dim = 0; dim < 3; dim++) {
2083 for (
int j = 1; j < nbSegCoef; j++) {
2084 M[line][startIndex + 3 * j + dim] = tmp[j];
2085 M[startIndex + 3 * j + dim][line] = -tmp[j];
2087 M[line][startIndex + 3 * (nbSegCoef + 1) + dim] = -1;
2088 M[startIndex + 3 * (nbSegCoef + 1) + dim][line] = 1;
2097 for (
int j = 3; j < nbSegCoef; j++)
2098 tmp[j] = segLength * tmp[j - 1];
2099 for (
int j = 2; j < nbSegCoef; j++)
2100 tmp[j] *= j * (j - 1);
2102 for (
int dim = 0; dim < 3; dim++) {
2103 for (
int j = 2; j < nbSegCoef; j++) {
2104 M[line][startIndex + 3 * j + dim] = tmp[j];
2105 M[startIndex + 3 * j + dim][line] = -tmp[j];
2107 M[line][startIndex + 3 * (nbSegCoef + 2) + dim] = -2;
2108 M[startIndex + 3 * (nbSegCoef + 2) + dim][line] = 2;
2113 startIndex += 3 * nbSegCoef;
2121 int nbSegEq = nbSegCoef;
2126 double currentRestParam = 0;
2127 int layerIndex = -1;
2128 double currentDepth = -trueFreeLength;
2129 double nextLayerDepth = 0;
2130 for (
int i = 0; i < nbSegments; i++) {
2132 nbSegEq = nbSegCoef;
2137 double LsegMax = segLength;
2138 while (lseg < segLength) {
2139 double stiffnessPerUnitLength = 0;
2140 if (layerIndex >= 0)
2143 if (currentDepth - lseg + segLength > nextLayerDepth && layerIndex + 1 < (
int)
m_layerLength.size()) {
2144 LsegMax = nextLayerDepth - currentDepth;
2147 for (
int j = 0; j < nbSegEq; j++) {
2148 for (
int k = 0; k < nbSegCoef; k++) {
2152 c += EI * (pow(LsegMax, j + k - 3) - pow(LsegMin, j + k - 3)) * j * (j - 1) * k * (k - 1) / (j + k - 3);
2155 c += stiffnessPerUnitLength * (pow(LsegMax, j + k + 1) - pow(LsegMin, j + k + 1)) / (j + k + 1);
2157 for (
int dim = 0; dim < 3; dim++)
2158 M[line + 3 * j + dim][startIndex + 3 * k + dim] = c;
2162 if (layerIndex >= 0) {
2165 while (l < LsegMax) {
2171 int nbRestSegCoef = p.
getOrder() + 1;
2177 currentRestParam += (LsegMax - l) / factor;
2182 currentRestParam = 0;
2187 for (
int j = 0; j < nbSegEq; j++) {
2188 for (
int k = 0; k < nbRestSegCoef; k++) {
2189 double c = stiffnessPerUnitLength * (pow(Lmax, j + k + 1) - pow(Lmin, j + k + 1)) / (j + k + 1);
2190 for (
int dim = 0; dim < 3; dim++) {
2191 B[line + 3 * j + dim] += c * coefP[dim][k];
2198 if (LsegMax < segLength) {
2201 lseg += LsegMax - LsegMin;
2205 currentDepth += LsegMax - LsegMin;
2207 LsegMax = segLength;
2210 line += 3 * nbSegEq;
2211 startIndex += 3 * nbSegCoef;
2219 if (layerIndex < 0) {
2225 vpRotationMatrix R(0, 0, 0);
2228 double bevLength = bevelSegment.frobeniusNorm();
2229 bevelSegment.normalize();
2231 R.buildFrom(p[0], p[1], p[2]);
2235 if (currentDepth == 0) {
2237 if (cosTheta > std::numeric_limits<double>::epsilon())
2242 LbevMin = bevLength;
2244 double lbev = LbevMin;
2245 double LbevMax = bevLength;
2246 while (lbev < bevLength) {
2249 if (currentDepth - lbev + bevLength > nextLayerDepth && layerIndex + 1 < (
int)
m_layerLength.size()) {
2250 LbevMax = nextLayerDepth - currentDepth;
2253 for (
int j = 0; j < nbSegEq; j++) {
2254 for (
int k = 0; k < nbSegCoef; k++) {
2260 c0 = pow(segLength, j + k) * (LbevMax - LbevMin);
2262 c1 = j * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
2264 c2 = k * pow(segLength, j + k - 1) * (pow(LbevMax, 2) - pow(LbevMin, 2)) / 2;
2266 c3 = (j * k) * pow(segLength, j + k - 2) * (pow(LbevMax, 3) - pow(LbevMin, 3)) / 3;
2268 vpMatrix coefMat = stiffnessPerUnitLength * (c0 * I + c1 * R.t() + c2 * R + c3 * R.t() * R);
2270 for (
int dimj = 0; dimj < 3; dimj++)
2271 for (
int dimk = 0; dimk < 3; dimk++)
2272 M[line + 3 * j + dimj][startIndex + 3 * k + dimk] += coefMat[dimj][dimk];
2277 while (l < LbevMax) {
2283 int nbRestSegCoef = p.
getOrder() + 1;
2289 currentRestParam += LbevMax - l;
2294 currentRestParam = 0;
2299 for (
int j = 0; j < nbSegEq; j++) {
2300 vpColVector b0(3, 0);
2301 vpColVector b1(3, 0);
2302 for (
int k = 0; k < nbRestSegCoef; k++) {
2303 b0 += pow(segLength, j) * (pow(Lmax, k + 1) - pow(Lmin, k + 1)) / (k + 1) * coefP.getCol(k);
2306 for (
int k = 0; k < nbRestSegCoef; k++) {
2307 b1 += j * pow(segLength, j - 1) * (pow(Lmax, k + 2) - pow(Lmin, k + 2)) / (k + 2) * coefP.getCol(k);
2309 vpColVector coef = stiffnessPerUnitLength * (b0 + R.t() * b1);
2311 for (
int dim = 0; dim < 3; dim++)
2312 B[line + 3 * j + dim] += coef[dim];
2316 if (LbevMax < bevLength) {
2319 lbev += LbevMax - LbevMin;
2323 currentDepth += LbevMax - LbevMin;
2325 LbevMax = bevLength;
2329 A = M.inverseByLU() * B;
2333 for (
int i = 0; i < nbSegments; i++) {
2335 vpMatrix m(3, order + 1);
2336 for (
int j = 0; j < order + 1; j++) {
2337 for (
int dim = 0; dim < 3; dim++) {
2338 m[dim][j] = A[startIndex + 3 * j + dim];
2342 startIndex += 3 * (order + 1);
2351 double trueLength = 0;
2373 vpTranslationVector t(pt[0], pt[1], pt[2]);
2379 double theta = atan2(vect.frobeniusNorm(), dot);
2381 vect = theta * vect;
2382 vpThetaUVector thetaU(vect[0], vect[1], vect[2]);
2383 vpRotationMatrix R(thetaU);
2385 worldRtip = R * worldRtip;
2387 vpPoseVector tipPose(t, worldRtip);
2394 #ifdef VISP_HAVE_EIGEN3
2425 double restLength = -1;
2453 }
while (this->
updatePath() && (loopIndex < 2));
2468 vpColVector lastPoint(3);
2469 vpColVector lastDirection(3);
2471 double restParam = -1;
2475 restIndex, restParam);
2485 double insertionStep = 0;
2497 M.insert(lastPoint, 0, 0);
2501 M.insert((1 * u).normalize(), 0, 1);
2510 vpColVector lastPoint(3);
2511 vpColVector lastDirection(3);
2513 double restParam = -1;
2517 restIndex, restParam);
2527 double insertionStep = 0;
2539 M.insert(lastPoint, 0, 0);
2544 M.insert((newPoint - lastPoint).normalize(), 0, 1);
2559 s <<
"usNeedleInsertionModelRayleighRitzSpline\n";
2566 s << *dynamic_cast<usNeedleTipActuated *>(model.
m_needleTip);
2572 s << *dynamic_cast<usNeedleTipBeveled *>(model.
m_needleTip);
2577 s << *dynamic_cast<usNeedleTipPrebent *>(model.
m_needleTip);
2582 s << *dynamic_cast<usNeedleTipSymmetric *>(model.
m_needleTip);
2591 for (
int i = 0; i < n; i++)
2593 for (
int i = 0; i < n; i++)
2598 for (
int i = 0; i < n; i++)
2609 if (c !=
"usNeedleInsertionModelRayleighRitzSpline") {
2610 vpException e(vpException::ioError,
"Stream does not contain usNeedleInsertionModelRayleighRitzSpline data");
2646 for (
int i = 0; i < n; i++)
2648 for (
int i = 0; i < n; i++)
2653 for (
int i = 0; i < n; i++)
2661 s.write(
"usNeedleInsertionModelRayleighRitzSpline", 41);
2669 s.write((
char *)&(t),
sizeof(
int));
2670 s <<= *dynamic_cast<usNeedleTipActuated *>(model.
m_needleTip);
2675 s.write((
char *)&(t),
sizeof(
int));
2676 s <<= *dynamic_cast<usNeedleTipBeveled *>(model.
m_needleTip);
2681 s.write((
char *)&(t),
sizeof(
int));
2682 s <<= *dynamic_cast<usNeedleTipPrebent *>(model.
m_needleTip);
2687 s.write((
char *)&(t),
sizeof(
int));
2688 s <<= *dynamic_cast<usNeedleTipSymmetric *>(model.
m_needleTip);
2696 s.write((
char *)&(n),
sizeof(
int));
2698 for (
int i = 0; i < n; i++)
2700 for (
int i = 0; i < n; i++)
2701 s.write((
char *)&(model.
m_layerLength.at(i)),
sizeof(
double));
2704 s.write((
char *)&(n),
sizeof(
int));
2705 for (
int i = 0; i < n; i++)
2716 if (strcmp(c,
"usNeedleInsertionModelRayleighRitzSpline")) {
2717 vpException e(vpException::ioError,
"Stream does not contain usNeedleInsertionModelRayleighRitzSpline data");
2724 s.read((
char *)&(t),
sizeof(
int));
2747 s.read((
char *)&(n),
sizeof(
int));
2751 for (
int i = 0; i < n; i++)
2753 for (
int i = 0; i < n; i++)
2754 s.read((
char *)&(model.
m_layerLength.at(i)),
sizeof(
double));
2756 s.read((
char *)&(n),
sizeof(
int));
2758 for (
int i = 0; i < n; i++)
void setSegment(int i, const usPolynomialCurve3D &poly)
bool getParametersFromLength(double l, int &index, double ¶m) const
void removeSegments(int i, int j)
const usPolynomialCurve3D & accessSegment(int i) const
void addSegment(const usPolynomialCurve3D &seg)
Spline definition.
int getNbSegments() const
Parameters setters and getters.
const usPolynomialCurve3D & accessLastSegment() const
vpColVector getPoint(double param) const
Measure curve information.
double getParametricLength() const
double getInsertionDepth() const
std::vector< double > m_stiffnessPerUnitLength
usTissueModelSpline m_tissue
Tissue.
void setPathUpdateMixCoefficient(double coef)
void loadPreset(const ModelPreset preset)
Parameters saving and loading.
vpColVector getTissueInsertionPoint() const
void solveSegmentsParametersFullSparseEigen()
bool setStiffnessPerUnitLength(int i, double K)
usNeedleTip * m_needleTip
virtual bool setBasePose(const vpPoseVector &pose)=0
Control of the needle.
double m_pathUpdateLengthThreshold
usNeedleModelSpline m_needle
Model Parameters.
NeedleTipType getNeedleTipType() const
vpPoseVector getBasePose() const
double getStiffnessPerUnitLength(int i=0) const
usNeedleTip const & accessNeedleTip() const
double m_pathUpdateMixCoefficient
void solveSegmentsParametersFullSparseEigenFixedLength()
vpColVector getNeedleInsertionPoint() const
double getNeedleFreeLength(int *seg=nullptr, double *param=nullptr) const
const usTissueModelSpline & accessTissue() const
Tissue parameters.
PathUpdateType m_pathUpdateType
Path update.
double getLayerLength(int i) const
double getMeanTissueStretch() const
void solveSegmentsParameters()
SolvingMethod m_solvingMethod
Internal.
bool addTissueLayer(double K, double l)
const usNeedleModelSpline & accessNeedle() const
Parameters setters and getters.
std::vector< double > m_layerLength
bool getCorrespondingPathPoint(double l, int &correspondingRestIndex, double &correspondingRestParam) const
double getTissueDeformationEnergy() const
Measure model information.
void setNeedleTipType(NeedleTipType type)
const usNeedleInsertionModelRayleighRitzSpline & operator=(const usNeedleInsertionModelRayleighRitzSpline &model)
void setSolvingMethod(SolvingMethod method)
void setPathUpdateLengthThreshold(double length)
void solveSegmentsParametersSparseEigen()
Internal model command.
double getMaxTissueStretch(double *lmax=nullptr) const
void solveSegmentsParametersDense()
void setPathUpdateType(PathUpdateType type)
Model behavior.
bool cutPathToPoint(const vpColVector &P)
int getNbCurrentLayers() const
virtual ~usNeedleInsertionModelRayleighRitzSpline()
NeedleTipType m_needleTipType
virtual bool updateState()
virtual usNeedleInsertionModelRayleighRitzSpline * clone() const
std::vector< double > m_restDilatationFactor
bool IsNeedleInserted() const
Model parameters.
double getSurfaceTissueStretch() const
void setSurfaceAtTip()
Control of the tissue.
bool setLayerLength(int i, double l)
usNeedleInsertionModelRayleighRitzSpline()
Constructors, destructor.
vpPoseVector getBasePose() const
Parameters setters and getters.
void setBasePose(double tx, double ty, double tz, double thetax, double thetay, double thetaz)
Command of the needle.
vpColVector getTipDirection() const
vpColVector getTipPosition() const
vpHomogeneousMatrix getWorldMbase() const
vpPoseVector getTipPose() const
vpColVector getBasePosition() const
void setTipPose(double tx, double ty, double tz, double thetax, double thetay, double thetaz)
double getFullLength() const
void init()
Spline definition.
double getOuterDiameter() const
void loadPreset(const NeedlePreset preset)
Parameters saving and loading.
void setDiameter(double diameter)
Parameters setters and getters.
void setTipAngleRad(double angle)
void setSteeringAngleRad(double angle)
void setDiameter(double diameter)
Parameters setters and getters.
void setDiameter(double diameter)
Parameters setters and getters.
virtual usNeedleTip * clone() const
vpPoseVector getBasePose() const
vpColVector getTipPosition() const
vpColVector getBasePosition() const
vpColVector getTipDirection() const
vpColVector getBaseAxisZ() const
void setBasePose(const vpPoseVector &pose)
Parameters setters and getters.
vpColVector getDirection() const
void setPose(const vpPoseVector &pose)
Parameters setters and getters.
void setPosition(const vpColVector &P)
vpColVector getStartTangent() const
usPolynomialCurve3D getSubPolynomialCurve(double startParameter, double endParameter) const
double getLength(int nbCountSeg=50) const
unsigned int getOrder() const
vpColVector getPoint(double parameter) const
void setParametricLength(double length)
void setPolynomialCoefficients(const vpMatrix &polynomialCoefficients)
vpColVector getEndPoint() const
vpMatrix getPolynomialCoefficients() const
vpColVector getEndTangent() const
double getParametricLength() const
void changeCoefficientsToFitBoundaries(double startParameter, double endParameter)
vpColVector getStartPoint() const
const usBSpline3D & accessPath() const
const usOrientedPlane3D & accessSurface() const
Parameters setters and getters.