The robot's body

A robot arm is a chain of rigid parts moved by motors. This chapter names the parts and counts the ways they can move. By the end you can read the SO-106 as a list of six joints, which is exactly how Solarian describes it.

A manipulator is a chain of rigid links (solid bodies) connected by joints. The first link is the base, usually bolted to a table or a mobile base. Each joint moves every link after it. The last link carries the end effector: the part that touches the world.

BaseRevolute jointLinkEnd-effectorPrismatic jointMobile baseend effector Parallel gripper · cyclingbase wheeled

Dragging a joint pauses the loop. The SO-106 also has three wrist joints, wrist_flex, wrist_yaw, and wrist_roll. This model leaves them off so the two joint types stay readable.

What goes on the end effector depends on the job:

  • A gripper closes on an object. The simplest is a parallel gripper, two fingers that slide toward each other. This tutorial uses one.
  • A hand has several fingers. It holds more shapes, it has more dexterity, and needs many more motors.
  • A tool does one job: a screwdriver, a suction cup, a pen.

A camera often rides next to the gripper, so the robot sees what its hand sees.

Degrees of freedom

A degree of freedom (DoF) is one independent way to move. A box floating in space has six: it can slide along x, y, and z, and it can rotate about x, y, and z.

XYZ1 translate along x2 translate along y3 translate along z4 rotate about x5 rotate about y6 rotate about z
1 of 6 · translate along x

Red is X, green is Y, blue is Z. The bright axis is the one the box is using right now.

A joint connects two links and by doing so it adds constrains that only alllow some of those degrees of freedom. The two kinds of joints you meet most:

  • A revolute joint is a hinge. It keeps one rotation DoF, and its value is an angle.
  • A prismatic joint is a slide. It keeps one translation DoF, and its value is a distance.

An arm's elbow is a revolute joint. The fingers of a parallel gripper slide on prismatic joints:

Revolute jointangle 27°Prismatic jointtravel 0 mm

The amber line is the joint axis. The elbow turns about its axis, so its value is an angle. Each finger slides along the rail, so its value is a distance.

Each of these joints adds one degree of freedom to the chain. Count the joints and you have counted the arm's degrees of freedom.

Actutors

Every joint needs something to drive it. That part is the actuator, and on a typical arm it is an electric motor or servo.

A bare motor only spins: fast, with little force, and blind to its own angle. A servo puts three more parts in the same box as the motor:

  • a gearbox, which trades speed for force by combining gears;
  • a sensor, often a magnetic encoder, which measures the angle of the output shaft;
  • a small controller, which runs the motor until the sensor reads the angle you asked for.
Target angle, from you90°Controllertarget90°measured0°error+90°power+100%Motorfast, weakGearbox 4 : 1 and outputslow, strong. The white horn turns the next link.Encodera magnet on the output shaftNSfield sensormeasured angle0°

The motor turns four times for every turn of the output. Real servos stack several gear stages like this one.

The controller compares the target with the encoder's reading and powers the motor according to the error. A large error gets full power. As the output closes in, the error shrinks, the power drops, and the output settles on the target.

So you send a servo a target angle, and it moves there and holds. It also reports the angle it reached, which is how the robot knows its own pose.

A servo drives one joint. Its body is bolted to one link, and its output shaft turns the next link. On the SO-106 every joint has its own servo.

The SO-106: six joints

The SO-106 is the arm this course uses. Here is its real simulation model, the same MuJoCo file Solarian loads, with the UMI Slim gripper mounted on the end. Each slider drives one joint, the way a command to its servo would.

Loading MuJoCo model…

The arm is green and the gripper is orange. Moving a slider stops the demo.

right_armSO-106 arm, six servos

right_gripperUMI Slim gripper, one servo

Loading the gripper…

The arm and the gripper are two separate pieces of hardware, bolted together at the arm's flange, the mounting plate at the end of the wrist. Solarian models them the same way: two modules, right_arm and right_gripper, each with its own servos. A different gripper means a different gripper module, and the arm module stays as it is.

The arm has six revolute joints, from the base out to the wrist:

JointMotion
shoulder_panturns the whole arm left and right
shoulder_liftraises and lowers the upper arm
elbow_flexbends the elbow
wrist_flextilts the hand up and down
wrist_yawswings the hand sideways
wrist_rollspins the hand around its own axis

Six revolute joints give the arm six degrees of freedom. The gripper adds a seventh motion, the gap between the fingers, driven by its own servo.

Why six

To pick something up, the hand has to arrive at a position, three numbers, and at an orientation, three more. A cup handle, a screw, and a block that has to face the camera all care about the orientation.

With three joints the arm can reach a point, and the hand arrives turned however the arm happens to fold. With six joints the arm can choose the point and the orientation together. That is why six is the standard count for a manipulator. Arms with seven or more degrees of freedom exist. The extra joints let them reach the same pose in more than one way, which helps on a crowded space (eg: to avoid collisions with other objects).

In Solarian

The whole machine is a Robot. Each piece of hardware on it is a Module: the arm, the gripper, the camera. A module has its own control loop and its own config file.

A module declares its joints as class attributes, one per joint, along with the actuator that drives it. Here is the arm you write in Tutorial 2, with the six joints from the table:

so106/modules/right_arm.py

from solarian.core.module import Module
from solarian_feetech.actuator import FeetechServo


class RightArmModule(Module):
    shoulder_pan = FeetechServo(model="sts3250")
    shoulder_lift = FeetechServo(model="sts3250")
    elbow_flex = FeetechServo(model="sts3250")
    wrist_flex = FeetechServo(model="sts3250")
    wrist_yaw = FeetechServo(model="sts3215")
    wrist_roll = FeetechServo(model="sts3215")

Each FeetechServo is one servo, so each line is one joint. sts3250 and sts3215 are two Feetech servo models: the stronger one carries the shoulder, elbow, and wrist flex.

The gripper follows the same pattern. It ships in a plugin, so you install it instead of writing it. Its module declares a single servo:

solarian_umi_slim/umi_slim_feetech.py

class UmiSlimFeetechModule(GripperModule):
    gripper = FeetechServo(model="sts3215")

The robot lists its modules the same way:

so106/robot.py

class So106Robot(Robot):
    right_arm = RightArmModule()
    right_gripper = UmiSlimFeetechModule()

The attribute names, right_arm and right_gripper, are the names you use from then on: in config files, in commands, and in recorded data.

Next: configuration and coordinates.

Was this page helpful?