RustX/Autonomous_Driving_Simulation
3
1class Car{2 constructor(x,y,width,height,controlType,maxSpeed=3){3 this.x=x;4 this.y=y;5 this.width=width;6 this.height=height;7 8 this.speed=0;9 this.acceleration=0.2;10 this.maxSpeed=maxSpeed;11 this.friction=0.05;12 this.angle=0;13 14 this.damaged=false;15 16 this.useBrain=controlType=="AI";17 18 if(controlType!="DUMMY"){19 this.sensor=new Sensor();20 this.brain=new NeuralNetwork(21 [this.sensor.rayCount,6,4]22 );23 } 24 this.controls=new Controls(controlType);25 }26 27 update(roadBorders,traffic){28 if(!this.damaged){29 this.#move();30 this.polygon=this.#createPolygon();31 this.damaged=this.#assessDamage(roadBorders,traffic);32 }33 if(this.sensor){34 this.sensor.update(this.x,this.y,this.angle,roadBorders,traffic);35 const offsets=this.sensor.readings.map(36 s=>s==null?0:1-s.offset37 );38 const outputs=NeuralNetwork.feedForward(offsets,this.brain);39 if(this.useBrain){40 this.controls.forward=outputs[0];41 this.controls.left=outputs[1];42 this.controls.right=outputs[2];43 this.controls.reverse=outputs[3];44 }45 } 46 }47 48 #assessDamage(roadBorders,traffic){49 for(let i=0;i<roadBorders.length;i++){50 if(polysIntersect(51 [...this.polygon,this.polygon[0]],52 roadBorders[i])53 ){54 return true;55 }56 }57 for(let i=0;i<traffic.length;i++){58 const poly=traffic[i].polygon;59 if(polysIntersect(60 [...this.polygon,this.polygon[0]],61 [...poly,poly[0]])62 ){63 return true;64 }65 }66 return false;67 }68 69 #createPolygon(){70 const points=[];71 const rad=Math.hypot(this.width,this.height)/2;72 const alpha=Math.atan2(this.width,this.height);73 points.push({74 x:this.x-Math.sin(this.angle-alpha)*rad,75 y:this.y-Math.cos(this.angle-alpha)*rad76 });77 points.push({78 x:this.x-Math.sin(this.angle+alpha)*rad,79 y:this.y-Math.cos(this.angle+alpha)*rad80 });81 points.push({82 x:this.x-Math.sin(Math.PI+this.angle-alpha)*rad,83 y:this.y-Math.cos(Math.PI+this.angle-alpha)*rad84 });85 points.push({86 x:this.x-Math.sin(Math.PI+this.angle+alpha)*rad,87 y:this.y-Math.cos(Math.PI+this.angle+alpha)*rad88 });89 return points;90 }91 92 #move(){93 if(this.controls.forward){94 this.speed+=this.acceleration; 95 }96 if(this.controls.reverse){97 this.speed-=this.acceleration;98 }99 100 if(this.speed!=0){101 const flip=this.speed>0?1:-1;102 if(this.controls.left){103 this.angle+=0.03*flip;104 }105 if(this.controls.right){106 this.angle-=0.03*flip;107 }108 }109 110 if(this.speed>this.maxSpeed){111 this.speed=this.maxSpeed;112 }113 if(this.speed<-this.maxSpeed/2){114 this.speed=-this.maxSpeed/2;115 }116 117 if(this.speed>0){118 this.speed-=this.friction;119 }120 if(this.speed<0){121 this.speed+=this.friction;122 }123 if(Math.abs(this.speed)<this.friction){124 this.speed=0;125 }126 this.x-=Math.sin(this.angle)*this.speed;127 this.y-=Math.cos(this.angle)*this.speed;128 }129 130 draw(ctx,drawSensor=false){131 if(this.damaged){132 ctx.fillStyle="gray";133 }else{134 ctx.fillStyle="black";135 }136 ctx.beginPath();137 ctx.moveTo(this.polygon[0].x,this.polygon[0].y);138 for(let i=1;i<this.polygon.length;i++){139 ctx.lineTo(this.polygon[i].x,this.polygon[i].y);140 }141 ctx.fill();142 if(this.sensor && drawSensor){143 this.sensor.draw(ctx);144 }145 }146}