00001 #include "Spherus.h" 00002 #include "RandomController.h" 00003 #include "Circle.h" 00004 00005 static const int nVisionSensors=7; //per circle 00006 static const int nTactileSensors=8;//per circle 00007 //1 proprioceptive extension sensor, 2*2 proprioceptive velocity sensors, 00008 //total sensors: 2*(nVisionSensors+nTactileSensors)+1+4=35 00009 //2*2 rocket effectors, 1 extension effector 00010 //total effectors: 5 00011 static const real maxExtension=0.8; 00012 static const real maxExtensionForce=0.5; 00013 static const real maxRocketForce=0.5; 00014 static const real elasticK=maxExtensionForce/(maxExtension/5); 00015 00016 const unsigned int Spherus::nSensors=2*(nVisionSensors+nTactileSensors)+1+4; 00017 const unsigned int Spherus::nEffectors=2*2+1; 00018 00019 Spherus::Spherus(real x, real y, real alpha, real extension, real R, Controller* controller) : 00020 PhysicalObject("Spherus"){ 00021 this->r.setXY(x,y); 00022 this->alpha=alpha; 00023 this->computeSinCos(); 00024 this->extension=extension; 00025 this->R=R; 00026 circles[0]=new Circle(R, 0,0, "left body", nTactileSensors, M_PI-M_PI/nTactileSensors, 0.1); //Pi-2Pi/8/2 00027 circles[1]=new Circle(R, 0,0, "right body", nTactileSensors, M_PI/nTactileSensors, 0.1); //2Pi/8/2 00028 for(int i=0;i<2;i++){ 00029 eyes[i]=new VisualSensor(circles[i], 0,0, M_PI/2, R, 7*M_PI/12, nVisionSensors); 00030 rocketActivations[i]=0.0; 00031 rocketForceValues[i]=0.0; 00032 } 00033 extensionActivation=1.0; 00034 targetExtension=extensionActivation*maxExtension; 00035 computeMemberPositions(); 00036 if(controller==NULL){ 00037 this->controller=new RandomController(35,5); 00038 } else { 00039 this->controller=controller; 00040 } 00041 //bounding box is infinite because of the visual sensors 00042 boxMin.setXY(-ThyrixParameters::infinity,-ThyrixParameters::infinity); 00043 boxMax.setXY(ThyrixParameters::infinity,ThyrixParameters::infinity); 00044 } 00045 00046 Spherus::~Spherus(){ 00047 for(int i=0;i<2;i++){ 00048 delete(circles[i]); 00049 delete(eyes[i]); 00050 } 00051 delete controller; 00052 } 00053 00054 void Spherus::computeState(){ 00055 real dx=circles[1]->r.x-circles[0]->r.x; 00056 real dy=circles[1]->r.y-circles[0]->r.y; 00057 extension=sqrt(sqr(dx)+sqr(dy)); 00058 alpha=atan2(dy,dx);//-Pi..Pi 00059 if(alpha<0) alpha+=2*M_PI; //0..2Pi 00060 computeSinCos(); 00061 r=circles[0]->r; 00062 r+=circles[1]->r; 00063 r/=2; 00064 } 00065 00066 void Spherus::computeSinCos(){ 00067 sinAlpha=sin(alpha); 00068 cosAlpha=cos(alpha); 00069 } 00070 00071 void Spherus::computeMemberPositions(){ 00072 circles[0]->r.setXY(r.x-extension/2*cosAlpha,r.y-extension/2*sinAlpha); 00073 circles[1]->r.setXY(r.x+extension/2*cosAlpha,r.y+extension/2*sinAlpha); 00074 } 00075 00076 void Spherus::controll(){ 00077 int i, i0; 00078 /* 00079 Sensors: 00080 0..13 vision 00081 14..29 tactile 00082 30 length proprioception 00083 31..34 velocity proprioception 00084 00085 Effectors: 00086 0..3 rockets 00087 4 extension 00088 */ 00089 00090 //set sensor activations 00091 //visual sensors 00092 for(i=0;i<nVisionSensors;i++) 00093 controller->setInput(i, eyes[1]->activations[i]); 00094 i0=i; 00095 for(;i<i0+nVisionSensors;i++) 00096 controller->setInput(i, eyes[0]->activations[i-i0]); 00097 i0=i; 00098 //tactile sensors 00099 for(;i<i0+nTactileSensors;i++) 00100 controller->setInput(i, circles[1]->activations[i-i0]); 00101 i0=i; 00102 for(;i<i0+nTactileSensors;i++) 00103 controller->setInput(i, circles[0]->activations[i-i0]); 00104 //extension proprioception 00105 controller->setInput(i, extension/maxExtension); 00106 i++; 00107 float p1,p2; 00108 //velocity proprioception 00109 computeCircleProprioception(circles[1],p1,p2); 00110 controller->setInput(i, p1); i++; 00111 controller->setInput(i, p2); i++; 00112 computeCircleProprioception(circles[0],p1,p2); 00113 controller->setInput(i, p1); i++; 00114 controller->setInput(i, p2); i++; 00115 00116 controller->advanceTime(); 00117 00118 00119 //srand( (unsigned)time( NULL ) ); 00120 //each rocket is controlled by 2 neurons, one inhibitory and one excitatory 00121 //total activation: -1..1 00122 rocketActivations[1]=controller->getOutput(0)-controller->getOutput(1); 00123 rocketActivations[0]=controller->getOutput(2)-controller->getOutput(3); 00124 extensionActivation=controller->getOutput(4); 00125 00126 for(i=0;i<2;i++){ 00127 rocketForceValues[i]=rocketActivations[i]*maxRocketForce; 00128 } 00129 00130 targetExtension=extensionActivation*maxExtension; 00131 } 00132 00133 void Spherus::computeCircleProprioception(Circle* circle, float& forward, float& backward){ 00134 real u=-(alpha+M_PI/2); //rotation angle 00135 u=circle->m*(circle->v.x*cos(u)-circle->v.y*sin(u))/maxRocketForce; 00136 if(u>0){ 00137 if(u>1.0) u=1.0; 00138 forward=(float)u; 00139 backward=0.0; 00140 } else { 00141 if(u<-1.0) u=-1.0; 00142 forward=0.0; 00143 backward=(float)-u; 00144 } 00145 } 00146 00147 void Spherus::computeDerivativesWithoutContacts(ContactSolver* contactSolver){ 00148 real elasticForceValue; 00149 Vector2 force; 00150 Vector2 elasticForce; 00151 00152 elasticForceValue=elasticK*(extension-targetExtension); 00153 //elastic force applied towards body 0, oriented from body 0 to 1 00154 //elasticForceValue>0 => compression 00155 elasticForce.setXY(elasticForceValue*cosAlpha, elasticForceValue*sinAlpha); 00156 00157 00158 00159 rocketForces[0].setXY(-rocketForceValues[0]*sinAlpha,rocketForceValues[0]*cosAlpha); 00160 force=rocketForces[0]; 00161 force+=elasticForce; 00162 circles[0]->externalForce+=force; 00163 circles[0]->computeDerivativesWithoutContacts(contactSolver); 00164 00165 rocketForces[1].setXY(-rocketForceValues[1]*sinAlpha,rocketForceValues[1]*cosAlpha); 00166 force=rocketForces[1]; 00167 force-=elasticForce; 00168 circles[1]->externalForce+=force; 00169 circles[1]->computeDerivativesWithoutContacts(contactSolver); 00170 00171 } 00172 00173 bool Spherus::detectContacts(PhysicalObject* object, GlobalContactInfoVector* contacts){ 00174 bool isContact=false; 00175 for(int i = 0; i < 2; ++i){ 00176 isContact=circles[i]->detectContacts(object, contacts) || isContact; 00177 eyes[i]->detectContacts(object, contacts); 00178 } 00179 return isContact; 00180 } 00181 00182 void Spherus::detectInternalContacts(GlobalContactInfoVector* contacts){ 00183 circles[0]->detectContacts(circles[1], contacts); 00184 } 00185 00186 void Spherus::deleteContacts(){ 00187 for(int i=0;i<2;i++){ 00188 circles[i]->deleteContacts(); 00189 eyes[i]->deleteContacts(); 00190 } 00191 } 00192 00193 bool Spherus::detectMouseContact(const Vector2& rMouse, Vector2& p, PhysicalObject*& object){ 00194 bool isContact=false; 00195 for(int i=0;i<2 && !isContact;i++){ 00196 isContact = circles[i]->detectMouseContact(rMouse, p, object); 00197 } 00198 return isContact; 00199 } 00200 00201 void Spherus::computeDerivatives(GlobalContactInfoVector* globalContacts){ 00202 for(int i = 0; i < 2; ++i){ 00203 circles[i]->computeDerivatives(globalContacts); 00204 } 00205 00206 } 00207 00208 void Spherus::integrate(const Integrator &integrator){ 00209 int i; 00210 for(i=0;i<2;i++){ 00211 circles[i]->integrate(integrator); 00212 } 00213 computeState(); 00214 for(i=0;i<2;i++){ 00215 circles[i]->alpha=alpha; 00216 } 00217 } 00218 00219 void Spherus::draw(GUI *gui){ 00220 gui->setBrushColor(Color("gray")); 00221 for(int i=0;i<2;i++){ 00222 eyes[i]->draw(gui); 00223 circles[i]->draw(gui); 00224 gui->drawForce(circles[i]->r,rocketForces[i]); 00225 00226 } 00227 gui->setBrushColor(GUI::colorTransparent); 00228 00229 gui->setPenColor(Color("green")); 00230 gui->drawLine(circles[0]->r.x,circles[0]->r.y,circles[1]->r.x,circles[1]->r.y); 00231 gui->setPenColor(GUI::colorBlack); 00232 }
Thyrix homepage Users' guide
(C) Arxia 2004-2005