I’ve been playing around a bit with different simulators, and one that we’re a big fan of in the lab is VREP. It’s free for academics and you can talk to them about licences if you’re looking for commercial use. I haven’t actually had much experience with it before myself, so I decided to make a simple force controlled arm model to get experience using it. All in all, there were only a few weird API things that I had to get through, and once you have them down it’s pretty straight forward. This post is going to be about the steps that I needed to take to get things all set up. For a more general start-up on VREP check out All the code in this post and the model I use can be found up on my GitHub.
Getting the right files where you need them
As discussed in the remote API overview, you’ll need three files in whatever folder you want to run your Python script from to be able to hook into VREP remotely:
remoteApi.so(depending on what OS you’re using)
You can find these files inside your
VREP_HOME/programming/remoteApiBindings/lib/lib folders. Make sure that these files are in whatever folder you’re running your Python scripts from.
It’s easy to create a new model to mess around with in VREP, so that’s the route I went, rather than importing one of their pre-made models and having some sneaky parameter setting cause me a bunch of grief. You can just right click->add then go at it. There are a bunch of tutorials so I’m not going to go into detail here. The main things are:
- Make sure joints are in ‘Torque/force’ mode.
- Make sure that joint ‘Motor enabled’ property is checked. The motor enabled property is in the ‘Show dynamic properties dialogue’ menu, which you find when you double click on the joint in the Scene Hierarchy.
- Know the names of the joints as shown in the Scene Hierarchy.
So here’s a picture:
where you can see the names of the objects in the model highlighted in red, the Torque/force selection highlighted in blue, and the Motor enabled option highlighted in green. And of course my beautiful arm model in the background.
Setting up the continuous server
The goal is to connect VREP to Python so that we can send torques to the arm from our Python script and get the feedback necessary to calculate those torques. There are a few ways to set up a remote connection in VREP.
The basic one is they have you add a child script in VREP and attach it to an object in the world that sets up a port and then you hit go on your simulation and can then run your Python script to connect in. This gets old real fast. Fortunately, it’s easy to automate everything from Python so that you can connect in, start the simulation, run it for however long, and then stop the simulation without having to click back and forth.
The first step is to make sure that your
remoteApiConnections.txt file in you VREP home directory is set up properly. A continuous server should be set up by default, but doesn’t hurt to double check. And you can take the chance to turn on debugging, which can be pretty helpful. So open up that file and make sure it looks like this:
portIndex1_port = 19997 portIndex1_debug = true portIndex1_syncSimTrigger = true
Once that’s set up, when VREP starts we can connect in from Python. In our Python script, first we’ll close any open connections that might be around, and then we’ll set up a new connection in:
import vrep # close any open connections vrep.simxFinish(-1) # Connect to the V-REP continuous server clientID = vrep.simxStart('127.0.0.1', 19997, True, True, 500, 5) if clientID != -1: # if we connected successfully print ('Connected to remote API server')
So once the connection is made, we check the
clientID value to make sure that it didn’t fail, and then we carry on with our script.
By default, VREP will run its simulation in its own thread, and both the simulation and the controller using the remote API will be running simultaneously. This can lead to some weird behaviour as things fall out of synch etc etc, so what we want instead is for the VREP sim to only run one time step for each time step the controller runs. To do that, we need to set VREP to synchronous mode. So the next few lines of our Python script look like:
# --------------------- Setup the simulation vrep.simxSynchronous(clientID,True)
and then later, once we’ve calculated our control signal, sent it over, and want the simulation to run one time step forward, we do that by calling
# move simulation ahead one time step vrep.simxSynchronousTrigger(clientID)
Get the handles to objects of interest
OK the next chunk of code in our script uses the names of our objects (as specified in the Scene Hierarchy in VREP) to get an ID for each which to identify which object we want to send a command to or receive feedback from:
joint_names = ['shoulder', 'elbow'] # joint target velocities discussed below joint_target_velocities = np.ones(len(joint_names)) * 10000.0 # get the handles for each joint and set up streaming joint_handles = [vrep.simxGetObjectHandle(clientID, name, vrep.simx_opmode_blocking) for name in joint_names] # get handle for target and set up streaming _, target_handle = vrep.simxGetObjectHandle(clientID, 'target', vrep.simx_opmode_blocking)
Set dt and start the simulation
And the final thing that we’re going to do in our simulation set up is specify the timestep that we want to use, and then start the simulation. I found this in a forum post, and I must say whatever VREP lacks in intuitive API their forum moderators are on the ball. NOTE: To use a custom time step you have to also set the dt option in the VREP simulator to ‘custom’. The drop down is to the left of the ‘play’ arrow, and if you don’t have it set to ‘custom’ you won’t be able to set the time step through Python.
dt = .01 vrep.simxSetFloatingParameter(clientID, vrep.sim_floatparam_simulation_time_step, dt, # specify a simulation time step vrep.simx_opmode_oneshot) # --------------------- Start the simulation # start our simulation in lockstep with our code vrep.simxStartSimulation(clientID, vrep.simx_opmode_blocking)
So, once we’ve started the simulation, I’ve set things up for the arm to be controlled for 1 second and then for the simulation to stop and everything shut down and disconnect.
while count < 1: # run for 1 simulated second # get the (x,y,z) position of the target _, target_xyz = vrep.simxGetObjectPosition(clientID, target_handle, -1, # retrieve absolute, not relative, position vrep.simx_opmode_blocking) if _ !=0 : raise Exception() track_target.append(np.copy(target_xyz)) # store for plotting target_xyz = np.asarray(target_xyz) q = np.zeros(len(joint_handles)) dq = np.zeros(len(joint_handles)) for ii,joint_handle in enumerate(joint_handles): # get the joint angles _, q[ii] = vrep.simxGetJointPosition(clientID, joint_handle, vrep.simx_opmode_blocking) if _ !=0 : raise Exception() # get the joint velocity _, dq[ii] = vrep.simxGetObjectFloatParameter(clientID, joint_handle, 2012, # ID for angular velocity of the joint vrep.simx_opmode_blocking) if _ !=0 : raise Exception()
In the above chunk of code, I think the big thing to point out is that I’m using
vrep.simx_opmode_blocking in each call, instead of
vrep.simx_opmode_buffer. The difference is that you for sure get the current values of the simulation when you use
blocking, and you can be behind a time step using
Aside from that the other notable things are I raise an exception if the first parameter (which is the return code) is ever not 0, and that I use
simxGetObjectFloatParameter to get the joint velocity instead of
simxGetObjectVelocity, which has a rotational velocity component. Zero is the return code for ‘everything worked’, and if you don’t check it and have some silly things going on you can be veeerrrrryyy mystified when things don’t work. And what
simxGetObjectVelocity returns is the rotational velocity of the joint relative to the world frame, and not the angular velocity of the joint in its own coordinates. That was also a briefly confusing.
So the next thing I do is calculate
u, which we’ll skip, and then we need to set the forces for the joint. This part of the API is real screwy. You can’t set the force applied to the joint directly. Instead, you have to set the target velocity of the joint to some really high value (hence that array we made before), and then modulate the maximum force that can be applied to that joint. Also important: When you want to apply a force in the other direction, you change the sign on the target velocity, but keep the force sign positive.
# ... calculate u ... for ii,joint_handle in enumerate(joint_handles): # get the current joint torque _, torque = \ vrep.simxGetJointForce(clientID, joint_handle, vrep.simx_opmode_blocking) if _ !=0 : raise Exception() # if force has changed signs, # we need to change the target velocity sign if np.sign(torque) * np.sign(u[ii]) < 0: joint_target_velocities[ii] = \ joint_target_velocities[ii] * -1 vrep.simxSetJointTargetVelocity(clientID, joint_handle, joint_target_velocities[ii], # target velocity vrep.simx_opmode_blocking) if _ !=0 : raise Exception() # and now modulate the force vrep.simxSetJointForce(clientID, joint_handle, abs(u[ii]), # force to apply vrep.simx_opmode_blocking) if _ !=0 : raise Exception() # move simulation ahead one time step vrep.simxSynchronousTrigger(clientID) count += dt
So as you can see we check the current torque, see if we need to change the sign on the target velocity, modulate the maximum allowed force, and then finally step the VREP simulation forward.
And there you go! Here’s an animation of it in action (note this is a super low quality gif and it looks way better / smoother when actually running it yourself):
All in all, VREP has been enjoyable to work with so far. It didn’t take long to get things moving and off the ground, the visualization is great, and I haven’t even scratched the surface of what you can do with it. Best of all (so far) you can fully automate everything from Python. Hopefully this is enough to help some people get their own models going and save a few hours and headaches! Again, the full code and the model are up on my GitHub.
- When you’re applying your control signal, make sure you test each joint in isolation, to make sure your torques push things in the direction you think they do. I had checked the rotation direction in VREP, but the control signal for both joints ended up needing to be multiplied by -1.
- Another nit when you’re building your model, if you use the rotate button from the VREP toolbar on your model, wherever that joint rotates to is now 0 degrees. If you want to set the joint to start at 45 degrees, instead double click and change Pos[deg] option inside ‘Joint’ in Scene Object Properties.