Skip to content

Commit cf294c5

Browse files
committed
bdsim blocks: shorten names, add tr2t and jtraj blocks
1 parent 3455429 commit cf294c5

File tree

1 file changed

+187
-11
lines changed

1 file changed

+187
-11
lines changed

roboticstoolbox/blocks/arm.py

Lines changed: 187 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121

2222
# ------------------------------------------------------------------------ #
2323
@block
24-
class Forward_Kinematics(FunctionBlock):
24+
class FKine(FunctionBlock):
2525
"""
26-
:blockname:`FORWARD_KINEMATICS`
26+
:blockname:`FKINE`
2727
2828
.. table::
2929
:align: left
@@ -74,9 +74,9 @@ def output(self, t=None):
7474
return [self.robot.fkine(self.inputs[0], **self.args)]
7575

7676
@block
77-
class Inverse_Kinematics(FunctionBlock):
77+
class IKine(FunctionBlock):
7878
"""
79-
:blockname:`INVERSE_KINEMATICS`
79+
:blockname:`IKINE`
8080
8181
.. table::
8282
:align: left
@@ -385,10 +385,59 @@ def output(self, t=None):
385385
return [T]
386386

387387
# ------------------------------------------------------------------------ #
388+
388389
@block
389-
class Foward_Dynamics(TransferBlock):
390+
class TR2T(FunctionBlock):
390391
"""
391-
:blockname:`FORWARD_DYNAMICS`
392+
:blockname:`TR2T`
393+
394+
.. table::
395+
:align: left
396+
397+
+------------+----------+---------+
398+
| inputs | outputs | states |
399+
+------------+----------+---------+
400+
| 1 | 3 | 0 |
401+
+------------+----------+---------+
402+
| SE3 | float | |
403+
+------------+----------+---------+
404+
"""
405+
406+
def __init__(self, *inputs, **kwargs):
407+
"""
408+
:param T: the transform
409+
:type T: SE3
410+
:param ``*inputs``: Optional incoming connections
411+
:type ``*inputs``: Block or Plug
412+
:param ``**kwargs``: common Block options
413+
:return: a POINT2TR block
414+
:rtype: Point2Tr instance
415+
416+
The block has one input port:
417+
418+
1. a 3D point as an ndarray(3)
419+
420+
and one output port:
421+
422+
1. T as an SE3 with its position part replaced by the input
423+
424+
:seealso: :func:`spatialmath.base.delta2tr`
425+
"""
426+
super().__init__(nin=1, nout=3, inputs=inputs, **kwargs)
427+
self.type = 'tr2t'
428+
429+
self.inport_names(('T',))
430+
self.outport_names(('x', 'y', 'z'))
431+
432+
def output(self, t=None):
433+
t = self.inputs[0].t
434+
return list(t)
435+
436+
# ------------------------------------------------------------------------ #
437+
@block
438+
class FDyn(TransferBlock):
439+
"""
440+
:blockname:`FDYN`
392441
393442
.. table::
394443
:align: left
@@ -468,9 +517,9 @@ def deriv(self):
468517
return np.r_[qd, qdd]
469518

470519
@block
471-
class Inverse_Dynamics(FunctionBlock):
520+
class IDyncs(FunctionBlock):
472521
"""
473-
:blockname:`INVERSE_DYNAMICS`
522+
:blockname:`IDYN`
474523
475524
.. table::
476525
:align: left
@@ -571,6 +620,7 @@ def __init__(self, robot=None, *inputs, q0=None, backend=None, **kwargs):
571620
"""
572621
super().__init__(nin=1, inputs=inputs, **kwargs)
573622
self.type = 'armplot'
623+
self.inport_names(('q',))
574624

575625
if q0 is None:
576626
q0 = np.zeros((robot.n,))
@@ -592,7 +642,9 @@ def step(self):
592642
if self.bd.options.graphics:
593643

594644
self.robot.q = self.inputs[0]
595-
self.env.step()
645+
646+
if self.bd.options.animation:
647+
self.env.step()
596648

597649
super().step()
598650

@@ -601,8 +653,6 @@ def done(self, block=False, **kwargs):
601653
plt.show(block=block)
602654

603655
super().done()
604-
605-
606656
@block
607657
class Traj(FunctionBlock):
608658
"""
@@ -709,6 +759,132 @@ def output(self, t=None):
709759
return [np.hstack(y), np.hstack(yd), np.hstack(ydd)]
710760

