jremington / UWB-Indoor-Localization_Arduino

Open source Indoor localization using Arduino and ESP32_UWB tags + anchors
GNU General Public License v3.0
143 stars 37 forks source link

Problem when connecting more than 4 anchors and 1 tag #22

Open santiagocano298366 opened 3 months ago

santiagocano298366 commented 3 months ago

I have a problem when connecting more than 4 anchors, I am using a decawave DW1000 module and I don't know how to modify the code to show me the location with more than 4 anchors, at the moment I want to test it with 6 anchors and a tag.

What parameters should I modify, or what part of the code or library should I change to make it work with 6 anchors?

jremington commented 3 months ago

Unfortunately, the DW1000 library by Thomas Trojer has one or more bugs and does not support more than five devices.

Various people have looked, but no one seems to know what the problem is.

pizzo00 commented 3 months ago

The problem is that the tag is telling the anchors when to respond in order to avoid packet collision and this information is stored on the packet. The packet has a maximum size and every anchor information occupies some space.

I have modified the libraries in order to have multiple anchors and multiple tags but I need to adapt it before publishing it to the public because at the moment it has some paricular feature that is specific to my use case

pizzo00 commented 3 months ago

@jremington I have re-write and changes the library in various part, if you want we can publish it in this repo under another folder, or we can create a github organization to work on it

pizzo00 commented 3 months ago

For example:

jremington commented 3 months ago

Sounds fantastic! I would be delighted to add another library folder for your version, or once tested, just replace the existing ones. I have to modify the trilateration code to accommodate more anchors as well.

I have no experience with creating a github team but am happy to learn how.

russelh15 commented 3 months ago

This sounds promising!

@pizzo00 Do you have the code published anywhere? I help test if needed. I have 6 chips in total, so I can test with 4 anchors and 2 tags, or 5 anchors and 1 tag.

anthony211212 commented 2 months ago

Do you encounter occasional random values in the distance measurements when you increase the number of nodes? If not, how did you prevent this?

jremington commented 2 months ago

Yes, occasionally there are errors in the distance measurements. Errors cannot be prevented, only recognized and ignored.

pizzo00 commented 2 months ago

Sounds fantastic! I would be delighted to add another library folder for your version, or once tested, just replace the existing ones. I have to modify the trilateration code to accommodate more anchors as well.

I have no experience with creating a github team but am happy to learn how.

Maybe the best solution is to add a folder to this repo, I will prepare a pull request as soon as possible

pizzo00 commented 2 months ago

@jremington I have created pull request #23

hsutzu commented 2 months ago

Hi, I am using 4 anchors and 1 tag, and when I use them at the same time, I find out there is a large error, for example, it stayed at 1.5 meters, but suddenly it jumped to 33.7 meters, and then dropped slowly, after that it still may turn into large range number occasionally, has anyone had the same problem and have any solutions on it?

I want to do the 3D localization but with this error, I cannot do the localization, since the original anchor to tag range is wrong, and the filter did not help.

anthony211212 commented 2 months ago

First of all, can the antennas clearly see each other? Also, which tag code are you using? Lastly, are the coordinates you've entered for the anchors correct?

jremington commented 2 months ago

I occasionally see large distance errors, but they don't "drop slowly" and can be filtered out using a median filter.

Did you calibrate the antenna delay for each anchor? While doing that, you have a good opportunity to test each anchor+ tag setup and check whether the distance reports are well behaved and stable.

hsutzu commented 2 months ago

First of all, can the antennas clearly see each other? Also, which tag code are you using? Lastly, are the coordinates you've entered for the anchors correct?

yes, I have make sure the antenna able to see each other, the following method of mean error is how I calibrate them, however when I use one anchor to tag the error can be very small and won't have occasionally error, since I saw you mention about this problem, so i think maybe you know the solution of it, I've been bother for this problem for a long time my tag code is as following:

#include <SPI.h>
#include "DW1000Ranging.h" 
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <WiFiUdp.h>
#include "link.h"

// Define the pin connected to the output of the voltage divider
#define VOLTAGE_PIN 36  // GPIO 35 (ADC1_CH7) is commonly used for analog input

#define TAG_ADDR "7D:00:22:EA:82:60:3B:9B" // UWB Tag Address

