Self-Driving Car with JavaScript Course – Neural Networks and Machine Learning

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
In this course, you will learn how to build a  self driving car simulation. By making every   component yourself with no libraries. This course  is a great way to learn about neural networks.   You will also learn about modern JavaScript  techniques, Raju teaches this course.   He has a PhD in computer science, and is one  of the more creative tech YouTubers out there.   Hi, I'm Raju, and welcome to the self  driving car, no libraries JavaScript course.   It's a course where I teach you how to make a  self driving car. The and will do it without   using any kind of libraries so that you really  understand what's going on under the hood.   Now, before you say anything, yeah, it won't be a  real car you drive outside. But making this kind   of simulation is maybe even harder than doing  it for real. Let me explain. In this course,   you'll learn how to implement simple physics  to move the car in the beginning will control   the car ourselves using the keyboard to get  the field that we want. I'll also teach how   to create the road and how to follow the car on  the road like a drone is filming it from above   will then simulate some sensors on the car.  These sensors work by raycasting and detect   if the car is too close to the side of the road or  to other cars in traffic. To implement these will   use a formula for a segment intersection. Don't  worry, I'll explain the math in a nice visual way.   You'll see we'll implement collision detection  using the same segment intersection formula.   It's great, it works with any orientation and  can even support other shapes as well. Now all   of these are things you don't have to worry  about if you're working with real hardware.   The world gives you the best  physics better than any simulation.   There are plenty of rows to drive on,  we don't need to create them ourselves.   And nowadays, cars have a bunch of sensors that  tell if something is touching or around the car.   Of course, if you want to build  all of these yourself, then yeah,   making the simulation is easier. But what are you  Elon Musk? Anyway, the second half of the course   is the really interesting part, you'll learn  how to create and visualize a neural network,   an algorithm inspired by the biological neural  networks in our brains. I'll briefly explain   how our brains work to the best of my ability and  teach you how to code something similar ourselves,   then we'll optimize the brain by trial and error.   Yeah, to keep things simple, we just try  randomly generating brains until we get   something that works. We'll parallelize this step  and use hundreds of cars at once to save time.   By the way, this is something you can't do with  real hardware unless you're really, really rich.   And that's why car companies use simulations  to train their neural networks as well.   I'll also teach you a basic genetic algorithm to  optimize faster. But don't expect anything too   fancy. This entire system is complex, but I made  it so that each component is relatively simple   in and of itself. I made this course keeping  in mind my high school days back in Romania.   So the knowledge you get from school should  be enough depending on the curriculum. We'll   work with JavaScript because it's so easy to get  started. You just need an editor and a browser,   which you probably have already. I'll teach you  many modern JavaScript techniques. So this course   is perfect if you want to become a better  coder, as well as a machine learning expert.   Now, JavaScript is not the best choice  when doing artificial intelligence.   But since we're not using any libraries, it  doesn't really matter. If you want to learn these   in a more useful language, like Python, then come  study at Karelia University of Applied Sciences   there, I teach the same thing in Python as well.  And we also study machine learning libraries and   even use hardware components. But now start your  engines because the course is about to start.   I'll first teach you how to implement the car  driving mechanics. You learn to make a car   that moves like this. It's not really that  hard. You'll see. I'll refresh your memory   with some basic physics and trigonometry.  And you'll be able to code this in no time.   We begin with this simple project setup. We have  three files right here, index, HTML main, Jas, and   style css, and they're all empty for now. And  I'm using Visual Studio code to write this.   And on the right, I have Google Chrome, and you  need to have the developer tools open there.   It's really important. So if you plan to follow  along, have a similar setup. You can use another   editor if you want to If I recommend this Visual  Studio Code nowadays, let's begin with basic HTML.   In the head, I'm going to write a title for  this. And it's going to be self driving car,   no libraries. Really, everything here is going to  be just written by us, linking now the stylesheet.   And let me close the head and in the  body, I'm going to define a canvas,   we are mostly going to use this canvas in this  project here, I'm also linking the JavaScript file   like this. And we are done with the HTML for  the moment, at least, refresh the page. And   not much happens rarely. It says here self  driving car, no libraries in the in the tab   of the browser, but nothing appears in the page  itself. Apparently, if you open this elements,   you will see that the canvas is actually  there. It's just transparent. And the body   actually has this orange small margin there, I  want to get rid of that margin and also make this   canvas visible somehow. So let's go to this style  css next, and write some styles, I will remove   the margin for the body. And let's make the body  have a dark gray background overflow to hidden.   And I'm going to use text align to center for now.  Overflow is important. Otherwise, we might get   the scroll bar coming if the canvas is too big.  And I don't want that. And I want everything to   align to center in the middle of the page. Now my  canvas should have a different colored background,   maybe we set it to light gray like this. And save,  refresh. And now you can actually see the canvas   without needing to inspect these elements right  here. I'm gonna move back to the console, it's   probably the most important thing in the developer  tools, I want my canvas to stretch the full   screen vertically. So I'm gonna go in main.js,  right here. And I'm going to get a reference   to our canvas with ID my canvas we defined  previously. And I'm going to set the height of   this to be the full window inner height like this.  And the width is going to be just 200 pixels,   it will be like a road going upwards, we will need  the space on the side to draw the neural network   later. Now if I save this and refresh, you can  see it appearing there exactly how we want it.   Let's next pretend that we have a car, and we want  to draw it on the canvas. To draw on the canvas,   we first need to get the drawing context, we will  just use the to the context in this whole project.   So I'm going to have a reference to this canvas  context right here and the city X. And it's going   to contain all the methods we need to draw the  things that we need to draw in this project.   And if we would have a car, we would say  something like this, let's get the car at,   for example, 100x 100 y, and the car  maybe has a 30, width, and 50 height.   All of these are in pixels. And let's draw the  car using this context. But we don't have the car   yet. This is the thing that we are going to  need to define next, the car object. And we are   going to do this first by going inside the index  html here and preparing to import the new file.   Car Jas like this. And now I'm going to add a new  file here. Car JS in here. I'm going to say class   car. So we are defining our car class. And the  constructor for this class is going to have   four different parameters. So we have here the  X and the Y and a width and a height. So these   are properties of the car where we want it to be  in how big should the car be? And we are going to   store these as attributes inside of the object  like this so that the car remembers where it   is and how big it is. Now, remember, we also had  this draw being called. So that draw was a method.   And it looks something like this, it gets context  as a parameter. And in here, we begin path. And we   are going to draw a car as a simple rectangle.  For now, the rectangle is going to start   at an x&y location. So I'm going to use this  dot x minus this dot width divided by two.   So the x of the car is going to be the  center inside the car, and it's going to have   parts in front behind, left and right, so on  the top bottom, left and right, the y value,   I subtract half the height. So here, we also need  to specify what is the width and the height of   this rectangle like this, and ask the context to  fill it like so. And if I'm going to save this and   refresh the page, you can see the car there, or  at least the black rectangle. For now, the car   is here at 100 100. So on computer screens, the  y axis actually goes downwards. And the 00 point   relative to this canvas is actually right up  here. Now, this is really boring as such. So I'm   going to teach you next how to move the car using  the keyboard arrow keys. So for now, let's just   pretend that we have here some controls  like this controls is equal to new controls.   And let me link a new file here in  index controls J S, and also create   controls, J S. And we will do a similar thing as  previously. So we need a class for these controls.   And the constructor, the controls object  will have four different attributes,   one of it will know if it's going  forward, one of it for the left,   one of it for the right, one for the reverse, like  this. And I set them to false initially, but this   will change depending on what you press on the  keyboard. So I'm next going to define a method for   adding so called keyboard listeners,  so that we have a piece of code that   checks whenever we press a key or release a  key. So I'm going to call here, add keyboard   listeners. And this is going to be a method inside  of the controls class, like so. The reason I put   here this hashtag in front is because this is  a private method. You can't access this from   outside that this controls class and you shouldn't  it's its own responsibility. So how does this add   keyboard listeners look like? Well, we will add  a key down event to the document and set this   to be equal to this arrow function. I will  explain arrow functions in just a second. But   let's implement this first. So  depending on the key that was pressed,   if this was the arrow left key, we are  going to set this left to true and break   and do the same thing for the arrow right  key like this. The arrow up key for forward   and the arrow down key for reverse   and that's it. But we also need  to know when we release a key.   So I'm going to actually copy this code  here like so. And this is going to be   on key up. And all of these things  are going to be set to false.   I want to debug if all of this code that we wrote  works. So I'm going to put here a console table.   This, I'm going to output this entire object into  the console in a table format. When I press a key,   and when I release a key, I save the file refresh.  And every time you press something like now I'm   pressing the up key. Now I released the app key.  Now I'm pressing the Down key, I released the down   key left. And right, you can see the values in  the console have changed. So this code seems to   be working. Great. But why is it working? So let's  look a little bit up here. And this part of the   code may be a little strange to you, if you're  not familiar with this arrow function notation.   This is actually the same thing as writing  here, function of event like this. So we say   that unki down, this is the function that you're  going to call. But if you write it like this,   this here stops referring to the object here  to the controls object, it actually refers to   this function right here. And if I undo and use  this arrow function notation, this continues   to refer to this object right here. So it's a  difference in how these two type of functions   work in JavaScript. And it's convenient to have  it in this way. Now, controls are triggering,   but let's move the car with them. So I'm going  to go to car Jas. And we are going to write here   an update method. This update method is going to  check if the controls say forward, let's just move   the car upward. So that means y minus equals to  remember that y increases downwards on a computer.   And if these controls are reverse, then  we add to y so that it goes downwards.   Now this won't do anything just yet, we need  to go to main js here and start to animate.   So I'm going to right here animate and define  an animate function like this. And inside here,   I'm going to update the car. And then I'm going  to draw the car using this code we had previously   like this and call request animation frame  with animate like so. Request Animation Frame   calls the Animate method again and again  many times per second, it gives the illusion   of movement that we want. Now we can save the  file, refresh the page. And when I press down,   something happens. So the car updates and redraws  itself. But all the past positions of the car are   still there. And if I press up now takes a while  but then it reaches again the top part and you   start seeing it again. But it leaves this black  trail there. So we need to fix this. And actually,   we need to fix something else as well. If I'm  going to resize this console here, you will see   that this canvas here doesn't stretch to fill  the screen vertically anymore. This bothers me.   But it's, it's great, because we can fix both  of these issues by moving this piece of code   from here to here. When you resize the canvas in  this way, it means that it also becomes cleared.   So if I refresh now and press the Down  key, the car is actually seemingly moving   and it doesn't leave that trail anymore. Also,  if I resize this console here, it looks proper.   You might have to click on the screen here before  you can press the top and down arrows. Sometimes   these listeners don't activate them unless you  click inside the page. Okay, problem now is that   this doesn't move like a car at all. We need to  work on this cars don't move so that you press   on something And then immediately stop, I'm going  to go to the car constructor here and give the car   a speed attribute and an acceleration value  like this. And here, instead of changing the   y value on forward, we are going to say that  the speed will increase by the acceleration,   like this. And I'm going to copy this here below.  But with minus, and here, I will say this dot   y minus equals this dot speed, I save the file,  refresh the page, I press down. I press up, we,   okay, we need to stop the car from going  too fast and implement some friction. So   I'm going to go here and say, max  speed equals to something like three   and the friction of, let's say, 0.05, like this.  And in the update method, I'm going to move here   and say, if the speed is more than this max speed,  this speed becomes max speed, we are capping it   the same if the speed is less than minus this max  speed. But in reverse, I want the car to be not as   fast, I'm just gonna divide by two here. If it's  less than this, then I'm gonna cap it to be minus   max speed divided by two, maybe you want to have  a max reverse speed or something declared on top,   feel free to do it, I think it's overkill.  Also, there's no such thing as a negative speed,   like what we have here, the negative sign is  just to indicate that the car is going backwards.   Luckily, this is another course on physics,  otherwise, I might get in trouble for this.   Next thing we do is check if the speed is  greater than zero, I will decrease it by   the friction like this. And if the speed is less  than zero, then speed increases by the friction,   like this. Now I save the file, refresh the  page, press it down, and the car is moving.   I released and it's slowed down a bit, and then  it stopped. I'm pressing now up, and I release.   You can see it's still moving a little bit before  it stops. And I think that this fields quite   okay. But at the moment, the car is only going  forward and backward and the left and right,   don't do anything. One small issue though,  let me see if I can get it to happen.   Okay, if you release in just the right way,  you will see this, let me zoom in a little bit   more. See, the car is actually always  moving, it's constantly moving, no matter   if we press a key or not, actually, if we don't  press any key. And it's moving by by a very,   very, very small value. And that's because  if the speed is not equal to zero, exactly,   then this friction is going to bounce it  around, and eventually is going to move it   forwards by a very, very small value. So  to fix this, we can actually right here.   If this speed has absolute value that is less  than the friction just have it becomes zero   like so. And this is going to work, no need to  test anymore. Let's implement the left and right   controls next. And say as before, if we press  left, x gets minus two. And if we press WRITE,   x gets plus two, notice how I implement the  basic thing first, and make it more advanced   afterwards. I really want you to get the idea that  everything can be improved, but that you can make   a complex system even with easy components. I  mean, by the end of this course you will have   a self driving car no matter if it moves like  now, or if we implement better physics into it.   Now If I refresh the zoom out a  bit. Now, if I press left and right,   the car moves in a very, very funny,  non realistic way. But this is actually   how cars move in some games, for example. So if  you want to make a self driving car for a game,   then this might be enough for you. But I'm  gonna teach you how to do better than this. And,   actually, I don't like this for one important  reason, we are breaking the laws of physics,   we have here, the value for this maximum  speed. And we can reach that maximum   speed by going forward like this. But if I  press right now, I'm actually going faster   than the maximum speed, but diagonally,  because I'm going to maximum speed vertically   and a little bit to the left in this case.  So this is bad for many reasons. Let me teach   you how to fix it. We are gonna go up here and  define an angle, let's set it to zero. And here,   instead of doing this, we are actually going to  modify the angle to increase by 0.03, for example.   And here we have angle minus equals 0.03. So  this angle works according to the unit circle.   But in our case, the value of zero is  upward. So it's a unit circle that is   rotated 90 degrees counterclockwise, if you will.  But keep this image of the unit circle in mind of   the rotated unit circle in mind, because this  is going to be our coordinate system for making   rotations. Speaking of which, we can make a very  easy rotation like this using the Canvas context.   First, we save the context, then we translate  to the point where we want the rotation to be   centered at. And now I'm going to tell the context  to rotate by minus this angle. Next, I'm going to   remove here, this dot x and this dot y, because  we're already translating to that point. And one   last thing we need to do is here, add the call  to context restore. Because otherwise, on each   frame of the animation, we are going to translate  and rotate and translate and rotate and translate   and rotate. And this is going to do some infinite  series of translations and rotations. That will   look pretty funny, maybe, but not what we want.  So let me save this refresh. And now when I press   left, my car rotates counterclockwise. And  when I press right, it's rotates clockwise.   So we have something there. It's not yet good.  It's more like, like a tank that can rotate in   place. cars can do that. But more importantly,  if I rotate like this, and press the Down key,   my car just moves downwards in this weird way. And  this is not correct. And same goes for upwards,   we want the car to actually move in the direction  of this angle. So I'm going to implement this.   Based on the unit circle again, I'm going  to make X go minus the sine of the angle   times the speed. So unit circle has a radius of  one, this sign is between minus one and one. So   we need to scale this by the value of the speed  as well. And then for y, we do the same thing,   but with the cosine here, according to the unit  circle. Now we don't need this anymore. I can save   the file, refresh the page, rotate to the left,  press down and look at that. The car is moving   properly. And I can actually start to  feel like I'm driving a car. Mm hmm.   But backwards, it's flipped. Like, look  at this. If I press backwards and right,   the car turns left. That's an That's how it  happens in in real life. So we need to fix that.   And also this rotating in place. Next, I'm going  to just put here, if this speed is not zero,   I'm going to calculate a flip. So I'm  going to say the value of this flip   is one or minus one, depending on the speed,  so that I can flip the controls backwards.   And if if this is the case, then  here, I can just multiply by the flip.   If the flip is positive one, then this doesn't  do anything. So when the car is moving forward,   when it has a positive speed, then this won't  change. But when we go backwards, what essentially   happens is these signs are flipped. So let me  close this here, and test again. Now if I press   left and right, nothing happens, because our speed  is zero. But if I go backwards, and to the right,   it goes just the way I want. And now  I'm doing these kinds of, I'm trying to   change the direction in the car, similar to how  it would happen. When driving the car, play around   with it. And if there's something you don't like,  change it, especially if you're good at physics.   But if you're not, you can try using libraries  here as well. books to the is a really good one,   I think. But I'm happy with this, there's one  thing that we don't need anymore. That's the debug   here in the controls, I'm just going to remove  this, because now I'm confident that the controls   work as I want them to, I'm going to save this  file. And in car, this update method starts to be   quite big, and more things are going to be coming  here later. So one good thing would be to group   all this code here in a separate method, I'm going  to cut it, and the method is going to be called   move, because that's what this is doing. It's  moving the car, according to the controls. And   the move method is going to be a private method,  it has the hashtag there. And I paste the code   that we had previously in here, I save  this refresh, and everything still works.   As previously, I'll show you how to  do the road next. So in index html,   we are going to say here that we include road  Jas a new file that we have to also create here,   road Jas, like this. And in here, we are going to  start to write our road class. So very similar as   before, we have a constructor here. And I want the  roads to be centered around an x value, and have a   width. Now, these are going to be attributes  that the roads should remember. And actually,   I want it to have also a number of lanes. So let's  write here something like this. And define here,   a lane count that has a default value of three.  For now at least, it's useful to have a few more   attributes here that we can pre compute and  use later in our calculations. So for example,   we can have a value for left that is half the  width less than x and a right that is half the   width more than x. And I want the road to go  infinitely upwards and downwards. So let me   just define here a constant for infinity, really  large number. There's actually one in JavaScript   already but I found that when drawing things  with infinite size, weird things happen. So   let's just have a very, very big value here. Like  this. Our top is going to be minus infinity and   bottom is going to be plus infinity. Remember  that why on the computer grows downwards.   Now to draw the road I'm going to make a draw  method here similar what we had the car draw   method. And I'm going to set here a line width of  five. So a relatively thick line. And I'm going to   make it white. That's how the lines on the road  usually are. And let's begin a path and move to   left and top and the line to left  and bottom. So we are now drawing   a vertical line on the left side of  the screen. I'm going to copy this,   below like this. And I'm also going to draw  a line on the right side of the screen,   like so. And we are done with this route  js for now, I'm going to move in the main   js file. And above where we define this car, I'm  now going to say a road is equal to a new road   centered in half the width of the canvas.  So that's going to be our center X.   And it's going to have width of the whole canvas  width, I'm going to now go down here and write   road draw on the canvas as well before the car so  that the road comes first and then the car on top   of it. Let's now save this refresh. And almost  nothing happens. But you should be able to see   here on the sides, some white lines there.  Now they're exactly at the side of the road,   I want to leave a little bit of margin there. So  I'm gonna make here this with smaller, let's say   90% of the canvas width, save this, and refresh.  It looks better already. But we said that our   roads should have some lanes right here in the  constructor, the third argument, it has by default   three lanes, and we will need to make them appear  as well. I'll show you, we go back down here.   And I'm going to write a simple for  loop going from zero to this ln count,   inclusive. So notice here I have  less or equals to this lane count.   And now I want to know what is the x coordinate  of each of these lines of these vertical lines   that we are going to draw. And depending on the  lane count, we will have more or less of these   lines, but also the x values are different.  We get these using linear interpolation,   I'll show you. We say here, x is equal  to linear interpolation, or ulurp,   we will write this function Don't worry, it's not  not complicated. And we will interpolate from left   to right, so we need to get values between  left and right. According to a percentage,   this percentage is going to be i divided by this  lane count like this. Think about it. This last   value from here is going to be between zero and  one when I becomes this lane count, then this   is going to be one. And with all the in between  values, you just get percent values over here.   So how this slurp function looks like is function  ulurp. It's a funny name, but they've seen it used   by game developers at least. And that's it. So  you have the value of a and then the difference   between B and A times this percentage t. So when  t is zero, this part here is zero, you only have a   when t is one, this minus a from here will cancel  out and you're just left with b so zero and one or   zero and 100% just give you the two endpoints. And  for example, when t is in the middle, then this   difference is just half of that difference. So  it's gonna move half away from a and so on. It's   a really simple function, and I've used it in Very  many different projects, I really recommend that   you have it in your utilities as well. So let's  see if it works first, and then I'll move it in   the utils file, it doesn't belong here. We'll be  using this many times throughout this project.   So here, I'm going to align this part  like so. But replace here left with x   value like this, and also this one. And  we don't need this piece of code anymore.   Closing this here, and I think that we  can save and test and look at that we have   three lanes on our road, I'll move this function  now in a utils file. So let me create it utils.js,   paste it here. Say save the file, go to index  html, include it, like this. And now if I refresh,   everything still works. Let me go next to row j,  s, and add dashes to the middle lines, like so   I'm going to check if I is greater than  zero and less than this line count,   like this. And in that case, I'm going to  set line Dash. And I'm going to open an array   20 and 20. And this means that our dash will  have 20 pixels, and then a break of 20 pixels   and another dash and so on. So let me close this  otherwise, for the borders, we are going to put   line dash equal to an empty array like  that, I'm going to save this refresh.   And there are the dashes. Let's test also with the  lane count of four just to see if it works. It's   quite nice. But you can see the car is off center.  Now, I would like it to be on lane, right. So it   would be useful to have a method that tells us  what is the center of a given lane, let's do it.   Get Lane center with a given index. So this  will start from left to right starting at zero,   I'm going to get a helper variable first, the  line width equal to a width divided by the line   count like this. And then using that, I'm going  to say this left plus half the line width. So   I want to be starting these in the middle of the  first lane. Plus, I'm going to multiply the lane   index by the line width like this. And this is  going to give us four different line indices,   an offset of line width away from the middle of  the first line, oh, not line with lane width.   Line Width is something else. It's the  thickness of the line. Okay. And to test this,   we can go in main Jas. And here instead of passing  this 100 for the X of the car, we can write road   get Lane center. And for example, maybe we right  here three, to put it on the rightmost lane,   save this refresh, and the car is on the  right lane, right. Let me go to the road   and move this to have a lane count of  three. Again, I liked that value more.   And now we see a problem the car  has gone. It's actually here. And   Lane index three, which is now outside the screen.  So this is something you may want to have fixed   for example, by going here and using the minimum  function and saying you want the minimum between   the lane index and this lane count minus one.  With this, the car is going to go on the right   most possible Lane even if you accidentally tell  it to go more than that. But I prefer my car to be   in the center. So let's put this on lane one  here. And we'll keep it here for quite some time.   Now This looks nice. And driving on  this road definitely feels feels nice.   But in the future, I want to detect these  borders of the road here, and also have   collision detections with them. Because naturally  we want the car to, to explode and impact. So   basically, it would be nice if the road object  could tell us where these borders are. And I'm   going to do that. Next, I'm going to go here in  the road in the constructor, and I'm going to say,   this borders is equal to an array, I'm  going to put these borders in an array,   we now have just two left and right, but think  about it, maybe we want to have highways, and   then you have another board there in the middle,  or maybe some complicated situation requires more   for some reason. So I'm just going to use an array  and you can experiment with different things.   And the first thing in this array is  going to be a segment. So top left,   bottom left points form a segment. And  I'm going to make this also an array,   something like this. And the reason for  using arrays so much here is that our line   segment here is straight. But maybe you  want to experiment with something else,   like adding curves on the road. Actually,  that would be a nice homework for you to do.   So I'm gonna keep a race here like this, the  borders for now are just two segments made of   two points each. And these are  going to be here defined like so.   And I just copy this three more times  and say two, top right. Bottom left.   Bottom Right. And here we have, right, I'm just  going to copy this down here as well. And here we   have bottom, and I'm gonna copy this here as well,  I will save this, and nothing really changed. Not   yet at least, because these borders are just here.  If we say road borders, for example, they are just   in memory. And they are easy to access. Whenever  we need them, we just ask the road, hey, where   are your borders, and it can give them to us like  this. So the left border here with the X of 10,   and the right border with x of 190. And plus  minus infinity for these great, but because   these borders are here, now, it makes sense here  at the bottom to draw them separately. Because   if we change them, like maybe if you're gonna make  them curved, this drawing here won't reflect that.   So I'm going to change this to be here  starting at one and going to lane count,   minus one. And I'm going to  keep just the line dash here,   like this. And then I'm going to move  below this and say context set line dash   to empty array. And now I'm going to show  you a for each syntax, we are going to go   through the borders for each border.  Let's call it border, I'm going to use   this arrow notation again. And I'm going to say  context, begin the path. Move to the first point   in the board their X and the Y and do align  to the second point in the board their x and y   stroke. And that's it. Now keep in mind  that this doesn't change anything. So   all the code that we are writing now is  just to make everything more consistent,   but I will teach you a cool trick. Next  we're gonna make it look like there's   a camera above the car and it's gonna  follow the car as it moves on the road.   So I'm gonna go here to main Jas, before  drawing the road. And I'm going to say   save the context and translate nothing on  X but minus the y value of the car. And   below drawing these things, I'm going to say,  restore again, like this. And now if I save,   my car moved up there. But if I accelerate,  you can see that the car actually stand still.   Unless I go left and right, but the road is  the thing that's moving. So what I want to do   is actually not keep the car up there, but maybe  move it somewhere down, like for example, CAN bus   height times 50%. So this is now centering the car  there. As I'm driving, this feels really great.   But maybe a better value would be something  like 0.7. Because we in this way, we see more   of what is ahead of the car. And later when we add  traffic, we want to be able to see those things,   and figure out if the car will do the right things  or not. Really funny how easy this last thing was.   To add sensors to the car, I'm going to go to  index html and include here. Sensor Jas, save this   file, and create a file called sensor Jas liked  this. And inside here, I'm gonna define my sensor.   And the constructor will take the car   as the argument. And the reason is that I  want the sensor to know where the car is,   it's attached to the car, and we're going  to be using the car properties to update it.   So let's store here the car and other attributes  will be the array count. So our sensor will   cast arrays in different directions. Let's just  have three of these arrays for now. And then   the array length. So usually sensors like this  have a range after which they don't work anymore.   So if they don't sense anything in this 100  pixels range, then they can see beyond that,   and array spread. So here I'm setting pi divided  by four, this is the same as 45 degrees. And   that means the angle that we are going to spread  these rays that are being casted by the sensor.   So I'm going to keep here also an array called  arrays. And this is going to keep each individual   array one by one after we create them. I'm next  going to create an update method like this.   And we begin by setting these arrays to an empty  array. So this arrays is what we are going to   start to populate next. And to do that I'm going  to loop from zero to this array count, like this.   And I'm going to figure out the angle of each  individual array. And to do that, I'm going to   use the loop function, our utility function from  earlier here, that gives us a value between A and   B, depending on T, right. So if I go now back to  sensors, the angle here is going to be between   Ray spread divided by two, remember the unit  circle, the rotated unit circle and minus Ray   spread divided by two and the t value. Let's  have it i divided by this array count minus   one this time, because I is not going to become  equal to array count. So the maximum value for I   is this array count minus one  actually need to remember this,   it's quite important. And with this, we can  calculate the start point for for our array.   And that's just going to be the car X and  Y like this and an endpoint of the array.   For this endpoint. I'm going to take the car x  as the starting point. And then using the unit   circle, I'm going to take this angle that we made  previously, and multiply it by the the length   so unit circle, just one big soul radius. We won't  see anything we need to scale it up by the array   length here. And we do the very same thing In  with the y, but with the cosine there instead.   Now with the start and end point available, I'm  going to push these inside of the array to form   a segment. So notice here, I'm using this way  of defining the segment, using an array here   in the same way that we used for the borders  here in road Jas, the road borders are also   going to be made of segments defined in this  way, it's good to be consistent like this.   Now, we also need to be able to draw  our sensor. And I'm going to say draw.   And we go through all of the rays like this  beginner path. And I'm going to put a line   with two. And I'm going to draw these arrays using  yellow. I will move to the arrays start location,   x and y. So the first thing in the array  of IRA is its start location. And then   I will line to the race and location. So one with  x and y there like that. And now I can stroke   and close these like so I seem to be missing  here a curly brace. Let's save this file,   and now instantiate the sensor, I will go  to car and inside the car constructor here   above the controls, I think  it's it's good. I'm going to say   this sensor is equal to new sensor  of this. So I'm passing the car   through this. And then in the update method here,  I'm also going to be telling the sensor to update   like this. And in the draw, in addition to drawing  the car, I'm also going to be telling the sensor   to draw itself. So the car has now the  responsibility to draw its own sensor.   Let's save this refresh. Okay, so we see now  three lines popping out from the center of   the car like this. And they're at the 45 degree  angle, which is good. And when we move the car,   maybe this is not what you want to happen. Maybe  it is what you want to happen. I don't know,   you can experiment with these things. But I  would like the sensor to rotate with the car.   So that when the car moves, the sensor also moves.  But nowadays with gyroscopic technology, you could   probably have this kind of sensor as well if you  if you actually want. So to fix this, it's really   easy. I just add here to the array angle plus this  car angle like this. And it works as expected.   Let's play a little bit with these values up here  more, for example, let's have 30 segments and   make them a bit longer like this. Wow. So many  rays coming from there. It's like the sun. Let's   actually go all the way. So by The Times two. This  is now spreading these rays in all directions. So   all 360 degrees, or pi times two there. Let's put  it to have by so a 90 degree angle. I think I I   liked that. And let's try with Ray count of one.  We'll have a surprise here. It doesn't work. Two   works just fine. But one doesn't. And  the reason for that is this thing here,   this array count minus one. If array count is one  then this becomes zero and we can divide by zero.   So what I'm going to do is I'm just going to  replace this line. If this array count is one   I'm going to just return half, I want my array  to be straight up in the middle between the array   span. Otherwise, I just do the exact same thing  as previously. So now it works, no, no problems.   And we got it to work, we needed to do a little  bit of more thinking right here, because of this   division by zero. Let's try with more arrays  to see if that still works. Maybe five. Okay.   Nice. Now, before we get them to work to actually  detect that there are some road borders here. I   want to refactor this a little bit. So all the  code here in this update method, I'm going to   cut it and I'm going to say here, this dot private  method, cast race, like this, and cast race.   He's going to get this code right here.  This doesn't change anything, everything   still works. But now our update method here is  simpler and more code can go into it. And we can   read it more clearly. Now, to be able to detect  the road borders, we need to know where they are.   And at the moment, the sensor has no idea, we need  to go to main Jas. And the first pass to the car   update method, the road borders like this. Now I'm  going to go to car Jas and have the road borders   here, like this. And I'm going to take them  and pass them to the sensor update as well.   So now in the sensor js, the update method  receives them as well. And now we can use   them to detect with the sensor if the road  borders are close or not, I'm going to add here,   an array for the readings. So these readings  are going to be some values for each array,   telling if there is a border there or not.  And how far is now in this update method.   I'm going to say readings is equal to an  empty array, I initialize it here. And   then I will iterate through all the arrays  like this. And add to this readings array,   or reading. So we will get readings  using a new method that we need to define   that takes a array like this, and the borders  as parameters. And now we're gonna go down here   and write our get reading method with a array and  the given borders. So now what I'm going to do   is check to see where this array touches the  road borders. And now we have just two borders,   one on each side. So one array can only touch  both of them if the car goes off screen like this,   but it's good to consider multiple intersections  anyway, especially because later we'll have   traffic. And we'll handle that using the same  strategy as well. What we'll do is find all these   touches, and then keep the closest one to  the sensor. And that will be our reading   in the same way that the real sensor would work.  So let's see where this array touches any borders,   these touches is going to be an empty array. And  I'm going to go through all the borders one by   one, we just have to at the moment, but it's good  to write it like this. And we say that the touch   is equal to get intersection, this is going to be  a function that we will need to write it's going   to be a very useful utility function, you'll  see and the intersection will be between the   array of zero and the array of one. So this is  gonna be one segment, so far. And another segment   the I wrote border zero and I wrote border one  like this. Now if there is a touch, we will add   to our touches. So this get intersection  function may return know if the segments   don't intersect. So that case nothing gets added  to this touches array. Now, if we have absolutely   no touches with the given array, Arrays, then  that means that there is no reading here, we   don't encounter anything with this array. So I'm  going to say here return no like this. Otherwise.   And now I'm going to teach you a  little bit more modern JavaScript,   you'll see this get intersection doesn't  just return the intersection point,   but also an offset how far the  point is from this array of zero,   which is pretty much the center of the car. So we  do get with this get intersection, three things,   an x, a y, and this offset value that will be  quite useful. So I just want all the offsets from   all the touches here in one array. And we can  use modern JavaScript methods to get that.   Like this, the array map method basically  goes through all the elements from this array.   And for each element, it takes its offset.  Now this part here returns a new array.   In this case, it's called offsets. And that's it,  we don't have to write a lot of code to get this   result here. And I think that's great. Now,  we want to know from all of these offsets,   the minimum one, like if array touches many  different things, like many borders or cars will   be later when we add the traffic. So we want to  know the nearest one after the rate touches that   all the other ones don't exist, basically.  So we are going to get the minimum offset   using the math minimum method. This minimum method  here doesn't accept an array as an argument. But   it does work with many, many different values.  So this dot, dot dot operator is spreading   the array into many different individual  values. And finally, I'm going to return   the touch that has this minimum offset using  this find method here. So going through all   the touches, element by element, if the offset  of that touch is equal to this minimum offset,   it will return that touch. In this  way, this code is pretty complex   take a while to look over it. But because  we're using modern JavaScript methods, here,   the code is really short. So try to get used to  the syntax, because you will see it everywhere,   especially if you work with React. Now I'm  going to draw these readings somehow here   in the draw method, let, and is equal to the rays  and points pretty much. But if there is a reading,   I'm going to set and to the value of that  reading, remember the readings, what comes   from this get intersection function will be three  things, the x, the y and the offset. So if we say   this here, we essentially pass the x and y to  this and, and becomes a point with an X and Y   attributes. I'm going to now make this  yellow segment until end, right here.   Like so. And I still want to know  where this line would have continued,   I think it's nice to visualize that.  So I'm going to copy all of this.   And I'm going to just make it, let's say black.  And here I will draw from the tip of where the   end of the array could be to this end point. If  it's a reading or not, if not, then this is just   going to be a line that is so small, you can't  see it. Now, if I save all of this, and refresh,   it works for me, but it doesn't work for you. And  that's because I have here in the utility file a   secret function that I added without telling you.  Sorry, let me just indent this a little bit like   so so that you can actually see it. If you want to  implement this yourself by watching on the screen   right now. I will make a separate video for this  because I think the topic is very interesting,   and I have a nice way to teach it as well. But  it works. Look, when I'm moving my car like this,   the race are going to the borders. And immediately  when they are reaching the board, there's there,   they are turning black, like so. And only the  yellow part is really interesting. And it's   what we will use later when we define the neural  network. I'll show you how to implement collisions   next. That is when the car is approaching the side  of the road here. I wanted to get damaged somehow.   So there's a good news and bad news. Good news  is that I'm going to teach you how to detect   collisions using the segment intersection code  from previously. The bad news is that the way that   we draw the car here, by rotating the context, we  actually don't know where the corners of the car   are, like, what are their coordinates, and we're  going to need to figure those out first. So   in car js, I'm going to create here a new  method, and I will call this private method,   Create Polygon, this polygon will have a list  of points an array of points. So one point per   corner of the car. And great news is that you can  add more points, you can have different shapes.   And this method I'm going to teach you is going  to work. So if you look at this car right here,   let me refresh so that it points upwards. And then  we can use this distance right here as a radius,   like, it's pretty much the same distance no  matter which of the corners we are looking at.   And the other thing that we will need to figure  out is this angle, like what is this angle,   knowing the width and the height. So  this radius is actually very easy to get   using the hypoid method here. So this is the  hypotenuse of the triangle with width and height,   and I'm dividing it by two, because I just need  half of it. And the angle here is a little bit   more tricky, maybe. So the tangent of this angle  is actually the width divided by the height.   So we can use the arc tangent method,  this eight and two method from the math   library to give us the angle, knowing the width  and the height, like this. And I don't need to   divide this by two because that angle is the same  no matter how you look at it. Now with these,   I can add my first point here, that x is  going to be the center x of the Car minus   the sine of this car angle minus this  alpha value. So I'm combining here,   the alpha angle, and the car angle as well,  and then multiplying these by the radius.   And the same thing goes with y. But here I'm  using the cosine, like this. So this was the top   right point. And we need to do the next ones as  well. So here, let's just add alpha, like this.   Next point, I'm going to keep minus alpha there,  but add here, math, pi plus, or 180 degrees.   And the last one, I will copy this one  from here and change this alpha to a plus.   Like so. And now we just return the points.   And that's it. We want to update  this after we move the car like this.   So this car will have a polygon attribute that  will be generated in this way. And to draw the   car, we can now use this polygon instead. So  instead of this trick here where we translate   the Rotate and then just draw a rectangle here,  essentially losing the coordinate points, we   can remove all of this and just draw our polygon  points in order I'll show you, we do begin path,   move to the first point in the polygon, like this.   And now loop through all remaining points.   So notice that I'm starting here at one, because  I already moved to the first one previously.   And here I'm just going to line to the eighth  polygons, x and y, like so. And I'm going to film,   save the file, refresh the page. Here, nothing  happens. So everything still works. But   in a different way, in a better way, I'll  show you. If we go up here, for example,   and just change one of these points, let's change  this one by multiplying this radius by three,   then our car will look like that. It's kind of  kind of funny. So we couldn't do this previously.   And and now we can do crazy things like this,  like give complex shapes to our car. And we can,   of course, add more points if we want. But I'm  not going to do that it's your job to experiment.   What I will do is teach how to do the  intersection between this car polygon   and this line segment on the right, and  detect if the car is damaged or not. So   let's go up here and say this damaged is equal  to false, all cars are not damaged to begin with.   And then here, after we have our  polygon, I'm going to assess damage   a method that we're going to need to write with  the road borders. So now, here, let's define this   assess damage method, given some roads, borders,  like so and loop through all the borders.   And check if there is an intersection between  this polygon and the road border of i The   road border, then we return true.  If the code reaches here, we return   false. Now we need to implement this Polly's  intersect function here. And it will be a really   useful utility function that takes two polygons  here as parameters. Now, notice here that this   road borders of it is actually not  the polygon. It's a line segment,   but it will be general enough for it to work. So  let's go now to utils J S. And I'm going to define   our polies intersect method with poly one  and poly two, like so we look through all   of the points in poly one. And for each of them,  we check all the points in poly two. And we   are going to see if they touch or not using  our get intersection function from up here.   So we say here poly one of I and poly one of  i plus one modulo the length. So this may look   tricky, but all the things that I'm doing here  is I'm taking one point in the first polygon,   and then the next point in the first polygon. So  I'm making segments essentially from one point   after the other. But at the end, this will give  an error when we are reaching is equal to poly one   length minus one, because adding one to that then  it will go over the array. But if we use here,   the modulo operator like this, then that value  will become zero. And that's actually great   because the last point in the polygon needs  to connect to the first point in the polygon,   like point zero. So this code solves two things.  And I will continue and put the same thing   for poly two with the J this time. So essentially  I'm taking all the segments that make the first   polygon and comparing them against every segment  of the other polygon. And if there is a touch,   then I'm going to return true. Otherwise,  if all of those checks have returned No,   then I will return here. False. So our policies  don't intersect. Now to see if this works,   I'm going to go back to my car JS here. And  actually in the draw method, the first thing   that I will do is see if this is a damaged car,  I'm going to set the field style to gray color.   Otherwise, I will set the field style to one  black color, like this saving the refresh, and   it changes color. And it changes color immediately  when the car touches the border, even with this   complicated shape, because we are using each  segment forming this polygon and comparing it   with the border of the road. Now this method  is quite general. And it works for complicated   polygons as well. But it can become slow if you  have very many points. So then you would need   to do some optimization here, maybe look at the  bounding boxes, first star, or something like   that. And it's really reliable, as long as your  object doesn't move too quickly. For example,   like if our car would move so fast that it could  actually jump over a border or over another car in   traffic, then you will need a different collision  detection strategy for that. But we won't let that   happen. And if I zoom in here, a lot I should  mention this, because you may wonder why the car   doesn't detect a collision now.  And the reason for that is that,   well, that line, that border of the road,  it's a line, it's a mathematical line,   which actually has no thickness. And here we are  drawing it with relatively thick thickness. And   that's why it looks like it's intersecting even  though it's not, you could fix this if you want   by drawing the borders of the road with  actual, very thin, infinitely long rectangles,   put, I'm not gonna do something like that this  is great for our purpose, let me zoom back out.   Change this car to be a rectangle. Again, I don't  want to keep it in this crazy shape. And now in   the update method, I will not allow it to move  if it's damaged. So I'm going to say here, if not   damaged, then do all these things.   Sensor, maybe it's good to be like that. So the  sensor will still work even if the car is damaged.   Let's see if this has any consequences. If I  refresh, now, the car is a rectangle again.   And if I go to the side of the road, everything  stops. So now I can play with the arrow keys,   nothing happens my car is useless. We really  want to take any kind of impact seriously in   this so I am rendering the car useless at this  stage. Now the car works, it has sensors, it's   detecting the borders, and it's getting damaged on  impact. But this is quite lonely, don't you think?   It's time to add some traffic without it making  it self driving cars not much of a challenge.   You just press the up arrow key and perfect  driving. So let's add the traffic next. I'm gonna   go in main Jas. And up here I'm going to write  const traffic is equal to and this is going to be   an array of cars pretty much. I'm going to add the  nother car here that is on the same lane as our   card that we were used to, but I'm gonna put it in  front and it's gonna be our first obstacle that we   need to avoid. Now here, we need to update this  as well. So I'm going to go through all the cars   in our traffic and I'm going to tell each of them  to update and keep in mind the road borders or   you can also pass there An empty array instead  of the board, there's, if you want the traffic   to be invulnerable to everything. But I'm gonna  keep it there for now, let's see later. And   we need to draw these as well. So I'm going  to go here, another for loop going through   all the things in the traffic. Now we just have  one thing, but this is going to be a general code.   And it's going to draw each of them on the canvas  like now I save the file, refresh the page,   and there is another car in front of  us. And if we press the arrow keys,   something strange happens. We are not controlling  our car anymore, we are controlling the other car.   And that's because the key listeners are being  overwritten from the original car to the last car   in the traffic, we're going to need to specify  which car gets these controls and which not.   So I'm going to go up here and  tell this car to have here.   Keys, I'm going to say this one to be just  the dummy, maybe we will have it move slowly   or standstill or something like that. Dummy cars  will have some very simple behavior. And now we   are going to go to car js. And in the constructor  here, I'm going to also pass control type. So   either keys or dummy. And I'm going to pass this  to the controls as well. And in controls Jas.   This constructor will get type like so. And here,  we are going to switch according to the type.   And we are going to say that in  case it was keys, we are doing that   break. And in case this is a dumping, I'm going  to set forward to true and break. Now I save this   refresh a hint, the current front, the current  front moved, I actually can't catch it.   Because we have the same movement speed, I  mean, max speed. So it would be nice to go   here in the car constructor. And maybe specify  here, a value for this max speed. Let's have it   default to three, but allow us to change it from  the main file. So in main Jas here, I'm going   to set a value of two for the dummy, save this  refresh. And now I can actually catch that dummy.   So far, the sensors are not reading this  dummy car, and we're not even getting   damaged by it. We'll take care of that in  a sec. But first, this scene is becoming   a bit too crowded with all these lines. And  the dummy car doesn't really need a sensor.   So I'm going to disable this by going  to our car J S. And if control type   is not dummy, then we will equip this car with  the sensor. And later where we update the sensor.   We will check if this sensor exists.  And only then update it. And same goes   down below for the trolling. So if there is  a sensor, then we are going to draw it. And   now if I refresh that car in front doesn't  have any sensors doesn't draw any sensors.   It's just a dummy going at fixed max speed  there on the road. Let's interact with it.   I'm gonna go here in main Jas. And where we  update here our car, I'm also going to pass   the traffic and because I'm going  to write some general code here,   this is going to be needed to hear in traffic  update as well. But I'm just gonna pass nothing   here because if I do pass traffic here, then that  means that car in traffic is going to interact   with itself. So it's just going to get damaged  by itself. And I would need to write some code   to prevent that. I'm also thinking about later,  when we do some more complex simulations. And we   have a bunch of cars, I don't want to have a lot  of broken down cars on the road and blockades. So   I think that I don't want the traffic to get  damaged when it's touching other traffic or   us. So I'm leaving it empty. Here in case  of the traffic, I'm saving this file,   and then I'm going to our car. And in our  update method, here, I'm going to pass   traffic as well. And this is going to be needed  inside the assess damage. Here, we will assess   damage with the traffic as well. But also, in  the sensor update, the sensor will perceive   the traffic as well. Let's do this assess the  damage first, it's quite easy. I'm going to pass   traffic. And I'm just going to copy this code  and replace here road borders with traffic.   And here road borders with traffic of i dot  polygon. I think it's right, I save this   refresh. And now when I press up, I'm catching,  catching catching that car. And when we collide,   I'm damaged, it's not damaged. Because  our car it's not in its traffic   list. But feel free to play with the code then  make it like that if you wish. Now let's do   the sensors as well. So the sensor update here  gets the traffic. I'm gonna go now to sensor js   and pass the traffic here as well.  And also to this get reading here,   let me just write it a bit nicer.  So you can see this on screen.   Like so. And the get reading has now  a traffic to deal with as well. So   our touches, the things that the rays are  going to intersect may be road borders, but now   polygon segments from the traffic cars. Let's  do this. I'm gonna go here below. And I will say   I going through the traffic like this,  I will get a poorly. I'm doing this just   so that I don't repeat traffic Have I got  polygon everywhere. And now I'm going to go   through all of the points in that polygon and get  an intersection value using our utility function   from the array of zero and array of one so this  is the same as there. But here we are going to   take the polygon J point and J point plus one with  our module shrink. Now if there is a value here,   then we add it to our touches as well.  And that's it. Let's Save and test   okay, because the traffic cars are  black and my array turns black is   it touches the nearest segment of its  polygon. I don't see things very clearly.   Let me color the cars differently so that  our car is blue and the traffic is red.   I'm gonna go in main Jas. And here let's  draw this one as blue and the traffic   as red like this. And inside car Jas.  I'm going to go down to our troll method   here and say color and the non damaged  color is going to be color. We save this   refresh. And now we can actually see that the  array turning black like that and our sensors   are reading that there is dancing in front of it.  They are working from all different angles. Let   me try a trick I saw once in what was it fast and  furious, maybe it was much better in that movie.   How it went right through us. We now have a  complete simulation, a drivable car with sensors   that can see the road borders and other cars in  traffic. But so far we've been doing the driving,   and that's about to change. Next, I'll give you  a brief lesson in how our brains work. And then   I'll show you how to code something similar,  an artificial neural network, you'll learn the   components of this kind of network and how to  connect it to the car so it can move by itself.   Neural networks are computing systems inspired  by the biological neural networks in our brain.   These are some neurons, these branch  like structures received the signals.   When stimulated enough, a neuron will  fire a signal through its axon. So a   single neuron does something really simple, and  intelligence only comes when they work as a team.   You see, your brain has 86 billion neurons. You  also have quite many of them in your spinal cord,   then sensory organs like in your eyes and yours.  These sensors send signal to some neurons that   pass it to the brain. There the processing happens  like a chain reaction where some neurons fire   some don't eventually signals arriving to motor  neurons that pass them through your spinal cord   and make some muscles contract in very specific  ways. Hey, a lot happened in just a split second,   let me try to slow this down and  explain it to you. Pay attention.   sensors inside the year pick up  compression waves from the air and sends   signals to the brain which figures out the  direction based on different intensities.   signals then traveled to neck muscles tell them  to contract and turn the head in that direction.   The eye catches a glimpse of what's happening  and use signals travel to the brain. peripheral   vision is blurry. But good enough information  exists to detect some kind of object approaching   and new signals travel to facial muscles to  contract and protect the eyes from getting hurt.   Eyes are really important. At the same time,  the brain begins to kind of defense protocol by   sending signals throughout the body. Time passes  and the image becomes more clear. The brain does   pattern matching and recognizes the object as a  bowl. Contextual and historical information will   play an important role in what happens next. Let's  stick to the first one. The brain concludes there   is no threat and uses knowledge about physics it  learned during its lifetime to predict where the   object is headed. It then sends new signals to  the muscles to contract in slightly different   ways to catch the object instead of blocking it.  And the rest is history. One history where the   brain did the good thing and not much happens  afterwards. But sometimes this happens and the   brain learns it did something wrong and configures  itself. So the same thing doesn't happen again.   Hopefully, anyway, I'm feeling really good about  myself now that I know my brain can do something   like that in an instant. hope you do too. I work  cars neural network, we'll do something like that.   Neurons on the first layer will be connected  to the sensors, they will send signals forward   a few times, and the last layer will be  connected to the car controls to make it   actually do something. Spoiler alert, we'll be  working with relatively small networks here.   But that's okay, because we actually don't  need very large networks to solve this problem.   Now implementing all this in one shot is well,  scary. But it's easier if you break it into levels   like a building. Each level has a floor  a ceiling and connections in between.   The ceiling of one level is the floor of the  next man so on. Now, let's start to code one of   these levels. I'm going to go in index html  and include a new file here. Let's call it   network Jas and create the file here like this.   Inside the file, we begin to write our level  class. And a level has a layer of input neurons   and the layer of output neurons. Their numbers  doesn't necessarily match. So I'll specify these   parameters here like this to define The actual  neurons, we use simple arrays of values like this,   we need one for the inputs,  and one for the outputs.   And I'll also add one for the biases,  each output neuron has a bias,   a value above which it will fire. So I'm  defining these as an array, like this.   Now, when coding this, I'm actually going to  connect every input neuron to every output neuron.   That's not the case in our biological brains,  but these connections will have weights. So   a weight of zero means pretty much the same  thing. So let's have here, weights equals to   an empty array. And going through all of the  inputs, I'm going to prepare here, an empty array,   the size of the output count. So  for each input node, I'm gonna have   output count number of connections. And now what  we have here so far is actually only a shell for   the brain to function, these weights and biases  need to be set to some real values. So for that,   I'm actually going to simply randomize for now,  we're going to have a random brain to begin with.   And to randomize, I'm actually going to define a  static method here. This is different from what we   usually do, but we do it because I want  to serialize this object afterwards,   and the methods don't serialize. So here, given  a level, I'm going to go through its inputs   like this. And for each input, I'm going  to go through its outputs like this.   And for every input output pair, I'm going  to set the weight to a random value between   minus one and one. And to do that, I'm gonna  write here, math dot random, which gives us   a value between zero and one, multiply this by  two. So now we have a value between zero and two,   and subtract one. And now we have a value between  minus one and one. And actually biases are going   to be in the same range as well. And you may  wonder why negative values. And here's one reason   for it, think what should happen here, the car  sees something with the front sensor, so it should   turn to avoid collision. But which way, negative  weights connected to these sensors on the right   could send the message that don't turn to the  right. So the remaining option is to turn left,   both weights and biases can be between minus one  and one. And there is a nice mathematical reason   for this, which I will explain soon. Now, these  inputs, they will be the values that we get from   the car sensors. And what we need to do is compute  the outputs using these weights and biases that we   defined. Those are random for now. But in a smart  brain, they will have some kind of structure,   we compute the output values using a feed forward  algorithm. And it's actually quite simple.   Given some inputs, these given inputs,  and I'm passing here the level as well,   I'm going to go through all of the level inputs,  and I'm first going to just set them to these   given inputs, these will be the values that come  from the sensor. So we do that using a simple for   loop like this. And now to get the outputs  we are going to loop through every output   like this. And we are going to calculate some  kind of sum between the value of the inputs   and the weights, I'll show you. So this sum is  zero in the beginning. And now we are going to use   another variable j to loop through the inputs like  this. And the sum will actually add the product   between the JSON input and the weight between  the Chained input and the output like so. And   we repeat this with every input neuron. So,  in the end, what we will have to do is check   is this sum greater than the bias of this output  neuron and if so, we are going to set the output   neuron to one so we are essential Returning it on.  Otherwise, the output neuron is going to be set to   zero. It's as simple as that. And now I just want  to close this and return here, the outputs for   convenience. And I need to also close this level  class right here. Now this code will work. And   we'll leave it as such. But I'm going to tell you  a story. And it's a bit scary. So brace yourself.   You see, scientists like to write it by adding the  bias here and comparing with zero. Because biases   can go either way, any structure implemented  like this can be implemented this way as well.   And this, what we have now is  the hyperplane equation. But   don't be scared. You see, in a very, very  simple network, this is the line equation,   a very simple function. The one and  only wait here controls the slope,   and the bias controls the y intercept, we  have a function like this for each output,   these neurons will fire if the  value of the function is above zero.   And with weights and biases between minus one and  one, you can implement any situation. That's why   that rage. Now, when you have two sensors, you  have a plane in 3d space. Think about the plane   that goes out of water like this. If the value of  the two sensors is on dry land, then the neuron   will fire. When you add more sensors, you have  higher dimensions that are harder to visualize.   But the math still works. And you  can have as many sensors as you want.   I could go on with this story for hours and tell  you that scientists don't use binary values here,   but instead allow neurons to fire all the time  just at different amounts. I mean, it happens here   for these first ones, so why not for the other  ones as well. Only the last ones need to be binary   to give you a clear yes or no answer. But networks  are more powerful if these are left as such,   actually not exactly as such, because the values  here tend to go a bit out of control and a more   complex function is often used to bring them back  to scale. Now the story may turn into an actual   horror, if I start to tell you about what the  layers actually do. Moving from linearly separable   cases to non linearly separable ones, and fine,  fine, I stopped this now. But if you want to   experiment with things like that, you probably  want to try some kind of library, like TensorFlow,   and there are actually more of them out there.  Also, let me know if you're ready for more   advanced content like this, and maybe I'll make  it someday. Meanwhile, I recommend three blue one   brown video on neural networks, it focuses more  on the mathematics and uses things like vectors,   matrices, and other things that tend to scare  students off for some reason, I try to avoid these   here. But if you plan to master machine learning,  someday, you're gonna have to learn them. Sorry.   Now let's get back to completing our neural  network code. So far, we have just one level.   Let's go now up here in the beginning, and define  a neural network made out of many of these.   So I'm going to say here, class neural network,  like so. And the constructor is going to get an   array of neuron counts. So this is going  to be the number of neurons in each layer.   And I will define here, the levels, I'm going to  make my neural network out of an array of levels,   those we defined earlier. And for  each level, I'm going to specify   the input and output count like this. So I'm  adding here, a new level with the neuron counts   from the eyes index, and the neuron counts from  the i plus one index. That's it. Simple as that.   And here, we're going to need a feed forward  algorithm as well. And this is also going to be   really easy. So in the same way, given inputs  and the network, I'm going to get the outputs   by calling the feed forward method from the  level with the given inputs and the network's   first level like so. So this is now calling  the first level All to produce its outputs.   But then I'm going to loop through the remaining  levels. So notice that here, I'm starting at   i equals to one. So looping through the remaining  levels like this, I'm going to update this outputs   with the feed forward result. From the level, I  like this, let me close this, return the final   outputs. And we are done with the feed forward  method and with the neural network object.   So what we're doing here is essentially putting  in the output of the previous level, into the   new level as the input. And the final outputs will  tell us if the car should go forward, backward to   left or right. Now let's connect this network to  our car sensors. So I'm going to go to car here,   all the way up in the constructor. And where we're  saying that we defined sensors for our car, I'm   also going to say this dot grain is equal to new  neural network. And here we have to specify our   array of neuron counts the size of the layers.  So in the first layer, we are going to have   this dot sensor that array count. And here you  can have as many layers as you want, but I'm just   going to add two of them. one hidden layer, and  the output layer, which will have four neurons,   one for forward, one for backward, one for left,  and one for right. Let's close this, like so.   And now, after we update the sensor here,  I'm going to first take out the offsets from   the sensor readings. Remember, our readings  had three things an x of y, and the offset   of where the reading was. And from each sensor  reading, let's call it S, I'm going to check if it   is no, then I'm just going to return zero, there  is no reading here, the sensor goes as far as   possible and doesn't see anything. Otherwise,  I'm going to return here, one minus the sensor   offset. I'm doing this because I want our neurons  to receive low values if the object is far away,   and higher values close to  one if the object is close,   kind of like this flashlight. When we pointed  at the wall, we see the light coming back at us.   And if we get closer, the light that bounces back  is stronger. That's how sensors work in practice.   Now to see what the neural network has to say,  we just say outputs is equal to a neural network,   feed forward these offsets with this brain. And  I'm going to log here these outputs to test for   now, if I save the file, and refresh the page, I'm  gonna get there at the bottom in the console, some   array of values for values, one for forward, one  for left, one for right and one for backwards. So   at the moment, the car should actually go forward,  left and right at the same time. But it can't do   that because the brain is not yet connected to  the controls. It's kind of like when I had the   knee surgery a while back and they paralyzed me  from the waist down. While the anesthetic was   wearing off, I really tried moving my feet brain  was working normally, but motor neurons were   just not sending the signals properly. To make  the car do its own decisions, we are going to   go here in main js. And instead of using the  keys to control the car, let's write here, a   AI for artificial intelligence. I'm going to save  this file and then car js. Up in the constructor.   I'm going to define here an attribute called  use brain that is going to be equal to control   type double equals AI. So if our control  type is AI, it means that the brain that   the car actually has already is going  to be in use. So down here in update   if This brain is in use, we are going to say the  controls forward, this is going to be equal to   output six zero controls left, this  is going to be equal to outputs of one   controls, right, this is going to be called  two outputs of two and controls. Reverse,   I think it was, is equal to outputs of  three, let me just check this real quick.   Yes, it's reverse, saving this file, refresh  the page. And nothing happens. But if you look   in the output, you'll see that this array has  four zeros in it. So nothing is on forward,   reverse left or right, nothing is pressed. Let's  try to refresh again, remember, these networks   are random so we can get anything out of this.  Okay, this was interesting. So we have their   right and reverse turned on. So this was a card  that just went backwards and to the right, okay,   here, we have a car going forwards,  left, and then reverse. So the forward   then reverse actually cancel each other  out, and the car is standing still. Okay.   Now, this is really interesting, we have a  car that goes forward. So it went forward in   the beginning. But look what happens. Now, when  those two sensors are touching the car in front,   the network somehow triggers the brake. It's  amazing, this was randomly generated, and we   were lucky to get the really nice behavior out  of this. So our car is supplying the brake, every   time it gets really close to the other car, and  just out of luck, it's not colliding with it. So   it's doing this kind of stoking motion there. Now,  this debugging here is not really very useful,   printing out the outputs like this. And actually  debugging things like this is really hard,   you could go here and say, for example, car dot  brain, and look at it and see that yes, it does   have these two levels that we defined previously.  And the first level has some inputs, some biases.   So we have the inputs, here, you can see 000, for  the middle ones, and some values for the first   and the last one, which is great, we visually  see that one as well. And the outputs should be   for the first level here. One, one, and all the  other ones are zero. But then the second level   is going to get those inputs, the 110000. And this  network with these biases, random values between   minus one and one. And these weights, also many,  many random values between minus one and one,   produce the result that you see here. So  going forward, and reverse and left and right,   everything just cancels each other out, then  our car with all this brain does nothing.   So you can see how debugging like this is  very, very difficult. And we don't really   get the full picture unless we really start to  analyze all these numbers here. And that's why   it's gonna be really great. When we visualize  something here, I mean, make something that   at a glance, we can see this entire network in  action. So I'm gonna go to index html here. And   I'm actually going to refactor things a bit. This,  my canvas from the beginning, is gonna be called   car canvas like this. And we're gonna use another  canvas on the right to display the network.   So we're gonna visualize a neural network in  this one. Now, let me save this and go to our CSS   file. And my canvas will be renamed to  car canvas. And I'm going to copy this   as network canvas and to distinguish between  them. Let's make this background black.   Like this, now, in main Jas, I'm going to  go here at the top and say that this all we   did so far is on the car canvas. And I'm actually  going to refactor everywhere it says canvas here,   by pressing right click Rename symbol and saying  here, car canvas like this, and this CT x is going   to be renamed to car seat dx, like this. And I'm  gonna copy this part right here for the network   Canvas. So here we have network, Canvas, and  network canvas. And here also network canvas.   And I think this one can be a little bit wider.  Let's see if we can fit 300 pixels wide Canvas   next to our car Canvas from previously,  then here, the car context is going to need   network context next to it. So network  context coming from our network canvas,   right. And one more thing we need to do here,  when we make our car Canvas have the same size as   the screen vertically, I'm going to do the same  thing for our network accounts. Save the file,   refresh the page, and we have our car on the  left doing something, whatever it's doing,   and every time we refresh, it's probably gonna do  something different. Probably not something smart.   And on the right, we have a blank blank canvas  that also stretches quite nicely with the size   of the screen. And what will be really great is if  you can go here, after drawing all the car related   stuff, and saying visualizer draw me a network  on the network context, and put there the car   brain like this. And now I'm actually going to add  some code here that does the visualization for us.   I'm not teaching it here, because I think we  would be sidetracking too much. But it's really   well described on my channel and their source  code in the description. So saving everything   refreshed the page, and we have network  that decides our car should go in reverse.   quite boring, let's try refreshing again.   This network says it should go forward, left  and then reverse. So basically, it stands still   forward right and reverse. Right then  reverse. That was kind of interesting.   One more thing is that this visualization  also supports animation. So we could animate   this visualizer if you want by going  here and specifying a time argument,   this value comes from the request animation  frame method here. And here we can say network,   C dx dot line dash offset is equal to  time. And when we do this, all by, okay,   this is a bit too fast. Let's slow down this  a bit by dividing here by 50. And actually,   this animation should go the other way around. So  I'm going to specify here minus time divided by   50. And now it's a visual reminder that this  is implementing the feed forward algorithm.   This thing here, one by one, these randomly  generated networks and expecting some miracle is   not very convenient. So let's write some code  to parallelize this and have many cars running   simultaneously, like in different parallel  universes. I'm going to define here a function   called Generate cars that accepts and as the  argument and I'm going to have an empty array   of cars at first. And then for i from one to N,  I'm going to push a new car into this array and   the car is going to be centered in the middle lane  at 100 Why with 30, width and 50 height like so,   and they are all going to be AI cars. And  here I just return these cars like so. And up   here where we have car defined we are actually  going to define cars instead equal to generate   cars have n like this and our n is equal to  100. So we are going to have 100 cars going   in parallel, and hopefully one of them is going to  do something right, we need to update these cars   here. So where we have here car dot update, we  are going to write a loop and say, let i is equal   to zero, i is less than cars dot length, i plus  plus. And then we have here cars of hi update,   like so. And we are going to do the same  for the drawing down here, drawing them   as blue like this. But we still have two  individual car objects here from previously.   And I only need one car here. So let's  just replace it with the first car in the   array for now. Otherwise, this code will not  work. So this is for translating the canvas on   one car from the 100. And this is just printing  the brain of this one car somewhere on the right,   save the file, refresh the page, and then how its  total mesh. One thing we can do to make this nicer   is actually drawed them semi transparent. So I'm  going to go here and say car city x dot global   alpha is equal to 0.2. And after I'm done drawing  these cars, I'm going to set global Alpha back to   one. So it doesn't affect what I'm going to  be drawing afterwards or on the next frame.   So saving this and refreshing, it's a little bit  better, but still quite much happening there.   I think that I want to emphasize one  car, like for example, the zeroeth car,   this one that we are using everywhere, pretty  much by drawing it again with the maximum opacity.   But also I want this one to be the only car  for which we draw the sensors. So I'm going to   modify this draw method of the car next,  and say here, a third parameter for draw   sensor. This is by default set to false. And  here, if this sensor exists, and draw sensor,   only then we are going to draw its sensor.  And now it's a little bit clearer, not so many   yellow lines there. And you can see something  interesting already, that this car right here,   car zero is not the most interesting one, the most  interesting one went somewhere up there, and it   was chasing the other red car. So back to main js,  here, our cars have zero choices not really great,   we want to focus on the best car, the one that  goes upwards, the most or the one with the minimum   y value. And I'm going to define this best car  here and say, best car is equal to find the car   whose y value is equal to  the minimum value, okay? Of   all the Y values of the cars. So this may seem a  little bit scary. So what is happening here, cars   dot map, see going to see dot y this means that we  are creating a new array with only the y values of   the cars. That's it. And here we are spreading  this array because the math main method here   doesn't work with arrays. It works with many,  many different values no matter how many you   want to pass it, but not with actual arrays.  And that's why we need to spread it here.   And we just find the car whose y value is the  minimum value of all the y values. The code is   not really complicated. But if you're not used  to this modern syntax, then this can be a little   bit daunting at first. I added here because  you will see it if you work with JavaScript.   So now with this best car, I'm going to copy  it everywhere. We were using cars of zero   previously so we translate the canvas to the  best cars. Why like this. And then here we are   drawing the best car without transparency so  that we clearly see it. And with the sensors,   we are also drawing the brain of this best  car. And that's it, I'm going to save this   and refresh. And now our canvas is always centered  on the car that goes upwards, the most, in this   case, these stalking cars that are behind this  red one. All right, let's try to refresh again.   And again, I'm waiting for a  car that passes this red car,   but then continues to go in a straight  line somehow. So just by trial and error,   I think that we're going to be able to  get to something like that, let's see.   Okay, we got something, it's fidgeting quite  a lot, but definitely better than all other   cars we had so far, it passed the car in the  traffic, and it's just going forward forever,   pretty much. But now the problem is that when I  leave the browser, this car is going to be gone.   And all my experimenting was for nothing.  So let's write some code to save this car.   I'm going to use local storage for  this. So I'm going to say, local storage   set item, the best brain that we have. So far,  we're going to store it in this best brain   attribute and local storage. And the value is  going to be a JSON string coming from the best   cars brain. So I'm essentially serializing that  brain into local storage. And come to think of it   we might need to destroy the saved brain as well.  So I'm going to discard, maybe it's a better word,   the value from local storage with this other  function, I'm sure is going to be needed   sooner or later. Now this best car is actually not  accessible here. So let me just update its value   here. But define it here as a global variable.  Like this, I'm using lit because it's changing.   And I'm gonna set it to be the first car in the  beginning, but it's gonna update on every frame.   Now, if we have in local storage  of brain or best brain stored,   I'm going to set the brain of this best  car to the value and I'm using JSON parse   because I am parsing the JSON string we saved  previously, local storage only works with strings   like this. Now, in index html, I'm going to put  these buttons vertically between the two canvases.   So here, I'm going to use a div to define river  vertical buttons with ID vertical buttons.   And I'm going to say here, the first  button is going to have an unclick of safe   like this and our second button is going  to have an on click of this card, like so.   And here I'm actually going to use emojis  for these boughten contents like this with   the save icon and trash like you can find  emojis like this just by searching online.   So I'm gonna save this file and go to  the CSS next, and remove this text align   from the body because we're going to use flex  display instead. So I'm going to remove this   and say, display, flex, justify content and align  items to center like this. And now our vertical   buttons are going to go here with display flex and  flex direction column So this is by default row.   And making it column means that our buttons will  go below each other. And here we define our button   next. So I like to remove the border and give it  a round shape. So a radius there. And a padding,   this is some value that I found goes nicely  with the emojis that we use, and the margin   of two pixels. And the cursor is set to pointer  so that our arrow icon changes into a hand cursor   when the mouse is over it. And speaking of  hovering with the mouse, let's set hover   for the button so that it gets blue background  like this. So save the file, refresh the page.   And looks like we have another shaky car over  here. But we are not going to lose it this   time. Because we can press the save button. And  this means that now inside of our local storage,   we have this cars brain. So now when I'm going  to refresh the page, what that means is that   here inside of main js, where we are loading the  value from local storage, we still get the car   from previously. Now what we are doing here,  could we actually fully automated so that the   computer tries again and again, and always keeps  the best. But let's think about what the goal is.   I mean, what will a good network be able to do?  Let's look at the definition of the best car here.   We're just using the y coordinate. But you can  use other functions here as well. These are   called fitness functions. For example, you  could measure the travel distance instead.   Doing that may result in cars that go backwards  as an easy way to avoid the obstacles. Or just   go around in circles forever, going infinitely  far, but also going nowhere at the same time.   So need to be careful when choosing a fitness  function. I'm using the y value here. But if the   road would be turning, it wouldn't work anymore.  So think about these and play around with the code   and try to think about other stuff as well. Like  could you come up with a fitness function that   keeps rewarding the car for going upwards,  but penalizes for going too much sideways,   or even better penalizes if you're  not in the center of the lane.   These are all homework ideas for you. But  now I think we're ready for more traffic.   Let's go here in our traffic array, put a comma at  the end and add two more cars. One is going to be   on lane zero, and minus say 300 and the other  one at the same vertical level. But lane   two, I'm going to save this refresh.  And now let's see what happens   almost there. But that looks like even our  shaky car didn't make it. So let's try again.   It looks like there are just not enough cars  passing that first car in traffic. What we would   like to have is more cars like this shaky car.  But not exactly like it so that one of them may be   is gonna stand the chance and pass the  second and third car in the traffic. So   let's go now to network Jas. And I will teach  you how to mutate a network. And it might   sound fancy, but it's really really easy. I'll  show you. We right here a method called mutate,   which takes a network as a parameter and an  amount. Let's default this to one or 100%.   This will just randomize everything what we had  previously. But if you set this value to like 10%,   then you're gonna get the network that is  close to the original one that we pass it here.   So how does this work? Well, we are going to go  through all the levels of the network using a   for each loop like this. And for each level, I'm  going to use this arrow function notation here.   I'm going to iterate through all the biases and  then through all the weights later, but first   with the biases and I'm going to say that the AI  bias is going to be equal to learn, we're going   to use linear interpolation again. And I will  interpolate between the current value of the bias,   whatever that is, and a random value between minus  one and one, as we did in the randomizing, but now   we're using loop to go from the current value of  the bias to words, whatever that random value is,   depending on this amount right here. As  simple as that. And I'm just going to repeat   the same thing for all the weights. So I  just go through all the IJ weights like this.   And say that those weights, that  weight of ing scoring to be equal to   linear interpolation between the current value of  the weight and a value between minus one and one   random value. And again, depending on this  amount, so if this amount is going to be   let me see, did I close this properly? Nope. So if  this amount is going to be 100%, then we just get   this part right here. And this mutate is pretty  much our randomized method that we had previously   here for a level. But now it works for the entire  network. So if the amount is zero, then our   biases, and our weights just stayed the same. But  if this value is somewhere in between, then it's   going to move away from these biases, depending  on this amount. So let me save this file now.   And go back to main js, where we are reading the  brain from the local storage here. And actually,   we are going to loop through all the cars and say,  let i is equal to zero, less than cars dot length,   i plus plus. So for each car here, cars  of high hits brain, it's going to become   equal to that from the local storage. So this  as such is going to be really, really boring,   right? Because it means that if we refresh now, we  just see 100 cars that are overlapping each other,   and they're, that are acting exactly the same.   But I'm going to put here a condition and say  that if AI is not zero, so the brain that we have   in local storage will be kept for the case when  I zero and that is our best car initialization   there. But for all the other ones, I'm going  to mutate and say neural network, dot mutate   the car, have I brain by an amount, let's  say 0.1. And now let's see what happens.   You can see many cars this time, but they are  all following our shaky car quite closely.   This one, none of them was able to go beyond  that second car in traffic. Let's try again.   Nope, it looks like this 0.1 might be too low.  Basically, our new networks are too similar to the   one that we already have in memory. So let's try  0.2. Now our cars look a little bit more different   than before, but still quite similar to our shaky  car. And look at that we have a new best car.   Maybe. I hope it doesn't hit the border  now. Yes, it figured out it has to turn.   That's great. So I'm going to save this new car  right now. And when I'm going to refresh, now,   our new car the more improved car which  wasn't even shaking is stored in memory   and it's going to mutate and try to become even  better if possible. But our scenario now with   three cars is not a match anymore, so we can try  even harder one. Let's go here and copy this.   Maybe The four more times. And here let's have  two cars at minus 500. And the last at minus   700. And we are going to have here maybe on  lane zero and Lane one, and then on lane one   and lane two. So I'm just thinking how to  make a complicated scenario that involves   all kinds of twists and turns. So let's save  this and refresh. And now let's see what happens   okay, I'm gonna save this I did it before  this other boring car over took it.   So that's something that you may want  to pay attention to. Let's refresh   nothing I think we want the lower  value for the mutation here.   So that more cars are going to be like that one  that almost wented past these other two cars.   You can see quite many of them here  now. Still nothing. Let's try again   okay, this is interesting. I would  say this is a new winner now.   It got to this stage and now it's going  in line with the other cars. Let's save   it. It's taking too long. Let me try with 1000  cars. I think this should work on my computer   if your computer is too slow, then just  stick with 100 cars and repeat more.   Ah, almost there. You   Yes, yes, we did it. We did it.  Oh, no, no, no, no, no, no, no.   I should have saved that one. I think it could  have mutated into something good eventually.   Hmm. Let me save this. It's clearly better.   Come on. I'm hopeful that this time  we're going to make it. Let's see.   Okay, two cars there now. Will one  of them stop before hit? Yes. Yes,   that car stopped just before hitting the  sides there. Let me save this. Try again.   And now we have quite many of  them that are quite similar.   Okay, let's keep just one car here and see it in  action without any other things disturbing it.   Okay, that was quite, quite close there.   Oh, yes. Somehow I thought it's gonna get damaged  even though I know that it's the best car from   previously so it won't get damaged. There are many  more sophisticated genetic algorithms out there.   For example, some algorithms use crossover. So  they take two networks and mush them together   somehow. The hope is that maybe one car knows how  to turn left really well and another one knows how   to turn right. So combining these networks  could give you a new one that can do both.   Thank you can implement this. If you got this  far. I think You can try it out and let me know   how it went. We are now actually done, I  won't be teaching you any more algorithms,   you have many things you can play around with.  And I'm quite happy with the car we have right now   it's making its own decisions, and it's avoiding  all other cars. It couldn't be better like if it   would recognize the lanes, but I'll let you worry  about that. Meanwhile, I'm going to relax and show   you how to draw a car in PowerPoint. Since you've  got this far, all I can say is congratulations.   Hope you took things seriously. And by now  you've learned how to simulate driving mechanics   detect collisions and create artificial  sensors. You also know about neural networks,   what they can do and how to optimize  them using a simple genetic algorithm.   But we just scratched the surface here, and  I haven't really taught you why the neural   network works. I mean, sure, we built one.  And because it's so complex, you can assume   some smart behavior is possible. But how does it  really work? We have such a great system now that   it's a shame to put it to waste. So I'm thinking  about making a new course where we start off with   a very simple network and gradually go bigger  and bigger and see what each of them can do.   We could also try new things like  teaching the car to stop before impact,   how to respect the lanes, maybe even how  to park and other cool stuff like that.   What do you think? Would you like a course  like that to practice even more JavaScript   and become a master of making diagrams that  show what's inside these so called black boxes.   And if you want something else right now, I do  have a lot of content on YouTube. This course   teaches how to build location based applications.  In this one, we make an augmented reality piano.   And here we use the camera to make a new kind of  puzzle game. I have many small projects as well,   but it's really hard to keep track. Maybe they're  better organized on my website. I don't know.   By the way, on the website, you can find a more  enhanced version of the self driving car. Check   it out if curious. Anyway, thanks for watching.  Please share this course with anyone you think is   interested. And since you got this far, you're  probably subscribed already. So see you guys
Info
Channel: freeCodeCamp.org
Views: 1,874,162
Rating: undefined out of 5
Keywords:
Id: Rs_rAxEsAvI
Channel Id: undefined
Length: 152min 40sec (9160 seconds)
Published: Thu May 12 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.