711761
@block
762+
class JTraj(SourceBlock):
763+
"""
764+
:blockname:`JTRAJ`
765+
766+
.. table::
767+
:align: left
768+
769+
+------------+------------+---------+
770+
| inputs | outputs | states |
771+
+------------+------------+---------+
772+
| 0 | 3 | 0 |
773+
+------------+------------+---------+
774+
| | ndarray(n) | |
775+
+------------+------------+---------+
776+
"""
777+
778+
def __init__(self, q0, qf, qd0=None, qdf=None, T=None, *inputs, **kwargs):
779+
"""
780+
Compute a joint-space trajectory
781+
782+
:param q0: initial joint coordinate
783+
:type q0: array_like(n)
784+
:param qf: final joint coordinate
785+
:type qf: array_like(n)
786+
:param tv: time vector or number of steps
787+
:type tv: array_like or int
788+
:param qd0: initial velocity, defaults to zero
789+
:type qd0: array_like(n), optional
790+
:param qd1: final velocity, defaults to zero
791+
:type qd1: array_like(n), optional
792+
:param ``*inputs``: Optional incoming connections
793+
:type ``*inputs``: Block or Plug
794+
:param ``**kwargs``: common Block options
795+
:return: TRAJ block
796+
:rtype: Traj instance
797+
798+
- ``tg = jtraj(q0, qf, N)`` is a joint space trajectory where the joint
799+
coordinates vary from ``q0`` (M) to ``qf`` (M). A quintic (5th order)
800+
polynomial is used with default zero boundary conditions for velocity and
801+
acceleration. Time is assumed to vary from 0 to 1 in ``N`` steps.
802+
803+
- ``tg = jtraj(q0, qf, t)`` as above but ``t`` is a uniformly-spaced time
804+
vector
805+
806+
The return value is an object that contains position, velocity and
807+
acceleration data.
808+
809+
Notes:
810+
811+
- The time vector, if given, scales the velocity and acceleration outputs
812+
assuming that the time vector starts at zero and increases
813+
linearly.
814+
815+
:seealso: :func:`ctraj`, :func:`qplot`, :func:`~SerialLink.jtraj`
816+
"""
817+
super().__init__(nin=0, nout=3, **kwargs)
818+
self.blockclass = 'jtraj'
819+
self.type = 'source'
820+
self.outport_names(('q', 'qd', 'qdd',))
821+
self.T = T
822+
823+
q0 = base.getvector(q0)
824+
qf = base.getvector(qf)
825+
826+
if not len(q0) == len(qf):
827+
raise ValueError('q0 and q1 must be same size')
828+
829+
if qd0 is None:
830+
qd0 = np.zeros(q0.shape)
831+
else:
832+
qd0 = getvector(qd0)
833+
if not len(qd0) == len(q0):
834+
raise ValueError('qd0 has wrong size')
835+
if qdf is None:
836+
qdf = np.zeros(q0.shape)
837+
else:
838+
qd1 = getvector(qdf)
839+
if not len(qd1) == len(q0):
840+
raise ValueError('qd1 has wrong size')
841+
842+
self.q0 = q0
843+
self.qf = qf
844+
self.qd0 = qd0
845+
self.qdf = qf
846+
847+
848+
def start(self):
849+
850+
if self.T is None:
851+
self.T = self.bd.state.T
852+
tscal = self.T
853+
854+
q0 = self.q0
855+
qf = self.qf
856+
qd0 = self.qd0
857+
qdf = self.qdf
858+
859+
# compute the polynomial coefficients
860+
A = 6 * (qf - q0) - 3 * (qdf + qd0) * tscal
861+
B = -15 * (qf - q0) + (8 * qd0 + 7 * qdf) * tscal
862+
C = 10 * (qf - q0) - (6 * qd0 + 4 * qdf) * tscal
863+
E = qd0 * tscal
864+
F = q0
865+
866+
self.coeffs = np.array([A, B, C, np.zeros(A.shape), E, F])
867+
self.dcoeffs = np.array(
868+
[np.zeros(A.shape), 5 * A, 4 * B, 3 * C, np.zeros(A.shape), E])
869+
self.ddcoeffs = np.array([
870+
np.zeros(A.shape), np.zeros(A.shape),
871+
20 * A, 12 * B, 6 * C, np.zeros(A.shape)])
872+
873+
def output(self, t=None):
874+
875+
tscal = self.T
876+
tt = np.array([t**5, t**4, t**3, t**2, t, 1]).T
877+
878+
qt = tt @ self.coeffs
879+
880+
# compute velocity
881+
qdt = tt @ self.dcoeffs / tscal
882+
883+
# compute acceleration
884+
qddt = tt @ self.ddcoeffs / tscal ** 2
885+
886+
return [qt, qdt, qddt]
887+
@block
712888
class CirclePath(SourceBlock):
713889
"""
714890
:blockname:`CIRCLEPATH`

0 commit comments

Comments
 (0)