# How do we reduce variation of the coordinates.

Hello everyone, i am doing a indoor positioning project, using 4 anchors, 1 pozyx tag and 1 Arduino Uno R3. I can successfully retrieve the coordinates of the position of the tag(mounted on the arduino ) when i move it around. However, when i place it on the table without moving it the coordinates doesn’t stay or rather it varies a lot like around +/- 200.?

Does anyone know how to reduce the variations and get a more accurate reading.?

I appreciate your help Thank you very much

Have you considered averaging the values?

Paul

Values like +/- 200 are completely meaningless without stating the units of measurement.

Hello Paul_KD7HB & jremington Thanks for the reply.

Yes, I have tried averaging the values, but it still deviates too much.

Sorry jremington for my negligence, it is in millimetres. +/- 200mm

Pozyx claims +/- 1 cm accuracy, but you claim to be getting +/- 20 cm.

That is a problem that I would bring to the attention of the Pozyx people.

I do have trouble believing that averaging does not help. Averaging should reduce the standard error by a factor of sqrt(N), where N is the number of samples averaged. So, averaging 16 samples should reduce the standard deviation to +/- 5 cm.

I am a little confused about your statement about implementing a square root to lower the standard deviation.

This is my code
:

``````#include <Pozyx.h>
#include <Pozyx_definitions.h>
#include <Wire.h>

////////////////////////////////////////////////
////////////////// PARAMETERS //////////////////
////////////////////////////////////////////////

uint16_t remote_id ;
boolean use_processing = false;
bool remote = false;
coordinates_t coor;

const uint8_t num_anchors = 4;                                           // the number of anchors
uint16_t anchors_id[num_anchors] = {0x6e6d, 0x6923, 0x6961, 0x6969};     // the network id of the anchors: change these to the network ids of your anchors.
int32_t anchors_x[num_anchors] =   {0,       0,      3420,    3380};       // anchor x-coorindates in mm
int32_t anchors_y[num_anchors] =   {0,      6880,      0,     6130};       // anchor y-coordinates in mm
int32_t heights[num_anchors]   =   {900,      470,     1060,    760};       // anchor z-coordinates in mm

uint8_t algorithm = POZYX_POS_ALG_TRACKING;                              // positioning algorithm to use. try POZYX_POS_ALG_TRACKING for fast moving objects.
uint8_t dimension = POZYX_3D;                                            // positioning dimension. ( 2.5D fixed height, 3D variable height)

int  setOperationMode(POZYX_TAG_MODE, remote_id);                        //to tell the system that the local device is a tag and not a anchor

////////////////////////////////////////////////

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

while(!Serial); // for the Arduino Leonardo/Micro only

Pozyx.begin();

if(!remote){
remote_id = NULL;
}

Serial.println(F("----------POZYX POSITIONING V1.1----------"));
Serial.println(F("NOTES:"));
Serial.println(F("- No parameters required."));
Serial.println();
Serial.println(F("- System will auto start anchor configuration"));
Serial.println();
Serial.println(F("- System will auto start positioning"));
Serial.println(F("----------POZYX POSITIONING V1.1----------"));
Serial.println();
Serial.println(F("Performing manual anchor configuration:"));

// clear all previous devices in the device list
Pozyx.clearDevices(remote_id);
// sets the anchor manually
setAnchorsManual();

delay(2000);
printCalibrationResult();

Serial.println(F("Starting positioning: "));
Serial.print("\n");

}

void loop(){

coordinates_t position;
int status;

Pozyx.begin();

int32_t height = coor.z;                                                      // height of device

if(remote){
status = Pozyx.doRemotePositioning(remote_id, &position, dimension, height,algorithm);
}
else{
status = Pozyx.doPositioning(&position, dimension, height, algorithm);
}
if (status == POZYX_SUCCESS){
// prints out the result
printCoordinates(position);
}

}

