DMW1001- Dev with Raspberry Pi4

Hi @meomap887
the RTSL system will give tou a position with the regards to the anchors. You dont need to implement your triangulation method. In this case you sill do the same as the TN does.

I would do this: For the TRLS system I would select the 0,0,0 point as the center of the robot → set AN positions against this center and then let TN calculate its position. TN will return you back the XYZ position and then you can easily calculate the distance between robot and TN. IN this case you would be fine with Listener function (it reports TN positions) and you will not need the BN.

However note that 3 anchors it the minimum for triangulation! I would recommend you to use 4 anchors.

Cheers
JK

@leapslabs , Seem that it will be easier to do. From my understanding, I need 4 anchors ion the robot as the pictures and the center (0,0) will be Anchor 3, another listener will be connected to Pi4 by the usb cable. Can we setup the position by RTLS Android App or it need to manual with Shell mode on Raspberry Pi4.

For xyz position, can I understand it as the unit is meter. For example, (1,1.5, 0.5) is that x = 1m, y = 1.5m compare to the robot as the origin (0,0). And distance d will be square root of x^2 + y^2.

Hi @meomap887
put the anchors in to the corners of the robot - it will make the RTLS easier life (it more likes it for position estimation).

You can use android app and distances are in meters.

The calculation of 3d Distance is
d = ((x2 - x1)^2 + (y2 - y1)^2 + (z2 - z1)^2)^1/2 however it you need just 2D tne you can use your equation.

Side note: as all anchors are in the same height it would not be able to recognize if the TN is above or below the anchors.

How big is the robot? How far is is from one corner to other corner?

Cheers
JK

@leaplabs The robot is just 60cm for the width and 80 cm for the length. I So If i put the anchors in the corner, it should be around 40cm from each other. Right now, I can get the data from the listener with the position of the Tag, so we can separate the x value and y value. As my understanding, we have the location every 100 us so It ispretty fast to what we need. With the tag location, is that compare to the 1 str anchor (0,0,0) or how the tag location is determine. Because we just need one anchor to compare. Until now, seem that we dont need the gateway so we dont need to use any API for the module. Is that correct?

Hi @meomap887
40cm is a quite short distance, but ti should work - try to maximize this distance. The tag update rate is maximally 100ms 8-).

The tag location is calculated against 0,0,0 coordinate (no matter where it is). You can select one anchor to be 0,0,0, or you can select 0,0,0 in the center of your robot and then calculated anchors positions against the center of your robot. It depends on your needs.

Yes, in this scenario you dont need the bridge with RPi.

Cheers
JK

@leapslabs I’m able to get it run and separate the x value, y value and calculate the distance. But I dont feel it right since my calculation is 1.1m instead of 2.5m on the app with the same location. I also want to slow down the input rate so I put the time sleep in 3s and if the result is nan I will skip it.

For some reason while it run and then suddenly stuck as lec command as figure 1. Do you know why and how we run it non stop.
Capture_1

With figure 2, It stop in the beginning and I need to rerun the program.
Capture_2

Can you help me with these problems? I really appreciate that.

Here is the code im using

#DWM Serial Parser by Brian H. | Updated 3/6/19
import serial
import time
import datetime
from math import *

