Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/iksolver/intern/IK_QJacobian.cpp')
-rw-r--r--intern/iksolver/intern/IK_QJacobian.cpp617
1 files changed, 308 insertions, 309 deletions
diff --git a/intern/iksolver/intern/IK_QJacobian.cpp b/intern/iksolver/intern/IK_QJacobian.cpp
index 678486e36f4..7f77968a5d4 100644
--- a/intern/iksolver/intern/IK_QJacobian.cpp
+++ b/intern/iksolver/intern/IK_QJacobian.cpp
@@ -21,11 +21,9 @@
* \ingroup iksolver
*/
-
#include "IK_QJacobian.h"
-IK_QJacobian::IK_QJacobian()
- : m_sdls(true), m_min_damp(1.0)
+IK_QJacobian::IK_QJacobian() : m_sdls(true), m_min_damp(1.0)
{
}
@@ -35,392 +33,393 @@ IK_QJacobian::~IK_QJacobian()
void IK_QJacobian::ArmMatrices(int dof, int task_size)
{
- m_dof = dof;
- m_task_size = task_size;
+ m_dof = dof;
+ m_task_size = task_size;
- m_jacobian.resize(task_size, dof);
- m_jacobian.setZero();
+ m_jacobian.resize(task_size, dof);
+ m_jacobian.setZero();
- m_alpha.resize(dof);
- m_alpha.setZero();
+ m_alpha.resize(dof);
+ m_alpha.setZero();
- m_nullspace.resize(dof, dof);
+ m_nullspace.resize(dof, dof);
- m_d_theta.resize(dof);
- m_d_theta_tmp.resize(dof);
- m_d_norm_weight.resize(dof);
+ m_d_theta.resize(dof);
+ m_d_theta_tmp.resize(dof);
+ m_d_norm_weight.resize(dof);
- m_norm.resize(dof);
- m_norm.setZero();
+ m_norm.resize(dof);
+ m_norm.setZero();
- m_beta.resize(task_size);
+ m_beta.resize(task_size);
- m_weight.resize(dof);
- m_weight_sqrt.resize(dof);
- m_weight.setOnes();
- m_weight_sqrt.setOnes();
+ m_weight.resize(dof);
+ m_weight_sqrt.resize(dof);
+ m_weight.setOnes();
+ m_weight_sqrt.setOnes();
- if (task_size >= dof) {
- m_transpose = false;
+ if (task_size >= dof) {
+ m_transpose = false;
- m_jacobian_tmp.resize(task_size, dof);
+ m_jacobian_tmp.resize(task_size, dof);
- m_svd_u.resize(task_size, dof);
- m_svd_v.resize(dof, dof);
- m_svd_w.resize(dof);
+ m_svd_u.resize(task_size, dof);
+ m_svd_v.resize(dof, dof);
+ m_svd_w.resize(dof);
- m_svd_u_beta.resize(dof);
- }
- else {
- // use the SVD of the transpose jacobian, it works just as well
- // as the original, and often allows using smaller matrices.
- m_transpose = true;
+ m_svd_u_beta.resize(dof);
+ }
+ else {
+ // use the SVD of the transpose jacobian, it works just as well
+ // as the original, and often allows using smaller matrices.
+ m_transpose = true;
- m_jacobian_tmp.resize(dof, task_size);
+ m_jacobian_tmp.resize(dof, task_size);
- m_svd_u.resize(task_size, task_size);
- m_svd_v.resize(dof, task_size);
- m_svd_w.resize(task_size);
+ m_svd_u.resize(task_size, task_size);
+ m_svd_v.resize(dof, task_size);
+ m_svd_w.resize(task_size);
- m_svd_u_beta.resize(task_size);
- }
+ m_svd_u_beta.resize(task_size);
+ }
}
-void IK_QJacobian::SetBetas(int id, int, const Vector3d& v)
+void IK_QJacobian::SetBetas(int id, int, const Vector3d &v)
{
- m_beta[id + 0] = v.x();
- m_beta[id + 1] = v.y();
- m_beta[id + 2] = v.z();
+ m_beta[id + 0] = v.x();
+ m_beta[id + 1] = v.y();
+ m_beta[id + 2] = v.z();
}
-void IK_QJacobian::SetDerivatives(int id, int dof_id, const Vector3d& v, double norm_weight)
+void IK_QJacobian::SetDerivatives(int id, int dof_id, const Vector3d &v, double norm_weight)
{
- m_jacobian(id + 0, dof_id) = v.x() * m_weight_sqrt[dof_id];
- m_jacobian(id + 1, dof_id) = v.y() * m_weight_sqrt[dof_id];
- m_jacobian(id + 2, dof_id) = v.z() * m_weight_sqrt[dof_id];
+ m_jacobian(id + 0, dof_id) = v.x() * m_weight_sqrt[dof_id];
+ m_jacobian(id + 1, dof_id) = v.y() * m_weight_sqrt[dof_id];
+ m_jacobian(id + 2, dof_id) = v.z() * m_weight_sqrt[dof_id];
- m_d_norm_weight[dof_id] = norm_weight;
+ m_d_norm_weight[dof_id] = norm_weight;
}
void IK_QJacobian::Invert()
{
- if (m_transpose) {
- // SVD will decompose Jt into V*W*Ut with U,V orthogonal and W diagonal,
- // so J = U*W*Vt and Jinv = V*Winv*Ut
- Eigen::JacobiSVD<MatrixXd> svd(m_jacobian.transpose(), Eigen::ComputeThinU | Eigen::ComputeThinV);
- m_svd_u = svd.matrixV();
- m_svd_w = svd.singularValues();
- m_svd_v = svd.matrixU();
- }
- else {
- // SVD will decompose J into U*W*Vt with U,V orthogonal and W diagonal,
- // so Jinv = V*Winv*Ut
- Eigen::JacobiSVD<MatrixXd> svd(m_jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
- m_svd_u = svd.matrixU();
- m_svd_w = svd.singularValues();
- m_svd_v = svd.matrixV();
- }
-
- if (m_sdls)
- InvertSDLS();
- else
- InvertDLS();
+ if (m_transpose) {
+ // SVD will decompose Jt into V*W*Ut with U,V orthogonal and W diagonal,
+ // so J = U*W*Vt and Jinv = V*Winv*Ut
+ Eigen::JacobiSVD<MatrixXd> svd(m_jacobian.transpose(),
+ Eigen::ComputeThinU | Eigen::ComputeThinV);
+ m_svd_u = svd.matrixV();
+ m_svd_w = svd.singularValues();
+ m_svd_v = svd.matrixU();
+ }
+ else {
+ // SVD will decompose J into U*W*Vt with U,V orthogonal and W diagonal,
+ // so Jinv = V*Winv*Ut
+ Eigen::JacobiSVD<MatrixXd> svd(m_jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
+ m_svd_u = svd.matrixU();
+ m_svd_w = svd.singularValues();
+ m_svd_v = svd.matrixV();
+ }
+
+ if (m_sdls)
+ InvertSDLS();
+ else
+ InvertDLS();
}
bool IK_QJacobian::ComputeNullProjection()
{
- double epsilon = 1e-10;
-
- // compute null space projection based on V
- int i, j, rank = 0;
- for (i = 0; i < m_svd_w.size(); i++)
- if (m_svd_w[i] > epsilon)
- rank++;
-
- if (rank < m_task_size)
- return false;
-
- MatrixXd basis(m_svd_v.rows(), rank);
- int b = 0;
-
- for (i = 0; i < m_svd_w.size(); i++)
- if (m_svd_w[i] > epsilon) {
- for (j = 0; j < m_svd_v.rows(); j++)
- basis(j, b) = m_svd_v(j, i);
- b++;
- }
-
- m_nullspace = basis * basis.transpose();
-
- for (i = 0; i < m_nullspace.rows(); i++)
- for (j = 0; j < m_nullspace.cols(); j++)
- if (i == j)
- m_nullspace(i, j) = 1.0 - m_nullspace(i, j);
- else
- m_nullspace(i, j) = -m_nullspace(i, j);
-
- return true;
+ double epsilon = 1e-10;
+
+ // compute null space projection based on V
+ int i, j, rank = 0;
+ for (i = 0; i < m_svd_w.size(); i++)
+ if (m_svd_w[i] > epsilon)
+ rank++;
+
+ if (rank < m_task_size)
+ return false;
+
+ MatrixXd basis(m_svd_v.rows(), rank);
+ int b = 0;
+
+ for (i = 0; i < m_svd_w.size(); i++)
+ if (m_svd_w[i] > epsilon) {
+ for (j = 0; j < m_svd_v.rows(); j++)
+ basis(j, b) = m_svd_v(j, i);
+ b++;
+ }
+
+ m_nullspace = basis * basis.transpose();
+
+ for (i = 0; i < m_nullspace.rows(); i++)
+ for (j = 0; j < m_nullspace.cols(); j++)
+ if (i == j)
+ m_nullspace(i, j) = 1.0 - m_nullspace(i, j);
+ else
+ m_nullspace(i, j) = -m_nullspace(i, j);
+
+ return true;
}
-void IK_QJacobian::SubTask(IK_QJacobian& jacobian)
+void IK_QJacobian::SubTask(IK_QJacobian &jacobian)
{
- if (!ComputeNullProjection())
- return;
+ if (!ComputeNullProjection())
+ return;
- // restrict lower priority jacobian
- jacobian.Restrict(m_d_theta, m_nullspace);
+ // restrict lower priority jacobian
+ jacobian.Restrict(m_d_theta, m_nullspace);
- // add angle update from lower priority
- jacobian.Invert();
+ // add angle update from lower priority
+ jacobian.Invert();
- // note: now damps secondary angles with minimum damping value from
- // SDLS, to avoid shaking when the primary task is near singularities,
- // doesn't work well at all
- int i;
- for (i = 0; i < m_d_theta.size(); i++)
- m_d_theta[i] = m_d_theta[i] + /*m_min_damp * */ jacobian.AngleUpdate(i);
+ // note: now damps secondary angles with minimum damping value from
+ // SDLS, to avoid shaking when the primary task is near singularities,
+ // doesn't work well at all
+ int i;
+ for (i = 0; i < m_d_theta.size(); i++)
+ m_d_theta[i] = m_d_theta[i] + /*m_min_damp * */ jacobian.AngleUpdate(i);
}
-void IK_QJacobian::Restrict(VectorXd& d_theta, MatrixXd& nullspace)
+void IK_QJacobian::Restrict(VectorXd &d_theta, MatrixXd &nullspace)
{
- // subtract part already moved by higher task from beta
- m_beta = m_beta - m_jacobian * d_theta;
+ // subtract part already moved by higher task from beta
+ m_beta = m_beta - m_jacobian * d_theta;
+
+ // note: should we be using the norm of the unrestricted jacobian for SDLS?
- // note: should we be using the norm of the unrestricted jacobian for SDLS?
-
- // project jacobian on to null space of higher priority task
- m_jacobian = m_jacobian * nullspace;
+ // project jacobian on to null space of higher priority task
+ m_jacobian = m_jacobian * nullspace;
}
void IK_QJacobian::InvertSDLS()
{
- // Compute the dampeds least squeares pseudo inverse of J.
- //
- // Since J is usually not invertible (most of the times it's not even
- // square), the psuedo inverse is used. This gives us a least squares
- // solution.
- //
- // This is fine when the J*Jt is of full rank. When J*Jt is near to
- // singular the least squares inverse tries to minimize |J(dtheta) - dX)|
- // and doesn't try to minimize dTheta. This results in eratic changes in
- // angle. The damped least squares minimizes |dtheta| to try and reduce this
- // erratic behaviour.
- //
- // The selectively damped least squares (SDLS) is used here instead of the
- // DLS. The SDLS damps individual singular values, instead of using a single
- // damping term.
-
- double max_angle_change = M_PI / 4.0;
- double epsilon = 1e-10;
- int i, j;
-
- m_d_theta.setZero();
- m_min_damp = 1.0;
-
- for (i = 0; i < m_dof; i++) {
- m_norm[i] = 0.0;
- for (j = 0; j < m_task_size; j += 3) {
- double n = 0.0;
- n += m_jacobian(j, i) * m_jacobian(j, i);
- n += m_jacobian(j + 1, i) * m_jacobian(j + 1, i);
- n += m_jacobian(j + 2, i) * m_jacobian(j + 2, i);
- m_norm[i] += sqrt(n);
- }
- }
-
- for (i = 0; i < m_svd_w.size(); i++) {
- if (m_svd_w[i] <= epsilon)
- continue;
-
- double wInv = 1.0 / m_svd_w[i];
- double alpha = 0.0;
- double N = 0.0;
-
- // compute alpha and N
- for (j = 0; j < m_svd_u.rows(); j += 3) {
- alpha += m_svd_u(j, i) * m_beta[j];
- alpha += m_svd_u(j + 1, i) * m_beta[j + 1];
- alpha += m_svd_u(j + 2, i) * m_beta[j + 2];
-
- // note: for 1 end effector, N will always be 1, since U is
- // orthogonal, .. so could be optimized
- double tmp;
- tmp = m_svd_u(j, i) * m_svd_u(j, i);
- tmp += m_svd_u(j + 1, i) * m_svd_u(j + 1, i);
- tmp += m_svd_u(j + 2, i) * m_svd_u(j + 2, i);
- N += sqrt(tmp);
- }
- alpha *= wInv;
-
- // compute M, dTheta and max_dtheta
- double M = 0.0;
- double max_dtheta = 0.0, abs_dtheta;
-
- for (j = 0; j < m_d_theta.size(); j++) {
- double v = m_svd_v(j, i);
- M += fabs(v) * m_norm[j];
-
- // compute tmporary dTheta's
- m_d_theta_tmp[j] = v * alpha;
-
- // find largest absolute dTheta
- // multiply with weight to prevent unnecessary damping
- abs_dtheta = fabs(m_d_theta_tmp[j]) * m_weight_sqrt[j];
- if (abs_dtheta > max_dtheta)
- max_dtheta = abs_dtheta;
- }
-
- M *= wInv;
-
- // compute damping term and damp the dTheta's
- double gamma = max_angle_change;
- if (N < M)
- gamma *= N / M;
-
- double damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0;
-
- for (j = 0; j < m_d_theta.size(); j++) {
- // slight hack: we do 0.80*, so that if there is some oscillation,
- // the system can still converge (for joint limits). also, it's
- // better to go a little to slow than to far
-
- double dofdamp = damp / m_weight[j];
- if (dofdamp > 1.0) dofdamp = 1.0;
-
- m_d_theta[j] += 0.80 * dofdamp * m_d_theta_tmp[j];
- }
-
- if (damp < m_min_damp)
- m_min_damp = damp;
- }
-
- // weight + prevent from doing angle updates with angles > max_angle_change
- double max_angle = 0.0, abs_angle;
-
- for (j = 0; j < m_dof; j++) {
- m_d_theta[j] *= m_weight[j];
-
- abs_angle = fabs(m_d_theta[j]);
-
- if (abs_angle > max_angle)
- max_angle = abs_angle;
- }
-
- if (max_angle > max_angle_change) {
- double damp = (max_angle_change) / (max_angle_change + max_angle);
-
- for (j = 0; j < m_dof; j++)
- m_d_theta[j] *= damp;
- }
+ // Compute the dampeds least squeares pseudo inverse of J.
+ //
+ // Since J is usually not invertible (most of the times it's not even
+ // square), the psuedo inverse is used. This gives us a least squares
+ // solution.
+ //
+ // This is fine when the J*Jt is of full rank. When J*Jt is near to
+ // singular the least squares inverse tries to minimize |J(dtheta) - dX)|
+ // and doesn't try to minimize dTheta. This results in eratic changes in
+ // angle. The damped least squares minimizes |dtheta| to try and reduce this
+ // erratic behaviour.
+ //
+ // The selectively damped least squares (SDLS) is used here instead of the
+ // DLS. The SDLS damps individual singular values, instead of using a single
+ // damping term.
+
+ double max_angle_change = M_PI / 4.0;
+ double epsilon = 1e-10;
+ int i, j;
+
+ m_d_theta.setZero();
+ m_min_damp = 1.0;
+
+ for (i = 0; i < m_dof; i++) {
+ m_norm[i] = 0.0;
+ for (j = 0; j < m_task_size; j += 3) {
+ double n = 0.0;
+ n += m_jacobian(j, i) * m_jacobian(j, i);
+ n += m_jacobian(j + 1, i) * m_jacobian(j + 1, i);
+ n += m_jacobian(j + 2, i) * m_jacobian(j + 2, i);
+ m_norm[i] += sqrt(n);
+ }
+ }
+
+ for (i = 0; i < m_svd_w.size(); i++) {
+ if (m_svd_w[i] <= epsilon)
+ continue;
+
+ double wInv = 1.0 / m_svd_w[i];
+ double alpha = 0.0;
+ double N = 0.0;
+
+ // compute alpha and N
+ for (j = 0; j < m_svd_u.rows(); j += 3) {
+ alpha += m_svd_u(j, i) * m_beta[j];
+ alpha += m_svd_u(j + 1, i) * m_beta[j + 1];
+ alpha += m_svd_u(j + 2, i) * m_beta[j + 2];
+
+ // note: for 1 end effector, N will always be 1, since U is
+ // orthogonal, .. so could be optimized
+ double tmp;
+ tmp = m_svd_u(j, i) * m_svd_u(j, i);
+ tmp += m_svd_u(j + 1, i) * m_svd_u(j + 1, i);
+ tmp += m_svd_u(j + 2, i) * m_svd_u(j + 2, i);
+ N += sqrt(tmp);
+ }
+ alpha *= wInv;
+
+ // compute M, dTheta and max_dtheta
+ double M = 0.0;
+ double max_dtheta = 0.0, abs_dtheta;
+
+ for (j = 0; j < m_d_theta.size(); j++) {
+ double v = m_svd_v(j, i);
+ M += fabs(v) * m_norm[j];
+
+ // compute tmporary dTheta's
+ m_d_theta_tmp[j] = v * alpha;
+
+ // find largest absolute dTheta
+ // multiply with weight to prevent unnecessary damping
+ abs_dtheta = fabs(m_d_theta_tmp[j]) * m_weight_sqrt[j];
+ if (abs_dtheta > max_dtheta)
+ max_dtheta = abs_dtheta;
+ }
+
+ M *= wInv;
+
+ // compute damping term and damp the dTheta's
+ double gamma = max_angle_change;
+ if (N < M)
+ gamma *= N / M;
+
+ double damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0;
+
+ for (j = 0; j < m_d_theta.size(); j++) {
+ // slight hack: we do 0.80*, so that if there is some oscillation,
+ // the system can still converge (for joint limits). also, it's
+ // better to go a little to slow than to far
+
+ double dofdamp = damp / m_weight[j];
+ if (dofdamp > 1.0)
+ dofdamp = 1.0;
+
+ m_d_theta[j] += 0.80 * dofdamp * m_d_theta_tmp[j];
+ }
+
+ if (damp < m_min_damp)
+ m_min_damp = damp;
+ }
+
+ // weight + prevent from doing angle updates with angles > max_angle_change
+ double max_angle = 0.0, abs_angle;
+
+ for (j = 0; j < m_dof; j++) {
+ m_d_theta[j] *= m_weight[j];
+
+ abs_angle = fabs(m_d_theta[j]);
+
+ if (abs_angle > max_angle)
+ max_angle = abs_angle;
+ }
+
+ if (max_angle > max_angle_change) {
+ double damp = (max_angle_change) / (max_angle_change + max_angle);
+
+ for (j = 0; j < m_dof; j++)
+ m_d_theta[j] *= damp;
+ }
}
void IK_QJacobian::InvertDLS()
{
- // Compute damped least squares inverse of pseudo inverse
- // Compute damping term lambda
+ // Compute damped least squares inverse of pseudo inverse
+ // Compute damping term lambda
+
+ // Note when lambda is zero this is equivalent to the
+ // least squares solution. This is fine when the m_jjt is
+ // of full rank. When m_jjt is near to singular the least squares
+ // inverse tries to minimize |J(dtheta) - dX)| and doesn't
+ // try to minimize dTheta. This results in eratic changes in angle.
+ // Damped least squares minimizes |dtheta| to try and reduce this
+ // erratic behaviour.
- // Note when lambda is zero this is equivalent to the
- // least squares solution. This is fine when the m_jjt is
- // of full rank. When m_jjt is near to singular the least squares
- // inverse tries to minimize |J(dtheta) - dX)| and doesn't
- // try to minimize dTheta. This results in eratic changes in angle.
- // Damped least squares minimizes |dtheta| to try and reduce this
- // erratic behaviour.
+ // We don't want to use the damped solution everywhere so we
+ // only increase lamda from zero as we approach a singularity.
- // We don't want to use the damped solution everywhere so we
- // only increase lamda from zero as we approach a singularity.
+ // find the smallest non-zero W value, anything below epsilon is
+ // treated as zero
- // find the smallest non-zero W value, anything below epsilon is
- // treated as zero
+ double epsilon = 1e-10;
+ double max_angle_change = 0.1;
+ double x_length = sqrt(m_beta.dot(m_beta));
- double epsilon = 1e-10;
- double max_angle_change = 0.1;
- double x_length = sqrt(m_beta.dot(m_beta));
+ int i, j;
+ double w_min = std::numeric_limits<double>::max();
- int i, j;
- double w_min = std::numeric_limits<double>::max();
+ for (i = 0; i < m_svd_w.size(); i++) {
+ if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min)
+ w_min = m_svd_w[i];
+ }
- for (i = 0; i < m_svd_w.size(); i++) {
- if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min)
- w_min = m_svd_w[i];
- }
-
- // compute lambda damping term
+ // compute lambda damping term
- double d = x_length / max_angle_change;
- double lambda;
+ double d = x_length / max_angle_change;
+ double lambda;
- if (w_min <= d / 2)
- lambda = d / 2;
- else if (w_min < d)
- lambda = sqrt(w_min * (d - w_min));
- else
- lambda = 0.0;
+ if (w_min <= d / 2)
+ lambda = d / 2;
+ else if (w_min < d)
+ lambda = sqrt(w_min * (d - w_min));
+ else
+ lambda = 0.0;
- lambda *= lambda;
+ lambda *= lambda;
- if (lambda > 10)
- lambda = 10;
+ if (lambda > 10)
+ lambda = 10;
- // immediately multiply with Beta, so we can do matrix*vector products
- // rather than matrix*matrix products
+ // immediately multiply with Beta, so we can do matrix*vector products
+ // rather than matrix*matrix products
- // compute Ut*Beta
- m_svd_u_beta = m_svd_u.transpose() * m_beta;
+ // compute Ut*Beta
+ m_svd_u_beta = m_svd_u.transpose() * m_beta;
- m_d_theta.setZero();
+ m_d_theta.setZero();
- for (i = 0; i < m_svd_w.size(); i++) {
- if (m_svd_w[i] > epsilon) {
- double wInv = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
+ for (i = 0; i < m_svd_w.size(); i++) {
+ if (m_svd_w[i] > epsilon) {
+ double wInv = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
- // compute V*Winv*Ut*Beta
- m_svd_u_beta[i] *= wInv;
+ // compute V*Winv*Ut*Beta
+ m_svd_u_beta[i] *= wInv;
- for (j = 0; j < m_d_theta.size(); j++)
- m_d_theta[j] += m_svd_v(j, i) * m_svd_u_beta[i];
- }
- }
+ for (j = 0; j < m_d_theta.size(); j++)
+ m_d_theta[j] += m_svd_v(j, i) * m_svd_u_beta[i];
+ }
+ }
- for (j = 0; j < m_d_theta.size(); j++)
- m_d_theta[j] *= m_weight[j];
+ for (j = 0; j < m_d_theta.size(); j++)
+ m_d_theta[j] *= m_weight[j];
}
void IK_QJacobian::Lock(int dof_id, double delta)
{
- int i;
+ int i;
- for (i = 0; i < m_task_size; i++) {
- m_beta[i] -= m_jacobian(i, dof_id) * delta;
- m_jacobian(i, dof_id) = 0.0;
- }
+ for (i = 0; i < m_task_size; i++) {
+ m_beta[i] -= m_jacobian(i, dof_id) * delta;
+ m_jacobian(i, dof_id) = 0.0;
+ }
- m_norm[dof_id] = 0.0; // unneeded
- m_d_theta[dof_id] = 0.0;
+ m_norm[dof_id] = 0.0; // unneeded
+ m_d_theta[dof_id] = 0.0;
}
double IK_QJacobian::AngleUpdate(int dof_id) const
{
- return m_d_theta[dof_id];
+ return m_d_theta[dof_id];
}
double IK_QJacobian::AngleUpdateNorm() const
{
- int i;
- double mx = 0.0, dtheta_abs;
-
- for (i = 0; i < m_d_theta.size(); i++) {
- dtheta_abs = fabs(m_d_theta[i] * m_d_norm_weight[i]);
- if (dtheta_abs > mx)
- mx = dtheta_abs;
- }
-
- return mx;
+ int i;
+ double mx = 0.0, dtheta_abs;
+
+ for (i = 0; i < m_d_theta.size(); i++) {
+ dtheta_abs = fabs(m_d_theta[i] * m_d_norm_weight[i]);
+ if (dtheta_abs > mx)
+ mx = dtheta_abs;
+ }
+
+ return mx;
}
void IK_QJacobian::SetDoFWeight(int dof, double weight)
{
- m_weight[dof] = weight;
- m_weight_sqrt[dof] = sqrt(weight);
+ m_weight[dof] = weight;
+ m_weight_sqrt[dof] = sqrt(weight);
}
-