// prints the coordinates for either humans or for processing
void printCoordinates(coordinates_t coor){
if (remote_id == NULL){
remote_id = 0;
}

if(!use_processing){
Serial.print("POSITION 0x");
Serial.println(remote_id , HEX);
Serial.print(", x(mm): ");
Serial.print(coor.x);
Serial.print(", y(mm): ");
Serial.print(coor.y);
Serial.print(", z(mm): ");
Serial.println(coor.z);
}else{
Serial.print("POSITION 0x");
Serial.print(remote_id ,HEX);
Serial.print(",");
Serial.print(coor.x);
Serial.print(",");
Serial.print(coor.y);
Serial.print(",");
Serial.println(coor.z);
}
return;
}

// function to manually set the anchor coordinates
void setAnchorsManual(){
for(int i = 0; i < num_anchors; i++){
device_coordinates_t anchor;                     // Define-ing each anchor as a device_coordinates_t object.
anchor.network_id = anchors_id[i];
anchor.flag = 0x1;                               // choose that it is an anchor and not a tag
anchor.pos.x = anchors_x[i];
anchor.pos.y = anchors_y[i];
anchor.pos.z = heights[i];
}

}

void printCalibrationResult(){

uint8_t list_size;
int status;

status = Pozyx.getDeviceListSize(&list_size, remote_id);
Serial.print("list size: ");
Serial.println(status*list_size);

uint16_t anchors_id[list_size];
Pozyx.getDeviceIds(anchors_id, list_size, remote_id);
Serial.println(F("Calibration result:"));
Serial.print(F("Anchors found: "));
Serial.println(list_size);

coordinates_t anchor_coor;
for(int i = 0; i < list_size; i++)
{
Serial.print("ANCHOR,");
Serial.print("0x");
Serial.print(anchors_id[i], HEX);
Serial.print(",");
Pozyx.getDeviceCoordinates(anchors_id[i], &anchor_coor, remote_id);
Serial.print(anchor_coor.x);
Serial.print(",");
Serial.print(anchor_coor.y);
Serial.print(",");
Serial.println(anchor_coor.z);
}
}
``````

There is no coordinate averaging in that code. Try it and post the results.

Averaging should reduce the standard error by a factor of sqrt(N), where N is the number of samples averaged.

Hi jremington, so sorry to trouble you, but thank you so much for your effort to reply and help me.

Maybe your term of " averaging the coordinates " and mine is a little different. Averaging as in adding the coordinates and dividing.?

Averaging, as commonly understood, means to add up N numbers (for example, X-coordinates) and divide the result by N.

Choose a number for N (like 10 or 100) and proceed for X, Y and Z coordinates separately.

Hello jremington, thank you for replying. :)

Alright, i understand where you're coming from right now.

But here's another problem. Let's say for my X Axis, the value for my X Axie is stored inside the variable " coor.x "

each time the void loop() , loops, it produces different X value. So how can i code for it to add up the different X values.? Like for eg, the first time it loops, coor.x = 1000mm , second time it loops, coor.x = 1150, third time it loops coor.x = 1200. when the pozyx isnt even moving, which is the current problem now, when it doesn't move at all the X, Y and Z coordinates varies too much.

Though after each loop the value is different, the variable that stores it is the same. So i don't really know how to code for it.

I am very sure if i just change it like this, the results won't be the expected results.

if(!use_processing){

int avg_x_coor; Serial.print("POSITION 0x"); Serial.println(remote_id , HEX); Serial.print(", x(mm): "); avg_x_coor = coor.x + coor.x; Serial.print(avg_x_coor);

Serial.print(", y(mm): "); Serial.print(coor.y); Serial.print(", z(mm): "); Serial.println(coor.z); }

So i don't really know how to code for the averaging.

i understand where you're coming from now and it makes a lot of sense, just that i am not very familliar with c++ coding, thus i don't know how to code for it. Sorry if i caused a lot of trouble for you.

``````float avg_x = 0.0;
for (int i=0; i<10; i++) {
get_new_coordinates(); //or whatever is required
avg_x = avg_x + coor.x;
}
avg_x = avg_x/10.0; //calculate the average of 10 X coordinates
``````