User Tools

Site Tools


vrep:socket-com-with-robot

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
vrep:socket-com-with-robot [2020/03/17 16:36]
admin
vrep:socket-com-with-robot [2020/06/09 16:39] (current)
admin
Line 1: Line 1:
-Th socket communication allows for an external program to control the robot inside V-REP. The external program is a Python script. We will use for the socket a server/​client communication. The server is written in Lua inside a threaded script in V-REP. The client is written in Python, It will :+Back to [[vrep:​main|V-REP Main Page]] 
 + 
 +The socket communication allows for an external program to control the robot inside V-REP. The external program is a Python script. We will use for the socket a server/​client communication. The server is written in Lua inside a threaded script in V-REP. The client is written in Python, It will :
   * connect to the server   * connect to the server
   * send commands to the robot   * send commands to the robot
Line 7: Line 9:
 On the server side of the socket, we use a [[https://​www.coppeliarobotics.com/​helpFiles/​en/​childScripts.htm|threaded script]] in Lua as we want to listen to the client'​s commands synchronously with the V-REP simulation loop. On the server side of the socket, we use a [[https://​www.coppeliarobotics.com/​helpFiles/​en/​childScripts.htm|threaded script]] in Lua as we want to listen to the client'​s commands synchronously with the V-REP simulation loop.
  
-We will use a  [[https://​www.ensta-bretagne.fr/​zerr/​filerepo/​vrep/​myLittleBot.ttt|simple 3 wheels robot]] and we load it in V-REP.+We will use a  [[https://​www.ensta-bretagne.fr/​zerr/​filerepo/​vrep/​myLittleBotNoScript.ttt|simple 3 wheels robot]] and we load it in V-REP. You can rename it **myLittleBot.ttt**.
  
-{{:vrep:mylittlebot2_view.png?300|}}+{{:vrep:mylittlebot_view.png?300|}}
  
  
Line 29: Line 31:
 Then you will have to create a file called ​ **simple_robot_control.lua** in the directory where your scene file (here **myLittleBot.ttt**) is stored. ​ Then you will have to create a file called ​ **simple_robot_control.lua** in the directory where your scene file (here **myLittleBot.ttt**) is stored. ​
  
-The Lua code looks like this :+The [[https://​www.ensta-bretagne.fr/​zerr/​filerepo/​vrep/​simple_robot_control.lua|Lua code]] looks like this :
 <code lua> <code lua>
-function hex(s) +-- load pack library 
-   s=string.gsub(s,"(.)",​function (x) return string.format("​%02X",​string.byte(x)) end) +-- must have been added previoulsy in V-REP folder 
-   ​return s +-- if not done yetsee tutorial ​... 
-end +require ("​pack"​) ​
- +
-require ("​pack"​)+
 bpack=string.pack bpack=string.pack
 bunpack=string.unpack bunpack=string.unpack
  
 +-- define socket
 portNb = 33211 portNb = 33211
 serverOn = false serverOn = false
-connexionTimeout = 0.01 +connexionTimeout = 0.001 -- set 1 ms time out
-cntTimeout = 0+
 socket=require("​socket"​) socket=require("​socket"​)
 srv = nil srv = nil
Line 74: Line 74:
       -- if server is running, accept command and send back status       -- if server is running, accept command and send back status
       if serverOn then       if serverOn then
 + -- to prevent lock on accept, a timeout is set
  srv:​settimeout(connexionTimeout)  srv:​settimeout(connexionTimeout)
  clt1 = srv:​accept()  clt1 = srv:​accept()
- if clt1 == nil then + if clt1 ~= nil then 
-     cntTimeout = cntTimeout + 1 +     -- to prevent ​lock, a timeout is set 
- else +     ​--clt1:​settimeout(connexionTimeout)
-     -- to prevent ​locks, a timeout is set +
-     clt1:​settimeout(connexionTimeout)+
      -- get the data (command) from the client      -- get the data (command) from the client
      dataIn = clt1:​receive(nCharMessage)      dataIn = clt1:​receive(nCharMessage)
Line 121: Line 120:
 </​code>​ </​code>​
  
-The socket transfers binary data, so we need to pack the data before sending them and unpack them at the reception. For Lua we use the [[http://​webserver2.tecgraf.puc-rio.br/​~lhf/​ftp/​lua/​|lpack ​libary]. You can either download the code and recompile **the pack.so** shared library or get it  [[https://​www.ensta-bretagne.fr/​zerr/​filerepo/​vrep/​pack.so|already compiled here]] if you work on x86_64 linux computer. The file **pack.so** should be added in the main V-REP directory.+The socket transfers binary data, so we need to pack the data before sending them and unpack them at the reception. For Lua we use the [[http://​webserver2.tecgraf.puc-rio.br/​~lhf/​ftp/​lua/​|lpack ​library]]. You can either download the code and recompile ​the **pack.so** shared library or get it  [[https://​www.ensta-bretagne.fr/​zerr/​filerepo/​vrep/​pack.so|already compiled here]] if you work on x86_64 linux computer. The file **pack.so** should be added in the main V-REP directory. ​ 
 + 
 +//Todo : provide a .dll for windows//
  
 The socket is between processes on the same computer so the IP address is **localhost** or **127.0.0.1**. The communication port is set to **33211**. The port number is arbitrary, if this port is already used, we will get an error message. To get a list of used port, you can use **lsof**. Here we print only the ports used by V-REP: ​ The socket is between processes on the same computer so the IP address is **localhost** or **127.0.0.1**. The communication port is set to **33211**. The port number is arbitrary, if this port is already used, we will get an error message. To get a list of used port, you can use **lsof**. Here we print only the ports used by V-REP: ​
Line 131: Line 132:
 </​code>​ </​code>​
  
 +The Lua server expects to receive a command from the Python client with 4 values :
 +  * character A (1 byte)
 +  * character Z (1 byte)
 +  * float speed_left (4 bytes)
 +  * float speed_right (4 bytes)
 +It has first to unpack these data with **bunpack()** function. Then it checks if the two first values are '​A'​ and '​Z'​. This is just to ensures that the connection is synchronized properly. In principle, TCP/IP sockets already check if all is OK, so may no used it and transmit only the usefull values.
 +
 +If the message received is OK (starting with '​A'​ and '​Z'​),​ the Lua server applies the command to the left and right motors.
 +
 +Finally it reads the status data. Here the status has 3 values : the simulation time and the angular position of the two wheels. The angular position of the wheels is very useful if we want to simulate odometers. The status message is made of five values :
 +  * character A (1 byte)
 +  * character Z (1 byte)
 +  * float simulation time (4 bytes)
 +  * float angular_position_wheel_left (4 bytes)
 +  * float angular_position_wheel_right (4 bytes)
 +The 5 values are packed with **bpack()** function and sent back to the python client.
 +
 +The Python3 code of the client controls the robot by sending the motor speed for the two wheels. It can be executed via a terminal. For example to set the left motor speed to 0.5 and the right to -0.5, type:
 +<code bash>
 +python3 simple_robot_control.py 0.5 -0.5
 +sockect time=6.8 ms, simTime=4.85 s, left angle=-0.0, right angle=0.0
 +sockect time=3.9 ms, simTime=4.95 s, left angle=2.4, right angle=-2.4
 +sockect time=6.7 ms, simTime=4.95 s, left angle=3.8, right angle=-3.8
 +sockect time=7.0 ms, simTime=5.05 s, left angle=5.2, right angle=-5.2
 +sockect time=0.4 ms, simTime=5.10 s, left angle=8.0, right angle=-8.0
 +</​code>​
 +The robot will turn in place to the right.  ​
 +
 +Do not forget to start the simulation in V-REP before executing the Python client code. Otherwise, the communication socket will not work :
 +<code bash>
 +python3 simple_robot_control.py 0.5 -0.5
 +Cannot connect to server
 +</​code>​
 +
 +The [[https://​www.ensta-bretagne.fr/​zerr/​filerepo/​vrep/​simple_robot_control.py|Python3 client code]] is as follows:
 +<code python>
 +import socket
 +import time
 +import struct
 +import signal
 +import sys
 +import math
 +
 +code_sync_1 = '​A'​
 +code_sync_2 = '​Z'​
 +
 +# set the speed of the two wheels
 +try:
 +    speed_left = float(sys.argv[1])
 +    speed_right = float(sys.argv[2])
 +except:
 +    speed_left = 0.0
 +    speed_right = 0.0
 +
 +# set address and port for the socket communication
 +server_address_port = ('​localhost',​ 33211)
 +
 +# interrupt handler
 +def interrupt_handler(signal,​ frame):
 +    print ('You pressed CTRL-C, end of communication with V-REP robot'​)
 +    time.sleep(0.5)
 +    try:
 +        sock.close()
 +    except:
 +        print (sock,"​socket already closed"​)
 +    sys.exit(0)
 +    ​
 +# trap hit of ctrl-C to stop the communication with V-REP
 +signal.signal(signal.SIGINT,​ interrupt_handler)
 +
 +# client connects to server every 50 ms
 +loop_duration = 0.050
 +while True:
 +    # Create a TCP/IP socket
 +    t0 = time.time()
 +    sock = socket.socket(socket.AF_INET,​ socket.SOCK_STREAM)
 +    try:
 +        sock.connect(server_address_port)
 +    except:
 +        print ("​Cannot connect to server"​)
 +        break
 +
 +    sock.settimeout(0.1) # set connection timeout
 +    # pack command
 +    strSend = struct.pack('<​BBff',​ord(code_sync_1),​ord(code_sync_2),​speed_left,​speed_right)
 +    # send command to V-REP
 +    sock.sendall(strSend)
 +
 +    # wait for status back from V-REP
 +    data = b''​
 +    nch_rx = 14 # expect receiving 14 bytes from  V-REP 
 +    try:
 +        while len(data) < nch_rx:
 +            data += sock.recv(nch_rx)
 +    except:
 +        print ("​socker error , duration is %f ms, try to reconnect !!!"​%((time.time() - t0)*1000.0))
 +    # unpack the received data
 +    data_ok = False
 +    if len(data) == nch_rx:
 +        vrx = struct.unpack('<​ccfff',​data)
 +        if vrx[0] == b'​A'​ and  vrx[1] == b'​Z':​
 +            data_ok = True
 +    else:
 +        pass
 +
 +    sock.close()
 +    tsock = (time.time() - t0)*1000.0
 +
 +    if data_ok:
 +        print ("​sockect time=%.1f ms, simTime=%.2f s, left angle=%.1f, right angle=%.1f"​%
 +               ​(tsock,​vrx[2],​vrx[3]*180.0/​math.pi,​vrx[4]*180.0/​math.pi))
 +    else:
 +        print ("​tsock",​tsock,"​ms,​ bad data !!")
 +
 +    tsleep = loop_duration - (time.time()-t0)
 +    if tsleep>​0:​
 +        time.sleep (tsleep)  ​
 +</​code>​
  
 +Go to [[vrep:​socket-com-with-robot|top]]
vrep/socket-com-with-robot.1584459401.txt.gz · Last modified: 2020/03/17 16:36 by admin