 Right, this talk is going to be slightly faster and more confusing than I planned. So I hope you've had your coffee because we are going to spend the next hour doing maths. Growns, cheers. Excellent. Well done. And the reason I'm doing maths is because you need to do it to drive this robot which has been sitting down here looking pretty. If you can't see it, I will show you a video of it quickly. So this is the vague structure of the talk. I'm going to talk a bit about the physical build of the robot, why I built it, something about the electronics, but primarily going to focus on the maths and the software needed to actually make it move at all. Because unlike other designs, you can't just hack this intuitively. You have to do it properly. So on the basis that you probably can't see the robot on the stage, this is what she looks like. My beautiful screen. No. OK. That's hopefully a bit more evident. So what you can see is that it's triangular, hence being called triangular. It's capable of moving in any direction from any starting pose. It's capable of rotation and translation simultaneously and all sorts of quite clever things you can do. So the motion that's happening shortly will be a translation in world space while simultaneously spinning, which if you were to try and control that manually would be extremely difficult. So we'll get to exactly how that's done towards the end of the talk. Ow. You're really dark on one side. I do have a dark side. That's fine. I can... I'll take it on trust that the audience hasn't run away because I can't really see you. Spend it. They'll be extra confused. Oh, come on. So the talk is about holonomic robots. So I should probably define what a holonomic system is. So as the slide says here, it's a system where the number of directly controllable degrees of freedom is equal to the number of degrees of freedom. When we're talking about degrees of freedom from a mechanical system, we're referring to the number of different ways it can move within its environment. So this list might be slightly surprising because we typically think of a quadcopter as a super agile vehicle and you might think it would be holonomic. But that's actually not. So you are holonomic. When you're walking around, you can independently translate and rotate and you can move through your environment, assuming we're restricting motion onto the ground. I noticed that most of you probably can't fly. Trains are holonomic because they have exactly one degree of freedom. They can go forwards and backwards and they can control that directly. And this robot is holonomic because she has three degrees of freedom. It has translation into axes and rotation. And those all can be controlled independently. So you never have any restrictions on the type of motion you can perform based on where you currently are. Unlike, for example, a car. I mean, if you've ever tried to park a car, you'll be aware that they typically can't jump sideways. So the pain would be much easier if they could. So most things with regular wheels are not holonomic for this reason, that the wheels constrain their motion to be in a particular direction. This robot was built for a competition called Pi Wars. Pi Wars is organised by the Raspberry Pi Foundation or some organisation affiliated with them. It's a bit confusing because this is in Cambridge and where the Pi Foundation is based, so I tend to just assume it's them doing it. They certainly appear. And I had various objectives for this. I wanted to build something fun that wouldn't win anything. Basically, because I'm a professional software developer, I have a lot of free time. I have a reasonable amount of disposable income. And it felt a bit unfair to be competing with school teams and family groups. I catastrophically failed to win, to not win anything. Because the mystery robots on robot dueling challenge, which in previous years had been a sumo contest for which this robot is woefully unsuited, turned out to actually be an agility contest instead, for which this robot is just going to absolutely steam roller over any possible alternatives. So this was Pi Noon. And if you've dropped by the Cambridge makespace village yesterday, you might have seen Brian's mini Pi Noon, which is the microscopic version of this. And today, I'm told, what time, Brian? Yeah, so, yeah, if you want to go and play with the teeny little two-wheeled ones, I think it's an A6 footprint, the micro Pi Noon. This one is much bigger than that, so I couldn't build one of these, so that's more. But the way the competition worked was that you had an L shape coat hanger wire with a pin on the pointy bit, and a balloon on the crook, and you had to pop the other robots balloon before yours was popped. It turns out that being able to dodge sideways, spin around behind your opponents and lunge in, is actually quite a good thing. So I accidentally won Pi Noon, and then people gave me some form of prize for aesthetics, build quality, and innovation. So rather than winning nothing, I actually won as sufficiently large amount, I couldn't carry it. I have managed to donate everything now, so I feel comically OK with that. It's important when you design anything like this to test, ideally in as hostile an environment as possible. And the testing for Triangular's first version was at an Ada Lovelace Day event at a local school, with two or 300, 10 to 14-year-old mostly girls. And it turns out that if you give small children a PlayStation controller, they don't do what I do, which is very gently move the sticks with extreme care. Now they sort of whack them randomly in different directions. And that has a tendency to chew up the tires, spin the motors, break everything. A bunch of other things were learned. So that design is rather less polished. And this is the final one. So this was designed in Onshape, which is an alarmingly web-based CAD program. I'd probably recommend having a play with it. You can dare free accounts available. It's somewhat ridiculous that you can actually do full parametric CAD in a web browser. The physical construction is C-section aluminium for the bits that look like they might plausibly be C-section aluminium, and laser cut acrylic for almost everything else. The wheels are off the shelf, so most of the other components. So a rough bit of materials. We have motor drivers because, frankly, it's much easier to talk to something on a serial bus than it is to do high-power electrical stuff. Three motors, as you'd imagine. Big lipo-pattery pack, probably more powerful than it used by having it lying around. A bunch of flashing lights and pre-made aluminium omni-wheels, which are the interesting bit. The chassis itself are Raspberry Pi 2B, an Arduino nano, and some bridging logic and an IMU that I'm not actually using. There's also a camera, which is also not relevant here, but quite handy if you want to do line following, for example. The headline figure down there is the other reason I didn't want to win anything, which is that most teams wouldn't be spending hundreds of pounds and months of time on their robots. This is pretty much the last we'll talk about the actual physical build, but this is how everything connects up electrically. So there's quite a lot of wiring, quite a lot of actuals of amateur electrical engineering. I'm terrible at all this stuff. I don't really understand it. I can wire part A to part B, and if it goes wrong, I'll just try doing it again and hope it does something wrong the first time. So the Raspberry Pi is doing the high-level code. So things like pathfinding, responding to the controller, it's connected to a PlayStation controller over Bluetooth. It talks to its camera over its own thing, and it talks to an Arduino microcontroller, 80 mega 328 based over ITC, the interintegrated circuit communication bus. The reason it has an Arduino is because sometimes we need to respond extremely quickly to inputs, and I'll get to that later, in a way that the Pi can't really do unless you get rid of its operating system. The Arduino then talks to the motor controllers, and it talks to the wheel encoders, so we know how fast we're driving the wheels, but we also know exactly how fast the wheels are actually moving. And the light show is also run by the Arduino. This is not particularly relevant to the main thrust of the dog, but I thought I'd do an overview on how the thing was put together. So the omni-wheels are the reason the robot has to use a lot of maths, and they're also the reason it can move in the way it can. So these are wheels you may have seen. They consist of a set of rollers, so within each wheel you have rollers, and the key thing is this means the wheel can slide at 90 degrees to its main motion axis, if you like. So if your wheel is moving forward, typically if you have a bicycle or a car or something like that, the wheel will move forward, and if you try to push it sideways it will skid, or it's clearly not intended to do that. Whereas with this, the rollers that make up the wheels actually allow it to move freely in that other axis of motion. And that's why we can have a design like this where the wheels are all at 120 degrees to one another and the robot can move in a straight line. If these were normal wheels, obviously all it could do was spin around on the spot. And clearly it can do more than that. So I hope you've had your coffee. Either that or really like doing vector maths early on a Sunday morning. We're not entirely sure why this talk was scheduled for a Sunday morning, but anyway, you're obviously all up for it. So excellent. So the main problem that we're gonna try and solve is how we move. How do we express the intent? Because the motion's quite complex. How do we read that data from the controller, figure out what we want to be doing, and ultimately we need to be mapping that into a set of signals to the motor controllers that tell it how fast and in what direction the wheels need to move. The coffee bit is basically because that's the hard stuff. So I need to introduce a few terms. What I would say is if you, at this point, it's gonna be very hard for me to completely walk through the maths here. However, it is written up. So if you go to the entry in the schedule for this talk, there should be hyperlinks to both these slides, which are on Google Docs if you want to follow along and you can't easily see the screen because there is some quite small detail on it. But also the documentation for the robots Python code, which includes a much more thoroughly described version of the maths. So if you're feeling that you're not getting enough information or you're having trouble seeing the screen, that's an easy way to follow along. So the first thing we have to sort out are coordinate systems. There are two frames of reference in this environment. There's the world frame. So if you're standing there driving your robot around, you have a notion of forwards backwards, left and right relative to you. And there's the robot's coordinate space, which moves around with the robot. So you'd encounter this typically if you drive a remote controlled vehicle around. Obviously when you turn left, each turns left as far as it's concerned, not as far as your concern. So if it's driving towards you, it'll actually turn right. So we define a motion as a quantity with three parts. It has a linear motion. So x and y axes forward and back or left and right if you prefer relative to the robot. And that's in distance per second. I use millimeters internally, but it doesn't really matter as long as you're consistent. An angular motion, which has to be in radians per second. Otherwise nothing works. In general, if you're doing any form of geometry, you work in radians and everything cancels out nicely. If you work in degrees, it's rather like trying to do measurements using imperial units. You end up with a lot of weird numbers in there to cancel everything out. So this is a vague representation of the robot. You can see the rectangles of the wheels are arbitrarily assigning a front. The robot doesn't really have a front because it's entirely software defined. But for our convenience and for our sanity, we need a frame of reference that says, forwards is this way. So when we talk about a motion, we talk about move forwards and a bit to the right whilst spinning counterclockwise at this number of radians per second. Okay, so we can derive that motion from the controller. So for example, what I've got here is I have the left analog stick drives the left and right forwards and backwards parts. And the right analog stick x axis drives the rotation. So I can set the robot going in one direction. I can drive it, steer with the other stick. So we still have to work out the wheel speed. So we haven't really done the hard bit yet. Here I'm going to use some subscription notation. So you can see this opposite map controller to a motion. And the motion is M and I'm splitting M into three numbers, x, y and theta. Now apologies for the use of the Greek lesser. I was probably a bit gratuitous, but it's the typical one used for rotational quantities. And the link at the bottom there has a much more thorough version of this talk. It's fairly obvious if you think about it, that the wheel speed we need to move is going to depend on the wheel. So if the wheel is in a different place, it's going to have to move at a different speed to maintain the motion. So we define a wheel relative to the robot's coordinate space, so the same as the motion. And we simply say where the wheel is. So in this case, this example shows that the front wheel is at zero comma two coordinate, because if we move up our x-axis relative to the robot, the one that's going directly with the plus x, we're at the origin on that one and we move two ticks up the y-axis. And we define that for each of the wheels. I'm just going to use one in the example. If the robot switches and lunges to more sweets, because there's probably a buffer overrun bug somewhere. Just tell me if that happens, because it's really heavy. My ankles aren't really protected. So this is more of a statement of what we'd need to do. We need to say in robot coordinates, what velocity is each wheel moving at? That's the first step. So we can treat the wheels independently. We know that if the robot's moving in a certain way, the first thing we need to do is say, what is every individual wheel doing? How fast is it moving and in what direction? So if you think about it, the robot doesn't deform, it's a rigid body. So if we're just translating, so we're not spinning around at all, every single point on the body has the same motion vector. Stay. Bad robot. However, if we're spinning, clearly those vectors are different. So if you imagine you're turning around and you're thinking about where your shoulders are moving or your hands are moving, if you keep your arms rigid, if you just walk forwards and backwards, they're moving in the same direction. You're left and right hand, there's no difference there. But if you start turning around, then while one of my shoulders would be going forwards, one of them is going backwards, clearly they're not moving in the same direction. So the velocities are different. However, because these are independent, all we need to do is work out the velocity due to rotation. And then we can just add them together and then we'll get the overall velocity which we will then turn magically into a wheel speed. So now we have some maths. So how do we work out velocity for rotation? Well, we know we are moving in a circle because we're spinning around our center point. It doesn't matter that center point might also be moving, all we care about is the relative motion. We know the distance the wheel is from the center of rotation because we've already defined that because we know where our wheel is. So we can define that easily enough. And we know our angle of velocity because we specified that straight up front. So with that's rm theta. So actually, as it turns out, the speed is our angular velocity radians per second multiplied by our distance, which in this case is the square root of the x-coordinate and the wheel coordinate squared. So that's just basic trigonometry. You're calculating the length of your hyposin use from a right angle triangle. The next clever bit is that we actually know what direction we're moving in. Now, if you're moving in a circle, the direction you move is perpendicular to the direction from you to the center point of the circle. And if that sounds counterintuitive or non-obvious, consider what would happen if you say take hold of a broom handle and you nail center of it down or not center, the one end of it down to the ground with a tent peg, say. You pick up the other end and you try and walk forwards. You're moving in a circle because the broom handle is a constant length and you'll always move so that the broom handle is sticking out to your right, say, or your left, depending on which direction you're going around the circle. So you can only actually move the end point of that rigid arm 90 degrees to the direction from you to the center of the circle. And we know what that direction is. So I'm asserting here that I know the direction and it's the coordinates. If our wheel is at x, y, our direction vector that we're moving in is at y, minus x. And that's because if you rotate a vector 90 degrees, you can transform it in this way. So this would be a clockwise rotation. I'm afraid I'm just gonna have to assert that without proving it. We can, if you want to see the proof, it's based on matrix rotations and is in the more involved documentation. So it means we know what direction we're going and we know how fast we're going. What we want, however, is that our direction vector is arbitrary size and we actually want a unit vector of length one. So what we do is we divide by this, which turns out that our unit vector of direction is our direction vector divided by this quantity. And if we multiply it by our speed, then these cancel out. So actually, what we end up with is our velocity of the wheel is the wheels y-coordinate minus the wheels x-coordinate all multiplied by our motion in radians per second, which is actually quite nice and simple because two of those are constants and one of them is a value that we know directly. Doesn't time fly. So we know velocity and we then can add on the translation part of our motion because we know that we can do that. Effectively, you can say your coordinate frame is simply moving with you and you're rotating within that. So you're moving the whole thing. So basically, we just add things together. So we now actually know exactly what direction and speed every single wheel is moving when I tell the robot to move in a certain way. And it's a simple equation. We can obviously, we can evaluate this easily in the code. No complex trig operations, nothing like calculus, nothing like that. It's just multiplication in addition. So now the question is, these omni-wheels, you recall, they can move in one direction, they can slide in the other direction. We need to know how fast the motor needs to run to make that motion work. And to do that, we need another vector, which is called wheel drive. And this is actually probably the most obscure concept in the talk. So if you get past this, well done. If you imagine the wheel is driven clockwise or positive power to the motor, it's going to move in a particular direction, right? If we just took that wheel in isolation, forget it's attached to the robot and we give it power to its motor, it's going to roll forwards. The wheel drive vector is the vector, that yellow arrow, so from a start point to an end point, where the start point doesn't really matter, but the end point is where the wheel would end up after one revolution of the start. So if our wheel was just floating in space and we drive it through one revolution, it ends up at the position where the blue thing is, if it starts with the red one. Now, this is again, I'm afraid you will have to take slightly on trust. The most complicated piece of maths in this talk is actually this slide, as it turns out. So we want to say how much of our wheel drive direction do we need to add in to get our velocity? So you can actually make any velocity or any vector on a two dimensional plane out of any two other vectors as long as those aren't the same. Now, we're typically used to doing this with coordinate systems where we have a vector that is our x-axis unit vector and a vector that is our y-axis unit vector. So we can say that a one comma two coordinate is actually one times our x-unit vector plus two times our y-unit vector. That's relevant because in this case, we actually have two vectors which are 90 degrees to one another. We have the drive vector, which is the direction that we will push if it moves. And we have the direction it will slip. And we actually don't care about how much that is because we can't control it. So what we want to do is determine the amount of the drive vector we need to put into the wheel to drive it so that in addition to the amount it will slide, which we don't know and can't control, it will end up with our wheel velocity that we worked out earlier. And that's this projection operator. It's actually, so this dot's notation for a vector is it has a geometric definition, which is it's the cosine of the angle between the vectors multiplied by their lengths. But in this case, we don't actually need that. What we can do is if you have a vector xy as another vector ab, your dot product is actually x times a plus y times b. So we're not doing anything particularly esoteric. It's all just multiplication in addition. And so we get that and we divide by this symbol at the bottom is the magnitude. So that's the length of the drive vector. In other words, it's actually the circumference of our wheel. So we can think about these in multiple ways because obviously in one revolution, the wheel moves by its circumference. So if we know that that's the p is the distance along our drive vector, which we have to move. So we know our velocity and we know how to, given that velocity and our drive vector work out the distance. And actually we simply need to divide by the size of our wheel at this point because if we know how far we're going and we know how big our wheel is, we can work out how many revolutions of the wheel it is. We divide by that and we get this actually reasonably sane equation here. The nice thing is that a lot of these things will cancel out shortly. So for each wheel speed, for each wheel, given a motion vector, this is how fast you use drive the wheel to make it go. And it explodes into this, but actually this might look annoyingly large and complicated. So all I've done here is I've taken, I'll allow you to take a picture. I'm just about to jump back from the slide. I've taken this equation here and I've rather than just saying v-wheel and w-d, I've actually written them out here. So I've written out the x and y components that we worked out earlier. And you see there's a dot product operator on the second row. That then turns into this equation on the third row. And although there's a lot going on there, the important thing you should see if you look carefully is that the only variables in this are mx, my and m theta. And those are just being multiplied by constants that are defined by the shape of our robot. So w-dx, w-d-y, w-y, w-x, those are all fixed. So we never need to actually compute this into our equation. We can just multiply three things by constants and add them together. And that's obviously very, very easy to do. And now we have a safety kitten. Is everyone okay? No one's brain is frying. So we have 25 minutes left. But if anyone does have precise questions about maths, I'm happy to talk about them later, but it may not be ideal to try and do it now because I'd like to get onto some of the cool stuff we can do having done all this work. So we have just solved what's known as the reverse kinematics for the robot. So the kinematics talk about how we relate the motion that the robot's actually doing that we see when we go like how it's moving around and how we actually have to drive it. So at the low level code, what we need to do. The reverse kinematics is given a target motion, how do we actually drive our electrical gear? How do we make it go? The forward kinematics is the other way, which is given a certain, you know, our motors have moved this much, what happened to the robot? And why did we bother? Because, you know, see the second subtitle. I enjoy maths, it might make me weird. We can control the robot without before doing this. You can't hack this motion. So if you have something with two wheels, for example, we could say, well, joystick control, let's make our left joystick move wheel, you know, the left wheel, let's make our right joystick move the right wheel, you drive it like a tank. It's intuitively reasonable, you can probably manage to control it. This thing, not so much. So we can also build on this. So what we've done is actually quite naive in a sense. We said, well, we'll specify the motion we want and we'll immediately tell the wheels to go that speed and all sorts of problems are doing that, for example, skidding. So you remember my battle testing environment? If we just did this without any more sort of complexity, what would happen is what did happen in this particular case, which is you give it to the small children, they immediately whack the PlayStation controller to full forwards, full back, full forward, full back. The code goes, yes, I can do that, I know how to drive the wheels at those speeds. It does so. The motors have a lot of torque and you end up skidding the tires and because they're omni wheels, the tires are actually quite fragile. Net result, a lot of shredded tires and also some broken motors and these for cable ties and such like. So, yeah, so you don't want to come and drive a robot around. You'll have to promise not to drive it off the stage. It's not very robust in that. I can't see anyone. So can someone who can see just pick someone? So what I want to do here is demonstrate a very simple bit of fake kinematics. So you say, oh, your name, Keegan, right. Keegan is going to drive the robot around using without any of the smoothing applied and then I'm going to switch the smoothing on and hopefully there'll be a difference. So what you'll find is your left stick controls translation, so the pink bit of the robot, which is just about possible to tell where the display is, is forwards in this case. All your motion is going to be relative to the robot's frame of reference. So you see it's fairly quick. At this point, I'm going to attempt something. It's mainly not work. Let's have a look. Hello. Oh, God, that's terrifying. Right. Right. OK. I apologize for the probably rather jittery camera work. I'm trying to do this whilst looking at that screen and talking to the microphone. Also, I have no idea what that pop-up is. That's fine. Yeah, whatever. Ignore that. I had to back out and I had to be in a library update 10 minutes before the talk because I realized that the writing library had screwed up some timing system somewhere and nothing was working. So anyway, if you would drive it around a bit, you'll find that the right-hand stick will give you your rotation and the left-hand stick is translation. So back in the terms we were talking about earlier, that's our MX and MY on the left-hand stick directly just mapped to the X and Y axes of that stick. M theta is directly mapped to the X axis of the right-hand stick. And you find that it's fairly snappy. I mean, you would be able to skid it pretty easily on this. It also might be running as problems because we had a minor five-year-old related tire damage earlier. I should probably be a bit more careful as I play with it after the talk. Never mind. It's fine. The wheels are cheap. But you see, you move around and it's got a degree of control. Also, it's just generally shiny. Now, if you would press the X button twice. Right. Now what I've got is an additional layer which will limit the rate at which we can accelerate or decelerate in any axis. So you'll find that if you drive around, it will feel like it's got a much more inertia behind it. Does that make sense? So it also won't decelerate as fast. You have to be slightly careful. That's just how it goes. So is that easier to control? That's a question. So you shouldn't be skidding as much. So that's the simple thing we can do with kinematics. We can start imposing false kinematics if you like on the whole thing. Oh, God. Hairy arms and all. OK. So onwards with the talk, I think. Thank you. It's not as easy to drive as it looks. I would say there's... Oh, God. Make it go away. Oh, it won't go. Maybe. Yay. There we go. I have no idea what the time is because the screensaver on my clock has just come on. Right. I was good to my word. So... Thank you. So the second question is the forward kinematics. So if we know what our current motion is or if we know what our wheel speeds are and the robot does know what its wheel speeds are because it has magnetic Hall effect encoders on each of the wheels, which give us an extremely precise idea of where the wheels are, assuming they don't skid, of course, which is why this anti-skid thing was important. We could go on the basis that well, we asked for a particular motion, but that doesn't really work because we have inertia, we have things that the robot might run into, perhaps we're going up a hill, and so some motors are going to have to drive harder than others. So we actually need to measure these directly. They're just stuck on the back of the motor. They will spit out a very large number of pulses per second as the motor moves, and the quadrature encoding means we can tell which direction they're going in. These are actually wired up to the Arduino, so one of the reasons there's an Arduino in there is that we can fire six signals, so two from each encoder, into a pin change interrupt port on the Arduino and it can deal with that and it can tell the Raspberry Pi what's your current wheel count having gone round. A quick slide on how quadrature encoding works, upshot of which is you've got two pulse trains and depending on which one changes first, you know which direction you're going, but I'm just going to skid over that because we're running out of time. Now more maths. Excitement. So this is actually just a restatement of our previous thing, that we know what, given our motion components, the three Mx, My, Mtheta, we know what our wheel speed is. But of course we've got three wheels, so actually in the code we were running that equation three times with different constants, because the wheels are in different places. So this will actually look like a fairly familiar thing. If we have three unknowns and we have three equations with the three unknowns, we've got a system of simultaneous equations, they're all linear because it's simply our Mx times a constant plus My times a constant plus Mtheta times a constant equals s for the wheel. So we can actually just say well, let's make this a bit more concise by defining what the constants are for a given wheel. So for we have an x and y and a theta constant, which are what we're going to multiply the coefficients around which we multiply our motion to get our wheel speed. And the things in the box on the left of this slide are all constants. They are entirely defined by the chassis size of the robot, where the wheels are, what direction they're pointing and how big the wheels are. We can express that as a system of simultaneous equations and we can then express that as a matrix, containing all of those things. Then you realize it's late at night and you can't actually be bothered to remember how to do this properly and you throw the entire bunch into a numerical solver. There's a reason for that though that is simply, that is better than simply laziness, which is that we have three wheels, three unknowns, therefore there is a unique solution that says given this combination of wheel speed to what our motion is. However, you could easily have four, five, six, however many wheels you want on this system and if you have that, because you introduce errors from measurement, there will not be a unique algebraically correct solutions. You have to use a numeric solver to find the closest fit answer for what your motion components are. This approach works even when we add extra wheels. This one, not so much, not likely to grow wheels spontaneously but other designs could do. The actual code starts to look like this. For each wheel object, you've got that block at the top that says when you're set up, build a bunch of coefficients. This is using a Python nuclear library, so actually some of these quantities are vectors, hopefully it should be obvious when they are. The chassis code, which actually does the calculations, is to build at the bottom. There's not very much. You end up going through quite a lot of derivation to get to this point where you're writing the software but the software itself is quite concise. We now know our motion based on our wheel speeds. The question is where are we and what direction we're going, because that's actually what we care about. We have a pose, which is a bit like a motion, only it's in world space. As the robot moves around on the stage, we can imagine that the stage has a grid on it and the stage also has a direction that's north. The pose is where the robot is on that grid and what direction its front is pointing in. Question, if we have a motion and we hold that motion for time t, what's our new pose? Where do we move to? Again, as I said before, we're moving in a circle and we know various properties about how you move in a circle. We can find the center point of that circle, we can find our angular speed and we can simply rotate our current location around the center point of that circle to get our new location orientation. I'm having to go a bit faster than I planned here, sorry. However, I want to show you why I care about this. This is actually, again, the code that does it, so it's really not complicated. When you look at the software, this is a few lines of, I mean, it's concise partly because we can use a vector library in Python and so this is actually doing vector maths directly in the code. But why wouldn't you do that? So why do we care? Well, there's an obvious application, sort of the naivety obvious one for location awareness is navigation. After all, if we know where we are, we can do planning, we can do root finding, we can program the robots to move in a particular way. But actually the more interesting one is I'm calling world space motion control. So when we had the robot driving around earlier, forward on the left-hand stick move the robot forward as far as the robot was concerned. What we can do in this, however, is we can move the robot forward as far as we are concerned irrespective of what direction the robot is facing in the first place. So I will try and do this myself, I think. I have to remember what controls I've mapped to this joystick. I think I'm going to need another volunteer simply because I need someone to hold the the up top. Yeah. Yeah, we have a camera. It's terrifying. So what I have here is, this is going to be interesting because I'm trying to keep talking while watching the robot. I have the robot set up so that at the moment it looks pretty similar. I'm moving the joystick forward and backwards, the robot is moving forward to go backwards. Except this is kind of turning around occasionally and it's still moving forward and backwards along the stage. I'm not actually changing anything on the joystick as I do this. So what's happening is the code is doing dead reckoning and it allows me to have a motion where I turn and translate at the same time. I'm just moving left on my joystick and I'm spinning the robot and it's not 100% accurate because it's spinning a bit it's skidding slightly. You can hear the wheel that got damaged earlier. But that's the motion where we're able to move in a straight path while spinning would be almost impossible to do yourself. So what's happening there is the robot is working out what direction it's pointing. It's correcting the direction you're turning it to drive so it's rotating it around your current pose angle and it's sending that through. This allows us to make motions which would be incredibly hard to actually do manually. I occasionally have to reset. It's actually still even after all that skidding around forwards is still pretty much forwards on the stage so I can reset where it thinks forwards is at any point. I think that's probably I've got almost out of time I assume. Hello in a variety of anonymous animals who are apparently looking at the slides. So if you don't want to say do all of this maths yourself you could take advantage that someone has already done it. If say you're wanting to build one of these robots there's a whole bunch of code that is intended to be reusable and is not dependent on this robot's chassis at all. So what I created was a chassis abstraction pose motion objects are what we expect from the talk. There's a wheel object which defines how the wheel works which says which direction it can roll in relative to its drive, how big it is and where you put it on the chassis and then you can simply ask a chassis give me my wheel speeds or I've measured these wheel speeds where am I and that's all easy to do. So that's available on PyPy, Python Package Archive So you can simply do pip in store triangular it'll probably only work on a Raspberry Pi because some other bits and pieces which were described shortly rely on Linux properties so I can't actually compile the code on the Mac for example. So this is my spirit animal it's the demon catch from Adventure Time who has approximate knowledge of many things so this talk is there's been a bunch of stuff and we kind of vaguely know how everything works now There are a few other things you have to do to make one of these robots actually work which is more in the way of plumbing but some of them were non-trivial so I thought I'd mention them. Talking to the PlayStation 3 controllers if you ever tried this you'll realize that pretty much all the documentation online is either wrong, a copy of the original wrong thing without attribution or the thing I wrote one of these three works guess which it is So there's a whole bunch of stuff for the joysticks which helps there's a task framework so one of the things I can do is there's an LCD display on top of the robots I can create new tasks for it to do so manual motion, manual motion red to the world frame, that sort of thing means I could write just little snippets of codes that do purely what I want and have the task framework set up the environment, tell me about where my sensors are, give me objects that provide access to the chassis and motors and that sort of thing and there's a Linux service which means I can use system control to stop and restart and remotely manage the the Python code, none of which were particularly difficult but they're all things you will have to definitely do if you're doing this and so an example might be helpful the six-axis control support in particular is something that I decided to try and do properly so you can in Python you can do something like with joystick J as this do these things and it will set up the connection to the joystick it will manage calibration automatically it will manage dead zones so you don't have motion when you let go of sticks it will manage hot zones so you can have the joysticks reach their full range of motion slightly before they actually hit their physical limit because these sticks constrain to move in circles and you might want to effectively make them move in a square it has bus and handling event handling all that sort of stuff and that's it I think oh gosh yeah so we have time questions or anyone you like to see more detail of First how I saw it up was over here so you mentioned that we when we're walking around move holonomically as well what about feeding your motion walking around directly into the robot well if you've got a way of sensing it it would be fairly straightforward so one of the things I was planning to talk about is something I haven't actually done but I intend to or it would be easy to do with a type of motion the way that you actually get your inputs in is one interesting thing the other thing is that we've got a mathematical model for how chassis works effectively we now to have a software defined robot even although we can clearly move in this extremely flexible way but there's nothing to say we have to admit that we can do that so you could have kinematics that make the robot feel like you're driving a car that's prone to drifting for example so that you as you drive it like a car so turning when you're not moving doesn't do anything and we take that physical model that you'd otherwise just render to the screen and rather than rendering it to the screen we render it to the robot's chassis dynamics so actually you could do all sorts of fun stuff with this and it's really it's now very easy to do that you just use a task framework if you've got your physical model that you want to replicate or your input model that you want to capture from it should be straightforward enough the manual motion task I've got there is pretty much read data from joystick apply torque limit if you've pressed the button appropriately so the chassis get the wheel speed send them to the Arduino it's pretty much ten lines of code or something that's running that manual control loop good thank you I think we have another question over here thanks I think you made a statement earlier that you said drones couldn't be holonomic is that all drones or so the reason I said that is if you consider three-dimensional movement you suddenly have a very large number of degrees of freedom obviously you've got translation up and down left right forward back you've also got rotation around each of three axes and I think you'll find if you have a quadcopter that if you turn it so that it's banking left it will move sideways it's very difficult you could in principle create a drone that could behave in a holonomic way but no one ever would the logically it can't ever happen unless you have at least six propellers and they're all pointing in different directions the you can't make up stuff out of nowhere so this works because we have three inputs driving three dimensions of three degrees of freedom if you don't have three actuators that are independent so the wheels in this case are independent because they go through the omni-wheels you can't possibly actually acquire those independently controlled degrees of freedom it just you can't get something for nothing if you say take a quadcopter all you can vary is four different quantities so you're never going to be able to control the thing purely in a six-dimensional space not to mention that you've obviously got other physical constraints like gravity so although you can start to rotate the quadcopter the way that the quad will skid sideways is to boost power on one side so it's at an angle so your thrust vector is sideways you can't do that independently you can't roll translate as separate concerns that you can't translate without rolling and you can't roll without also end up translating sideways so it's more that if you have those six degrees of freedom you're going to have to have at least six inputs to your physical frame in order to control them because it mathematically can't happen otherwise you might need more because you have to deal with gravity we've got one more question over here I think, thank you so I'm wondering about a big barrier to people getting involved with this kind of system, this interface is going to be the hardware and I'm wondering about what kind of commercial robots are something that this kind of interface would work for so this actually is used in commercial industrial robots they don't use omni-wheels they use what are called mccarnan wheels so the omni-wheels will drive forwards and slide sideways a mccarnan wheel will drive diagonally forwards in one direction diagonally in the direction 90 degrees to that you can actually, if you were to google for a mccarnan forklift you'll see this actually being used and the maths and everything is actually generalizable to a mccarnan wheel as well as an omni-wheel so mccarnan wheels have, rather than having rotors at 90 degrees they have rotors at 30 or 60 degrees they have various mechanical properties such as a smoother load transference three different parts of the wheel they can support larger loads typically but these actually are used in cargo handling systems so building this chassis, the expensive parts were actually things that you could do much more cheaply, the wheels themselves are I think they're eight pounds each so the expensive parts are things like I'm using 35 pound motor controllers and you multiply by three and it goes up and you could build this or a much simpler version of a holonomic chassis for much less money and without a lot of the trickery I've had to use here part of the design was informed by my just wanting to make something cool doesn't have to be this shape Hello, there we go again I think it's three minutes to this is the greatest maths lecture I've ever had at nine o'clock on a Sunday morning I think should we just thank Tom at that point there Thank you