From 37da305bb6b40014738599bb839c47317783a600 Mon Sep 17 00:00:00 2001 From: Radu Mariescu-Istodor Date: Thu, 21 Apr 2022 09:48:14 +0300 Subject: [PATCH] Lecture 7 code --- 7. Visualizing neural networks/car.js | 141 +++++++++++++++++++ 7. Visualizing neural networks/controls.js | 52 +++++++ 7. Visualizing neural networks/index.html | 18 +++ 7. Visualizing neural networks/main.js | 40 ++++++ 7. Visualizing neural networks/network.js | 68 +++++++++ 7. Visualizing neural networks/road.js | 56 ++++++++ 7. Visualizing neural networks/sensor.js | 119 ++++++++++++++++ 7. Visualizing neural networks/style.css | 12 ++ 7. Visualizing neural networks/utils.js | 49 +++++++ 7. Visualizing neural networks/visualizer.js | Bin 0 -> 7098 bytes 10 files changed, 555 insertions(+) create mode 100644 7. Visualizing neural networks/car.js create mode 100644 7. Visualizing neural networks/controls.js create mode 100644 7. Visualizing neural networks/index.html create mode 100644 7. Visualizing neural networks/main.js create mode 100644 7. Visualizing neural networks/network.js create mode 100644 7. Visualizing neural networks/road.js create mode 100644 7. Visualizing neural networks/sensor.js create mode 100644 7. Visualizing neural networks/style.css create mode 100644 7. Visualizing neural networks/utils.js create mode 100644 7. Visualizing neural networks/visualizer.js diff --git a/7. Visualizing neural networks/car.js b/7. Visualizing neural networks/car.js new file mode 100644 index 0000000..d773c11 --- /dev/null +++ b/7. Visualizing neural networks/car.js @@ -0,0 +1,141 @@ +class Car{ + constructor(x,y,width,height,controlType,maxSpeed=3){ + this.x=x; + this.y=y; + this.width=width; + this.height=height; + + this.speed=0; + this.acceleration=0.2; + this.maxSpeed=maxSpeed; + this.friction=0.05; + this.angle=0; + this.damaged=false; + + this.useBrain=controlType=="AI"; + + if(controlType!="DUMMY"){ + this.sensor=new Sensor(this); + this.brain=new NeuralNetwork( + [this.sensor.rayCount,6,4] + ); + } + this.controls=new Controls(controlType); + } + + update(roadBorders,traffic){ + if(!this.damaged){ + this.#move(); + this.polygon=this.#createPolygon(); + this.damaged=this.#assessDamage(roadBorders,traffic); + } + if(this.sensor){ + this.sensor.update(roadBorders,traffic); + const offsets=this.sensor.readings.map( + s=>s==null?0:1-s.offset + ); + const outputs=NeuralNetwork.feedForward(offsets,this.brain); + + if(this.useBrain){ + this.controls.forward=outputs[0]; + this.controls.left=outputs[1]; + this.controls.right=outputs[2]; + this.controls.reverse=outputs[3]; + } + } + } + + #assessDamage(roadBorders,traffic){ + for(let i=0;ithis.maxSpeed){ + this.speed=this.maxSpeed; + } + if(this.speed<-this.maxSpeed/2){ + this.speed=-this.maxSpeed/2; + } + + if(this.speed>0){ + this.speed-=this.friction; + } + if(this.speed<0){ + this.speed+=this.friction; + } + if(Math.abs(this.speed)0?1:-1; + if(this.controls.left){ + this.angle+=0.03*flip; + } + if(this.controls.right){ + this.angle-=0.03*flip; + } + } + + this.x-=Math.sin(this.angle)*this.speed; + this.y-=Math.cos(this.angle)*this.speed; + } + + draw(ctx,color){ + if(this.damaged){ + ctx.fillStyle="gray"; + }else{ + ctx.fillStyle=color; + } + ctx.beginPath(); + ctx.moveTo(this.polygon[0].x,this.polygon[0].y); + for(let i=1;i{ + switch(event.key){ + case "ArrowLeft": + this.left=true; + break; + case "ArrowRight": + this.right=true; + break; + case "ArrowUp": + this.forward=true; + break; + case "ArrowDown": + this.reverse=true; + break; + } + } + document.onkeyup=(event)=>{ + switch(event.key){ + case "ArrowLeft": + this.left=false; + break; + case "ArrowRight": + this.right=false; + break; + case "ArrowUp": + this.forward=false; + break; + case "ArrowDown": + this.reverse=false; + break; + } + } + } +} \ No newline at end of file diff --git a/7. Visualizing neural networks/index.html b/7. Visualizing neural networks/index.html new file mode 100644 index 0000000..865df04 --- /dev/null +++ b/7. Visualizing neural networks/index.html @@ -0,0 +1,18 @@ + + + Self-driving car - No libraries + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/7. Visualizing neural networks/main.js b/7. Visualizing neural networks/main.js new file mode 100644 index 0000000..2ad537d --- /dev/null +++ b/7. Visualizing neural networks/main.js @@ -0,0 +1,40 @@ +const carCanvas=document.getElementById("carCanvas"); +carCanvas.width=200; +const networkCanvas=document.getElementById("networkCanvas"); +networkCanvas.width=300; + +const carCtx = carCanvas.getContext("2d"); +const networkCtx = networkCanvas.getContext("2d"); + +const road=new Road(carCanvas.width/2,carCanvas.width*0.9); +const car=new Car(road.getLaneCenter(1),100,30,50,"AI"); +const traffic=[ + new Car(road.getLaneCenter(1),-100,30,50,"DUMMY",2) +]; + +animate(); + +function animate(time){ + for(let i=0;ilevel.biases[i]){ + level.outputs[i]=1; + }else{ + level.outputs[i]=0; + } + } + + return level.outputs; + } +} \ No newline at end of file diff --git a/7. Visualizing neural networks/road.js b/7. Visualizing neural networks/road.js new file mode 100644 index 0000000..cf0d5df --- /dev/null +++ b/7. Visualizing neural networks/road.js @@ -0,0 +1,56 @@ +class Road{ + constructor(x,width,laneCount=3){ + this.x=x; + this.width=width; + this.laneCount=laneCount; + + this.left=x-width/2; + this.right=x+width/2; + + const infinity=1000000; + this.top=-infinity; + this.bottom=infinity; + + const topLeft={x:this.left,y:this.top}; + const topRight={x:this.right,y:this.top}; + const bottomLeft={x:this.left,y:this.bottom}; + const bottomRight={x:this.right,y:this.bottom}; + this.borders=[ + [topLeft,bottomLeft], + [topRight,bottomRight] + ]; + } + + getLaneCenter(laneIndex){ + const laneWidth=this.width/this.laneCount; + return this.left+laneWidth/2+ + Math.min(laneIndex,this.laneCount-1)*laneWidth; + } + + draw(ctx){ + ctx.lineWidth=5; + ctx.strokeStyle="white"; + + for(let i=1;i<=this.laneCount-1;i++){ + const x=lerp( + this.left, + this.right, + i/this.laneCount + ); + + ctx.setLineDash([20,20]); + ctx.beginPath(); + ctx.moveTo(x,this.top); + ctx.lineTo(x,this.bottom); + ctx.stroke(); + } + + ctx.setLineDash([]); + this.borders.forEach(border=>{ + ctx.beginPath(); + ctx.moveTo(border[0].x,border[0].y); + ctx.lineTo(border[1].x,border[1].y); + ctx.stroke(); + }); + } +} \ No newline at end of file diff --git a/7. Visualizing neural networks/sensor.js b/7. Visualizing neural networks/sensor.js new file mode 100644 index 0000000..7ab6bef --- /dev/null +++ b/7. Visualizing neural networks/sensor.js @@ -0,0 +1,119 @@ +class Sensor{ + constructor(car){ + this.car=car; + this.rayCount=5; + this.rayLength=150; + this.raySpread=Math.PI/2; + + this.rays=[]; + this.readings=[]; + } + + update(roadBorders,traffic){ + this.#castRays(); + this.readings=[]; + for(let i=0;ie.offset); + const minOffset=Math.min(...offsets); + return touches.find(e=>e.offset==minOffset); + } + } + + #castRays(){ + this.rays=[]; + for(let i=0;i=0 && t<=1 && u>=0 && u<=1){ + return { + x:lerp(A.x,B.x,t), + y:lerp(A.y,B.y,t), + offset:t + } + } + } + + return null; +} + +function polysIntersect(poly1, poly2){ + for(let i=0;i0?0:255; + return "rgba("+R+","+G+","+B+","+alpha+")"; +} + \ No newline at end of file diff --git a/7. Visualizing neural networks/visualizer.js b/7. Visualizing neural networks/visualizer.js new file mode 100644 index 0000000000000000000000000000000000000000..96d8c7848ea2630f8449294fb26d26f3352db451 GIT binary patch literal 7098 zcmeHM+fEcg5UoeW_zwgh*ky+WB`Q%DgE3JPBnF9^5FTI`WMEmz?jR`PKYj39)Kk+G zQ{8mWOmllO6PRmPbyuA_RbBh{PnY_%K_eXF^odfO4{_he)lb@@A)U~D8pAttj3~p~ z3~#%5(!=`=I-+HKnc@5m_j}a9yNr%0p@H?h>Bth9U5pz*Zw86`kT;~SkUyXfJ*HWD zZt3@p=|jslMt7{y)#EbgJ%}E4gt_&gZ3iRGI@>sJV7}k+e?)EALB5!_W;8{QYOH1l zt4U#joqR=p4f>mq4(+v&)xJYlpWa#;wd@(kgKd1hg>~{MUMb%VFjuyQvA0j_c8-fi z{x$nJh2?Byl*yf@hmf7p0!A?!QkupQ!czH4SI<0dJm2ynOC-pd*Ej@D8nwQbQQC^r z%4*uyNtDD{#FNjuqR~Cqw{QoReHbNMbiIT}+KAGadCAyk@Z=1vT7RC5gk~*W%@Q<< zeu=CR{F~7dX2UaioyYJF=CwvoVevUyhfY72h$J6tw$Hh72~thOgm}?L{~BhpUeni% zO=iACAKTJlAY@D=;n z)JGp+3C_HYN``V}>|aPs!5QvX5RpCD z=n(A0HPw8ea&S3=^XK(3lAhTyBwv5b`tw6!8Q%T1^NbYBRN_0{1$Kc3-bLz|=RKw2 z7;WnW)=TL986URk1HB{OZB<3TXxoO*`ZzQ$C!m*i#$6zGBH%}N#UiH~ZKC-yY%XKt zY&4bE>Q7*&>$jC*|00Gp_nQcg^+ec${y6oqURjjc9PDQ1dYS+7ab{~zfWA<6yxmAM z8RUPAjh}aRbc~f*=Qg9uM$c8_%NIE=uU&>utn%whI*x(#9*J=ZW>x}FT{FY2o@M5O39G?0P)drz^&Nv)b*R&p71x$DYMRUV_N zTtv?1y#;rVClJNlpX7JL${Ze&_zE=uTTO7xa`&O5hl6)CRkeXDS84=}ub5iHm8WrF z%RIu~FwIvVKS%D!b4Q)~a~JEaDb%*y_iJJYJAqx^F}k{o`L2$CIf&P0s;^a8lYLl) zuOzPu4Ii`u^W(lGcMHq&r)x{`vF0k%;f#}`eRBJ&@>fXq(~J8Wo^$cbj&DaVNZ>vU zS9rYB=la~gulIAn5Mwg1#}MPk^O4oP^+J9bGZj6B@{U5W3cKp7-vy89dUKasEM>ag SCYsz|Pr|)z7sJMLr}PgiU!J=F literal 0 HcmV?d00001