ETS for 2D space

An ET2 is one elementary \(\SE{2}\) transform: a rotation about, or a translation along, the x- or y-axis. The angle or distance is either a constant or, if it is left out, a variable, which makes the transform a joint. An ETS2 is a sequence of them. The three-dimensional equivalents are on the ETS for 3D space page.

We can use ETS to describes a planar arm that moves in 3D space.

>>> from roboticstoolbox import ET2
>>> e = ET2.R() * ET2.tx(1) * ET2.R() * ET2.tx(1)
>>> print(e)
R(q0) ⊕ tx(1) ⊕ R(q1) ⊕ tx(1)
>>> e.fkine([0.3, 0.4])
SE2(array([[ 0.7648, -0.6442,  1.7202],
           [ 0.6442,  0.7648,  0.9397],
           [ 0.    ,  0.    ,  1.    ]]))

Note

ETS2 has no inverse kinematics, Hessian or manipulability methods yet, see Issue 824.

ET2: Elementary Transform

Creating an elementary transform

The constructors R, tx and ty take the same arguments as their 3D equivalents on the ETS for 3D space page: no argument for a joint, a number for a constant, 'deg' for a rotation in degrees, flip, jindex and qlim. The angle or distance can also be a joint descriptor string, with the same rules, see Joint descriptors.

>>> from roboticstoolbox import ET2
>>> ET2.R()                        # a joint
ET2.R()
>>> ET2.R(30, 'deg')               # a constant, degrees
ET2.R(param=0.5235987755982988)
>>> ET2.tx(flip=True, qlim=[0, 1]) # a flipped prismatic joint with limits
ET2.tx(flip=True, qlim=array([0., 1.]))
>>> e = ET2.R("q0") * ET2.tx(1) * ET2.R("-q1") * ET2.tx(1)
>>> e, e.jindices
([ET2.R(jindex=0), ET2.tx(param=1.0), ET2.R(jindex=1, flip=True), ET2.tx(param=1.0)], array([0, 1]))

R

Pure rotation

tx

Pure translation along the x-axis

ty

Pure translation along the y-axis

SE2

A static SE2

Information

kind

The transform type and axis

axis

The transform type and axis

ax

The Cartesian axis this transform acts along/about

param

Get the transform constant

isjoint

Test if ET is a joint

isflip

Test if ET joint is flipped

isrotation

Test if ET is a rotation

istranslation

Test if ET is a translation

iselementary

Test if ET is an elementary transform

jindex

Get ET joint index

qlim

Joint limits

Kinematics

A

Evaluate an elementary transformation

inv

Inverse of ET

s

Motion subspace of the joint

Details

class ET2(**kwargs)[source]
property s: ndarray

Motion subspace of the joint

Returns:

the 3-vector \((v_x, v_y, \omega)\) that is the unit twist of the transform: a unit translation along x or y, or a unit rotation

classmethod R(param=None, unit='rad', *, eta=None, **kwargs)[source]

Pure rotation

Parameters:
  • param (float | None | str) – rotation angle, or a joint name such as "q2", see Joint descriptors

  • unit (str) – angular unit, “rad” [default] or “deg”

  • j – Explicit joint number within the robot

  • flip – Joint moves in opposite direction

Returns:

An elementary transform

Return type:

ET2

  • ET2.R(param) is an elementary rotation by a constant angle

  • ET2.R() is an elementary rotation by a variable angle, i.e. a revolute robot joint. j or flip can be set in this case.

Notes

  • In the 2D case this is rotation around the normal to the

    xy-plane.

See also

ET2(), isrotation()

classmethod tx(param=None, unit='rad', *, eta=None, **kwargs)[source]

Pure translation along the x-axis

Parameters:
  • param (float | None | str) – translation distance along the x-axis, or a joint name such as "q2", see Joint descriptors

  • j – Explicit joint number within the robot

  • flip – Joint moves in opposite direction

Returns:

An elementary transform

Return type:

