00001 #include "dynamics.hh"
00002 #include "register.hh"
00003 #include "element.hh"
00004 #include <iostream>
00005 #include "abstractworld.hh"
00006 #include "collisionmessage.hh"
00007
00008 namespace anoid {
00009 namespace plugin {
00010
00011 using namespace simple;
00012 using namespace base;
00013 using namespace config;
00014
00015 void Dynamics::update() {
00016 Vector Ft(0.0,0.0,0.0), Tt(0.0,0.0,0.0);
00017 for (vector<Force *>::iterator i = forces.begin(); i != forces.end(); ++i) {
00018 Ft += (*i)->getForce();
00019 Tt += ((*i)->getApplicationPoint() % (*i)->getForce());
00020 }
00021
00022 if (mass != 0.0)
00023 acceleration = (1.0 / mass) * Ft;
00024 else
00025 acceleration = O;
00026
00027 spinvelocity += getWorld()->getTime() * Tt;
00028
00029 Acceleration::update();
00030 SpinVelocity::update();
00031 Ability::update();
00032 }
00033
00034 void Dynamics::redraw() {
00035 Acceleration::redraw();
00036 SpinVelocity::redraw();
00037 Ability::update();
00038 }
00039
00040 void Dynamics::init(Configuration &c) {
00041 if (c.hasElement("restitution"))
00042 constantOfRestitution = c.getDouble("restitution");
00043 else
00044 constantOfRestitution = 1.0;
00045
00046 Ability::init(c);
00047 Acceleration::init(c);
00048 SpinVelocity::init(c);
00049
00050 registerName("Dynamics");
00051 }
00052
00053 Object *Dynamics::add(Object *o) {
00054 Force *f = dynamic_cast<Force *>(o);
00055 if (f) {
00056 forces.push_back(f);
00057 }
00058
00059 return Ability::add(o);
00060 }
00061
00062 void Dynamics::receive(Message *m) {
00063 CollisionMessage *c = dynamic_cast<CollisionMessage *>(m);
00064
00065 if (c) {
00066 double j = -1.0 - constantOfRestitution;
00067 double den = 0.0;
00068 Vector *n = c->getNormal();
00069 Element *e = c->getOther();
00070 Mass *omass = dynamic_cast<Mass *>(e->lookupAbility("Mass"));
00071 SpinVelocity *ospinvelocity = dynamic_cast<SpinVelocity *>(e->lookupAbility("SpinVelocity"));
00072 Velocity *ovelocity = dynamic_cast<Velocity *>(e->lookupAbility("Velocity"));
00073
00074 Vector p1 = Vector(*c->getP1());
00075 Vector p2 = Vector(*c->getP2());
00076 p1.scale(scale);
00077 Scale *oscale = dynamic_cast<Scale *>(e->lookupAbility("Scale"));
00078 if (oscale) {
00079 p2.scale(oscale->getScale());
00080 }
00081
00082 double m = 0.0;
00083 if (omass) {
00084 m = omass->getMass();
00085 }
00086
00087 Vector v;
00088 if (ovelocity)
00089 v = ovelocity->getVelocity();
00090
00091 if (mass != 0.0)
00092 den += 1.0 / mass;
00093 if (m != 0.0)
00094 den += 1.0 / m;
00095 den *= (*n * *n);
00096
00097 Vector tmp;
00098 if (mass != 0.0)
00099 tmp = (inverseInertiaTensor * (p1 % *n)) % p1;
00100 if ((m != 0.0) && (ospinvelocity)) {
00101 tmp += (ospinvelocity->getInverseWorldInertiaTensor() * (p2 % *n)) % p2;
00102 }
00103
00104 den += (tmp * *n);
00105
00106 tmp = velocity + ((inverseInertiaTensor * spinvelocity) % p1);
00107 if (ospinvelocity && ovelocity)
00108 tmp += (O - ovelocity->getVelocity() - ((*ospinvelocity->getInverseInertiaTensor() * ospinvelocity->getSpinVelocity()) % p2));
00109
00110 j *= (tmp * *n);
00111 j /= den;
00112
00113 if (mass != 0.0) {
00114 velocity = velocity + ((j / mass) * *n);
00115 spinvelocity += (p1 % (j * *n));
00116
00117 spinvelocity = O;
00118 }
00119
00120 position = oldPosition;
00121 copyMatrix(rotation, oldRotation);
00122 } else {
00123 Acceleration::receive(m);
00124 SpinVelocity::receive(m);
00125 }
00126
00127 }
00128
00129 Register(Dynamics)
00130
00131 };
00132 };