Blender V2.61 - r43446

IK_QTask.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Original Author: Laurence
00024  * Contributor(s): Brecht
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include "IK_QTask.h"
00035 
00036 // IK_QTask
00037 
00038 IK_QTask::IK_QTask(
00039     int size,
00040     bool primary,
00041     bool active,
00042     const IK_QSegment *segment
00043 ) :
00044     m_size(size), m_primary(primary), m_active(active), m_segment(segment),
00045     m_weight(1.0)
00046 {
00047 }
00048 
00049 // IK_QPositionTask
00050 
00051 IK_QPositionTask::IK_QPositionTask(
00052     bool primary,
00053     const IK_QSegment *segment,
00054     const MT_Vector3& goal
00055 ) :
00056     IK_QTask(3, primary, true, segment), m_goal(goal)
00057 {
00058     // computing clamping length
00059     int num;
00060     const IK_QSegment *seg;
00061 
00062     m_clamp_length = 0.0;
00063     num = 0;
00064 
00065     for (seg = m_segment; seg; seg = seg->Parent()) {
00066         m_clamp_length += seg->MaxExtension();
00067         num++;
00068     }
00069 
00070     m_clamp_length /= 2*num;
00071 }
00072 
00073 void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian)
00074 {
00075     // compute beta
00076     const MT_Vector3& pos = m_segment->GlobalEnd();
00077 
00078     MT_Vector3 d_pos = m_goal - pos;
00079     MT_Scalar length = d_pos.length();
00080 
00081     if (length > m_clamp_length)
00082         d_pos = (m_clamp_length/length)*d_pos;
00083     
00084     jacobian.SetBetas(m_id, m_size, m_weight*d_pos);
00085 
00086     // compute derivatives
00087     int i;
00088     const IK_QSegment *seg;
00089 
00090     for (seg = m_segment; seg; seg = seg->Parent()) {
00091         MT_Vector3 p = seg->GlobalStart() - pos;
00092 
00093         for (i = 0; i < seg->NumberOfDoF(); i++) {
00094             MT_Vector3 axis = seg->Axis(i)*m_weight;
00095 
00096             if (seg->Translational())
00097                 jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e2);
00098             else {
00099                 MT_Vector3 pa = p.cross(axis);
00100                 jacobian.SetDerivatives(m_id, seg->DoFId()+i, pa, 1e0);
00101             }
00102         }
00103     }
00104 }
00105 
00106 MT_Scalar IK_QPositionTask::Distance() const
00107 {
00108     const MT_Vector3& pos = m_segment->GlobalEnd();
00109     MT_Vector3 d_pos = m_goal - pos;
00110     return d_pos.length();
00111 }
00112 
00113 // IK_QOrientationTask
00114 
00115 IK_QOrientationTask::IK_QOrientationTask(
00116     bool primary,
00117     const IK_QSegment *segment,
00118     const MT_Matrix3x3& goal
00119 ) :
00120     IK_QTask(3, primary, true, segment), m_goal(goal), m_distance(0.0)
00121 {
00122 }
00123 
00124 void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian)
00125 {
00126     // compute betas
00127     const MT_Matrix3x3& rot = m_segment->GlobalTransform().getBasis();
00128 
00129     MT_Matrix3x3 d_rotm = m_goal*rot.transposed();
00130     d_rotm.transpose();
00131 
00132     MT_Vector3 d_rot;
00133     d_rot = -0.5*MT_Vector3(d_rotm[2][1] - d_rotm[1][2],
00134                             d_rotm[0][2] - d_rotm[2][0],
00135                             d_rotm[1][0] - d_rotm[0][1]);
00136 
00137     m_distance = d_rot.length();
00138 
00139     jacobian.SetBetas(m_id, m_size, m_weight*d_rot);
00140 
00141     // compute derivatives
00142     int i;
00143     const IK_QSegment *seg;
00144 
00145     for (seg = m_segment; seg; seg = seg->Parent())
00146         for (i = 0; i < seg->NumberOfDoF(); i++) {
00147 
00148             if (seg->Translational())
00149                 jacobian.SetDerivatives(m_id, seg->DoFId()+i, MT_Vector3(0, 0, 0), 1e2);
00150             else {
00151                 MT_Vector3 axis = seg->Axis(i)*m_weight;
00152                 jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e0);
00153             }
00154         }
00155 }
00156 
00157 // IK_QCenterOfMassTask
00158 // Note: implementation not finished!
00159 
00160 IK_QCenterOfMassTask::IK_QCenterOfMassTask(
00161     bool primary,
00162     const IK_QSegment *segment,
00163     const MT_Vector3& goal_center
00164 ) :
00165     IK_QTask(3, primary, true, segment), m_goal_center(goal_center)
00166 {
00167     m_total_mass_inv = ComputeTotalMass(m_segment);
00168     if (!MT_fuzzyZero(m_total_mass_inv))
00169         m_total_mass_inv = 1.0/m_total_mass_inv;
00170 }
00171 
00172 MT_Scalar IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
00173 {
00174     MT_Scalar mass = /*seg->Mass()*/ 1.0;
00175 
00176     const IK_QSegment *seg;
00177     for (seg = segment->Child(); seg; seg = seg->Sibling())
00178         mass += ComputeTotalMass(seg);
00179     
00180     return mass;
00181 }
00182 
00183 MT_Vector3 IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
00184 {
00185     MT_Vector3 center = /*seg->Mass()**/segment->GlobalStart();
00186 
00187     const IK_QSegment *seg;
00188     for (seg = segment->Child(); seg; seg = seg->Sibling())
00189         center += ComputeCenter(seg);
00190     
00191     return center;
00192 }
00193 
00194 void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& center, const IK_QSegment *segment)
00195 {
00196     int i;
00197     MT_Vector3 p = center - segment->GlobalStart();
00198 
00199     for (i = 0; i < segment->NumberOfDoF(); i++) {
00200         MT_Vector3 axis = segment->Axis(i)*m_weight;
00201         axis *= /*segment->Mass()**/m_total_mass_inv;
00202         
00203         if (segment->Translational())
00204             jacobian.SetDerivatives(m_id, segment->DoFId()+i, axis, 1e2);
00205         else {
00206             MT_Vector3 pa = axis.cross(p);
00207             jacobian.SetDerivatives(m_id, segment->DoFId()+i, pa, 1e0);
00208         }
00209     }
00210     
00211     const IK_QSegment *seg;
00212     for (seg = segment->Child(); seg; seg = seg->Sibling())
00213         JacobianSegment(jacobian, center, seg);
00214 }
00215 
00216 void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian& jacobian)
00217 {
00218     MT_Vector3 center = ComputeCenter(m_segment)*m_total_mass_inv;
00219 
00220     // compute beta
00221     MT_Vector3 d_pos = m_goal_center - center;
00222 
00223     m_distance = d_pos.length();
00224 
00225 #if 0
00226     if (m_distance > m_clamp_length)
00227         d_pos = (m_clamp_length/m_distance)*d_pos;
00228 #endif
00229     
00230     jacobian.SetBetas(m_id, m_size, m_weight*d_pos);
00231 
00232     // compute derivatives
00233     JacobianSegment(jacobian, center, m_segment);
00234 }
00235 
00236 MT_Scalar IK_QCenterOfMassTask::Distance() const
00237 {
00238     return m_distance;
00239 }
00240