#define AVERAGE_ERROR 1.0  // Define a default mean error if the anchor is not found

// SPI Pins for UWB
#define SPI_SCK 18
#define SPI_MISO 19
#define SPI_MOSI 23

// UWB Pin Definitions
#define UWB_RST 27  // Reset pin
#define UWB_IRQ 34  // IRQ pin
#define UWB_SS 21   // SPI select pin

// I2C Pins for OLED Display
#define I2C_SDA 4
#define I2C_SCL 5

// WiFi Credentials
const char *ssid = "BBLAB_New";
const char *password = "ntubime405";
const char *host = "192.168.0.137"; // The IP of the Python UDP listener
const int udpPort = 8080;           // The port of the Python UDP listener
unsigned long primaryTimestamp = 0;

WiFiUDP udp;  // UDP instance

// OLED Display Settings
Adafruit_SSD1306 display(128, 64, &Wire, -1);

// Mean Errors for Anchors
struct AnchorInfo {
    String address;
    float meanError;
};

// List of anchors and their mean errors
AnchorInfo anchors[] = {
    {"82175BD5A99AE29C", 0.94}, // Anchor 1
    {"83175BD5A99AE29D", 0.91}, // Anchor 2
    {"85175BD5A99AE29A", 0.97}, // Anchor 3
    {"84175BD5A99AE29B", 1.03}  // Anchor 4
};

// Link structure pointer
struct MyLink *uwb_data;
long runtime = 0;
String all_json = "";
unsigned long lastSendTime = 0;  // Track the last time a message was sent

void setup() {
    Serial.begin(115200);

    // Initialize I2C for OLED Display
    Wire.begin(I2C_SDA, I2C_SCL);
    if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
        Serial.println(F("SSD1306 allocation failed"));
        for (;;);
    }
    display.clearDisplay();

    // Show initial logo on OLED
    logoshow();

    // Measure and display the voltage before connecting to Wi-Fi
    measure_and_display_voltage();

    // Initialize SPI for UWB Communication
    SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);

    // UWB Module Initialization
    DW1000Ranging.initCommunication(UWB_RST, UWB_SS, UWB_IRQ); // Initialize communication with Reset, CS, and IRQ pins
    DW1000Ranging.attachNewRange(newRange);
    DW1000Ranging.attachNewDevice(newDevice);
    DW1000Ranging.attachInactiveDevice(inactiveDevice);
    DW1000Ranging.startAsTag(TAG_ADDR, DW1000.MODE_LONGDATA_RANGE_LOWPOWER);

    // Initialize WiFi connection
    WiFi.mode(WIFI_STA);
    WiFi.setSleep(false);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("Connected");
    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());

    // Initialize UWB data link structure
    uwb_data = init_link();

    // Initialize UDP
    udp.begin(udpPort);
}

void loop() {

    DW1000Ranging.loop();

    // Update display and send data every second
    if (millis() - runtime >= 1000) {
        display_uwb(uwb_data);
        make_link_json(uwb_data, &all_json);
        send_udp(&all_json);
        runtime += 1000;  // Ensure fixed 1-second intervals
    }
}

// Function to measure the voltage and display it on the OLED
void measure_and_display_voltage() {
    // Read the raw ADC value (0 - 4095)
    int adc_value = analogRead(VOLTAGE_PIN);

    // Convert the ADC value to actual voltage (3.3V reference) for a voltage divider that divides 5V to 2.5V
    float voltage = adc_value * (3.3 / 4095.0) * 2;  // Multiply by 2 to account for the voltage divider

    // Display the voltage on the OLED
    display.setTextSize(2);
    display.setCursor(0, 48); // Position below the other content
    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);
    display.print("V: ");
    display.print(voltage);
    display.println("V");
    display.display();

    // For debugging purposes
    Serial.print("Measured Voltage: ");
    Serial.print(voltage);
    Serial.println("V");
}

// Function to find the mean error based on the anchor address
float getMeanError(String anchorAddress) {
    for (int i = 0; i < sizeof(anchors)/sizeof(anchors[0]); i++) {
        if (anchors[i].address == anchorAddress) {
            return anchors[i].meanError;
        }
    }
    return AVERAGE_ERROR; // Default mean error if the anchor is not found
}

