Resurgence (PY2022)
Codebase for the Husky Robotics 2021-2022 rover Resurgence
Loading...
Searching...
No Matches
FabrikSolver.h
1#pragma once
2
3#include "../navtypes.h"
4#include "InverseArmKinematics.h"
5#include "PlanarArmFK.h"
6
7#include <memory>
8
9#include <Eigen/Core>
10#include <Eigen/Dense>
11
12namespace kinematics {
13
24template <int N>
26public:
35 FabrikSolver2D(std::shared_ptr<const PlanarArmFK<N>> fk, double thresh, int maxIter)
36 : InverseArmKinematics<2, N>(fk), segLens(fk->getSegLens()), thresh(thresh),
37 maxIter(maxIter) {}
38
39 navtypes::Vectord<N> solve(const Eigen::Vector2d& eePos,
40 const navtypes::Vectord<N>& jointAngles,
41 bool& success) const override {
42 navtypes::Arrayd<N + 1, 2> jointPos = jointAnglesToJointPos(jointAngles);
43 success = false;
44 for (int iter = 0; iter < maxIter; iter++) {
45 // forward
46 jointPos.row(N) = eePos;
47 for (int i = N - 1; i >= 0; i--) {
48 double jointDist = (jointPos.row(i) - jointPos.row(i + 1)).matrix().norm();
49 double lambda = segLens[i] / jointDist;
50 jointPos.row(i) =
51 lambda * jointPos.row(i) + (1 - lambda) * jointPos.row(i + 1);
52 }
53
54 // backward
55 jointPos.row(0) << 0, 0;
56 for (int i = 0; i < N; i++) {
57 double jointDist = (jointPos.row(i) - jointPos.row(i + 1)).matrix().norm();
58 double lambda = segLens[i] / jointDist;
59 jointPos.row(i + 1) =
60 lambda * jointPos.row(i + 1) + (1 - lambda) * jointPos.row(i);
61 }
62
63 double err = (jointPos.row(N).matrix().transpose() - eePos).norm();
64 if (err <= thresh) {
65 success = true;
66 break;
67 }
68 }
69
70 navtypes::Vectord<N> targetJointAngles = jointPosToJointAngles(jointPos);
71 return targetJointAngles;
72 }
73
74private:
75 navtypes::Arrayd<N> segLens;
76 double thresh;
77 int maxIter;
78
79 navtypes::Arrayd<N + 1, 2>
80 jointAnglesToJointPos(const navtypes::Vectord<N>& jointAngles) const {
81 std::array<double, N> jointAngleCumSum;
82 jointAngleCumSum[0] = jointAngles[0];
83 for (int i = 1; i < N; i++) {
84 jointAngleCumSum[i] = jointAngleCumSum[i - 1] + jointAngles[i];
85 }
86
87 navtypes::Arrayd<N + 1, 2> jointPos;
88 jointPos.row(0) << 0, 0;
89 for (int i = 1; i <= N; i++) {
90 Eigen::Vector2d seg;
91 seg << std::cos(jointAngleCumSum[i - 1]), std::sin(jointAngleCumSum[i - 1]);
92 jointPos.row(i) = jointPos.row(i - 1) + segLens[i - 1] * seg.array().transpose();
93 }
94 return jointPos;
95 }
96
97 navtypes::Vectord<N>
98 jointPosToJointAngles(const navtypes::Arrayd<N + 1, 2>& jointPos) const {
99 navtypes::Arrayd<N + 1, 3> jointPos3d;
100 jointPos3d << jointPos, navtypes::Arrayd<N + 1>::Zero();
101
102 navtypes::Vectord<N> jointAngles;
103 jointAngles[0] = std::atan2(jointPos(1, 1), jointPos(1, 0));
104 for (int i = 1; i < N; i++) {
105 Eigen::RowVector3d prevSeg =
106 (jointPos3d.row(i) - jointPos3d.row(i - 1)).matrix().normalized();
107 Eigen::RowVector3d seg =
108 (jointPos3d.row(i + 1) - jointPos3d.row(i)).matrix().normalized();
109
110 jointAngles[i] = std::atan2(prevSeg.cross(seg).z(), prevSeg.dot(seg));
111 }
112 return jointAngles;
113 }
114};
115
116} // namespace kinematics
complex< _Tp > sin(const complex< _Tp > &)
complex< _Tp > cos(const complex< _Tp > &)
FabrikSolver2D(std::shared_ptr< const PlanarArmFK< N > > fk, double thresh, int maxIter)
Construct an IK solver object.
Definition FabrikSolver.h:35
InverseArmKinematics(std::shared_ptr< const ForwardArmKinematics< D, N > > fk)
Definition InverseArmKinematics.h:26
Kinematics object for a sequence of arm segments in a 2d plane.
Definition PlanarArmFK.h:20
bool solve(InputArray src1, InputArray src2, OutputArray dst, int flags=DECOMP_LU)
void transpose(InputArray src, OutputArray dst)