In our last video, we set up an ultra-wideband network that measures the distance between a tag and up to eight base stations. If you haven't seen that already, go and check it out; it's linked below. In this video, we're going to expand on that system by creating some spatial tracking with it, both in 2D and 3D.
Welcome back to Core Electronics. I'm Jared, and we're going to be showing you 2D and 3D tracking and how you can apply it in your maker projects. This is such an incredibly powerful skill to have, and it's really cool to play around with. Let's get into it.
This whole system works on the idea of trilateration. Essentially, if you know where some points are and how far away you are from those points, you can figure out, with a little bit of math, where you are relative to those points. This is the same concept that GPS works on. There are satellites in space; you know where they are and how far away you are from those satellites, and you can find out where you are on Earth. What we're doing here is really similar, just on a really small scale, like the scale of a room.
By the way, it's not triangulation—that's using angles to know where you are. This is trilateration, which uses distances. Just had to get my little nerdy tangent out there. Can't be using wrong terminology.
So here's the plan: We place a number of base stations around the room in known locations. Then we use this system to measure the distance from the tag to each base station, which we've already done in the last video. And then we use a little bit of math in this video to figure out where we are in the room. Don't worry about the math part, though. We'll have code that does all of this, and you can just take it and apply it in your project however you want to.
To follow along, you'll need exactly the same things as the last video: some UBO3 ultra-wideband boards and some USB-C cables to supply power to them, and a microcontroller to read and process all of that data. We're still using the Pico, but in the written guide, you'll find code for an Arduino or ESP32 with C++, as well as the MicroPython code we'll be looking at in this video. Also, a measuring tape is probably going to be really handy here as well.
Alright, let's start by tracking the tag in 2D space. This 2D system is essentially going to give us a top-down video game-style mini-map view of your room, and you'll be able to see where the tag is in there. Essentially, if you are holding the tag, we would know whereabouts you're standing in the room, but we wouldn't know how high off the ground you're holding the tag.
For 2D tracking, you're going to need a minimum of three base stations, but we've written the code to support any number of base stations up to a maximum of eight. We need three because a bunch of nerdy math says that this is the minimum amount of distance requirements that you need to solve the equations to find your location in 2D.
Placement of your base stations is key to good tracking here, and you should aim to spread them out across the room as much as possible. Remember that you can get 10 meters somewhat reliably through obstacles and 15 meters, maybe more, with good line of sight. Place them all roughly at about the same height in the room and try to ensure that there's nothing in the way between them and the area you want to track. We found that four base stations with one in each corner of the room worked well.
Now, three is the minimum, but if you are only using three and one of them gets blocked, maybe doesn't read properly, or something goes wrong, this system is going to stop working because it needs three distance measurements to work. The extra fourth station gives you a layer of redundancy. So if it gets line of sight blocked or something like that, your system will keep working because it's still got three perfectly good readings. Obviously, more base stations around the room mean more layers of redundancy. In bigger rooms with lots of obstacles in the way, this can help a lot.
Also, when you're tracking your tag around the room, it should be tracked at about the same height as the stations. The closer it is to the height of all the base stations, the more accurate it will be, but it will still work just fine if it's higher or lower; it's just going to be less accurate.
Alrighty, in our IDE, I'm going to go ahead and paste in the 2D tracking code, which is too long to fully go over in this video. We'll have a breakdown of it in the written guide linked below. We are going to need some consistent X and Y coordinates, so pick a corner in your room. This is your reference corner. Every single measurement that we're going to make in this guide is going to be based on that corner. Stand in the corner and place your arms out 90 degrees apart like so. Your right arm is going to be the X direction, and your left arm is going to be the Y direction. You need to measure how far away each base station is from this corner in the X direction and the Y direction.
So I have my base station here on the bench. I might actually just tape it down to ensure it doesn't move around. I'm going to start by finding how far it is in the X direction from that corner. If I measure out, I want it to be in line there. So let's bring it over. I've just got it against the wall there, and that is 1.95 meters away from that wall, which is the X direction in that corner. I'm just going to go ahead and enter it into our code like so because it's X and Y. Then I'm going to find it in the Y direction. So really, it's the distance off the back wall here, and that is 3.1 meters away. I'm going to put that in like so. Now that one on the rear wall is a little bit tricky, so let's go and see what's going on there.
The direction, which is this one here, because it's on the wall, is zero meters away. So I'm going to put in zero into the X direction, like so. In the Y direction, which is this one here, I'm going to measure it off, and it is 0.34 meters off the wall. I'm just going to enter that in, like so. You're just going to need to go ahead and measure all the distances from that corner to your base stations and input them into the code to their corresponding names. Also, ensure you use the same corner for your measurements every time as well. Just for clarification, base two is base station two, which is the base station that you configured with an ID of two. If you aren't using a certain base station, just leave it as none here, and the code's going to ignore it entirely.
Once you've placed your base stations, input their locations, and supplied power to them, run the script. We're going to get nothing until we power on our tag, which I'm just going to do now. I'm going to have this connected to a battery bank so we can move it around and see what's up. Once you've done that, you should get some values being printed out in the shell. I'm just going to pause that so we can investigate what's going on.
The first two numbers here are the raw X and Y location being calculated, and the next two are some smoothed values coming from something called a Kalman filter. All of these X and Y coordinates use the same system and reference to the same corner that your base stations do. After our raw X and Y, then our filtered X and Y, we just have the distance from the tag to each base station being printed out here. We've only got four set up, so the other four are just zeros.
Alright, let's give that a run. The first number is X. So if I move it closer to the wall, because that's in the X direction, you should see that we start to approach zero. If I move it to the other side of the room, it goes to about 3.54, which is the width of this thing. If we watch the Y direction, if I move it back, we should get close to zero. If I move it forward, we get there. There we have it. X direction, Y direction, same coordinates, tracked in 2D space from just a few base stations. How wickedly cool.
Now, human brains are not built to analyze numbers like that. It might make sense. That's why we're going to go ahead and visualize it. This location printout to the shell is probably what your project needs, and in the code, you can access these numbers directly. But we're going to go ahead and visualize that so we can see what's going on. It's a really helpful debug tool, and it's just really cool to see a visualization of all your base stations and where the tag is moving relative to them.
We're going to be using something called Processing IDE, a fantastic and free open-source program that's great at producing visual displays like we want. Download it, create a new script, and paste in the demo processing code from the written guide. Like in the previous code, at the top here, you're going to need to input the location of your base stations. Just watch out because it uses curly brackets here instead of the regular round brackets that we use in MicroPython. You can also set the size of the room being visualized with these max and min Y and X values here. I'm going to leave my min values at negative 0.05, but then I'm going to set the max X and Y to the size of my room. So in the Y direction, my room is about four meters wide, and in the Y direction, it's about three and a half. So I'll leave it at three and a half.
Another very important setting is to ensure that down here, you input the correct COM port that your microcontroller is connected to. You should be able to just go to your IDE and see down here what COM port it is. I'm on three, so I'm going to go and put in COM port three there like so. Before we run this though, if you are using MicroPython, the previous code that we were just looking at, you need to ensure that it runs automatically. So once you're happy with it, go ahead and save it to the board as main.py. This step is only for MicroPython. If you're following along with C++, ignore this. The final thing, you will need to ensure that your IDE is closed. We're just going to go ahead and close it on here. It's got to be closed so Processing IDE can talk to it. So unplug your microcontroller and plug it back in just to ensure we reset the COM port. Run that sketch. You should be greeted to this awesome top-down visualization of your system.
All Processing IDE is doing here is taking the data that we saw being printed out before and just displaying it, with the red dot being the jittery raw data and the green being the filtered or smooth reading from the Kalman filter. These circles you see here are the distance from each station to the tag. How is this working though? Again, a better explanation in the written guide, but long story short, each station thinks that the tag is somewhere along that circle because that's the distance from the base station to the tag. If you looked at all of these circles, you could use your human brain to guess where it is. Super easy, right? Because you're a human. It's a bit harder to do in code, but it uses something called the least squares method to do this mathematically.
But like any sensor in the real world, you have to deal with noise, which makes this reading a little bit jittery. This is where the simple Kalman filter comes in. Let's say we read our tag here, and then the next one it's here, and then the next one it's here. If you look at that with your human brain, you would logically say, okay, it should be here next time. But what if instead of here, our ultra-wideband reading says that it's here instead and it's gone back? Well, do you trust this pattern here and this is a rogue reading? Or has the board actually moved in the other direction? Do you trust the new reading more? The Kalman filter lets you choose between the two.
Now, if you're running all of this and getting some dodgy data or it's a bit off, you might need to calibrate the offsets of your boards. Towards the top of the code is a section here to put in all of your offsets. Let's say I put the tag one meter away from base station three and it was instead reading 1.2 meters. Some of the code we looked at in the previous guide can help you figure this out. I would go ahead and put negative 0.02 here in offset three, which is going to fix the offset. Base station one, on the other hand, was reading 0.9 at one meter. So I put positive 0.1 in there to fix it. You may not need to do this step as all the errors might be canceling each other out. But if you're tracking in a really small room like I am here, or you're tracking when the tag is close to base stations, this may be very important because this error really starts to throw things off. That looks heaps better, doesn't it?
Something really handy to know, by the way, is that the data that we have been reading from base station zero is also being output from the tag as well. So if you had your tag on a robot driving around a warehouse or something like that, you can have your microcontroller on the bot getting the data from the tag that's being tracked. The position data of the tag is just being held in variables that you can freely access. So it's really easy to modify the code. We go over it in the written guide more.
We are, however, going to get to the peak of this mountain and instead track in a full three dimensions. This process is actually going to be pretty much the same as before because there's not too much work to expand this into a 3D system.
First things first, let's place our base stations. Same rules as last time, but you're going to need a minimum of four this time. We have an extra dimension, so we need one more base station. Again, if you only have four base stations and one of them gets blocked or something, this system will stop tracking because it needs four. So five or more base stations might be a smart idea just to have some redundancy.
Again, it's ideal here to have them spread out across the room, but this time it's also smart to have some as high as possible and some as low as possible. The ultimate overkill setup here is to have one in every single corner of the room for a total of eight, which will give you plenty of redundancy and some crazy good tracking. Maybe a bit of overkill for most projects though.
You'll need to put in the X and Y distances of your base stations in the code exactly like last time, but now you also need to give it the Z distance, which is just how high it is off the floor. If you've measured your offsets, ensure you copy them over into the code as well. Then all you need to do is run your code, and you should have the same output as last time, but now with a third Z axis showing you how high off the floor the tag is. The code is pretty much the same as last time; it just does the math in 3D instead of 2D.
We also have a Processing IDE script for this 3D setup as well. To use it, exactly the same process as before: put in your base station positions, put in the dimensions of your room, select the COM port, close your IDE, re-plug in your microcontroller, run it, and you should be greeted to this visualization of your tag in 3D space, which is just so fun to play around with. You can use the scroll wheel to zoom in and out a little bit and also drag around the room to see what's going on.
Because we're trying to view a 3D thing in 2D, it's a bit difficult. So what I'm going to do is that there is our back corner that we measured from. So I'm going to rotate this around to front view, which is what you guys should be seeing right now. If I come back into the tracking zone, you can see I move up, I go up, I move down, we go down, up, down, up. Let's go left, let's go right. Let's go in a circle like that. Beautiful.
Let's now rotate this and view it from the top. We should get something similar to what we had before in our 2D tracking. You can see we've got the same top-down visualization like we did before. But obviously, you can't see when I'm moving it up and down here. If we view it from the side, so you should be looking from that side there, I can walk forward, I can walk backward, I can move it up, and I can move it down, and up and down and up and around in circles, whatever I really want.
This is just such a wickedly cool thing that we're doing with some off-the-shelf hardware and a Pico. I think we need to take a moment here to appreciate what we have. This is a system that can reliably locate a tag in 3D space down to about 10 centimeters of accuracy. If you dial everything in, even like a decade or two ago, a system like this would have set you back thousands, if not tens of thousands of dollars. It might be difficult to access outside of something like a research lab or a large organization. But now you can build this system with relatively inexpensive off-the-shelf maker-tier hardware, and that is pretty incredible.
Of all the wonderful pieces of maker tech that have come across my table, this is by far one of the coolest and the one that has blown me the most away. It just works. We can get a system like this going in a few minutes, really.
The fact that accurate 3D spatial tracking can now be considered a maker-level technology is just really crazy. It is an incredible time to be a maker.
Well, I think that about wraps us up now with our little ultra-wideband ventures. You are now equipped with the knowledge, resources, and demo code to go and do anything from measuring distance between a few points to full 3D spatial tracking, which is a really fun and really helpful tool to have in your maker toolbox. Feel free to take any demo code we have here in the written guide and use it however you want in your projects. We designed it to be a nice jumping-off point so you can take it and run it and do your own thing.
If you do make something cool with it though, or you just need a hand with anything we covered in this video, feel free to head on over to our community forums. We're all makers over there, and we're happy to help. Till next time though, happy making.
I think I said "lobsticles," but we go to the width of the room, which is the camera. Ah, jump scare. Lobsticles.
Makers love reviews as much as you do, please follow this link to review the products you have purchased.