Tutorial 1
Tutorial 1
Bilkent University
Fall 2024
RAI Tutorial 1
2 Introduction
In RAI, the Configuration is a central concept representing the complete state of the
robotic environment, encompassing both the robot and any objects in the world. It serves
as a container for all relevant simulation information, including the positions, orientations,
and kinematic relationships of objects and robot links.
Another key term is Frame. A Frame represents a reference point or a rigid body in the
environment. It defines the position, orientation, and kinematic relationships of objects
or robot components. Frames can have shapes (such as boxes or spheres) attached to
them and are connected by joints or constraints, forming a kinematic tree.
• Let’s begin by building a configuration from scratch, adding some frames, and setting
their properties. You can create a new .ipynb file, add the code segments in separate
cells, and run them, or use the provided .ipynb file that contains the code.
• Add the necessary imports at the beginning, create our configuration, and add the
first frame. We will define the frame as a marker, which is not a physical shape
but displays the base vectors for visualization. Later, you can use this marker for
sub-goals.
RAI Tutorial 1
import robotic as ry
C = ry.Config()
f = C.addFrame(name="first")
f.setShape(type=ry.ST.marker, size=[.3])
f.setPosition([0.0 ,0.0 , 0.5])
f.setQuaternion([1.0, 0.3, 0.0, .0])
print("frame name:", f.name)
print("pos:", f.getPosition())
print("quat:", f.getQuaternion())
C.view()
C.view() opens a view window. You can right-click on the window bar and select
"Always on Top."
• For more details about configurations, basic shapes, frames, and joint states, you can
check https://github.com/MarcToussaint/rai-tutorials/blob/main/config_
1_intro.ipynb
C.view()
4 Relative Positions
Let’s examine the relative positions of the objects.
f = C.getFrame("box2")
print("position:", f.getPosition()) # position: [0. 0. 1.25]
print("orientation:", f.getQuaternion()) # orientation: [1. 0. 0. 0.]
2
RAI Tutorial 1
• When we used relative position, we mean the position of a frame with respect to
its reference (parent) frame in the environment. Instead of specifying the frame’s
position and orientation in absolute world coordinates, we define them relative to
the parent frame. As a result, the position values will reflect this relationship, so
you won’t see fixed coordinates like [0, 0, 1].
• One of the simplest ways to add frames is by using .g files. In this example, we
will define our manipulator in a .g file, though you can also create it directly using
Python commands.
• First, let’s create the world and a sphere representing the hinge joint on the [0,0,0].
3
RAI Tutorial 1
world: {}
zero (world): {
shape: sphere, size: [0.05],
mass: 1.0,
X:"T t(0 0 0) d(180 0 0 1)"
}
• Next, create the first joint and first link. We defined the first joint as a child of the
’zero’ frame. In the given code, hingeX is a type of joint that allows rotation around
a single axis, similar to a hinge. It is used to connect two body parts and specify
their relative motion. The "pre" matrix specifies the position and orientation of the
joint axis in the local coordinate system of the first body part,
joint1(zero):{
joint: hingeX,
pre:"T t(0 0 0)"
}
link1 (joint1): {
shape: capsule, size: [0.3, 0.05],
color: [0.0, 0.0, 1.0],
Q: [0.0, 0.0, 0.2]
}
• Next, create the second joint and link.
joint2(link1):{
joint: hingeX,
pre:"T t(0 0.0 .15)"
}
link2 (joint2): {
shape: capsule, size: [0.2, 0.05],
color: [1.0, 0.0, 0.0],
Q: [0.0, 0.0, 0.15]
}
• Last, create the third joint and the end-effector.
joint3 (link2): {
joint: hingeX,
pre:"T t(0 0.0 .12)",
}
end-effector (joint3): {
shape: sphere, size: [0.05],
color: [0.0, 1.0, 0.0],
Q: [0.0, 0.0, 0.03]
}
4
RAI Tutorial 1
• We simply need to use the ry.addFile() method to add the contents of the .g files
to the configuration. Additionally, we will include the Franka Panda robot using
these files.
K = ry.Config()
K.addFile("two_link_manipulator.g")
K.view()
• Finally, you should see the two-link manipulator in the Figure.
6 Features
Features represent differentiable properties of a configuration. They are fundamental in
formulating optimization problems, which we will frequently use.
• First, let’s explore how to compute them directly from the configuration. To do
this, we will clear our previous configuration and add a Franka Panda robot. We
can use the .eval(ry.FS.<name>, frame_set) method, where frame_set is a list
of frame names.
C.clear()
C = ry.Config()
C.addFile(ry.raiPath("panda/panda.g"))
q = C.getJointState()
C.view()
5
RAI Tutorial 1
7 Inverse Kinematics
We know that Forward Kinematics (FK) is the process of finding the position of a robot’s
end-effector based on the joint angles and link lengths. However, in general robotic
manipulation, the goal is typically to find the required joint angles to achieve a desired
position, which is known as Inverse Kinematics (IK). However, there may be multiple joint
configurations that fit the desired end-effector position; therefore, optimization helps us
find the most efficient one based on the provided constraints and objectives.
• Let’s begin with the necessary imports and add a Franka Panda robot and a table.
import robotic as ry
import numpy as np
import time
C = ry.Config()
C.addFile(ry.raiPath("../rai-robotModels/scenarios/pandaSingle.g"))
C.view()
• Next, we add the target frame
target = C.addFrame("target", "table")
target.setShape(ry.ST.marker, [.1])
target.setRelativePosition([0., .3, .3])
pos = target.getPosition()
cen = pos.copy()
C.view()
6
RAI Tutorial 1
• You will learn KOMO later. For now, think of this method as a basic inverse
kinematics approach.
• The IK() function first gets the current joint state of the robot using the getJointState()
method. It then creates a KOMO object with the configuration object C and adds
three optimization objectives to it using the addObjective() method. The first ob-
jective specifies that the robot should minimize the collisions over the course of the
trajectory. The second objective specifies that the cost should be minimized for
joint angles that are close to the current joint state. The third objective specifies
that the cost should be minimized for joint angles that are close to the home joint
state. The fourth objective specifies that the gripper position should be equal to
the target position.
• The NLP_Solver() method is then used to solve the optimization problem and
return the joint configuration that achieves the target position. The getPath()
method is used to extract the joint configuration from the KOMO object, and the
joint configuration and the optimization status are returned as a list.
qHome = C.getJointState()
q_target, ret = IK(C, "target", qHome)
print(ret)
C.setJointState(q_target)
C.view()
7
RAI Tutorial 1
• Here, we first compute the joint configuration of the robot that achieves the target
position using the IK() function and store it in q_target. The optimization status
is stored in ret and printed using the print() function. The joint configuration of
the robot is then set to q_target using the setJointState() method, and the scene
is updated using the view() method to show the new joint configuration.
K = ry.Config()
K.addFile("two_link_manipulator.g")
K.view()
• And here is the basic implementation of theoretical inverse kinematics.
n = K.getJointDimension()
q = K.getJointState()
w = 1e-1
W = w * np.identity(n)
y, J = K.eval(ry.FS.position, ["end-effector"])
K.setJointState(q)
K.view()
8
RAI Tutorial 1
9 Additional Tutorials
• https://github.com/MarcToussaint/rai-tutorials/blob/main/config_1_intro.ipynb
• https://github.com/MarcToussaint/rai-tutorials/blob/main/config_2_features.ipynb
• https://github.com/MarcToussaint/rai-tutorials/blob/main/config_3_import_edit.ipynb
• https://github.com/MarcToussaint/rai-tutorials/blob/main/komo_1_intro.ipynb
• https://github.com/MarcToussaint/rai-tutorials/blob/main/botop_1_intro.ipynb