// UWB Range Callback
void newRange() {
    String anchorAddress = String(DW1000Ranging.getDistantDevice()->getShortAddress(), HEX);
    anchorAddress.toUpperCase(); // Convert to uppercase for consistency
    float meanError = getMeanError(anchorAddress);

    float measuredRange = DW1000Ranging.getDistantDevice()->getRange();
    float correctedRange = measuredRange - meanError;  // Apply the specific mean error
    unsigned long timestamp = micros();  // Use micros() for precise timing
    // Check if this is the primary anchor
    if (anchorAddress == "82175BD5A99AE29C") {  // Example: First anchor as primary
        primaryTimestamp = currentTimestamp;
    }

    Serial.print("From: ");
    Serial.print(anchorAddress);
    Serial.print("\t Corrected Range: ");
    Serial.print(correctedRange, 2);  // Print with two decimal places
    Serial.print(" m");
    Serial.print("\t RX power: ");
    Serial.print(DW1000Ranging.getDistantDevice()->getRXPower());
    Serial.print(" dBm");
    Serial.print("\t Timestamp: ");
    Serial.println(primaryTimestamp);  // Print the timestamp

    // Update the link data structure with the new corrected range and timestamp
    fresh_link(uwb_data, DW1000Ranging.getDistantDevice()->getShortAddress(), correctedRange, DW1000Ranging.getDistantDevice()->getRXPower(), primaryTimestamp);

    // Send UDP packet immediately after new measurement
    make_link_json(uwb_data, &all_json);
    send_udp(&all_json);
}

// UWB New Device Callback
void newDevice(DW1000Device *device) {
    Serial.print("Ranging init; 1 device added! -> Short address: ");
    Serial.println(device->getShortAddress(), HEX);

    // Add the new device to the link structure
    add_link(uwb_data, device->getShortAddress());
}

// UWB Inactive Device Callback
void inactiveDevice(DW1000Device *device) {
    Serial.print("Removing inactive device: ");
    Serial.println(device->getShortAddress(), HEX);

    // Remove the inactive device from the link structure
    delete_link(uwb_data, device->getShortAddress());
}

void send_udp(String *msg_json) {
    udp.beginPacket(host, udpPort); // Begin UDP packet

    *msg_json += "\"Timestamp\":" + String(primaryTimestamp) + ",";
    // Convert the string to a byte array and send it
    //udp.write((const uint8_t *)msg_json->c_str(), msg_json->length());

    udp.endPacket(); // End and send the packet
    Serial.println("UDP data sent");
}

// OLED Logo Display
void logoshow(void) {
    display.clearDisplay();
    display.setTextSize(2);              // Normal 1:1 pixel scale
    display.setTextColor(SSD1306_WHITE); // Draw white text
    display.setCursor(0, 0);             // Start at top-left corner
    display.println(F("Makerfabs"));
    display.setTextSize(1);
    display.setCursor(0, 20);            // Start at top-left corner
    display.println(F("DW1000 DEMO"));
    display.display();
    delay(2000);
}

// Function to Display UWB Data on OLED
void display_uwb(struct MyLink *p) {
    struct MyLink *temp = p;
    int row = 0;

    display.clearDisplay();
    display.setTextColor(SSD1306_WHITE);
    display.setTextSize(1); // Smaller text size to fit more data

    if (temp->next == NULL) {
        display.setTextSize(2);
        display.setCursor(0, 0);
        display.println("No Anchor");
        display.display();
        return;
    }

    while (temp->next != NULL) {
        temp = temp->next;
        char c[40];

        sprintf(c, "Addr: %X\nRange: %.2fm", temp->anchor_addr, temp->range[0]);
        display.setCursor(0, row * 16); // Adjust row spacing for multiple anchors
        display.println(c);

        if (++row >= 4) { // Limit to 4 rows to fit the screen
            break;
        }
    }
    display.display();
}

Is the coordinate that you mention the placement of the anchors' coordinates? If so, I had make sure the coordinate is right!

anthony211212 commented 2 months ago

First, please try the standard codes for trilateration in a 2D scenario with 4 anchors and 1 tag. You likely won't encounter a significant error.

hsutzu commented 2 months ago