ET2

  • ET2.tx(param) is an elementary translation along the x-axis by a distance constant

  • ET2.tx() is an elementary translation along the x-axis by a variable distance, i.e. a prismatic robot joint. j or flip can be set in this case.

classmethod ty(param=None, unit='rad', *, eta=None, **kwargs)[source]

Pure translation along the y-axis

Parameters:
  • param (float | None | str) – translation distance along the y-axis, or a joint name such as "q2", see Joint descriptors

  • j – Explicit joint number within the robot

  • flip – Joint moves in opposite direction

Returns:

An elementary transform

Return type:

ET2

  • ET2.ty(param) is an elementary translation along the y-axis by a distance constant

  • ET2.ty() is an elementary translation along the y-axis by a variable distance, i.e. a prismatic robot joint. j or flip can be set in this case.

See also

ET2()

classmethod SE2(T, **kwargs)[source]

A static SE2

Parameters:

T (ndarray | SE2) – The SE2 transformation matrix

Returns:

An elementary transform

Return type:

ET2

See also

ET2() istranslation()

SymPy:

supported

A(q=0.0)

Evaluate an elementary transformation

Parameters:

q (float | Symbol) – Is used if this ET is variable (a joint)

Returns:

The SE(3) or SE(2) matrix value of the ET

Return type:

