Accurate positioning


Home > Documentation > Tutorials > Tutorial 4: Multitag positioning

Tutorial 4: Multitag positioning

Go to Arduino versionGo to Python version

Multitag positioning

The multitag positioning is an extension of tutorial 2, where we went over the positioning of a single device, and this being an extension is also visible in the code. Therefore, this tutorial will seem rather short and will go over the additions to allow for multitag. It is thus essential to follow that tutorial first.

For this tutorial you'll need an Arduino, at least four anchors and at least three other powered devices. These can be either tags or anchors, but remember that anchors don't have an IMU.
Open up the multitag positioning example in the Arduino IDE under File > Examples > Pozyx > multitag_positioning.

For this tutorial you'll need at least four anchors and at least three other powered devices. These can be either tags or anchors, but remember that anchors don't have an IMU.
If all tools are installed, open up multitag_positioning.py in the Pozyx library’s tutorial folder. Probably, the path to this file will be "Downloads/Pozyx-Python-library/tutorials/multitag_positioning.py". You can run the script from either command line or a text editor that allows running the scripts as well. If you're on Windows and have installed Python, you might be able to simply double-click it. If you you get an error, you likely forgot to install pythonosc, you can do this easily using pip install python-osc.

Plug and play

Looking at the parameters of the multitag positioning, you will see one major addition over the regular positioning example, namely the tags parameter which replaced the remote_id and remote parameters. In this list, you'll have to write the IDs of the remote devices you'll be using. For your anchors, use the setup you measured out in the positioning tutorial. You can also again choose the dimension and algorithm used for the positioning.

There is also the num_tags parameter, which you'll need to change to the size of your tags array.

int num_tags = 3;
  uint16_t tags[3] = {0x0001, 0x0002, 0x0003};
tags=[0x0001, 0x0002, 0x0003]        # remote tags

Once you put the IDs of your tags here, you can start with multitag positioning. You can use the positioning Processing sketch straight from the bat as well if you set your use_processing to true and set your Processing serial and port correctly. However, reading the terminal output offers a more deterministic way of knowing whether you've got it working.

Code additions and changes

As this is an extension of the ready to localize tutorial, the code has been modified to support multiple remote devices through the added tags parameter. Printing both error and position now takes an additional parameter: the ID of the device we're working with.

Anchor configuration

Each device needs to be configured with the anchors to successfully perform positioning. The anchor configuration is performed on every device using setAnchorsManual, which iterates over every remote device, and feedback on this configuration is printed.

void setAnchorsManual(){
  for (int i = 0; i < num_tags; i++){
    int status = Pozyx.clearDevices(tags[i]);
    for(int i = 0; i < num_anchors; i++){
      device_coordinates_t anchor;
      anchor.network_id = anchors[i];
      anchor.flag = 0x1;
      anchor.pos.x = anchors_x[i];
      anchor.pos.y = anchors_y[i];
      anchor.pos.z = heights[i];
      status &= Pozyx.addDevice(anchor, tags[i]);
    if (status == POZYX_SUCCESS){
      Serial.print("Configuring ID 0x");
      Serial.print(tags[i], HEX);
      Serial.println(" success!");
      printErrorCode("configuration", tags[i]);
def setAnchorsManual(self):
    """Adds the manually measured anchors to the Pozyx's device list one for one."""
    for tag in self.tags:
        status = self.pozyx.clearDevices(tag)
        for anchor in self.anchors:
            status &= self.pozyx.addDevice(anchor, tag)
        if len(anchors) > 4:
            status &= self.pozyx.setSelectionOfAnchors(POZYX_ANCHOR_SEL_AUTO, len(anchors))
        self.printConfigurationResult(status, tag)

Positioning loop

Positioning is done in the same way as the anchor configuration: every tag gets its turn. If successful, the position is printed and otherwise an error message gets printed. This is effectively a TDMA approach, where the remote devices won't interfere with each other, unlike if you perform positioning on different devices at the same time, which will not work.

void loop(){
  for (int i = 0; i < num_tags; i++){
    coordinates_t position;
    int status = Pozyx.doRemotePositioning(tags[i], &position, dimension, height, algorithm);
    if (status == POZYX_SUCCESS){
    // prints out the result
    printCoordinates(position, tags[i]);
      // prints out the error code
      printErrorCode("positioning", tags[i]);
def loop(self):
    """Performs positioning and prints the results."""
    for tag in self.tags:
        position = Coordinates()
        status = self.pozyx.doPositioning(
            position, self.dimension, self.height, self.algorithm, remote_id=tag)
        if status == POZYX_SUCCESS:
            self.printPublishPosition(position, tag)
            self.printPublishErrorCode("positioning", tag)


This is identical to the single tag positioning, and the same Processing sketch can be re-used for multitag. The same format is also reused, so if you made your own visualisation using the same format, you should be able to quickly enable multitag in your own application when parsing on the device ID.

Caveats and closing remarks

  • Positioning multiple devices at once is performed in a TDMA manner so that they don't interfere with each other. If your devices crash, try adding a small delay between the devices positioning to add robustness.
  • Since you're using TDMA, you're splitting the update rate between the different devices. If you'd start with 24 Hz for a single device, you'd get at most 12 Hz per device if you're using two devices on the same UWB settings. 8 Hz if you're using three, and so on. Depending on your usecase, this could be important.
  • Having more devices in a line-of-sight of both your master device and your anchors might be harder depending on your use case. Account for this to smartly set up your anchors and master.
  • If your area gets larger and you want to maintain a good update rate, adding more anchors which will loosen the constraints on your UWB settings is recommended.

Now that you finished all the tutorials, you should be all set for any usecase implementation that Pozyx is currently capable of. If you have any questions, remarks, or problems with the tutorials, please mail to support@pozyx.io

Home > Documentation > Tutorials > Tutorial 4: Multitag positioning