00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "SpringMotor.h"
00029 #include "Solid.h"
00030
00031 namespace opal
00032 {
00033 SpringMotor::SpringMotor()
00034 : Motor()
00035 {
00036
00037 }
00038
00039 SpringMotor::~SpringMotor()
00040 {
00041 }
00042
00043 void SpringMotor::init(const SpringMotorData& data)
00044 {
00045 Motor::init();
00046 mData = data;
00047 }
00048
00049 const SpringMotorData& SpringMotor::getData()const
00050 {
00051 return mData;
00052 }
00053
00054 MotorType SpringMotor::getType()const
00055 {
00056 return mData.getType();
00057 }
00058
00059 void SpringMotor::setName(const std::string& name)
00060 {
00061 mData.name = name;
00062 }
00063
00064 const std::string& SpringMotor::getName()const
00065 {
00066 return mData.name;
00067 }
00068
00069 bool SpringMotor::isEnabled()const
00070 {
00071 return mData.enabled;
00072 }
00073
00074 void SpringMotor::setEnabled(bool e)
00075 {
00076
00077
00078
00079
00080
00081 mData.enabled = e;
00082 }
00083
00084 void SpringMotor::internal_update()
00085 {
00086
00087
00088 if (mData.enabled && mData.solid)
00089 {
00090 if (LINEAR_MODE == mData.mode ||
00091 LINEAR_AND_ANGULAR_MODE == mData.mode)
00092 {
00093 Vec3r error = mData.desiredPos - getGlobalAttachPoint();
00094 Force f;
00095 f.singleStep = true;
00096 f.type = GLOBAL_FORCE_AT_LOCAL_POS;
00097 f.pos = mData.attachOffset;
00098 f.vec = mData.linearKs * error -
00099 mData.linearKd * mData.solid->getGlobalLinearVel();
00100
00101
00102 f.vec *= mData.solid->getMass();
00103 mData.solid->addForce(f);
00104 }
00105
00106 if (ANGULAR_MODE == mData.mode ||
00107 LINEAR_AND_ANGULAR_MODE == mData.mode)
00108 {
00109
00110
00111 Matrix44r transform = mData.solid->getTransform();
00112 Vec3r actualForward = transform.getForward();
00113 Vec3r actualUp = transform.getUp();
00114 Vec3r actualRight = transform.getRight();
00115
00116 if (0 != actualForward.lengthSquared())
00117 {
00118 actualForward.normalize();
00119 }
00120 if (0 != actualUp.lengthSquared())
00121 {
00122 actualUp.normalize();
00123 }
00124 if (0 != actualRight.lengthSquared())
00125 {
00126 actualRight.normalize();
00127 }
00128
00129 Vec3r forwardError = cross(mData.desiredForward,
00130 actualForward);
00131 Vec3r upError = cross(mData.desiredUp, actualUp);
00132 Vec3r rightError = cross(mData.desiredRight, actualRight);
00133
00134 if (0 != forwardError.lengthSquared())
00135 {
00136 forwardError.normalize();
00137 }
00138 if (0 != upError.lengthSquared())
00139 {
00140 upError.normalize();
00141 }
00142 if (0 != rightError.lengthSquared())
00143 {
00144 rightError.normalize();
00145 }
00146
00147
00148 real fangle = angleBetweenPreNorm(mData.desiredForward,
00149 actualForward);
00150 real uangle = angleBetweenPreNorm(mData.desiredUp,
00151 actualUp);
00152 real rangle = angleBetweenPreNorm(mData.desiredRight,
00153 actualRight);
00154
00155 forwardError *= -fangle;
00156 upError *= -uangle;
00157 rightError *= -rangle;
00158
00159
00160 Vec3r errorAxis = (forwardError + upError + rightError) *
00161 globals::OPAL_ONE_THIRD;
00162
00163
00164 Force f;
00165 f.singleStep = true;
00166 f.type = GLOBAL_TORQUE;
00167 f.vec = mData.angularKs * errorAxis - mData.angularKd *
00168 mData.solid->getGlobalAngularVel();
00169
00170
00171 f.vec = mData.solid->getInertiaTensor() * f.vec;
00172 mData.solid->addForce(f);
00173 }
00174 }
00175 }
00176
00177 void SpringMotor::setLocalAttachOffset(const Point3r& offset)
00178 {
00179 mData.attachOffset = offset;
00180 }
00181
00182 const Point3r& SpringMotor::getLocalAttachOffset()const
00183 {
00184 return mData.attachOffset;
00185 }
00186
00187 void SpringMotor::setGlobalAttachPoint(const Point3r& p)
00188 {
00189 if (!mData.solid)
00190 {
00191 OPAL_LOGGER("warning") <<
00192 "opal::SpringMotor::setGlobalAttachPoint: Solid pointer is \
00193 invalid. Ignoring request." << std::endl;
00194 return;
00195 }
00196
00197
00198
00199 Matrix44r inv = mData.solid->getTransform();
00200 inv.fastInvert();
00201 mData.attachOffset = inv * p;
00202 }
00203
00204 Point3r SpringMotor::getGlobalAttachPoint()const
00205 {
00206 if (!mData.solid)
00207 {
00208 OPAL_LOGGER("warning") <<
00209 "opal::SpringMotor::getGlobalAttachPoint: Solid pointer is \
00210 invalid. Returning (0,0,0)." << std::endl;
00211 return Point3r();
00212 }
00213
00214
00215
00216
00217 Vec3r offset(mData.attachOffset[0], mData.attachOffset[1],
00218 mData.attachOffset[2]);
00219 Point3r globalPos = mData.solid->getPosition() +
00220 mData.solid->getTransform() * offset;
00221
00222 return globalPos;
00223 }
00224
00225 void SpringMotor::setDesiredTransform(const Matrix44r& transform)
00226 {
00227 mData.desiredPos = transform.getPosition();
00228
00229 mData.desiredForward = transform.getForward();
00230 if (0 != mData.desiredForward.lengthSquared())
00231 {
00232 mData.desiredForward.normalize();
00233 }
00234
00235 mData.desiredUp = transform.getUp();
00236 if (0 != mData.desiredUp.lengthSquared())
00237 {
00238 mData.desiredUp.normalize();
00239 }
00240
00241 mData.desiredRight = transform.getRight();
00242 if (0 != mData.desiredRight.lengthSquared())
00243 {
00244 mData.desiredRight.normalize();
00245 }
00246 }
00247
00248 void SpringMotor::setDesiredPosition(const Point3r& pos)
00249 {
00250 mData.desiredPos = pos;
00251 }
00252
00253 void SpringMotor::setDesiredOrientation(const Vec3r& forward,
00254 const Vec3r& up, const Vec3r& right)
00255 {
00256 mData.desiredForward = forward;
00257 if (0 != mData.desiredForward.lengthSquared())
00258 {
00259 mData.desiredForward.normalize();
00260 }
00261
00262 mData.desiredUp = up;
00263 if (0 != mData.desiredUp.lengthSquared())
00264 {
00265 mData.desiredUp.normalize();
00266 }
00267
00268 mData.desiredRight = right;
00269 if (0 != mData.desiredRight.lengthSquared())
00270 {
00271 mData.desiredRight.normalize();
00272 }
00273 }
00274
00275 void SpringMotor::setLinearKd(real kd)
00276 {
00277 mData.linearKd = kd;
00278 }
00279
00280 void SpringMotor::setLinearKs(real ks)
00281 {
00282 mData.linearKs = ks;
00283 }
00284
00285 real SpringMotor::getLinearKd()const
00286 {
00287 return mData.linearKd;
00288 }
00289
00290 real SpringMotor::getLinearKs()const
00291 {
00292 return mData.linearKs;
00293 }
00294
00295 void SpringMotor::setAngularKd(real kd)
00296 {
00297 mData.angularKd = kd;
00298 }
00299
00300 void SpringMotor::setAngularKs(real ks)
00301 {
00302 mData.angularKs = ks;
00303 }
00304
00305 real SpringMotor::getAngularKd()const
00306 {
00307 return mData.angularKd;
00308 }
00309
00310 real SpringMotor::getAngularKs()const
00311 {
00312 return mData.angularKs;
00313 }
00314
00315 bool SpringMotor::internal_dependsOnSolid(Solid* s)
00316 {
00317 if (s == mData.solid)
00318 {
00319 return true;
00320 }
00321 else
00322 {
00323 return false;
00324 }
00325 }
00326 }