First, please try the standard codes for trilateration in a 2D scenario with 4 anchors and 1 tag. You likely won't encounter a significant error.

I got it. And I was thinking maybe I should using Antenna delay to do the calibration not using mean error, maybe the error is caused by it. So maybe when you using four anchors and 1 tag you won't receive large error number?

I think maybe it's not because 2D localization, since the origin each anchors to tag range data got a large error, so the localization won't be accurate.

hsutzu commented 2 months ago

I occasionally see large distance errors, but they don't "drop slowly" and can be filtered out using a median filter.

Did you calibrate the antenna delay for each anchor? While doing that, you have a good opportunity to test each anchor+ tag setup and check whether the distance reports are well behaved and stable.

I was calibrated them by mean error, I measure 1 meter and using 10 centimeters as one measure point, and counting their mean error, and for each anchor I measure one mean error, then, I abstract the mean error as the corrected range.

I did using antenna delay calibration, however, because it was not get the minimum mean error comparing with the mean error calibration method, so I did not use it eventually.

I was thinking maybe I should change it to antenna delay calibration and maybe my problem could be solved.

anthony211212 commented 2 months ago

Yes, that's why I first suggested trying the standard code. Secondly, you need to adjust the antenna delay values for calibration. The error starting high and gradually decreasing could indeed be due to the average error variable, as you mentioned. If you've used it within a loop, such a change in error is likely. By first trying the standard code, you can ensure that your system is set up correctly. When trying the standard code, it would be more accurate to start with the 2D version. Later, you can update and use the 3D version.

hsutzu commented 2 months ago

Currently, I changed the calibration method to Antenna delay, and I using the code doing tag 2D positioning, however, I still get some errors and it is hard to move the tag with a computer connection. Which is hard to see the moving trajectory of tag.

I was using udp forward to transmit the data to the local computer, and I think maybe a big error was caused by it.

jremington commented 1 month ago

I am finally in a position to try out the new version of the DW1000 library recently uploaded by Pizzolato Davide, and as a first test tried to compile the original ESP32_UWB_tag3D_4A example. Unfortunately, many library errors were emitted, as follows.

@pizzo00 Please upload example code that will compile without errors, and describe any changes in function names and call arguments made in the library.

`Arduino: 1.8.19 (Windows 10), TD: 1.58, Board: "ESP32 Dev Module, Disabled, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, Core 1, Core 1, None, Disabled"

C:\Users\Jim\Desktop\UWB\ESP32_UWB_tag3D_4A\ESP32_UWB_tag3D_4A.ino: In function 'void setup()': ESP32_UWB_tag3D_4A:52:17: error: 'static void DW1000RangingClass::initCommunication(uint8_t, uint8_t, uint8_t)' is private within this context DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ); //Reset, CS, IRQ pin ^~~~~~~~~~~~~~~~~ In file included from C:\Users\Jim\Desktop\UWB\ESP32_UWB_tag3D_4A\ESP32_UWB_tag3D_4A.ino:6: C:\Users\Jim\Desktop\UWB\libraries\DW1000_library_pizzo00\src/DW1000Ranging.h:97:17: note: declared private here static void initCommunication(uint8_t myRST, uint8_t mySS, uint8_t myIRQ); ^~~~~~~~~~~~~~~~~ ESP32_UWB_tag3D_4A:52:59: error: 'static void DW1000RangingClass::initCommunication(uint8_t, uint8_t, uint8_t)' is private within this context DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ); //Reset, CS, IRQ pin ^ In file included from C:\Users\Jim\Desktop\UWB\ESP32_UWB_tag3D_4A\ESP32_UWB_tag3D_4A.ino:6: C:\Users\Jim\Desktop\UWB\libraries\DW1000_library_pizzo00\src/DW1000Ranging.h:97:17: note: declared private here static void initCommunication(uint8_t myRST, uint8_t mySS, uint8_t myIRQ); ^~~~~~~~~~~~~~~~~ ESP32_UWB_tag3D_4A:54:32: error: invalid conversion from 'void (*)()' to 'void (*)(DW1000Device*)' [-fpermissive] DW1000Ranging.attachNewRange(newRange); ^~~~~~~~ In file included from C:\Users\Jim\Desktop\UWB\ESP32_UWB_tag3D_4A\ESP32_UWB_tag3D_4A.ino:6: C:\Users\Jim\Desktop\UWB\libraries\DW1000_library_pizzo00\src/DW1000Ranging.h:89:36: note: initializing argument 1 of 'static void DW1000RangingClass::attachNewRange(void (*)(DW1000Device*))' static void attachNewRange(void (*handleNewRange)(DW1000Device *)) { _handleNewRange = handleNewRange; }; ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ESP32_UWB_tag3D_4A:60:17: error: 'class DW1000RangingClass' has no member named 'startAsTag' DW1000Ranging.startAsTag(tag_addr, DW1000.MODE_LONGDATA_RANGE_LOWPOWER, false); ^~~~~~~~~~ C:\Users\Jim\Desktop\UWB\ESP32_UWB_tag3D_4A\ESP32_UWB_tag3D_4A.ino: In function 'void newRange()': ESP32_UWB_tag3D_4A:76:29: error: 'class DW1000RangingClass' has no member named 'getDistantDevice'; did you mean 'searchDistantDevice'? int index = DW1000Ranging.getDistantDevice()->getShortAddress() & 0x07; //expect devices 1 to 7 ^~~~~~~~~~~~~~~~ searchDistantDevice ESP32_UWB_tag3D_4A:79:33: error: 'class DW1000RangingClass' has no member named 'getDistantDevice'; did you mean 'searchDistantDevice'? float range = DW1000Ranging.getDistantDevice()->getRange(); ^~~~~~~~~~~~~~~~ searchDistantDevice Using library SPI at version 2.0.0 in folder: C:\Users\Jim\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.13\libraries\SPI Using library DW1000_library_pizzo00 at version 1.0 in folder: C:\Users\Jim\Desktop\UWB\libraries\DW1000_library_pizzo00 exit status 1 'static void DW1000RangingClass::initCommunication(uint8_t, uint8_t, uint8_t)' is private within this context `
pizzo00 commented 1 month ago

