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
00029
00030 #include<rng.h>
00031 #include "gmposition.h"
00032
00033
00034
00035
00036
00037 static class GMPositionClass : public TclClass {
00038 public:
00039 GMPositionClass() : TclClass("Position/GM") {}
00040 TclObject* create(int, const char*const*) {
00041 return (new GMPosition());
00042 }
00043 } class_gmposition;
00044
00045 GMPosition::GMPosition() :
00046 Position(),
00047 xFieldWidth_(0),
00048 yFieldWidth_(0),
00049 alpha_(0),
00050 speedMean_(0),
00051 directionMean_(0),
00052 bound_(REBOUNCE),
00053 updateTime_(0),
00054 debug_(0),
00055 speed_(0),
00056 direction_(0),
00057 nextUpdateTime_(0.0)
00058 {
00059 bind("xFieldWidth_", &xFieldWidth_);
00060 bind("yFieldWidth_", &yFieldWidth_);
00061 bind("alpha_", &alpha_);
00062 bind("directionMean_", &directionMean_);
00063 bind("updateTime_", &updateTime_);
00064 bind("debug_", &debug_);
00065 }
00066
00067 GMPosition::~GMPosition()
00068 {
00069 }
00070
00071 int GMPosition::command(int argc, const char*const* argv)
00072 {
00073 Tcl& tcl = Tcl::instance();
00074 if(argc == 3)
00075 {
00076 if(strcasecmp(argv[1], "bound") == 0)
00077 {
00078 if (strcasecmp(argv[2],"SPHERIC")==0)
00079 bound_ = SPHERIC;
00080 else
00081 {
00082 if (strcasecmp(argv[2],"THOROIDAL")==0)
00083 bound_ = THOROIDAL;
00084 else
00085 {
00086 if (strcasecmp(argv[2],"HARDWALL")==0)
00087 bound_ = HARDWALL;
00088 else
00089 {
00090 if (strcasecmp(argv[2],"REBOUNCE")==0)
00091 bound_ = REBOUNCE;
00092 else
00093 {
00094 fprintf(stderr,"GMPosition::command(%s), unrecognized bound_ type (%s)\n",argv[1],argv[2]);
00095 exit(1);
00096 }
00097 }
00098 }
00099 }
00100 return TCL_OK;
00101 }
00102 if(strcasecmp(argv[1], "speedMean") == 0)
00103 {
00104 speedMean_ = speed_ = atof(argv[2]);
00105 return TCL_OK;
00106 }
00107 }
00108 return Position::command(argc, argv);
00109 }
00110
00111
00112 double GMPosition::Gaussian()
00113 {
00114 double x1, x2, w, y1;
00115 static double y2;
00116 static int use_last = 0;
00117
00118 if (use_last)
00119 {
00120 y1 = y2;
00121 use_last = 0;
00122 }
00123 else
00124 {
00125 do
00126 {
00127
00128
00129 x1 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00130 x2 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00131 w = x1 * x1 + x2 * x2;
00132 } while ( w >= 1.0 );
00133
00134 w = sqrt( (-2.0 * log( w ) ) / w );
00135 y1 = x1 * w;
00136 y2 = x2 * w;
00137 use_last = 1;
00138 }
00139 return(y1);
00140 }
00141
00142 void GMPosition::update(double now)
00143 {
00144 double t;
00145 for(t = nextUpdateTime_; t < now; t += updateTime_)
00146 {
00147
00148 if (debug_>10)
00149 printf("Update at %.3f(%.3f) old speed %.2f old direction %.2f", now, t, speed_, direction_);
00150
00151 speed_ = (alpha_*speed_) + (((1.0-alpha_))*speedMean_) + (sqrt(1.0-pow(alpha_,2.0))*Gaussian());
00152 direction_ = (alpha_*direction_) + (((1.0-alpha_))*directionMean_) + (sqrt(1.0-pow(alpha_,2.0))*Gaussian());
00153
00154 if (debug_>10)
00155 printf(" new speed %.2f new direction %.2f \n", speed_, direction_);
00156
00157 double newx = x_ + (speed_*cos(direction_)*updateTime_);
00158 double newy = y_ + (speed_*sin(direction_)*updateTime_);
00159 if (debug_>10)
00160 printf("X:%.3f->%.3f Y:%.3f->%.3f\n", x_, newx, y_, newy);
00161
00162
00163
00164 if ((newy>yFieldWidth_) || (newy<0))
00165 {
00166 switch (bound_)
00167 {
00168 case SPHERIC:
00169 y_ -= yFieldWidth_*(sgn(newy));
00170 newy -= yFieldWidth_*(sgn(newy));
00171 break;
00172 case THOROIDAL:
00173 x_ = (xFieldWidth_/2) + x_ - newx;
00174 y_ = (yFieldWidth_/2) + y_ - newy;
00175 newx = xFieldWidth_/2;
00176 newy = yFieldWidth_/2;
00177 break;
00178 case HARDWALL:
00179 newy = newy<0?0:yFieldWidth_;
00180 break;
00181 case REBOUNCE:
00182 if (newy>yFieldWidth_)
00183 {
00184 newy = 2*yFieldWidth_ - newy;
00185 y_ = 2*yFieldWidth_ - y_;
00186 }else{
00187 newy = 0 - newy;
00188 y_ = 0 - y_;
00189 }
00190 direction_ *= -1;
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 break;
00201 }
00202 }
00203 if ((newx>xFieldWidth_) || (newx<0))
00204 {
00205 switch (bound_)
00206 {
00207 case SPHERIC:
00208 x_ -= xFieldWidth_*(sgn(newx));
00209 newx -= xFieldWidth_*(sgn(newx));
00210 break;
00211 case THOROIDAL:
00212 x_ = (xFieldWidth_/2) + x_ - newx;
00213 y_ = (yFieldWidth_/2) + y_ - newy;
00214 newx = xFieldWidth_/2;
00215 newy = yFieldWidth_/2;
00216 break;
00217 case HARDWALL:
00218 newx = newx<0?0:xFieldWidth_;
00219 break;
00220 case REBOUNCE:
00221 if (newx>xFieldWidth_)
00222 {
00223 newx = 2*xFieldWidth_ - newx;
00224 x_ = 2*xFieldWidth_ - x_;
00225 }else{
00226 newx = 0 - newx;
00227 x_ = 0 - x_;
00228 }
00229 if (newy==y_)
00230 {
00231 if (newx>x_)
00232 direction_ = 0;
00233 else
00234 direction_ = pi;
00235 }else{
00236 if (newy>y_)
00237 direction_ = pi - direction_;
00238 else
00239 direction_ = -pi - direction_;
00240 }
00241 break;
00242 }
00243 }
00244 x_ = newx;
00245 y_ = newy;
00246 directionMean_ = direction_;
00247 }
00248 nextUpdateTime_ = t;
00249 if (debug_>10)
00250 printf("nextUpdateTime = %f, now %f, updateTime %f\n", nextUpdateTime_, now, updateTime_);
00251 }
00252
00253 double GMPosition::getX()
00254 {
00255 double now = Scheduler::instance().clock();
00256 if (now > nextUpdateTime_)
00257 update(now);
00258 return (x_);
00259 }
00260
00261 double GMPosition::getY()
00262 {
00263 double now = Scheduler::instance().clock();
00264 if (now > nextUpdateTime_)
00265 update(now);
00266 return (y_);
00267 }