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.
Note
ETS2 has numerical inverse kinematics,
ikine_LM(), but no Hessian or manipulability
methods yet.
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]))
Pure rotation |
|
Pure translation along the x-axis |
|
Pure translation along the y-axis |
|
A static SE2 |
Information
The transform type and axis |
|
The transform type and axis |
|
The Cartesian axis this transform acts along/about |
|
Get the transform constant |
|
Test if ET is a joint |
|
Test if ET joint is flipped |
|
Offset of a joint |
|
Test if ET is a rotation |
|
Test if ET is a translation |
|
Test if ET is an elementary transform |
|
Get ET joint index |
|
Joint limits |
Kinematics
Evaluate an elementary transformation |
|
Inverse of ET |
|
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 descriptorsunit (
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.R(param)is an elementary rotation by a constant angleET2.R()is an elementary rotation by a variable angle, i.e. a revolute robot joint.jorflipcan be set in this case.
Notes
- In the 2D case this is rotation around the normal to the
xy-plane.
See also
- 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 descriptorsj – Explicit joint number within the robot
flip – Joint moves in opposite direction
- Returns:
An elementary transform
- Return type:
ET2.tx(param)is an elementary translation along the x-axis by a distance constantET2.tx()is an elementary translation along the x-axis by a variable distance, i.e. a prismatic robot joint.jorflipcan be set in this case.
See also
- 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 descriptorsj – Explicit joint number within the robot
flip – Joint moves in opposite direction
- Returns:
An elementary transform
- Return type:
ET2.ty(param)is an elementary translation along the y-axis by a distance constantET2.ty()is an elementary translation along the y-axis by a variable distance, i.e. a prismatic robot joint.jorflipcan be set in this case.
See also
- classmethod SE2(T, **kwargs)[source]
A static SE2
- Parameters:
- Returns:
An elementary transform
- Return type:
See also
- 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:
Examples
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, otherwiseNone(e.g.ET2’s rotation, which has no axis letter, or a compound/arbitrarySE3/SE2transform)- Return type:
str or None
Examples
- property axis: str
The transform type and axis
Deprecated since version 1.4.0: Use
kindinstead.axisis 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:
- inv()
Inverse of ET
- Returns:
Inverse of the ET
- Return type:
The inverse of a given ET.
Examples
- property iselementary: bool
Test if ET is an elementary transform
- Returns:
True if an elementary transform
- Return type:
Notes
- ET’s may not actually be “elementary”, it can be a complex
mix of rotations and translations.
See also
- property isflip: bool
Test if ET joint is flipped
- Returns:
True if joint is flipped
- Return type:
A flipped joint uses the negative of the joint variable, ie. it rotates or moves in the opposite direction.
Examples
- property isrotation: bool
Test if ET is a rotation
- Returns:
True if a rotation
- Return type:
Examples
- property istranslation: bool
Test if ET is a translation
- Returns:
True if a translation
- Return type:
Examples
- 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
- Setter accepts:
- property kind: str
The transform type and axis
- Returns:
The transform type and axis, e.g.
"Rx","tx","SE3"- Return type:
Examples
- property offset: float | Symbol
Offset of a joint
- Returns:
the offset, zero unless one has been set
- Raises:
TypeError – on set, if the transform is not a joint
A joint transforms by \(\pm q + a\): the joint variable, negated if the joint is flipped, plus the offset \(a\). This is the offset of a Denavit-Hartenberg link, and it is what remains of a constant transform of the same kind that is merged into a joint, see
merge(). The joint limitsqlimare limits on \(q\), not on \(\pm q + a\).The offset may be symbolic. It is zero if it is exactly zero or, for a rotation, a whole number of turns of a symbolic angle.
Examples
Note
A joint with an offset is evaluated by the Python code, not the compiled code, so it is slower.
ik_LM,ik_NRandik_GN, which need the compiled code, do not accept it.
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
Number of joints |
|
Number of transforms |
|
Joint structure string |
|
Get a list of the variable ETs with this ETS |
|
Get index of joint transforms |
|
Get an array of joint indices |
|
Get set of joint indices |
|
Get/Set Joint limits |
|
Generate a random valid joint configuration |
Modification
Insert value |
|
Inverse of ETS |
|
Return an independent ETS2 with the specified joint held constant. |
|
Split ETS into link segments |
|
Swap two adjacent transforms, in place |
|
Swap two adjacent transforms, returning a copy |
|
Merge two adjacent transforms into one, in place |
|
Merge two adjacent transforms, returning a copy |
|
Compile an ETS2 |
List operations
A sequence is a list of elementary transforms, so it has the methods of a list. Those that change it do so in place.
Method |
Does |
|---|---|
adds an elementary transform to the end |
|
adds the transforms of another sequence to the end |
|
|
removes and returns the transform at an index, by default the last |
removes the first transform that is equal to the given one |
|
reverses the order of the transforms, which is not the inverse of the sequence, see |
|
|
removes all the transforms |
|
the number of transforms equal to the given one |
|
the index of the first transform equal to the given one |
Kinematics
Forward kinematics |
|
Forward kinematics (returns raw ndarray) |
|
Manipulator Jacobian in the base frame |
|
Jacobian in end-effector frame |
|
Levenberg-Marquardt numerical inverse kinematics solver |
Other
Plot the sequence as a robot |
|
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 listET2.XY(η)is a constant elementary transformET2.XY(η, 'deg')as above but the angle is expressed in degreesET2.XY()is a joint variable, the value is left free until evaluation timeET2.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
XYis one ofR,tx,ty.Example
- References:
Kinematic Derivatives using the Elementary Transform Sequence, J. Haviland and P. Corke
See also
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:
- Return type:
- Returns:
ETS2 with one fewer joint
- Raises:
ValueError – for an invalid joint position or angular unit
Fixing a flipped revolute joint preserves the other joint as a variable:
>>> from roboticstoolbox import ET2 >>> ets = ET2.R(flip=True) * ET2.tx(1) * ET2.R() >>> fixed = ets.fixjoint(0, 90, unit="deg") >>> fixed.n, ets.n (1, 2) >>> (1, 2) (1, 2)
Added in version 1.5.0.
- compile()[source]
Compile an ETS2
- Return type:
- Returns:
optimised ETS2
Perform constant folding for faster evaluation. Consecutive constant ETs are compounded, leading to a constant ET which is denoted by
SE3when displayed.See also
isconstant
- insert(i, arg)[source]
Insert value
- Parameters:
- Return type:
Inserts an ET or ETS into the ET sequence. The inserted value is at position
i.Example:
- fkine(q=None, base=None, tool=None, include_base=True)[source]
Forward kinematics
- Parameters:
- Returns:
transformation matrix representing the end-effector pose
- Return type:
T = ets.fkine(q)evaluates forward kinematics for the robot at joint configurationq.Trajectory operation: If
qhas multiple rows (mxn), it is considered a trajectory and the result is anSE2instance withmvalues.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:
T = ets.eval(q)evaluates forward kinematics for the robot at joint configurationq, returning the raw ndarray.Trajectory operation: If
qhas 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
- jacob0(q)[source]
Manipulator Jacobian in the base frame
- Parameters:
- Return type:
- Returns:
the Jacobian, rows are \((v_x, v_y, \omega)\), one column per joint
Note
This is a simple, not efficient, implementation.
- append(value)
S.append(value) – append value to the end of the sequence
- extend(values)
S.extend(iterable) – extend sequence by appending elements from the iterable
- 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:
- Returns:
Inverse of the ETS
Examples
Notes
- It is essential to use explicit joint indices to account for
the reversed order of the transforms.
- jacobe(q)[source]
Jacobian in end-effector frame
- Parameters:
- Returns:
Jacobian matrix
- Return type:
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}\).
See also
jacob0(),hessian0
- jindex_set()
Get set of joint indices
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:
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:
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 adjacent transforms into one, in place
- Parameters:
i (
int) – index of the first transform- Raises:
IndexError – if
iandi+1are not both in the sequenceValueError – if the transforms are not of the same kind, or both are joints
- Return type:
Replaces the transforms at indices
iandi+1with a single transform. This changes the sequence it is called on and returnsNone; usemerged()to get a modified copy and leave the original alone.The two transforms must be of the same kind, for example two
txor twoRz. There are two cases:Two constants become a constant whose parameter is the sum of the two.
A joint and a constant become the same joint, with the constant added to its
offset, soRz(q) * Rz(a)isRz(q + a). The joint keeps itsjindex,flipandqlim.
Two joints cannot be merged, since they are two variables.
The parameters and offsets may be numeric or symbolic, or one of each. If two constants add up to nothing the transform is removed altogether, rather than being left as a transform that does nothing. An offset that adds up to nothing is zero but the joint stays. The sum is nothing if it is
exactly zero, for example
tx(x) * tx(-x)withxa SymPy symbol, orRx(5) * Rx(-5)for a rotation, a whole number of turns of a symbolic angle, for example
Rz(pi/2) * Rz(3*pi/2)withpifrom SymPy. A floating point sum such asRz(pi/2) * Rz(3*pi/2)usingmath.piis not exactly zero, so the rotation is kept.
Merging does not look at the neighbours of the result, so if removing a transform leaves two mergeable ones adjacent, call
merge()again.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) >>> e = ET.tx(1) * ET.Rx(0.5) * ET.Rx(-0.5) * ET.tx(2) >>> e.merge(1) >>> print(e) tx(1) ⊕ tx(2)
A constant merged into a joint becomes its offset, which may be symbolic:
>>> from roboticstoolbox import ET >>> from spatialmath.base import symbol >>> a = symbol("a") >>> e = ET.tx(1) * ET.Rz() * ET.Rz(a) * ET.tx(2) >>> e.merge(1) >>> print(e) tx(1) ⊕ Rz(q + a) ⊕ tx(2) >>> e = ET.Rz(-a) * ET.Rz() * ET.Rz(a) >>> e.merge(1) >>> print(e) Rz(-a) ⊕ Rz(q + a) >>> e.merge(0) >>> print(e) Rz(q)
Changed in version 1.5.0: A joint can be merged with a constant, and a transform that adds up to nothing is removed.
- merged(i)
Merge two adjacent transforms, returning a copy
- Parameters:
i (
int) – index of the first transform- Return type:
- Returns:
a copy of the sequence with transforms
iandi+1merged- Raises:
IndexError – if
iandi+1are not both in the sequenceValueError – if the transforms are not of the same kind, or both are joints
The sequence it is called on is not changed. See
merge()for which transforms can be merged and when the result is removed.Examples
Added in version 1.5.0.
- property n: int
Number of joints
- Returns:
the number of joints in the ETS
- Return type:
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
- plot(*args, **kwargs)
Plot the sequence as a robot
The sequence is wrapped in a
Robot(Robot2for a planar sequence) and itsplotmethod is called, which see for the arguments.- Return type:
- 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]])
- random_q(i=1)
Generate a random valid joint configuration
- Parameters:
i (
int) – number of configurations to generate- Returns:
random joint configuration
- Return type:
Generates a random q vector within the joint limits defined by
self.qlim.Examples
- remove(value)
S.remove(value) – remove first occurrence of value. Raise ValueError if the value is not present.
- reverse()
S.reverse() – reverse IN PLACE
- split(method='last')
Split ETS into link segments
- Parameters:
method (
str) – one of"first"or"last"(default).- Return type:
- Returns:
[base, *segments, gripper]– a list of lengthn_joints + 2.base/gripperare 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
methodargument:"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:
Examples
>>> from roboticstoolbox import ET >>> e = ET.tz() * ET.tx(1) * ET.Rz() * ET.tx(1) >>> e.structure 'PR'
- swap(i)
Swap two adjacent transforms, in place
- Parameters:
i (
int) – index of the first transform- Raises:
IndexError – if
iandi+1are not both in the sequenceValueError – if the two transforms cannot be swapped
- Return type:
Swaps the transforms at indices
iandi+1without changing what the sequence means. This changes the sequence it is called on and returnsNone; useswapped()to get a modified copy and leave the original alone.There are two ways the transforms can swap.
They commute, so they trade places 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
Rzandtz
One is a constant quarter or half turn, a rotation \(R\) of \(\pm 90^\circ\) or \(180^\circ\). The other transform \(B\) is carried across it by being turned with it, since \(R B = (R B R^{-1}) R\). The rotation is unchanged, and the other transform moves to the other side of it and changes axis, and its sign if the axis comes out reversed. For example
Rx(90°) ⊕ ty(d)istz(d) ⊕ Rx(90°), andRx(90°) ⊕ Ry(q)isRz(q) ⊕ Rx(90°). The other transform may be a translation or a rotation, a joint or a constant. A joint keeps itsjindexandqlim; if its axis comes out reversed it is flipped, and its offset changes sign.A rotation is a quarter turn if it is a whole number of quarter turns of a symbolic angle, such as
pi/2or3*pi/2withpifrom SymPy, or a float that is within \(10^{-9}\) of one, which a model loaded from a file will have. The new transform takes its parameter from the old one by a change of sign only, so it is as exact as the old one.Anything else, such as a rotation that is not a quarter turn and a translation along a different axis, does not swap and raises
ValueError, as do two quarter turns about different axes, since either could be the one that is carried across.Note
Joints may be swapped. Each joint keeps its
jindex, so the order of the elements ofqis unchanged even though the joints now appear in the opposite order in the sequence.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°)
A quarter turn carries the other transform with it:
>>> from math import pi >>> e = ET.Rx(pi / 2) * ET.ty(1) * ET.tx(2) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'ET' is not defined >>> print(e) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'e' is not defined >>> e.swap(0) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'e' is not defined >>> print(e) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'e' is not defined >>> e = ET.Rx(pi / 2) * ET.Ry() !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'ET' is not defined >>> e.swap(0) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'e' is not defined >>> print(e) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'e' is not defined >>> e = ET.Rx(-pi / 2) * ET.Ry() !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'ET' is not defined >>> e.swap(0) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'e' is not defined >>> print(e) !! [RUNBLOCK-ERROR] ets/ETS2.py:docstring of roboticstoolbox.ets._ETS.BaseETS.swap:712 NameError: name 'e' is not defined
Changed in version 1.5.0: A transform can be swapped across a constant quarter or half turn.
- swapped(i)
Swap two adjacent transforms, returning a copy
- Parameters:
i (
int) – index of the first transform- Return type:
- Returns:
a copy of the sequence with transforms
iandi+1swapped- Raises:
IndexError – if
iandi+1are not both in the sequenceValueError – if the two transforms do not commute
The sequence it is called on is not changed. See
swap()for which transforms can be swapped.Examples
Added in version 1.5.0.
- teach(*args, **kwargs)
Interactively explore the sequence as a robot
The sequence is wrapped in a
Robot(Robot2for a planar sequence) and itsteachmethod is called, which see for the arguments.- Return type:
- ikine_LM(Tep, q0=None, ilimit=30, slimit=100, tol=1e-06, mask=None, joint_limits=True, seed=None, k=1.0)[source]
Levenberg-Marquardt numerical inverse kinematics solver
- Parameters:
Tep (
ndarray|SE2) – the desired end-effector pose, anSE2or a 3x3 array, or a pose trajectory, anSE2with several values or an (N, 3, 3) arrayq0 (
ndarray|Sequence[float] |None) – the initial joint coordinates, a vector (n,), or a matrix (m, n) whose rows are the starting points of the first m searches (any further searches start from random coordinates within the joint limits)ilimit (
int) – maximum iterations allowed per searchslimit (
int) – maximum search attempts before failuretol (
float) – maximum allowed residual error Emask (
ndarray|Sequence[float] |None) – a 3-vector weighting the (x, y, θ) error priority, for example[1, 1, 0]to solve for position onlyjoint_limits (
bool) – reject solutions with joint limit violationsseed (
int|None) – seed for the RNG used to generate random joint configurationsk (
float) – gain λ of Chan’s damping matrix, see below
- Return type:
- Returns:
the solution, see
IKSolution- Raises:
ValueError –
Tepis not a 3x3 pose or an (N, 3, 3) trajectory,maskis not a 3-vector,q0has the wrong number of columns, or a joint has an infinite limit so no random configuration can be drawn
sol = ets.ikine_LM(Tep)are the joint coordinates (n) corresponding to the planar end-effector poseTep. The solver is the planar counterpart ofETS.ikine_LM(): the pose error is the 3-vector \(\vec{e} = (\Delta x, \Delta y, \Delta\theta)\) in the world frame, the residual is \(E = \tfrac{1}{2} \vec{e}^\top \mat{W}_e \vec{e}\) with \(\mat{W}_e = \text{diag}(\text{mask})\), and each step is\[\vec{q}_{k+1} = \vec{q}_k + \left( \mat{J}^\top \mat{W}_e \mat{J} + \lambda E_k \mat{1}_n \right)^{-1} \mat{J}^\top \mat{W}_e \vec{e}\]where \(\mat{J}\) is
jacob0(). BecauseEis quadratic,tolbounds the pose error only to roughly \(\sqrt{2 \cdot \text{tol}}\); tighten it if a specific linear-scale accuracy is needed.Each search starts from a row of
q0, or a random configuration drawn within the joint limits, and runs for at mostilimititerations; up toslimitsearches are made before the solver gives up. A solution that lies outside the joint limits is rejected whenjoint_limitsis True, and the search continues.Trajectory operation: for a trajectory of N poses the solver is run once per pose, each from the same starting points, and the returned
qhas shape (N, n).successis True only if every pose was solved,iterationsandsearchesare summed,residualis the largest over the poses andreasonis that of the last failed pose.Example:
>>> import roboticstoolbox as rtb >>> from roboticstoolbox.ets.ET2 import R, tx >>> ets = R() * tx(1) * R() * tx(1) >>> Tep = ets.fkine([0.3, 0.7]) >>> sol = ets.ikine_LM(Tep, seed=0) >>> sol.success True >>> ets.fkine(sol.q) SE2(array([[ 0.5403, -0.8415, 1.4956], [ 0.8415, 0.5403, 1.137 ], [ 0. , 0. , 1. ]]))
References
J. Haviland, and P. Corke. “Manipulator Differential Kinematics Part I: Kinematics, Velocity, and Applications.” arXiv preprint arXiv:2207.01796 (2022).
See also
Added in version 1.5.0.