Oh, sorry @jremington, I forgot to mention that now it is sufficient to call the function DW1000Ranging.init, with the type, the short address, a mac address, a flag for high_power, the transmission mode, and the usual parameters.

static constexpr byte MY_MODE[] = {DW1000.TRX_RATE_6800KBPS, DW1000.TX_PULSE_FREQ_16MHZ, DW1000.TX_PREAMBLE_LEN_64};

void setup()
{
    Serial.begin(115200);
    delay(1000);

    uint16_t shortMacAddress = 118;  //"76:00";
    char *wifiMacAddress = "00:00:00:AA:AA:AA"; //I get it from the esp board through WiFi.macAddress();

    // init the configuration
    SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
#if C_TAG
    DW1000Ranging.init(BoardType::TAG, shortMacAddress, wifiMacAddress, true, MY_MODE, PIN_RST, PIN_SS, PIN_IRQ);
#elif C_ANCHOR
    DW1000Ranging.init(BoardType::ANCHOR, shortMacAddress, wifiMacAddress, true, MY_MODE, PIN_RST, PIN_SS, PIN_IRQ);
#endif
}
pizzo00 commented 1 month ago

@jremington also there is no need for DW1000Ranging.getDistantDevice() because the device is passed as a parameter to void newRange(DW1000Device *device)

jremington commented 1 month ago

@pizzo00 For the benefit of the many people who are interested, please upload complete examples of tag and anchor code that will compile and run without errors, and describe any changes in function names and call arguments made in the library.

Perhaps in an "examples" folder added to the new library folder. Thanks!

kamtatli commented 1 month ago

@pizzo00 I try to use your library and the sample, but it show time out , can not communicate betweent anchor and tag. image

jremington commented 1 month ago

@pizzo00

I've been working with the latest version of your DW1000 library, the two examples you kindly uploaded, and have encountered a number of errors with my setup. I'm using what I believe to be the latest stable ESP32 board package from Espressif.

Compilation attempts produced three "warnings treated as errors" in DW1000Ranging.cpp, with these calls: memcpy(&_networkDevices[_networkDevicesNumber], device, sizeof(DW1000Device));

Fixed by casting: memcpy((void *)&_networkDevices[_networkDevicesNumber], device, sizeof(DW1000Device)); //sjr added (void *)

