Quick Start

This is a brief tutorial to plan your first robot motions with Jacobi, and we keep things simple to get started as quickly as possible! We also provide a range of examples to show end-to-end usage.

First, please select your programming langauge for the code examples below. We start by importing the Jacobi via

from jacobi import Environment, Planner, Box, Frame
from jacobi.robots import UniversalUR10e

To setup the robot’s workcell, we first need to specify the robot that we’re using. Jacobi has built-in support for various, most commonly used robot arms from leading manufacturors such as ABB, KUKA, Universal, or Yaskawa. Let’s use the Universal UR10 robot arm for now.

robot = UniversalUR10e()
robot.base = Frame(z=0.3)  # [m]
robot.flange_to_tcp = Frame(z=0.15)  # [m]
robot.max_acceleration = [4.0, 4.0, 4.0, 4.0, 4.0, 4.0]  # [rad/s^2]

Jacobi knows the robot’s kinematics, its dynamic limits, and the default link geometries for collision avoidance out of the box. We further specify the robot’s base frame as well the Tool Center Point (TCP) so that we can later specify Cartesian poses in the task space. We also set custom maximum acceleration limits to slow the robot down slightly.

Let us now construct the obstacle environment. In real-world applications, Jacobi usually imports convex meshes (e.g. in the *.obj or *.stl file format). For now however, we want to use simple boxes only. We define our Environment object and pass the robot, as well as a general security margin for collision checking to it.

environment = Environment(robot)

    object=Box(1.2, 2.0, 0.3),  # [m]
    origin=Frame(x=0.4, z=0.15),  # [m]
    object=Box(0.5, 0.1, 0.8), # [m]
    origin=Frame(x=0.74, z=0.5),  # [m]

Obstacles in Jacobi support optional names that might make debugging easier. The environment looks like this:

Quick Start Environment

Then, we construct the main Planner object that takes in the environment and the cycle time of the system (called delta_time). The cycle time is going to be the sampling rate for the computed trajectories, and it makes sense to use the control rate of the robot here.

planner = Planner(environment, delta_time=0.002)  # [s]

Cloud Version

When using the cloud version of the Jacobi motion library, make sure to authenticate with your account by setting the JACOBI_API_KEY environment variable.

We are now able to plan a collision-free trajectory from arbitrary joint or Cartesian positions! Let us first plan a small motion that moves the robot’s tool center point (TCP) slightly above the table.

trajectory = planner.plan(
    start=[-0.86, -1.26, 0.98, -1.20, -1.73, 0.0],  # [rad]
    goal=[-0.80, -0.73, 1.58, -2.26, -1.42, 0.0],  # [rad]

print(trajectory.duration, '[s]')

The trajectory duration should take around 1.03 s, and the calculation itself below 1ms (or even 0.2ms on modern hardware). Jacobi is oftentimes able to find collision-free motions straight away.

Second, let us plan a trajectory that moves to the other side of the divider box. While this is a very simple environment, it resembles many pick-and-place tasks found in bin picking or logistics.

trajectory = planner.plan(
    start=[-0.80, -0.73, 1.58, -2.26, -1.42, 0.0],  # [rad]
    goal=[0.45, -0.73, 1.40, -2.20, -1.60, 0.5],  # [rad]

print(trajectory.duration, '[s]')

This trajectory duration should be below 1.25s. The calculation should take around 500ms for now, but Jacobi has ways to accelerate the calculaion to less than 1ms with a bit of training. This is what the motion looks like:

Quick Start Environment

The positions (as well as the full kinematic states) of the trajectory are easily accessible via trajectory.positions. The trajectory is sampled with the specified delta_time, however the final state might be a bit earlier due to the overall trajectory duration. The precise timing for each state is available via trajectory.timings.

In the following, we will guide you through the advanced motion planning capabilities of Jacobi. If you have any questions or issues so far, reach out to us at contact@jacobirobotics.com!