Controlling Franka & ROS¶
Starting ROS to control Franka¶
The recommended setup for controlling the franka can be seen in the tree below. The top level shows the devices required and their IP address, the second tier shows the commands needed to run the files:
. ├── Franka Control Box (192.168.0.88) ├── Host workstation computer (192.168.0.77) │ ├── roscore │ └── ./franka_controller_sub 192.168.0.88 └── Project workstation computer ├── roslaunch openni2_launch openni2.launch ├── camera_subscriber.py (this does not need to be run seperately) └── main.py
To test the image feed out without using it in
main.py you can use the
test_camera.py file in the
Networking with other workstations¶
Instead of running the master node and subscriber nodes on your own workstation, these can be running on the main workstation in the lab instead. This means that libfranka won’t need to be installed on your specific workstation.
To communicate over the lab network you need to change two main ROS variables. Firstly you need to find the IP address of your computer when connected to the lab network (via ethernet). To do this you can use
ifconfig in a terminal window to give you your
You then need to run the following two commands in your terminal window (substitute in you IP address):
export ROS_MASTER_URI=http://192.168.0.77:11311 export ROS_IP=<ip_address_of_pc>
As you will see, this is connecting you to the static IP address of the main Franka workstation,
192.168.0.77. In order for you to continue with running a Python publisher, you need to ensure that roscore and the subscriber is running on the main workstation.
That this configuration of assigning IP addresses to ROS_MASTER_URI and ROS_IP is non-permanent, and is only active for the terminal window you are working in. This has to be repeated for every window you use to run rospy. Alternatively you can add these commands to your bashrc.
Running the subscriber¶
roscore is running, the subsciber has to run in the background to read the messages from our Python publisher and execute them with libfranka. To run the subscriber (from the project folder), run:
cd franka/ ./franka_controller_sub 192.168.0.88
Sometimes there is an “error with no active exception” thrown by this executable. This can sometimes be solved by simply manually moving the arm using the buttons a bit. Then rerun the command above again.
This subscriber is compiled for
libfranka 0.1.0. You can check your current
libfranka version with
rosversion libfranka command.
Using the publisher¶
First, make sure you are running
roscore and the subscriber,
franka_controller_sub on the main lab workstation.
Assuming you are writing a script (
script.py) that wants to use control franka, the files should be stored as:
. ├── README.md ├── franka │ ├── __init__.py │ ├── franka_control_ros.py │ ├── franka_controller_sub │ ├── franka_controller_sub.cpp │ ├── print_joint_positions │ └── print_joint_positions.cpp └── script.py
To use the
FrankaRos class in your own Python script would look something like this:
from franka.franka_control_ros import FrankaRos franka = FrankaRos(debug_flag=True) # we set the flag true to get prints to the console about what FrankaRos is doing while True: data = arm.get_position() print("End effector position:") print("X: ", data) print("Y: ", data) print("Z: ", data)
FrankaRos(log=False, ip='192.168.0.88', debug=False, init_ros_node=False)¶
Get x, y, z position of end-effector and returns it to caller.
Returns: list as [x, y, z]
grasp(object_width, speed, force)¶
Grasp an object in the grippers. Note that this can only be called if the object width is smaller than the current distance between the grippers.
The grippers attempt to move to the width of the object defined with speed defined, and then proceed to apply a defined force against the object. If no object is present it evaluates as failed and moves to next task.
0 width defined == 2.2 cm difference real-world
- object_width – width of target object to grab (float)
- speed – with which to move the gripper to object width (float)
- force – to apply to the object once the grippers are at object width (float)
Set gripper width by assigning
widthwith a desired speed to move at. Note this must be called before grasping if gripper fingers are too close together
0 width defined == 2.2 cm difference real-world
- width – desired distance between prongs on end-effector (in millimetres)
- speed – desired speed with which to move the grippers
move_relative(dx, dy, dz, speed)¶
Moves robot end effector in desired direction (in robot reference frame) given a target displacement and speed to travel at. The robot will not necessarily travel at this speed due to safety controls in the subscriber.
- dx – float value displacement in robot reference axis
- dy – float value displacement in robot reference axis
- dz – float value displacement in robot reference axis
- speed – float value desired speed to target displaced position
move_to(x, y, z, speed)¶
Moves robot end effector to desired coordinates (in robot reference frame) given a target velocity. The robot will not necessarily travel at this speed due to safety controls in the subscriber.
- x – float value position in robot reference axis
- y – float value position in robot reference axis
- z – float value position in robot reference axis
- speed – float value desired speed to target position
Used to test if the arm can be moved with gripper control.
Function moves the arm through a simple motion plan and then tried moving the grippers. To use this test, add the
--motion-exampleflag to the command line.
Used to test if position reporting is working from Arm.
It will repeatedly print the full arm position data and the XYZ position of the end-effector. To use this test, add the
--position-exampleflag to the command line.
Using Franka without ROS¶
This method is deprecated. It is now recommended you use ROS to control the Arm using a Python publisher, such as the way described above.
To control the Franka Arm, Fabian and Petar have written a small collection of C++ files which can be compiled to run as executables and control the Franka Arm using libfranka.
You need to ensure you have set the correct permissions for libfranka. You can check that in Using the franka_ros library.
Downloading the C++ Executables and Python Class¶
Now that you have libfranka set up properly you can get use the C++ files provided. These resources can be found in the
/franka directory of the repository. Firstly, go to your project directory in the terminal by using
cd <project_dir>. If you have already downloaded the files before and are replacing them with an up-to-date version, run
rm -rf franka/ first. To download the necessary folder, run:
svn export https://github.com/nebbles/DE3-ROB1-CHESS/trunk/franka
Once this directory is downloaded into your project directory, you need to change directory and then make the binaries executable:
cd franka/ chmod a+x franka* chmod a-x *.cpp
This next command will move the FRANKA. Make sure you have someone in charge of the external activation device (push button).
These binaries can now be used from the command line to control the Arm:
./franka_move_to_relative <ip_address> <delta_X> <delta_Y> <delta_Z>
Alternatively, you can control the Arm using the easy custom Python class
Caller (see below).
Python-Franka API with
The Python-FRANKA module (
franka_control.py) is designed to allow easy access to the C++ controller programs provided by Petar. The provided Python module is structured as follows.
To use the
FrankaControl class in your own Python script would look something like this:
from franka.franka_control import FrankaControl arm = FrankaControl(debug_flag=True) # we set the flag true to get prints to the console about what Caller is doing arm.move_relative(dx=0.1, dy=0.0, dz=-0.3) # we tell teh arm to move down by 30cm and along x away from base by 10cm
This example code assumes you are following the general project structure guide. See below for more information. The code above would be called from a main script such as
General Structure of Project¶
The structure of the project is important to ensure that importing between modules works properly and also seperates externally maintained code from your own. An example of a project tree is:
. ├── LICENSE.txt ├── README.md ├── run.py ├── __init__.py ├── docs │ ├── Makefile │ ├── build │ ├── make.bat │ └── source ├── franka │ ├── __init__.py │ ├── franka_control.py │ ├── franka_get_current_position │ ├── franka_get_current_position.cpp │ ├── franka_move_to_absolute │ ├── franka_move_to_absolute.cpp │ ├── franka_move_to_relative │ └── franka_move_to_relative.cpp ├── my_modules │ ├── module1.py │ ├── module2.py │ ├── module3.py │ ├── __init__.py └── test_script.py