Now, a tag and anchor #1 are running, and they are talking to each other, but I consistently get "RANGE ON TIMEOUT" errors.

Antenna delays were all the default of the library, 16384, separation between the modules on the bench is about 1 m.

Keep in mind that I'm using the original UWB modules from MakerFabs, https://www.makerfabs.com/esp32-uwb-ultra-wideband.html so I'm wondering if there are changes in the newer devices, and whether you modified the library code to take the newer ones into account. Have you tested your library with the originals?

Advice appreciated!

Examples of dialog (anchor):

Delete inactive device: 7D
<=BLINK
RANGING_INIT
<=POLL
POLL_ACK
<=POLL
POLL_ACK
<=POLL
POLL_ACK
<=POLL
POLL_ACK
<=BLINK
Delete inactive device: 7D

(tag)

RANGING_INIT from 81
Device added: 81
POLL
RANGE ON TIMEOUT
RANGE
POLL
RANGE ON TIMEOUT
RANGE
POLL
RANGE ON TIMEOUT
RANGE
POLL
RANGE ON TIMEOUT
RANGE
delete inactive device: 81
pizzo00 commented 1 month ago

I spotted the error, I tightened the response time in order to reach a better refresh frequency. And in my implementation I use this communication parameters (because they are faster): static constexpr byte MY_MODE[] = {DW1000.TRX_RATE_6800KBPS, DW1000.TX_PULSE_FREQ_16MHZ, DW1000.TX_PREAMBLE_LEN_64};

So with the default parameters the anchor doesn't respond in time. I can update the example to use the parameters that were used to calibrate the response times and add a note that if you change the parameters you should update the response times.

jremington commented 4 weeks ago

@pizzo00 No change in behavior, still getting "RANGE ON TIMEOUT" when compiling and linking with the most recent version of your library.

I'm still using this setup mode, DW1000Ranging.init(BoardType::TAG, shortAddress, macAddress, false, DW1000.MODE_LONGDATA_RANGE_LOWPOWER, PIN_RST, PIN_SS, PIN_IRQ);

as it does not make sense to me to force all users to adapt code to a specific set of parameters, without a clear explanation of the considerations involved in selecting the timeout, as suggested here:

// NOTE: Any change on this parameters will affect the transmission time of the packets
// So if you change this parameters you should also change the response times on the DW1000 library 
// (actual response times are based on experience made with these parameters)
static constexpr byte MY_MODE[] = {DW1000.TRX_RATE_6800KBPS, DW1000.TX_PULSE_FREQ_16MHZ, DW1000.TX_PREAMBLE_LEN_64};

I would be grateful if you would suggest (or better, implement) timeouts that are appropriate to the long ago established settings.

It is still not clear to me whether you are testing the library with the original ESP32 UWB modules from MakerFabs.

jhoydich commented 3 weeks ago

Looks like you guys figured this out, but the issue with >4 anchors is due to the transmitRange function. Particularly

for(uint8_t i = 0; i < _networkDevicesNumber; i++) {
            //we write the short address of our device:
            memcpy(data+SHORT_MAC_LEN+2+17*i, _networkDevices[i].getByteShortAddress(), 2); 
            //we get the device which correspond to the message which was sent (need to be filtered by MAC address)
            _networkDevices[i].timeRangeSent = timeRangeSent;
            _networkDevices[i].timePollSent.getTimestamp(data+SHORT_MAC_LEN+4+17*i);
            _networkDevices[i].timePollAckReceived.getTimestamp(data+SHORT_MAC_LEN+9+17*i);
            _networkDevices[i].timeRangeSent.getTimestamp(data+SHORT_MAC_LEN+14+17*i);

        }

data has length 90, and SHORT_MAC_LEN is 9 of those bytes. Each devices message is 17 bytes long, so you can only fit 4 anchors before data overflows. This can be fixed by putting the PollSent and RangeSent timestamp once in the data buffer, since it'll be the same for every device, saving you 8 bytes per device. I think you can get up to ~11 anchors with this alteration (I've only tried up to 5 I'm pretty sure).