ndarray

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx(1)
>>> e.A()
array([[1., 0., 0., 1.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])
>>> e = ET.tx()
>>> e.A(0.7)
array([[1. , 0. , 0. , 0.7],
       [0. , 1. , 0. , 0. ],
       [0. , 0. , 1. , 0. ],
       [0. , 0. , 0. , 1. ]])

Pure-Python evaluation, shared by ET2 and used by ET as the fallback when the compiled acceleration struct can’t be used.

property ax: str | None

The Cartesian axis this transform acts along/about

Returns:

"x", "y", or "z" for an elementary transform, otherwise None (e.g. ET2’s rotation, which has no axis letter, or a compound/arbitrary SE3/SE2 transform)

Return type:

str or None

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx(1)
>>> e.ax
'x'
>>> e = ET.Rx(90, 'deg')
>>> e.ax
'x'
property axis: str

The transform type and axis

Deprecated since version 1.4.0: Use kind instead. axis is kept as an alias and will not be repurposed to mean something else in a future release.

Returns:

The transform type and axis

Return type:

str

property eta: float | Symbol | None

Get the transform constant

Deprecated since version 1.4.0: eta (η) is the name used in the original Elementary Transform Sequence paper; kept as a permanent alias for param, which is otherwise identical.

Returns:

The constant value if set

Return type:

float or Sym or None

Setter accepts:

float | Symbol

inv()

Inverse of ET

Returns:

Inverse of the ET

Return type:

Any

The inverse of a given ET.

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rz(2.5)
>>> print(e)
Rz(143.2°)
>>> print(e.inv())
Rz(-143.2°)
property iselementary: bool

Test if ET is an elementary transform

Returns:

True if an elementary transform

Return type:

bool

Notes

  • ET’s may not actually be “elementary”, it can be a complex

    mix of rotations and translations.

See also

compile()

property isflip: bool

Test if ET joint is flipped

Returns:

True if joint is flipped

Return type:

bool

A flipped joint uses the negative of the joint variable, ie. it rotates or moves in the opposite direction.

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx()
>>> e.A(1)
array([[1., 0., 0., 1.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])
>>> eflip = ET.tx(flip=True)
>>> eflip.A(1)
array([[ 1.,  0.,  0., -1.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])
property isjoint: bool

Test if ET is a joint

Returns:

True if a joint

Return type:

bool

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx(1)
>>> e.isjoint
False
>>> e = ET.tx()
>>> e.isjoint
True
property isrotation: bool

Test if ET is a rotation

Returns:

True if a rotation

Return type:

bool

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx(1)
>>> e.isrotation
False
>>> e = ET.Rx()
>>> e.isrotation
True
property istranslation: bool

Test if ET is a translation

Returns:

True if a translation

Return type:

bool

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx(1)
>>> e.istranslation
True
>>> e = ET.Rx()
>>> e.istranslation
False
property jindex: int | None

Get ET joint index

Returns:

The assigned joint index

Return type:

int or None

Allows an ET to be associated with a numbered joint in a robot.

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx()
>>> print(e)
tx(q)
>>> e = ET.tx(jindex=3)
>>> print(e)
tx(q3)
>>> print(e.jindex)
3
Setter accepts:

Any

property kind: str

The transform type and axis

Returns:

The transform type and axis, e.g. "Rx", "tx", "SE3"

Return type:

str

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx(1)
>>> e.kind
'tx'
>>> e = ET.Rx(90, 'deg')
>>> e.kind
'Rx'
property param: float | Symbol | None

Get the transform constant

Returns:

The constant value if set

Return type:

float or Sym or None

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tx(1)
>>> e.param
1.0
>>> e = ET.Rx(90, 'deg')
>>> e.param
1.5707963267948966
>>> e = ET.ty()
>>> e.param

Notes

  • If the value was given in degrees it will be converted and

    stored internally in radians

  • Historically called eta (η), after the notation used in the

    original Elementary Transform Sequence paper (Haviland & Corke, “Manipulator Differential Kinematics”). eta is kept as a deprecated alias below.

Setter accepts:

float | Symbol

property qlim: ndarray | None

Joint limits

Returns:

the joint limits as a 2-vector [lower, upper], or None if the transform has no limits

Setter accepts:

ndarray | Sequence[float] | None

ETS: Elementary Transform Sequence

An ETS2 is a list-like object, with the same list methods as the ETS. Joint descriptors are the same as for the 3D case, see Joint descriptors.

Information

n

Number of joints

m

Number of transforms

structure

Joint structure string

joints

Get a list of the variable ETs with this ETS

joint_idx

Get index of joint transforms

jindices

Get an array of joint indices

jindex_set

Get set of joint indices

qlim

Get/Set Joint limits

random_q

Generate a random valid joint configuration

Modification

insert

Insert value

inv

Inverse of ETS

fixjoint

Return an independent ETS2 with the specified joint held constant.

split

Split ETS into link segments

swap

Swap two transforms in the ETS

merge

Merge two transforms in the ETS

compile

Compile an ETS2

Kinematics

fkine

Forward kinematics

eval

Forward kinematics (returns raw ndarray)

jacob0

Manipulator Jacobian in the base frame

jacobe

Jacobian in end-effector frame

Other

plot

Plot the sequence as a robot

teach

Interactively explore the sequence as a robot

Details

class ETS2(arg=None)[source]

This class implements an elementary transform sequence (ETS) for 2D

Parameters:

arg (list[ETS2 | ET2] | list[ET2] | list[ETS2] | ET2 | ETS2 | None) – Function to compute ET value

An instance can contain an elementary transform (ET) or an elementary transform sequence (ETS). It has list-like properties by subclassing UserList, which means we can perform indexing, slicing pop, insert, as well as using it as an iterator over its values.

  • ETS() an empty ETS list

  • ET2.XY(η) is a constant elementary transform

  • ET2.XY(η, 'deg') as above but the angle is expressed in degrees

  • ET2.XY() is a joint variable, the value is left free until evaluation time

  • ET2.XY(jindex=J) as above but the joint index is explicitly given, this might correspond to the joint number of a multi-joint robot.

  • ET2.XY(flip=True) as above but the joint moves in the opposite sense

where XY is one of R, tx, ty.

Example

>>> from roboticstoolbox import ET2
>>> e = ET2.R(0.3) * ET2.tx(2)  # an ETS2
>>> len(e)                      # of length 2
2
>>> e[1]                        # an ET2 indexed from the ETS2
ET2.tx(param=2.0)
References:
  • Kinematic Derivatives using the Elementary Transform Sequence, J. Haviland and P. Corke

Seealso:

r, tx, ty

fixjoint(j, value, unit='rad')[source]

Return an independent ETS2 with the specified joint held constant.

j is the zero-based position among joint ETs, independent of their jindex values. Remaining joints retain explicit global jindices; automatically indexed joints are renumbered to fill the gap. Joint limits and flip flags are preserved. The original is not modified.

Parameters:
  • j (int) – index of the joint to fix

  • value (float) – fixed joint coordinate, in radians/degrees or metres

  • unit (str) – angular unit for rotational joints, “rad” [default] or “deg”

Return type:

ETS2

Returns:

ETS2 with one fewer joint

Raises:

ValueError – for an invalid joint position or angular unit

compile()[source]

Compile an ETS2

Return type:

ETS2

Returns:

optimised ETS2

Perform constant folding for faster evaluation. Consecutive constant ETs are compounded, leading to a constant ET which is denoted by SE3 when displayed.

Seealso:

isconstant

insert(i, arg)[source]

Insert value

Parameters:
  • i (int) – position to insert at

  • arg (ET2 | ETS2) – the elementary transform or sequence to insert

Return type:

None

Inserts an ET or ETS into the ET sequence. The inserted value is at position i.

Example:

>>> from roboticstoolbox import ET2
>>> e = ET2.R() * ET2.tx(1) * ET2.R() * ET2.tx(1)
>>> f = ET2.R()
>>> e.insert(2, f)
>>> e
[ET2.R(jindex=0), ET2.tx(param=1.0), ET2.R(), ET2.R(jindex=1), ET2.tx(param=1.0)]
fkine(q=None, base=None, tool=None, include_base=True)[source]

Forward kinematics

Parameters:
Returns:

transformation matrix representing the end-effector pose

Return type:

SE2

T = ets.fkine(q) evaluates forward kinematics for the robot at joint configuration q.

Trajectory operation: If q has multiple rows (mxn), it is considered a trajectory and the result is an SE2 instance with m values.

Note

  • The robot’s base tool transform, if set, is incorporated into the result.

  • A tool transform, if provided, is incorporated into the result.

  • Works from the end-effector link to the base

References

  • Kinematic Derivatives using the Elementary Transform Sequence, J. Haviland and P. Corke

eval(q=None, base=None, tool=None, include_base=True)[source]

Forward kinematics (returns raw ndarray)

Parameters:
Returns:

transformation matrix representing the end-effector pose

Return type:

ndarray

T = ets.eval(q) evaluates forward kinematics for the robot at joint configuration q, returning the raw ndarray.

Trajectory operation: If q has multiple rows (mxn), it is considered a trajectory and the result is an ndarray of shape (m,3,3).

Note

  • The robot’s base tool transform, if set, is incorporated into the result.

  • A tool transform, if provided, is incorporated into the result.

  • Works from the end-effector link to the base

References

  • Kinematic Derivatives using the Elementary Transform Sequence, J. Haviland and P. Corke

inv()

Inverse of ETS

The inverse of a given ETS. It is computed as the inverse of the individual ETs in the reverse order.

\[(\mathbf{E}_0, \mathbf{E}_1 \cdots \mathbf{E}_{n-1} )^{-1} = (\mathbf{E}_{n-1}^{-1}, \mathbf{E}_{n-2}^{-1} \cdots \mathbf{E}_0^{-1}{n-1} )\]
Return type:

Self

Returns:

Inverse of the ETS

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rz(jindex=2) * ET.tx(1) * ET.Rx(jindex=3,flip=True) * ET.tx(1)
>>> print(e)
Rz(q2) ⊕ tx(1) ⊕ Rx(-q3) ⊕ tx(1)
>>> print(e.inv())
tx(-1) ⊕ Rx(q3) ⊕ tx(-1) ⊕ Rz(-q2)

Notes

  • It is essential to use explicit joint indices to account for

    the reversed order of the transforms.

jacob0(q)[source]

Manipulator Jacobian in the base frame

Parameters:

q (ndarray | Sequence[float]) – the joint coordinates

Return type:

ndarray

Returns:

the Jacobian, rows are \((v_x, v_y, \omega)\), one column per joint

Note

This is a simple, not efficient, implementation.

jindex_set()

Get set of joint indices

Returns:

set of unique joint indices

Return type:

set[int]

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1)
>>> e.jindex_set()
{1, 2}
property jindices: ndarray

Get an array of joint indices

Returns:

array of unique joint indices

Return type:

ndarray

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1)
>>> e.jindices
array([1, 2, 1])
joint_idx()

Get index of joint transforms

Returns:

indices of transforms that are joints

Return type:

ndarray

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
>>> e.joint_idx()
array([0, 2])
joints()

Get a list of the variable ETs with this ETS

Returns:

list of ETs that are joints

Return type:

list[ETT]

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1)
>>> e.joints()
[ET.Rz(jindex=0), ET.Rz(jindex=1)]
property m: int

