Skip to content

Commit 227fbf1

Browse files
committed
new version of fkine_path that works for branched robot
new method segments which represents the branched structure
1 parent 40beddf commit 227fbf1

File tree

1 file changed

+104
-32
lines changed

1 file changed

+104
-32
lines changed

roboticstoolbox/robot/ERobot.py

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ def reach(self):
515515
def ets(self, start=None, end=None, explored=None, path=None):
516516
"""
517517
ERobot to ETS
518+
518519
:param start: start of path, defaults to ``base_link``
519520
:type start: ELink or str, optional
520521
:param end: end of path, defaults to end-effector
@@ -523,12 +524,15 @@ def ets(self, start=None, end=None, explored=None, path=None):
523524
:raises TypeError: a bad link argument
524525
:return: elementary transform sequence
525526
:rtype: ETS instance
527+
528+
526529
- ``robot.ets()`` is an ETS representing the kinematics from base to
527530
end-effector.
528531
- ``robot.ets(end=link)`` is an ETS representing the kinematics from
529532
base to the link ``link`` specified as an ELink reference or a name.
530533
- ``robot.ets(start=l1, end=l2)`` is an ETS representing the kinematics
531534
from link ``l1`` to link ``l2``.
535+
532536
.. runblock:: pycon
533537
>>> import roboticstoolbox as rtb
534538
>>> panda = rtb.models.ETS.Panda()
@@ -575,6 +579,106 @@ def ets(self, start=None, end=None, explored=None, path=None):
575579
return p
576580
return None
577581

582+
# --------------------------------------------------------------------- #
583+
584+
def segments(self):
585+
"""
586+
Segments of branched robot
587+
588+
:return: Segment list
589+
:rtype: list of lists of Link
590+
591+
For a single-chain robot with structure::
592+
593+
L1 - L2 - L3
594+
595+
the return is ``[[None, L1, L2, L3]]``
596+
597+
For a robot with structure::
598+
599+
L1 - L2 +- L3 - L4
600+
+- L5 - L6
601+
602+
the return is ``[[None, L1, L2], [L2, L3, L4], [L2, L5, L6]]``
603+
604+
.. note::
605+
- the length of the list is the number of segments in the robot
606+
- the first segment always starts with ``None`` which represents
607+
the base transform (since there is no base link)
608+
- the last link of one segment is also the first link of subsequent
609+
segments
610+
"""
611+
612+
def recurse(link):
613+
614+
segs = [link.parent]
615+
while True:
616+
segs.append(link)
617+
if link.nchildren == 0:
618+
return segs
619+
elif link.nchildren == 1:
620+
link = link.children[0]
621+
continue
622+
elif link.nchildren > 1:
623+
segs = [segs]
624+
625+
for child in link.children:
626+
segs.append(recurse(child))
627+
628+
return segs
629+
630+
return recurse(self.links[0])
631+
632+
# --------------------------------------------------------------------- #
633+
634+
def fkine_path(self, q, old=None):
635+
'''
636+
Compute the pose of every link frame
637+
638+
:param q: The joint configuration
639+
:type q: darray(n)
640+
:return: Pose of all links
641+
:rtype: SE3 instance
642+
643+
``T = robot.fkine_path(q)`` is an SE3 instance with ``robot.nlinks +
644+
1`` values:
645+
646+
- ``T[0]`` is the base transform
647+
- ``T[i+1]`` is the pose of link whose ``number`` is ``i``
648+
649+
:references:
650+
- Kinematic Derivatives using the Elementary Transform
651+
Sequence, J. Haviland and P. Corke
652+
'''
653+
q = getvector(q)
654+
Tbase = self.base # add base, also sets the type
655+
linkframes = Tbase.__class__.Alloc(self.nlinks + 1)
656+
linkframes[0] = Tbase
657+
658+
def recurse(Tall, Tparent, q, link):
659+
# if joint??
660+
T = Tparent
661+
while True:
662+
T *= link.A(q[link.jindex])
663+
Tall[link.number + 1] = T
664+
665+
if link.nchildren == 1:
666+
link = link.children[0]
667+
continue
668+
669+
elif link.nchildren == 0:
670+
return
671+
672+
else:
673+
# multiple children
674+
for child in link.children:
675+
recurse(Tall, T, q, child)
676+
return
677+
678+
recurse(linkframes, Tbase, q, self.links[0])
679+
680+
681+
return linkframes
578682

579683
# --------------------------------------------------------------------- #
580684

@@ -859,38 +963,7 @@ def _getlink(self, link, default=None):
859963
else:
860964
raise TypeError('unknown argument')
861965

862-
def fkine_path(self, q, old=None):
863-
'''
864-
Tall = robot.fkine_all(q) evaluates fkine for each joint within a
865-
robot and returns a trajecotry of poses.
866-
Tall = fkine_all() as above except uses the stored q value of the
867-
robot object.
868-
:param q: The joint angles/configuration of the robot (Optional,
869-
if not supplied will use the stored q values).
870-
:type q: float ndarray(n)
871-
:param old: for compatibility with DHRobot version, ignored.
872-
:return T: Homogeneous transformation trajectory
873-
:rtype T: SE3 list
874-
.. note::
875-
- The robot's base transform, if present, are incorporated
876-
into the result.
877-
:references:
878-
- Kinematic Derivatives using the Elementary Transform
879-
Sequence, J. Haviland and P. Corke
880-
'''
881-
q = getvector(q)
882-
T = self.base
883-
linkframes = []
884-
j = 0
885-
for link in self.elinks:
886-
if link.isjoint:
887-
T *= link.A(q[j])
888-
j += 1
889-
else:
890-
T *= link.A()
891-
linkframes.append(T)
892966

893-
return linkframes
894967
# =========================================================================== #
895968

896969

@@ -2224,7 +2297,6 @@ def teach(
22242297
return env
22252298

22262299

2227-
22282300
if __name__ == "__main__": # pragma nocover
22292301

22302302
# import roboticstoolbox as rtb

0 commit comments

Comments
 (0)