There's also an annoying int overflow in the function that determines the reply time for the anchors for over 4 or 5 anchors. It provides the reply time in nano or micro seconds, but the numbers are round and large, so you can divide by one thousand on the tag side and mulitply by a thousand on the anchor side and have perfectly good results (On second thought, this will still overflow) :p

For anyone doing 2D (and even 3D) localization, I highly recommend trying the particle filter, pretty easy algorithm to program, doesn't suffer the unsolvable issue of some systems of equations approach, and is pretty dang accurate.

jremington commented 3 weeks ago

Thanks for those clarifying comments! I agree, and we need to finalize some details with the timing and message content in order to expand the number of anchors. It isn't clear what a practical upper limit might be for the number of anchors, and a modest increase would certainly be useful.

I'm quite happy with the simple least squares localization algorithm, as it is very fast, and no obvious instability has popped up in reasonably extensive field tests.

pizzo00 commented 3 weeks ago

It is still not clear to me whether you are testing the library with the original ESP32 UWB modules from MakerFabs.

Yes I am using the high power version of the makerfabs modules.

I would be grateful if you would suggest (or better, implement) timeouts that are appropriate to the long ago established settings.

As soon as possible I will adapt the timeouts for the standard settings

jremington commented 2 weeks ago

I am using the original, UWB modules. As stated above:

Keep in mind that I'm using the original UWB modules from MakerFabs, https://www.makerfabs.com/esp32-uwb-ultra-wideband.html

Note the excellent suggestions made recently @jhoydich, particularly regarding the counter overflow issue. I'm thinking that it may be reasonable to restrict the trilateration algorithm to use 4 to at most 6 anchors, selected from more (if available) by RSSI in descending order.

It is still not clear to me whether you are testing the library with the original ESP32 UWB modules from MakerFabs.

Yes I am using the high power version of the makerfabs modules.

I would be grateful if you would suggest (or better, implement) timeouts that are appropriate to the long ago established settings.

As soon as possible I will adapt the timeouts for the standard settings

— Reply to this email directly, view it on GitHubhttps://urldefense.com/v3/__https://github.com/jremington/UWB-Indoor-Localization_Arduino/issues/22*issuecomment-2435175881__;Iw!!C5qS4YX3!HX7Q3LZ2TZyyOGszHFgdCRSBxxtEB6dTTy4oTT3yTV5anPnyYDCruIX1I3juXPAO-Nrot1uMfBt5yDElEQos0pepA9U$, or unsubscribehttps://urldefense.com/v3/__https://github.com/notifications/unsubscribe-auth/ABKA7LJNGO5M7L3QIWCYWYTZ5DSR5AVCNFSM6AAAAABMHGNVZCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMZVGE3TKOBYGE__;!!C5qS4YX3!HX7Q3LZ2TZyyOGszHFgdCRSBxxtEB6dTTy4oTT3yTV5anPnyYDCruIX1I3juXPAO-Nrot1uMfBt5yDElEQosYntVdmM$. You are receiving this because you were mentioned.Message ID: @.***>

Rkramkhirin commented 3 days ago

Hi , I use your library DW1000_library_pizzo00 (Example ESP32_UWB_pizzo00_tag & ESP32_UWB_setup_anchor) In my case, I use 4 Anchor and 3 Tag and I have some problems with communication sometimes the rang of Anchor is lost sometimes rang error like the table. image

Could you please advice on my case?

anthony211212 commented 3 days ago

What is your frequency for measurement?

Rkramkhirin commented 3 days ago

What is your frequency for measurement? Hi, Thank you for your reply. I use the default frequency from the example static constexpr byte MY_MODE[] = {DW1000.TRX_RATE_6800KBPS, DW1000.TX_PULSE_FREQ_16MHZ, DW1000.TX_PREAMBLE_LEN_64};

anthony211212 commented 3 days ago

Can you control arduino serial monitor screen?

Rkramkhirin commented 3 days ago

Can you control arduino serial monitor screen? Yes I can, currently I am using Arduino monitor image

anthony211212 commented 3 days ago

You need the number of distance measurements per second to understand the measurement frequency. How many distance values can you read per second?

Rkramkhirin commented 2 days ago

You need the number of distance measurements per second to understand the measurement frequency. How many distance values can you read per second? 1 value per second. I think this problem is about the slot time.