Number of transforms

Returns:

the number of transforms in the ETS

Return type:

int

Counts the number of transforms in the ETS.

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rx() * ET.tx(1) * ET.tz()
>>> e.m
3
merge(i)

Merge two transforms in the ETS

Parameters:

i (int) – index of first transform

Return type:

None

Merges the two transforms at indices i and i+1. This is useful for reducing the number of transforms in an ETS.

Examples

>>> from roboticstoolbox import ET
>>> from math import pi
>>> e = ET.Rz() * ET.tx(1) * ET.tx(2) * ET.Rz(1)
>>> print(e)
Rz(q) ⊕ tx(1) ⊕ tx(2) ⊕ Rz(57.3°)
>>> e.merge(1)
>>> print(e)
Rz(q) ⊕ tx(3) ⊕ Rz(57.3°)
>>> e = ET.tx(1) * ET.Rx(0.1) * ET.Rx(pi/2) * ET.tx(2)
>>> print(e)
tx(1) ⊕ Rx(5.73°) ⊕ Rx(90°) ⊕ tx(2)
>>> e.merge(1)
>>> print(e)
tx(1) ⊕ Rx(95.73°) ⊕ tx(2)

Both transforms must be of the same kind, and at most one of them can be a joint.

property n: int

Number of joints

Returns:

