00001 package org.hfbk.vis.visnode;
00002
00003 import java.util.ArrayList;
00004 import java.util.Date;
00005 import java.util.HashMap;
00006 import java.util.List;
00007
00008 import org.dronus.gl.GLBoxRenderer;
00009 import org.dronus.gl.GLSphereRenderer;
00010 import org.dronus.gl.GLFont;
00011 import org.dronus.gl.GLUtil;
00012 import org.dronus.graph.Node;
00013 import org.hfbk.vis.Prefs;
00014 import org.lwjgl.opengl.GL11;
00015 import org.lwjgl.util.vector.Vector3f;
00016
00058 public class VisUeberwach extends VisNode {
00059
00061 final float DVARIANCE_DT=10f;
00063 final float NEW_COST=5f;
00065 final float EXIT_VARIANCE=100;
00066
00067
00068
00073 class Item{
00075 Vector3f pos;
00077 Vector3f dpos=new Vector3f();
00078 }
00079
00085 class VisTrack extends VisNode{
00086
00087 int id;
00088
00089 final int PAST_STATES=10;
00090 int index;
00091
00093 Item[] past=new Item[PAST_STATES];
00094
00096 Item current;
00097
00100 float variance;
00101
00102
00103 public VisTrack() {
00104 super(null, new Vector3f());
00105 id=maxTrackId++;
00106 Item tp=new Item();
00107 current=past[0]=tp;
00108 radius=10000;
00109 }
00110
00114 int push(){
00115 Item last=getOld(0);
00116 Item tp=new Item();
00117 tp.pos=new Vector3f(last.pos); tp.dpos=new Vector3f(last.dpos);
00118
00119 index++;
00120 index%=PAST_STATES;
00121 past[index]=tp;
00122 current=tp;
00123
00124 return index;
00125 }
00126
00135 protected void renderSelf() {
00136 float dt=getRoot().client.dt;
00137
00138 Item tp=past[index];
00139 Vector3f d=new Vector3f(tp.dpos);
00140 d.scale(dt);
00141 Vector3f.add(tp.pos, d, tp.pos);
00142 variance+=DVARIANCE_DT*dt;
00143
00144 position.set(current.pos);
00145
00146
00147 float c=id*523.724325f;
00148 GL11.glColor4f(1-c%1,(c*3)%1,c%1,1/(1+variance/100));
00149 GLSphereRenderer.renderSphere(variance/5);
00150
00151
00152 GL11.glTranslatef(-4,2,0);
00153 GLUtil.billboardCylinder();
00154 GL11.glColor3f(1,1,1);
00155 GLFont.getDefault().render();
00156 GLFont.getDefault().print(getDatasheet());
00157 GL11.glDisable(GL11.GL_TEXTURE_2D);
00158
00159
00160
00161
00162 if(variance>EXIT_VARIANCE)
00163 parent.remove(this);
00164 }
00165
00167 Item getOld(int lookback){
00168 int i=(index-lookback)%10;
00169 return past[i];
00170 }
00171
00172 long created=System.currentTimeMillis();
00173 long lastseen=created;
00174 String getDatasheet(){
00175 return
00176 "Known since: "+(new Date(created))+"\n"+
00177 "Last spotted: "+(new Date(lastseen))+"\n"+
00178 "ID:"+hashCode()+"\n";
00179 }
00180
00181 protected void transform() {
00182 super.transform();
00183 GL11.glRotatef(90, 0, 1, 0);
00184 }
00185 }
00186
00193 interface Sensor{
00195 abstract float getCost(VisTrack track);
00198 abstract void update(VisTrack track);
00199 }
00200
00201
00202 int maxTrackId=0;
00203
00204
00205 public VisUeberwach(Node node, Vector3f position) {
00206 super(node, position);
00207 radius=Float.MAX_VALUE;
00208 }
00209
00211 static Vector3f lerp(Vector3f a, Vector3f b, float t){
00212 a=new Vector3f(a); b=new Vector3f(b);
00213 a.scale(1-t); b.scale(t);
00214 Vector3f result=new Vector3f();
00215 Vector3f.add(a,b, result);
00216 return result;
00217 }
00218
00229 void trackOne(Sensor s){
00230 List<VisTrack> tracks=new ArrayList<VisTrack>();
00231
00232 for (VisNode n: children)
00233 if (n instanceof VisTrack)
00234 tracks.add((VisTrack)n);
00235
00236 int nt=tracks.size();
00237
00238 float[] costs=new float[nt+1];
00239 for (int t=0; t<nt; t++)
00240 costs[t]=s.getCost(tracks.get(t))/tracks.get(t).variance;
00241
00242 costs[nt]=NEW_COST;
00243
00244
00245
00246 int minT=-1;
00247 float minCost=Float.MAX_VALUE;
00248 for (int t=0; t<=nt; t++)
00249 if (costs[t]<minCost){
00250 minCost=costs[t];
00251 minT=t;
00252 }
00253
00254 VisTrack t;
00255 if (minT==nt){
00256 t=new VisTrack();
00257 add(t);
00258 }
00259 else t=tracks.get(minT);
00260
00261 s.update(t);
00262 }
00263
00264
00265 class VisCamera extends VisNode {
00266 float heading, pitch;
00267
00268 public VisCamera(Vector3f pos, float heading, float pitch, String ip) {
00269 super(null, pos);
00270 this.heading=heading;
00271 this.pitch=pitch;
00272 cameras.put(ip,this);
00273 }
00274
00275 protected void transform() {
00276 super.transform();
00277 GL11.glRotatef(heading, 0,1,0);
00278 GL11.glRotatef(pitch, 1,0,0);
00279 }
00280
00281 protected void renderSelf() {
00282 GL11.glDisable(GL11.GL_TEXTURE_2D);
00283 GL11.glColor4f(.3f,.5f,1,.5f);
00284 GLBoxRenderer.renderBox(3,3,1);
00285 GL11.glBegin(GL11.GL_LINES);
00286 GL11.glVertex3f(0,0,0); GL11.glVertex3f(-7,-5,50);
00287 GL11.glVertex3f(0,0,0); GL11.glVertex3f( 7,-5,50);
00288 GL11.glVertex3f(0,0,0); GL11.glVertex3f( 7, 5,50);
00289 GL11.glVertex3f(0,0,0); GL11.glVertex3f(-7, 5,50);
00290 GL11.glEnd();
00291 }
00292 }
00293
00298 class VisSonar extends VisNode implements Sensor{
00299
00300 float distance, speed;
00301
00302 float maxdistance;
00303
00304 float timer;
00305 final float TIMEOUT=1;
00306 final float MAX_FUZZ=5;
00307 final float WEIGHT_DIST=1, WEIGHT_SPEED=0;
00308
00309 float heading, pitch;
00310
00311 public VisSonar(Vector3f pos, float heading, float pitch) {
00312 super(null, pos);
00313 this.heading=heading;
00314 this.pitch=pitch;
00315 radius=10000;
00316 }
00317
00321 void receive(float distance, float speed){
00322
00323 maxdistance=Math.max(maxdistance, distance);
00324 if (distance>maxdistance-MAX_FUZZ) return;
00325
00326 this.distance=distance; this.speed=speed;
00327 trackOne(this);
00328 timer=0;
00329 }
00330
00331 protected void transform() {
00332 super.transform();
00333 GL11.glRotatef(heading, 0,1,0);
00334 GL11.glRotatef(pitch, 1,0,0);
00335 }
00336
00339 void renderSelf() {
00340
00341 timer+=getRoot().client.dt;
00342 if (timer>TIMEOUT){
00343 distance=speed=0;
00344 }
00345
00346 GL11.glDisable(GL11.GL_TEXTURE_2D);
00347 GL11.glColor4f(.3f,.5f,1,.5f);
00348 GL11.glPushMatrix();
00349 GL11.glScalef(1,1,.1f);
00350 GLSphereRenderer.renderSphere(2);
00351 GL11.glPopMatrix();
00352 GL11.glTranslatef(0,0,5);
00353 GL11.glColor3f(.3f,.5f,1);
00354 GLBoxRenderer.renderBox(.2f,.2f,10f);
00355 GL11.glTranslatef(0,0,-5);
00356
00357 if (distance!=0){
00358 GL11.glColor3f(1,1,1);
00359 GL11.glTranslatef(0,0,distance);
00360 GLSphereRenderer.renderSphere(1);
00361 }
00362 }
00363
00365 public float getCost(VisTrack track) {
00366 if (distance==0) return Float.MAX_VALUE;
00367
00368 Vector3f pos=parent.traverse(this,track.current.pos);
00369
00370 Vector3f tmp=new Vector3f();
00371 Vector3f.add(track.current.pos, track.current.dpos, tmp);
00372 Vector3f pos2=parent.traverse(this, tmp);
00373
00374 float dl=pos2.length()-pos.length();
00375
00376
00377 float cost= Math.abs(pos.length()-distance)*WEIGHT_DIST
00378 + Math.abs(dl-speed) *WEIGHT_SPEED;
00379
00380 return cost;
00381 }
00382
00388 public void update(VisTrack track) {
00389
00390 Vector3f pos=traverse(parent, new Vector3f(0,0,distance));
00391
00392
00393
00394 if (track.current.pos==null) track.current.pos=pos;
00395 else track.current.pos.set(pos);
00396
00397 Vector3f pos2=traverse(parent, new Vector3f(0,0,distance+speed));
00398 Vector3f.sub(pos2, pos, track.current.dpos);
00399
00400 track.variance=1f;
00401 track.lastseen=System.currentTimeMillis();
00402 }
00403 }
00404
00405
00406 public VisNode addSonar(Vector3f pos, float heading, float elevation){
00407 VisNode sonar= new VisSonar(pos,heading,elevation);
00408 add(sonar);
00409 return sonar;
00410 }
00411
00412 public VisNode addCamera(Vector3f pos, float heading, float elevation, String ip){
00413 VisNode cam= new VisCamera(pos,heading,elevation,ip);
00414 add(cam);
00415 return cam;
00416 }
00417
00418
00420 class VisSonarDummy extends VisSonar{
00421
00422 public VisSonarDummy(Vector3f pos, float heading, float pitch) {
00423 super(pos, heading, pitch);
00424 }
00425
00426 float olddist=10;
00427
00428 int dir=1;
00429
00431 void renderSelf() {
00432
00433 if (Math.random()>.99f){
00434
00435
00436
00437
00438
00439
00440
00441
00442 if (olddist>100 || olddist <= 5) dir=-dir;
00443
00444 float d= dir * ((float)Math.random()*.2f+1);
00445 receive(olddist + 100 * d * getRoot().client.dt, d);
00446 olddist=distance;
00447
00448 trackOne(this);
00449 }
00450 super.renderSelf();
00451 }
00452 }
00453
00454 final float SCALE=.1f, DSCALE=.01f;
00455
00456
00457
00459 public void parseMsg(String[] msg){
00460 if (!msg[1].matches("sonar[0-9]+")) return;
00461 int id=Integer.parseInt(msg[1].replace("sonar", ""));
00462 if (id>0 && id<=children.size()){
00463 int distance=Integer.decode(msg[2]),speed=Integer.decode(msg[3]);
00464
00465 if (speed>0x7FFF) speed-=0xFFFF;
00466 if (Math.abs(speed)>30) speed=0;
00467
00468 ((VisSonar)children.get(id-1)).receive(distance*SCALE, speed*DSCALE);
00469
00470
00471 }
00472 }
00473
00476 void renderSelf() {
00477
00478 }
00479
00480
00481
00482 HashMap<String, VisCamera> cameras=new HashMap<String, VisCamera>();
00488 public void addPortrait(String path, String ip) {
00489
00490 if(Prefs.current.verbose) System.out.println("Cam "+ip+": "+path);
00491
00492 Vector3f camera=cameras.get(ip).position;
00493 if (camera==null) return;
00494 if(Prefs.current.verbose) System.out.println("known. ");
00495
00496 float minDist=Float.MAX_VALUE;
00497 VisNode minTrack=null;
00498 for (VisNode n: children)
00499 if(n instanceof VisTrack){
00500 float dist=Vector3f.sub(n.position, camera,null).lengthSquared();
00501 if (dist<minDist){
00502 minDist=dist;
00503 minTrack=n;
00504 }
00505 }
00506 if (minTrack!=null) minTrack.add(new VisImage(new Node(path), new Vector3f()));
00507 }
00508
00509 }
00510
00511
00512