17 m_poleconstraint =
false;
18 m_getpoleangle =
false;
19 m_rootmatrix.setIdentity();
22double IK_QJacobianSolver::ComputeScale()
24 std::vector<IK_QSegment *>::iterator seg;
27 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
28 length += (*seg)->MaxExtension();
37void IK_QJacobianSolver::Scale(
double scale, std::list<IK_QTask *> &tasks)
39 std::list<IK_QTask *>::iterator task;
40 std::vector<IK_QSegment *>::iterator seg;
42 for (task = tasks.begin(); task != tasks.end(); task++) {
43 (*task)->Scale(scale);
46 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
50 m_rootmatrix.translation() *=
scale;
55void IK_QJacobianSolver::AddSegmentList(
IK_QSegment *seg)
57 m_segments.push_back(seg);
60 for (child = seg->
Child(); child; child = child->
Sibling()) {
61 AddSegmentList(child);
71 std::vector<IK_QSegment *>::iterator seg;
74 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
75 (*seg)->SetDoFId(num_dof);
76 num_dof += (*seg)->NumberOfDoF();
85 int secondary_size = 0, secondary = 0;
86 double primary_weight = 0.0, secondary_weight = 0.0;
87 std::list<IK_QTask *>::iterator task;
89 for (task = tasks.begin(); task != tasks.end(); task++) {
93 qtask->
SetId(primary_size);
94 primary_size += qtask->
Size();
95 primary_weight += qtask->
Weight();
98 qtask->
SetId(secondary_size);
99 secondary_size += qtask->
Size();
100 secondary_weight += qtask->
Weight();
105 if (primary_size == 0 ||
FuzzyZero(primary_weight)) {
109 m_secondary_enabled = (secondary > 0);
112 double primary_rescale = 1.0 / primary_weight;
113 double secondary_rescale;
115 secondary_rescale = 0.0;
118 secondary_rescale = 1.0 / secondary_weight;
121 for (task = tasks.begin(); task != tasks.end(); task++) {
133 m_jacobian.ArmMatrices(num_dof, primary_size);
135 m_jacobian_sub.ArmMatrices(num_dof, secondary_size);
141 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
142 for (
i = 0;
i < (*seg)->NumberOfDoF();
i++) {
143 m_jacobian.SetDoFWeight((*seg)->DoFId() +
i, (*seg)->Weight(
i));
151 IK_QSegment *tip, Vector3d &goal, Vector3d &polegoal,
float poleangle,
bool getangle)
153 m_poleconstraint =
true;
156 m_polegoal = polegoal;
157 m_poleangle = (getangle) ? 0.0f : poleangle;
158 m_getpoleangle = getangle;
161void IK_QJacobianSolver::ConstrainPoleVector(
IK_QSegment *root, std::list<IK_QTask *> &tasks)
167 if (!m_poleconstraint) {
172 std::list<IK_QTask *>::iterator task;
173 int positiontasks = 0;
175 for (task = tasks.begin(); task != tasks.end(); task++) {
176 if ((*task)->PositionTask()) {
181 if (positiontasks >= 2) {
182 m_poleconstraint =
false;
190 const Vector3d endpos = m_poletip->GlobalEnd();
196 Vector3d dir =
normalize(endpos - rootpos);
197 Vector3d rootx = rootbasis.col(0);
198 Vector3d rootz = rootbasis.col(2);
199 Vector3d up = rootx *
cos(m_poleangle) + rootz *
sin(m_poleangle);
202 Vector3d poledir = (m_getpoleangle) ? dir :
normalize(m_goal - rootpos);
203 Vector3d poleup =
normalize(m_polegoal - rootpos);
205 Matrix3d mat, polemat;
208 mat.row(1) = mat.row(0).cross(dir);
211 polemat.row(0) =
normalize(poledir.cross(poleup));
212 polemat.row(1) = polemat.row(0).cross(poledir);
213 polemat.row(2) = -poledir;
215 if (m_getpoleangle) {
217 m_poleangle =
angle(mat.row(1), polemat.row(1));
219 double dt = rootz.dot(mat.row(1) *
cos(m_poleangle) + mat.row(0) *
sin(m_poleangle));
221 m_poleangle = -m_poleangle;
225 m_getpoleangle =
false;
226 ConstrainPoleVector(root, tasks);
234 trans.linear() = polemat.transpose() * mat;
235 trans.translation() = Vector3d(0, 0, 0);
236 m_rootmatrix = trans * m_rootmatrix;
240bool IK_QJacobianSolver::UpdateAngles(
double &
norm)
243 std::vector<IK_QSegment *>::iterator seg;
244 IK_QSegment *qseg, *minseg =
nullptr;
245 double minabsdelta = 1e10, absdelta;
246 Vector3d delta, mindelta;
247 bool locked =
false,
clamp[3];
253 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
258 absdelta =
fabs(delta[
i]);
261 qseg->
Lock(
i, m_jacobian, delta);
264 else if (absdelta < minabsdelta) {
265 minabsdelta = absdelta;
277 minseg->
Lock(mindof, m_jacobian, mindelta);
283 if (locked ==
false) {
285 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
287 (*seg)->UpdateAngleApply();
296 std::list<IK_QTask *> tasks,
298 const int max_iterations)
300 float scale = ComputeScale();
306 ConstrainPoleVector(root, tasks);
311 for (
int iterations = 0; iterations < max_iterations; iterations++) {
315 std::list<IK_QTask *>::iterator task;
318 for (task = tasks.begin(); task != tasks.end(); task++) {
319 if ((*task)->Primary()) {
320 (*task)->ComputeJacobian(m_jacobian);
323 (*task)->ComputeJacobian(m_jacobian_sub);
333 if (m_secondary_enabled) {
334 m_jacobian.SubTask(m_jacobian_sub);
338 fprintf(stderr,
"IK Exception\n");
343 }
while (UpdateAngles(
norm));
346 std::vector<IK_QSegment *>::iterator seg;
347 for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
352 double maxnorm = m_jacobian.AngleUpdateNorm();
362 if (m_poleconstraint) {
366 Scale(1.0f / scale, tasks);
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
static const double IK_EPSILON
static bool FuzzyZero(double x)
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
void SetPoleVectorConstraint(IK_QSegment *tip, Vector3d &goal, Vector3d &polegoal, float poleangle, bool getangle)
bool Solve(IK_QSegment *root, std::list< IK_QTask * > tasks, const double tolerance, const int max_iterations)
bool Setup(IK_QSegment *root, std::list< IK_QTask * > &tasks)
const Affine3d & GlobalTransform() const
virtual void Lock(int, IK_QJacobian &, Vector3d &)
virtual bool UpdateAngle(const IK_QJacobian &, Vector3d &, bool *)=0
bool Locked(int dof) const
void UpdateTransform(const Affine3d &global)
Vector3d GlobalStart() const
void PrependBasis(const Matrix3d &mat)
IK_QSegment * Child() const
IK_QSegment * Sibling() const
void SetWeight(double weight)
VecBase< float, D > normalize(VecOp< float, D >) RET
constexpr T clamp(T, U, U) RET
float length(VecOp< float, D >) RET
ccl_device_inline float2 fabs(const float2 a)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)