I’m trying to send joint positions as a string via a socket connection to a python script I have. I’m having trouble sending stringified joint positions via TCP communication.
The python script receives strings, stores them in a buffer, and when the buffer is full dumps it.
Here’s a snippet of my script:
def listen_for_string(ip, port):
global last_timestamp
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((ip, port))
sock.listen(1)
print("Daemon listening on {}:{}".format(ip, port))
while True:
connection, client_address = sock.accept()
remainder = "" # Buffer to hold partial messages
try:
while True:
data = connection.recv(1024)
if not data:
break
combined = remainder + data.decode('utf-8')
parts = combined.split(']')
remainder = parts.pop()
for p in parts:
if '[' in p:
raw_values = p.split('[')[-1]
try:
joint_array = [float(x) for x in raw_values.split(',')]
current_timestamp = datetime.now()
delta_t = 0
if last_timestamp is not None:
delta_t = int((current_timestamp - last_timestamp).total_seconds() * 1000000)
last_timestamp = current_timestamp
entry = {
"delta_t": delta_t,
"joints": joint_array
}
with ring_lock:
ring_buffer.append(entry)
if len(ring_buffer) >= RING_SIZE:
threading.Thread(target=dump_to_json).start()
except ValueError:
continue
If anyone can see why my socket communication is not working, please let me know.
It does nothing at all from what I can tell: Returns false due to failure.
When I put a counter in the same loop which would increment each time the socket sent a string, the counter updated very slowly, which I believe means that the socket request blocks the thread, then times out.
My aim is to sample joint positions in the background and stream them very quickly to a python server via this socket.
Yes, I am. I run the thread, then writeChildren(), then kill the thread.
I’ve also tried just sending one string in the same way as an example I found on the forum, only to get the same result. This is how my generateScript looked then:
Start even simpler. You’ve got your python script doing quite a bit of stuff. When I hit the “nothing is working” state, it usually helps me to dial way back. For example, sending an array is a step further than I would go at this point. Can you send a single piece of text or a single number? Don’t try to parse it into something meaningful yet, just print it to the screen.
In my experience, the socket communication on the UR is fairly slow. At least when piping it back to a URCAP. That’s what the RTDE is for. For applications like yours, where you’re trying to stream joint positions to python, I see most people go the RTDE route. Which is where I would have to leave you with a wave and a “good luck” since I’ve never been able to get that working properly.
Currently I’m using and XML-RPC daemon to send the position information.
According to this page, socket communication should definitely be faster than XML, and due to the limitations of my project, I need to stick with local port communication (i.e. can’t use RTDE).
I’m using this thread to set up my socket communication.
I’ll take your advice and try scale my script back, but I don’t see what I’m doing wrong. The array parsing is straight from the above example.
I’m glad you’ve figured out your problem, but I would recommend using RTDE for monitoring things like joint angles - it requires nothing at all in your robot script as the interface is there and working anyway. The UR sample RTDE client for Python has always worked well for me; just update the recipe file to specify that you want the joint angles, and run the sample “record” script and voila you have a CSV of joint angles.