the number of joints in the ETS

Return type:

int

Counts the number of joints in the ETS.

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rx() * ET.tx(1) * ET.tz()
>>> e.n
2

See also

joints()

plot(*args, **kwargs)

Plot the sequence as a robot

The sequence is wrapped in a Robot (Robot2 for a planar sequence) and its plot method is called, which see for the arguments.

Return type:

None

property qlim: ndarray

Get/Set Joint limits

Limits are extracted from the link objects. If joints limits are not set for:

  • a revolute joint [-𝜋. 𝜋] is returned

  • a prismatic joint an exception is raised

Parameters:

new_qlim (ndarray(2,n)) – new joint limits to set

Returns:

array of joint limit values

Return type:

ndarray(2,n)

Raises:

ValueError – unset limits for a prismatic joint

Examples

>>> import roboticstoolbox as rtb
>>> robot = rtb.models.DH.Puma560()
>>> robot.qlim
array([[-2.7925, -0.7854, -3.927 , -1.9199, -1.7453, -4.6426],
       [ 2.7925,  3.927 ,  0.7854,  2.9671,  1.7453,  4.6426]])
Setter accepts:

ndarray | Sequence[float]

random_q(i=1)

Generate a random valid joint configuration

Parameters:

i (int) – number of configurations to generate

Returns:

random joint configuration

Return type:

ndarray

Generates a random q vector within the joint limits defined by self.qlim.

Examples

>>> import roboticstoolbox as rtb
>>> robot = rtb.models.Panda()
>>> ets = robot.ets()
>>> q = ets.random_q()
>>> q
array([ 1.1033, -0.7686,  2.8497, -1.7619,  0.7581,  2.4501,  1.4691])
split(method='last')

Split ETS into link segments