DWM=serial.Serial(port=“/dev/ttyACM0”, baudrate=115200)
print(“Connected to " +DWM.name)
DWM.write(”\r\r".encode())
time.sleep(1)
DWM.write(“lec\r”.encode())
time.sleep(1)

count = 0
while True:
try:
line=DWM.readline()
print(type(line))
if(line):
print(“Line1 is”,line)
parse=line.decode().split(“,”)
print(parse)
if parse[0]==“POS”:
pos_AN0=(parse[parse.index(“D3A8”)+1],parse[parse.index(“D3A8”)+2],parse[parse.index(“D3A8”)+3])

            print(datetime.datetime.now().strftime("%H:%M:%S"),pos_AN0)
           
            #Filter X coordinate
            x_pos=parse[parse.index("POS")+3]
            #print ("Xpos",x_pos, " Type ",type(x_pos))
            new_x =float(x_pos)
            print ("x coordinate: ",new_x, " Type ",type(new_x))
           
            #Filter Y coordinate
            y_pos=parse[parse.index("POS")+4]
            #print ("Ypos",y_pos, " Type ",type(y_pos))
            new_y =float(y_pos)
            print ("y coordinate: ",new_y, " Type ",type(new_y))
           
            Distance = sqrt(new_x**2 + new_y**2)
            print("Distance is ",Distance)
            print()
           
            #Skip if result is nan, otherwise will take value in 3 second
            if (x_pos !="nan"):
                time.sleep(3)
            else:
                time.sleep(0.1)
            count = count +1
            print("count time:" ,count)


           
           
        else:
            print("Distance not calculated: ",line.decode())
except Exception as ex:
    print(ex)
    break

DWM.write(“\r”.encode())
DWM.close()


@leapslabs I have one more question on delaying the input, Because the updating rate is 100ms and it is really too fast for my robot which I need the update location in every 1s. Currently I use sleep function but it will delay the program also. Is there any better way to deal with that and what should I do if the collecting data is nan.

Hi @meomap887
first of all, Im not Python friendly … But it is code like any other…

If you need update rate 1s the it is better to set the update rate to 1 sec (aurs 10 10) then suspending the app by sleep command. If you sleep the app for a while like 3s then with the default update rate (100ms) you will have 30lines in the OS buffer so when your app will read just a one line then 29 will remain the buffer. So each 3sec there will be another +30 messages in the buffer and you will read only one again (the oldest one)… You need to flush the buffer after reading the line or slow down the update rate. This is probably the reason why you see different values in the DRTSL app - you see there the current values, but your app is showing you old data.

Regarding the app re run) Shell is device to human interface so it is expecting cca 20ms space between characters. When you wan to send “lec\n” you need to send it like this: ‘l’ 20ms delay ‘e’ 20ms delay ‘c’ 20ms delay ‘\n’ - the nordic uart has some limits so it is a bit unpleasant but for human typing it is totally OK. Normally you should use binary API as a device-to-program interface.

Cheers
JK

@leapslabs I can solve the problem to delay the result right now by using the function and call it whenever I need. For the second part about “lec”, I dont understand it pretty well/. Can you explain it to me more clearly and how to do that because it cause the program stuck.

@leapslabs is there any way to imrpove the accuracy since I stay in one position and the value of x or y maybet go from -1m to 1m

Hi @meomap887
you should use Binary AIPI instead of shell for reading the data from TN.

Or at least for shell you should implement (implement n in python) function like this:


sendDwmText(string text)
{
   for(int i = 0; i < text.len; ; i++)
   { 
       DWM.Write(text[i]); // write single character)
       time.sleep(20); 
   }
} 
 

Regarding the precision - the main issue here would be the distance between anchors - 40cm square. The problem is the math here - dilution od precision (Dilution of precision (navigation) - Wikipedia) as the Anchors are too close. If the TN is too far from the Anchors then any small range change can significantly affect the calculated. The only one solution O see is to increase the distance between anchors, but Im not sure if it is doable in your case.

Cheers
JK

@leapslabs , so far I put some delay 20ms in comments for “lec” command and it seem run stable than before. But we want to getting data faster and stable without “nan” value. I’m using this code

DWM=serial.Serial(port=“/dev/ttyACM0”, baudrate=115200)
print(“Connected to " +DWM.name)
DWM.write(”\r\r".encode())
time.sleep(1)
DWM.write(“l”.encode())
time.sleep(0.02)
DWM.write(“e”.encode())
time.sleep(0.02)
DWM.write(“c\r”.encode())
time.sleep(0.02)

and can you help me explain what the meaning of this line DWM.write(”\r\r".encode())
time.sleep(1)
I change the value for time.sleep here for faster response but sometimes it will stuck and not getting any data from the tag.

Another main concern is, currently im using the whole program above as a function and call it whenever we need the position. But we need to update it faster because whenever we call the function it will take time to reconnect to the usb port and write the command “lec”. Is there anyway we can connect to the usb port just 1 time when we start and get the data whenever we want?

And my main issue right now is the stability, when I run my function with counting 1000 times ( in more than 5 mins). It will stuck in the lec command or Clec which I have no idea why is that. The result is in the pictures below.


It supposed to run as previous count, we can see it in the picture.

And here is my code. Do you have any idea in this situtation? I also put another anchor so I have 4 anchors right now in triangle shape with (0.0) on the top.

Hi @meomap887
you should start with reading the documentation and not vice versa - to write program and then ask what to do 8-).

re shaking tag) You need to disable stationary detection. Or set the same update rate for normal and stationary update rate (shell example: aurs 1 1)

re binary API) Please see the DWM1001-API-Guide.pdf in the MDEK package -
DWM1001C Software and Documentation Pack

re \r\r ) This disable the binary interface and and enable shell over the UART.

re re-running the program) This is actually up to you and your programming skills. You might need to write a program that read the data from module permanently and send the data to your core program via some interface (UDP/ shared memory, character device / mqtt /… there are too many ways how to do that)

re issuing lec) the lec command works as a toggle switch - when you call it for a first time - you enable the output and when you call it for the second time you disable the output. So when tou re-run the program you toggling it - this is not a good idea

re Clec) Dor some reason the shell receives ‘C’ character before the lec command, it could be related to program rerunning - hard to guess why. As I have mentioned before, shell is device - human interface it is not designed for device to program interface - you should use the binary API (which is also much faster). However you should evaluate the output and when it report en error you should issue the command again. UART it globally no to reliable communication so you must work with that.

re shortening sleep(1) ) As noted above device - to human interface. You need to wait until it gets initialized.

I hope that I didnt miss any of your questions :wink:

Cheers
JK

Hello
Have a nice time
I have a question:
If this mini app can be written to use gateway mode, is it possible to write such a program to send distances while using listener mode? Right? I said this according to some previous messages that you explained. In this case, can the listener receive the intervals? Does it have a register to record it?
Should we write this mini app in the Teraterm environment, that is, in the shell?
Thank you in advance for your reply?
Good luck

Hi Leapslabs
Have a nice time
I have a question:
If this mini app can be written to use gateway mode, is it possible to write such a program to send distances while using listener mode? Right? I said this according to some previous messages that you explained. In this case, can the listener receive the intervals? Does it have a register to record it?
Should we write this mini app in the Teraterm environment, that is, in the shell?
Thank you in advance for your reply?
Good luck

Hi @nrahnama
listener is a just a listener. It cannot do anything else.

Cheers
JK