 Can you hear me okay? Okay. So what does it take to simulate orbits? Before we can actually do that, we're going to need a couple of things. So the first thing that we're going to need is a complete model of space. And after that, we're going to need a dynamic rule to update the state of the bodies that are in our space. And those two things together should be sufficient for simulating an orbit, or at least getting something that kind of looks orbit-y. So the first complete model of space ever compiled was put together by Euclid over 2,000 years ago, and it's still good today. It's good enough to get the Apollo mission to the moon, so we're going to study that. And it consists of five axioms and a collection of definitions, but I'm just going to cover the axioms here. So the first axiom says that between any two points, A and B, a line segment L can be drawn. And axiom 2 states that, given any line segment, you can extend that line segment indefinitely in a new and just get a larger line segment that contains the original one. The third is that a circle can be drawn at any point with any radius. The fourth is that all right angles are congruent, which is like an equivalence relation. So given any two right angles you can always line them up in this way. And finally, this one is the point of divergence from more modern theories of space. It's sometimes called the parallel postulate. It states that given any line at a point not on that line, there's exactly one other line that runs through it that doesn't intersect the original line. And that is actually, that's what we're going to take as the definition of parallel. And that's a very special property and we'll be using it later. And so using these almost trivial collection of five axioms, we can actually derive some pretty useful stuff. And the thing that we'll be using here you probably recognize from high school, this is just a Pythagorean theorem. The relevance for the problem of simulating planets or simulating orbits is mainly the way to calculate distance. So you can imagine we have a body here like the sun, a body here like the earth. And we have some coordinate system that we're going to use to get these numbers A and B. And then using this formula here we can figure out the distance between them. And that will be useful for figuring out the force between them. So we're going to be using vectors. And vectors are just directed line segments. And they also have this ability to be scaled by a real number. So we can take some vector V and then we can scale it just by multiplying by a real number. And you can see the connection between the first and two axioms right away. And for some terminology, we're just going to call that the arrowhead part. We're going to call that the head of the vector. And then the other end is the tail. So you can kind of think of vectors representing a displacement from the tail to the head. So vectors are really useful because they can be added together. And the operation, we're going to start by defining it geometrically. So given any two vectors where the tail of the vector is the same, we can add these two vectors together. And the way that we add them is we pick one of the vectors and go from the tail up to its head. And then travel along another vector that's parallel to the other vector. And if you see it geometrically, if you go along the other vector and then travel parallel to this vector, you get the same point. So that's another way of saying that it's commutative operation. So V plus Y is equal to, or V plus W is W plus V. And this will come up later when we try to work with forces because we're going to be adding these things together in order to get the total force acting on the object. And vectors aren't really that useful when you just consider them geometrically. What we really want is to be able to put calculations on them and ultimately put it in a computer. So a computer doesn't really work in geometry. It works in numbers and arrays and all those nice things. So the way that we go from getting a, this geometric arrow right here to a something that we can compute with is by choosing a coordinate system. So we can pick any three axes arbitrarily. We just have to require that the axes are perpendicular. So we just take these three lines that are all mutually perpendicular. And once we choose that and we choose a unit, then we can count along each of these three axes and write down the number of units that this vector goes out in this direction and the number of units that goes out in this direction and then this direction. And this way we have a triple of numbers. Or in two-dimensional space we'd have a pair. So that's the connection between all this geometry and the code that'll come up. And a few more things about vectors that will really come in handy. And it's really just rooted all in that Euclidean geometry that we did earlier. When we take these vectors here, if we define this product on the array representation or that triple of number representation of vectors, this thing that called the dot product is just you take the x component, multiply those numbers together. You take the y component, you multiply those together. And then you take the z component and multiply those together and sum it all up. This operation turns out to tell you something about the length of the two vectors and the angle between them. So if we take a simple case of this where you just take a vector and then dot it with itself, notice that that would be v1 squared plus v2 squared plus v3 squared, which once you see that you can kind of see how that's related to the length because that's like the a squared plus b squared in that you put in the Pythagorean theorem that we saw earlier. So if we want to find out the length of the vector, all we have to do is dot it with itself and then square root it. And that's so we can represent the positions by vectors, the positions of the bodies that we're trying to simulate. And if we want to find the distance between them, we just take the difference. So the way we'd implement this using all this stuff that we've defined up until now is we'd multiply w by the scalar minus 1 and then add them together and that'll give you a vector that goes from this point to that point or from that point to this point depending on whether it's v minus w or w minus v. And then if you take that, this hypotenuse vector between the two points, if you just dot that with itself, then that'll give you the distance between those two points. So that's what we'll use in the simulation. So now that we have kind of the first abstraction that we'll be working with, we can write some code. So we'll just, we'll have a wrapper class called vector. It'll have an array of components. And when we initialize, that's really all there is to it. Next, this is the more interesting part. We'll be implementing the algebra on it. So we want the addition and the scalar multiplication operation. So when we add vectors together, it turns out that parallelogram law that we saw, we can implement that just by, once we have the vector in component form, we can just add the x components together and the y components together and the z components together. So we can do this using the awesome zip method. And what that would do is zip, if you're not familiar, we'll just take two arrays that are the same length, and it'll produce a new array where each element is pairs. So like if you had, say, abc dot r zipped with x, y, z, the result would be a comma x. And then the second element would be b comma y. And then the third element would be c comma z. And then summing those together. That'll give you a single new vector, which is just a representation of the sum. And scaling multiplication is easy. We just multiply the scalar that we pass in by the component numbers themselves. And then on top of that, we also want to check whether two vectors are equal. And most importantly, we want to be able to dot vectors. So we again zip them together and then multiply the components and then just sum them up. So that'll give us a way, given a vector in another vector, we can pass it in, get the dot product, and then do some science with that. So now we have a model of space, but next we have to go on to the dynamic rule. This is where it gets a little bit more complicated but also more interesting. And we can represent bodies in space. We can figure out the distances and represent the state of a system at a moment in time. But what we'd really like to be able to do is play that forward in time and actually see how things would play out. So we'll have to talk a little bit about velocity and acceleration. So you can think about the thing that we want to, given a body, we want to simulate a path. So that you can think about as a sequence of vectors. And for each vector, at each moment in time, we can kind of organize that all together with this function x of t. So that x right here, this little arrow over the top means it's a vector. And that's the position at time t. So given any function right here that tells you the position of a body at a certain point in time, we can easily calculate the velocity. And if you haven't taken calculus, this is basically just saying the displacement in x divided by the displacement in time. So you can think about it as if you took some small amount of time in the future, you'd get a small displacement that would represent its movement. You take that and then scale it by one over the time. And that would give you the velocity vector. So there's a similar relation between acceleration and velocity. And using this, we'll be able to relate what I guess all await. So this relation just says that the acceleration is the rate of change of velocity. Velocity is the rate of change of position. And if we don't have any acceleration at all, it actually turns out to be really simple. So Newton's very first law gives us a complete specification for that position vector or that position function. Because if there are no forces acting on a body, it just travels in a straight line. So if we imagine a state at one moment in time, we have some initial position. We have some initial velocity. And all we have to do is have it trace out a line along that velocity vector because nothing's going to change it. So this just traces out a straight line in space. And that's another way to understand Newton's first law. Now Newton's second law is the familiar f equals ma. But I wrote this form a little bit more kind of decompose the f because when you see f equals ma, that's easy to remember. But the problem is that you can't really do that much with it until you consider each of the individual forces. Unless you just happen to know what the force is, just because you're lucky, you can't really do much with it. So this is where the sum operation is kind of indispensable. We'll want to be able to calculate all of the forces that we can imagine. And the way to imagine this is we're trying to figure the force on the ife object. So you have some n objects, or n bodies that you want to simulate. And for each one you want to figure out the total force on it. So if I is ranging over from one to n, i is going to be this number here is fixed for the sum and then j represents that ranges over all the other bodies that are not i. So you're literally taking the force between every single pair of bodies in the universe that you're simulating. And the way to calculate each of these individually is using Newton's law of universal gravitation, which apocryphally involved an apple. And it ultimately doesn't really matter. It's just a we can just kind of take it and run with it. But it is kind of worth trying to analyze why it has this form. I think you can ignore the gravitational constant. In my code I actually just set it to one. And it turns out that there's a lot of research papers that do that too. So physicists do this all the time. So we can kind of ignore this term. This right here, you can see just to make sure the types work out, I guess, is that this is going to be a vector. This is the force from the body at position j on the body at position i. And down here what you have is this little r vector with a hat. That just means that it's a vector with unit length. So this thing has length one. So when you basically this is the scalar that you multiply by your vector. So it makes sense that the force would go from this object or from this body towards that body because that's what we're trying to figure out. But this distance, so this r i j, these vertical bars if you haven't seen before, they just mean the length of the vector. So this vector from position j to position i, that would be r i j. That vector right there, the length of it is what we're dividing by the length squared. And the reason it's squared actually has to do with three dimensional geometry. So if you think about this as the center of a sphere, and then this, just imagine the length of that right there's r, then if you try to take all of the points that were distance r away from point i, you get a sphere. In two dimensions you get a circle and that whole sphere you can kind of think about is there's some amount of potential energy that is sort of spread out along the surface of that sphere. And as the sphere expands that same amount of energy decreases because you essentially have, by the conservation of energy you have a, you know that as you get a larger and larger surface area, you're going to get a smaller amount of energy. And the surface area scales like the square of that radius. So in one, or in two dimensions, a circle scales like the radius itself. It's like one over r. So, or the circle two pi r would give you the circumference. And as you expand since it's expanding proportional to r, the total amount that's spread out over that circle decreases proportional to one over r. So in three dimensions it would decrease proportional to one over r squared. So this number really here has to, this reflects the fact that we're measuring these things in a three dimensional space. And this is also something that Newton figured out just by looking at a whole bunch of astronomical observations and kind of working, using a little geometry and then turns out this works out really well. And there's a strong geometrical reason for this. So more code. So we want to represent bodies and they have the relevant data is the mass, the position and the velocity. So this initializes right here this is where you plug in the initial conditions. And then we'll update this state as time progresses. And just to note about bodies, the Newton's laws don't care about radius or shapes. It doesn't care. All that matters is the total mass and the center of mass. So a way to think about that is if you were to take the sun and just collapse it down into a black hole, just somehow, without changing its mass, without changing its center of mass, all of the Earth's orbits and Mars orbits and everything would travel around as if nothing had changed other than light. So in our simulation we don't actually need some notion of the shape of the body. We can imagine it's equivalent to a bunch of little black holes where all of the mass is collapsed to a single point and the motion, the path through space is going to be the same. And it doesn't even have to be a sphere. It could be a hot dog. Just as long as if you were to take this hot dog and then squish it down into a sphere and then center of mass of the hot dog, it would travel along the same path as that meatball. So this is where we actually implement Newton's law of universal gravitation. And the way that we'll do it here is we'll have something that'll take a body, so say it's body I and we'll pass in body J and we want to figure out the force from the body that we passed in on self. So the first thing we want to do is take that remember the U and V diagram. This right here, we're just calculating that vector from V to U. Here we're calculating the norm, which is like the length of the vector, so that'll be the R. Our hat is that little length one vector from body J to body I. And then finally we'll just plug it in the formula. So we take the unit vector and then this big scalar right here and that right there is the force component from body on self. Next we move on to the universe, which a wise man once said is very, very big. I can't emphasize this enough, it's really, really, really big. It's difficult to even imagine. We'll represent the universe in Ruby and it's going to just have some number of dimensions and bodies. And really we want the number of dimensions because we don't add a three dimensional vector to a two dimensional vector because that's not defined. And the bodies themselves we're going to kind of identify the time within the computer with the time in the simulation. So one second in computer time represents one second in the simulator time. So we'll just be updating all of the bodies states in place. So all the bodies will just be these objects and their internal states going to be updated by the universe. So the body doesn't really know about all the different bodies in the universe. The universe tells each body about the other bodies. And it'll be useful since we're taking all the, we're going to calculate each unique pair of bodies in the universe and work out the force for each one. And we'll only be considering different bodies. So this iterator will be useful. So for each of these pairs we'll be calculating the force. And the first thing we'll do is initialize a whole bunch of zero vectors. And each of those n zero vectors are going to be the force on the i-th object. Actually let's go back. Let's just kind of like break this down a little bit. So for each pair we want to make sure that we sum up the force from body j on body i. Just add them all up. That'll give you the left side of the f equals ma equation. And this right here is where we'll use those forces to update the position. But we can't just do that directly. We'll have to go kind of from force to acceleration. So it's f equals ma. That means that a is equal to f over m. So now that we have this acceleration that's just the force divided by the mass. We also want to figure out the velocity. So the velocity right here, since the velocity is the rate of change of the acceleration, the other way around, acceleration is the rate of change of velocity. That means that acceleration is in meters per second squared. So in order to make the units work out we want to multiply by some times. We'll have meters per second. That'll give you a velocity. And position, since the velocity is the rate of change of position, we'll do the same thing where we have meters per second but we want a meter, something in meter units. So multiply again by the time interval dt. And then that will give you the... We're going to be adding it so that'll be the displacement in position after dt seconds. And in the simulator I used milliseconds. But it just has to be a sufficiently small time step right there. So all of this calculation is going to be going on in Ruby. And I don't really know any graphical libraries for Ruby and I figured it would be kind of interesting to try to stream it to a browser and do it in a canvas. So I wrote this little server and then also a web socket server because I didn't actually write the web socket server because that's hard. I tried and failed miserably. There's a lot of bit masking and you really have to understand the protocol. So for now I found this great tool, WebSocketD which it takes standard out and then maps it to a WebSocket server. And it also takes anything that comes into the WebSocket server and maps it to standard in. So you can just write plain Ruby and then work with standard input and standard output and then just pipe it to WebSocketD. So that was a lot of... That was a relief. So since we're going to be running both a Web server and WebSocket server it gets kind of tricky so we need to fork the Web server into the background and then shell out to WebSocketD since it's actually a separate command line tool. So this server right here, this is just WebRick. I did this because I didn't want to pull in too many dependencies and then this will kill the background process if it gets an interrupt like a control c or something. And then we also want to mount slash so that we can visit in the browser. And so these examples right here, these are some simulators that I wrote using all that Ruby code and we'll actually see this running. That's the fun part coming up. Yeah, so the first application is going to be a binary star system. So that's just where we'll have two bodies will assume that their masses are equal and that they're moving in such a way that they're traveling around in a circle. So this velocity is just going to be the negative of that. And that very kind of predictable motion in advance is just called uniform circular motion. And that's a really kind of special type of motion. That's where you have a perfect circle and you have this quantity called the centripetal acceleration. Sometimes you hear centripetal, but it means center seeking. And the reason it's pointed inward, you can kind of imagine it's got some tangential velocity and it's about to fly off into space. But if it's moving in a circle, there's something pulling it towards the center of the circle. So that's what this A vector is. And we know that the length of that A is just equal to V squared over R, which I just, you can just look it up in a book. There's a way to figure this out by deriving it, but this is kind of, as you might see in like a freshman physics class. And it's just something that'll be we can use to figure out the initial velocity. Because we've already know the masses. The two masses are going to be equal. We can put them in some configuration where they're some distance apart. But if we didn't get the velocities right, they would either fall into each other or they would fly off into space. So we want to make sure that we get the velocities just right so that they travel around in a circle. Now that we have that A, we can just plug in the Newton's Universal Law of Gravitation and then do some more algebraic messing around. And then finally get that velocity right there. It's coming up. Killing me. Seriously. Seriously. Alright, this actually worked. I'm just going to keep going. Anyway, I think that's just the WebSocket server though. Because yeah, so the, we could live debug this. I got a few more minutes. Let's do it. Alright. So it looks like we have an error here. Yeah, so I have a couple of cool initial conditions in here and I'll go over some of the more advanced ones if we have time and if this actually gets working. But it's the thing that you can expect is just two bodies that are traveling around in a circle around some common center of mass. Anybody have any questions? I built it locally. Actually that's embarrassing. Frame rate. Oh, that's a good question. So I used a request animation frame in the browser. So essentially the WebSocket server streams a whole bunch of data to the browser and it updates the current state and it's just in a global variable. And I use a request animation frame so that whenever the browser is ready to render something, it will then run whatever, it'll render whatever the current state is. So it'll render as fast as it can and it's also nice because if you're away from the tab it will it won't actually render anything. So one sec. This is actually pretty cool. I'm not going to wake you guys. Make everyone here wait. So this is actually on GitHub right now. I had it running at Rails PDX in Portland. But yeah, so that's something that we can run later and you can all check out it. It could be. Oh, you know what? That's probably it. Yeah, so it is local host. That's right. This is good. This is actually really good. It's like not pair programming but like end body programming. So that's the issue. Is the WebSocket server there? Yeah, that's probably the problem. So it is local host. Yes. So server B, plan address, 8080. It's how's it off? Yeah. I'm looking. Yeah. There it is. Thank you. Oh, there it is. Right there. Thank you. What's that? Binary orbits by pair programming. There we go. Okay, cool. There we go. Thank you. That was intense. All right. Thank you all. That was really great. So with only two bodies, it turns out to be really easy to solve in general. You don't even have to run a numerical simulation like that. You can actually solve it analytically so that you know for all time the whole path of the body. It turns out to be really, really simple. But just by adding a third body to your universe, it turns out to be in general impossible to solve. And the more bodies you add, the more rounding error and other things can kind of cause your simulation to diverge from what would have actually happened in nature. But it's been studied for really, really long time. So there's some examples that have a really nice symmetry to them. And those are instructive to study. They have to be really, really, really highly symmetrical. And they're very, they're kind of brittle. They're rarely observed in nature because they just as soon as you have more than three bodies, you easily get chaos. And you might get stable orbits for a few billion years, but I mean when you think about infinity, even something that seems stable like our own solar system can be really, can have chaotic tendencies of time. So this great paper right here, which is only about 15 years old, this found a orbit, a three body orbit that traces out an infinity shape, a limb to skate, as we call. And the initial conditions, I just ripped them right out of the paper. And if you kind of look at them, you can see already there's some symmetry. So for the first body, it has this, it starts at some point right there. And then you have another body right here at the zero point. And then this third body right here is the negative of this first one. So this vector right here multiplied by negative one. So already they're along a straight line at that one moment in time. And for the velocities, there's also a lot of symmetry. Here you have a tangent vector going off in this direction, and it's the exact same velocity at that body right there. And then this one down here is two times that vector, but times negative, or it's in the opposite direction. So those initial conditions, so assuming the masses are all equal, assuming these positions and these initial velocities, this should move around in a figure eight. Yeah, so I have it already running. Hopefully. Real quick check. So that was three body. Thank you. Yeah, that works. There we go. So this is really cool because you could watch this for a while. It's like juggling. It's like planets juggling themselves. And it's mesmerizing. But this is also something that I looked around and I haven't found anything like this that astronomers have observed because there are more than three bodies in the universe, and that kind of makes things complicated because the left hand side of that equation had a sum of all, it's a sum over all bodies in the universe. So as long as you have more than three, you're always going to get small perturbations that are going to fling things off in other directions, and this is just something that is just, it's too brittle. And some random initial conditions are also kind of fun to watch. These, again if you notice, there's no collision detection because they all kind of are simulated as if all of the mass is concentrated at a single infinitesimal point. But the random initial conditions are a little bit more realistic because that's kind of how stuff works out in the universe. Things get around. Some orbits that are stable remain. Most of them just get flung off into space. And those are some random initial conditions. Those are fun. And yeah, so after Newton, so even though Newtonian mechanics work really well, physics is kind of branched off in two directions. We have special and general relativity, and then we also have quantum mechanics, which deals with electromagnetism and everything other than gravity. And if we imagine physics as kind of a get repository, Newtonian physics right here is the initial commit. And general relativity is one branch. And then quantum mechanics is another branch. And as of yet, those branches have merged conflicts that nobody's been able to work out. So that's it. We don't know what's going to come next, but it's all of these possibilities. Thank you. Thank you for debugging. Thank you for everything.