Parameters:

method (str) – one of "first" or "last" (default).

Return type:

list[Self]

Returns:

[base, *segments, gripper] – a list of length n_joints + 2. base/gripper are empty ETS when the method has no concept of one.

Split an ETS into segments representing links, plus a base and gripper segment. Unpack with base, *segments, gripper = ets.split(method).

The behaviour depends on the method argument:

  • "first": each link segment begins with a joint and continues upto, but not including the next joint. Any constant ET before the first joint are part of the base. There are no gripper ET, they are included in the last link segment.

  • "last": each link segment ends with a joint and include all ET after the previous joint. Any constant ET after the last joint are part of the gripper. There are no base ET, they are included in the first link segment.

>>> from roboticstoolbox import ET
>>> e = ET.tz(1) * ET.Rx("q1") * ET.tx(2) * ET.Ry("q2") * ET.ty(3) * ET.Rz("q3") * ET.tz(4)
>>> base, *segments, gripper = e.split("first")
>>> print("|".join(str(_) for _ in segments), f"+ base={str(base)}, gripper={str(gripper)}")
Rx(q1) ⊕ tx(2)|Ry(q2) ⊕ ty(3)|Rz(q3) ⊕ tz(4) + base=tz(1), gripper=SE3()
>>> base, *segments, gripper = e.split("last")
>>> print("|".join(str(_) for _ in segments), f"+ base={str(base)}, gripper={str(gripper)}")
tz(1) ⊕ Rx(q1)|tx(2) ⊕ Ry(q2)|ty(3) ⊕ Rz(q3) + base=SE3(), gripper=tz(4)
property structure: str

Joint structure string

A string comprising the characters ‘R’ or ‘P’ which indicate the types of joints in order from left to right.

Returns:

a string indicating the joint types

Return type:

str

Examples

>>> from roboticstoolbox import ET
>>> e = ET.tz() * ET.tx(1) * ET.Rz() * ET.tx(1)
>>> e.structure
'PR'
swap(i)

Swap two transforms in the ETS

Parameters:

i (int) – index of first transform

Raises:

ValueError – if the two transforms do not commute

Return type:

None

Swaps the two transforms at indices i and i+1. This is useful for changing the order of commutative transforms in an ETS, and the kinematics of the sequence are unchanged. Two transforms commute if they are

  • of the same kind, for example two translations along x

  • both translations, along any axes

  • a rotation and a translation along the axis of that rotation, for example Rz and tz

Anything else, such as a rotation and a translation along a different axis, does not commute and raises ValueError.

Examples

>>> from roboticstoolbox import ET
>>> e = ET.Rz() * ET.tx(1) * ET.ty(2) * ET.Rz(1)
>>> print(e)
Rz(q) ⊕ tx(1) ⊕ ty(2) ⊕ Rz(57.3°)
>>> e.swap(1)
>>> print(e)
Rz(q) ⊕ ty(2) ⊕ tx(1) ⊕ Rz(57.3°)
>>> e = ET.Rz() * ET.tz(1) * ET.Rx() * ET.Rz(1)
>>> e.swap(0)
>>> print(e)
tz(1) ⊕ Rz(q0) ⊕ Rx(q1) ⊕ Rz(57.3°)
teach(*args, **kwargs)

Interactively explore the sequence as a robot

The sequence is wrapped in a Robot (Robot2 for a planar sequence) and its teach method is called, which see for the arguments.

Return type:

None

jacobe(q)[source]

Jacobian in end-effector frame

Parameters:

q (ndarray | Sequence[float]) – joint coordinates

Returns:

Jacobian matrix

Return type:

Any

jacobe(q) is the manipulator Jacobian matrix which maps joint velocity to end-effector spatial velocity.

End-effector spatial velocity \(\nu = (v_x, v_y, \omega)^T\) is related to joint velocity by \({}^{e}\nu = {}^{e}\mathbf{J}_0(q) \dot{q}\).

Seealso:

jacob0(), hessian0