00001 #include "VisualSensor.h" 00002 #include "Circle.h" 00003 #include "CappedRectangle.h" 00004 #include "MathTools.h" 00005 00006 00007 VisualSensor::VisualSensor(PhysicalObject* parent, 00008 real relativeX, real relativeY, real relativeAlpha, 00009 real R, real viewAngle, unsigned int nSensors, 00010 std::string label): 00011 PhysicalObject(label, nSensors), 00012 viewAngle(viewAngle) 00013 { 00014 this->parent=parent; 00015 this->relativeR.setXY(relativeX, relativeY); 00016 this->relativeAlpha=relativeAlpha; 00017 assert(viewAngle>0 && viewAngle<=2*M_PI); 00018 delta=viewAngle/2; 00019 epsilon=viewAngle/nSensors; 00020 boxMin.setXY(-ThyrixParameters::infinity,-ThyrixParameters::infinity); 00021 boxMax.setXY(ThyrixParameters::infinity,ThyrixParameters::infinity); 00022 } 00023 00024 VisualSensor::~VisualSensor(){ 00025 } 00026 00027 bool VisualSensor::detectContacts(Circle* circle, GlobalContactInfoVector* contacts){ 00028 if(circle==parent) return false; 00029 00030 real dx = circle->r.x - (parent->r.x+relativeR.x); 00031 real dy = circle->r.y - (parent->r.y+relativeR.y); 00032 real d = MathTools::modulus(dx,dy); 00033 00034 //compute visual activation 00035 real gamma=computeGamma(dx,dy); 00036 00037 assert(d > circle->R); 00038 real phi = asin(circle->R / d); //0..Pi/2 00039 00040 real gammaM = gamma - phi; //-3Pi/2..Pi 00041 real gammaP = gamma + phi; //-Pi..3Pi/2 00042 00043 activate(gammaM, gammaP); 00044 00045 return false; 00046 } 00047 00048 bool VisualSensor::detectContacts(CappedRectangle* capsule, GlobalContactInfoVector* contacts){ 00049 if(capsule==parent) return false; 00050 00051 real lx=capsule->cosAlpha*capsule->l; 00052 real ly=capsule->sinAlpha*capsule->l; 00053 00054 real dx1 = capsule->r.x+lx - (parent->r.x+relativeR.x); 00055 real dy1 = capsule->r.y+ly - (parent->r.y+relativeR.y); 00056 real d1 = MathTools::modulus(dx1,dy1); 00057 00058 real dx2 = capsule->r.x-lx - (parent->r.x+relativeR.x); 00059 real dy2 = capsule->r.y-ly - (parent->r.y+relativeR.y); 00060 real d2 = MathTools::modulus(dx2,dy2); 00061 00062 //compute visual activation 00063 real gamma1=computeGamma(dx1,dy1); 00064 real gamma2=computeGamma(dx2,dy2); 00065 00066 bool change=false; 00067 if(gamma1<=gamma2){ 00068 if(gamma2-gamma1>=M_PI) { 00069 change=true; 00070 gamma2-=2*M_PI; 00071 } 00072 } else { 00073 change=true; 00074 if(gamma1-gamma2>=M_PI) { 00075 change=false; 00076 gamma1-=2*M_PI; 00077 } 00078 } 00079 00080 if(change){ 00081 real temp=gamma1; 00082 gamma1=gamma2; 00083 gamma2=temp; 00084 temp=d1; 00085 d1=d2; 00086 d2=temp; 00087 } 00088 00089 00090 //gammaP in (-Pi,Pi); gammaM in (-2Pi,Pi); but gammaP-gammaM in (0,Pi) 00091 //assert((d1 > capsule->R) && (d2 > capsule->R)); 00092 assert((d1 > 1e-6) && (d2 > 1e-6)); 00093 // asin returns a value 0..Pi/2 00094 real phi1=asin(capsule->R / d1); 00095 real phi2=asin(capsule->R / d2); 00096 real gammaM=gamma1-phi1; 00097 if(gamma2-phi2<gammaM) gammaM=gamma2-phi2; 00098 real gammaP=gamma2+phi2; 00099 if(gamma1+phi1>gammaP) gammaP=gamma1+phi1; 00100 00101 activate(gammaM, gammaP); 00102 00103 return false; 00104 } 00105 00106 00107 void VisualSensor::activate(real gammaM, real gammaP){ 00108 //g1=gammaM; g2=gammaP; //for debugging 00109 00110 int where; 00111 00112 //check where the beginning of the first sensor is relative to the angle covered by the object 00113 if(gammaM < -delta){ 00114 if(gammaP >= -delta){ 00115 where=0; //inside 00116 } else { 00117 where=1; //after 00118 } 00119 } else { 00120 where=-1; //before 00121 } 00122 00123 00124 real u=-delta; 00125 for(int i=0; i<nSensors; i++, u+=epsilon){ 00126 00127 if(where==1){ 00128 //we are after the covered angle 00129 //prepare for the case that -2Pi<gammaM<-Pi 00130 //since gammaP-gammaM<Pi (we assume that the viewed object does not cover the sensor), 00131 //in this case -Pi<gammaP<0 00132 gammaM+=2*M_PI; 00133 gammaP+=2*M_PI; 00134 where=-1; 00135 //we are now before the covered angle 00136 //gammaM in (0,Pi); gammaP in (Pi,2Pi) 00137 } 00138 00139 if(where==-1){ 00140 //we were before the beginning of the covered angle 00141 if(gammaM<u+epsilon){ 00142 //the covered angle starts within the current pixel 00143 if(gammaP<=u+epsilon){ 00144 //the covered angle also ends within the current pixel 00145 //set pixel to a fractional activation 00146 activations[i]+=(gammaP-gammaM)/epsilon; 00147 if(activations[i]>1) activations[i]=1; 00148 //the beginning of the next pixel will be after the covered angle 00149 where=1; 00150 } else { 00151 //the covered angle ends after the current pixel 00152 //set pixel to a fractional activation 00153 activations[i]+=(u+epsilon-gammaM)/epsilon; 00154 if(activations[i]>1) activations[i]=1; 00155 //the beginning of the next pixel will be within the covered angle 00156 where=0; 00157 } 00158 } 00159 } else{ 00160 if(where==0){ 00161 //we are inside the covered angle 00162 if(gammaP<=u+epsilon){ 00163 //the covered angle also ends within the current pixel 00164 //set pixel to a fractional activation 00165 activations[i]+=(gammaP-u)/epsilon; 00166 if(activations[i]>1) activations[i]=1; 00167 where=1; 00168 } else { 00169 //current pixel is fully covered 00170 activations[i]=1; 00171 } 00172 } 00173 } 00174 } 00175 } 00176 00177 00178 void VisualSensor::draw(GUI *gui){ 00179 real l=2, u; 00180 int i; 00181 //activations 00182 gui->setPenColor(Color("orange")); 00183 real x=parent->r.x+relativeR.x; 00184 real y=parent->r.y+relativeR.y; 00185 for(i=0; i<nSensors; i++){ 00186 u=parent->alpha+relativeAlpha-delta+(i+0.5)*epsilon; 00187 gui->drawLine(x, y, x+l*cos(u)*activations[i], y+l*sin(u)*activations[i]); 00188 00189 } 00190 gui->setPenColor(Color("papayaWhip")); 00191 for(i=0; i<=nSensors; i++){ 00192 u=parent->alpha+relativeAlpha-delta+i*epsilon; 00193 gui->drawLine(x, y, x+l*cos(u), y+l*sin(u)); 00194 } 00195 /* 00196 //for debugging: draw gammas 00197 gui->setPenColor(Color("red")); 00198 u=parent->alpha+relativeAlpha+g1; 00199 gui->drawLine(x, y, x+l*cos(u), y+l*sin(u)); 00200 gui->setPenColor(Color("green")); 00201 u=parent->alpha+relativeAlpha+g2; 00202 gui->drawLine(x, y, x+l*cos(u), y+l*sin(u)); 00203 */ 00204 }
Thyrix homepage Users' guide
(C) Arxia 2004-2005