Skip to content

Commit 0983b36

Browse files
committed
move some code to dynamics
add flesh to jointdynamics and twists jointdynamics runs but not agreeing with MATLAB
1 parent 90fc9f0 commit 0983b36

File tree

2 files changed

+104
-66
lines changed

2 files changed

+104
-66
lines changed

roboticstoolbox/robot/Dynamics.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,71 @@ def pay(self, W, q=None, J=None, frame=1):
223223

224224
return tau
225225

226+
def payload(self, m, p=np.zeros(3)):
227+
"""
228+
payload(m, p) adds payload mass adds a payload with point mass m at
229+
position p in the end-effector coordinate frame.
230+
231+
payload(m) adds payload mass adds a payload with point mass m at
232+
in the end-effector coordinate frame.
233+
234+
payload(0) removes added payload.
235+
236+
:param m: mass (kg)
237+
:type m: float
238+
:param p: position in end-effector frame
239+
:type p: float ndarray(3,1)
240+
241+
"""
242+
243+
p = getvector(p, 3, out='col')
244+
lastlink = self.links[self.n - 1]
245+
246+
lastlink.m = m
247+
lastlink.r = p
248+
249+
def jointdynamics(self, q, qd=None):
250+
"""
251+
Transfer function of joint actuator
252+
253+
:param q: The joint angles/configuration of the robot
254+
:type q: float ndarray(n)
255+
:param qd: The joint velocities of the robot
256+
:type qd: float ndarray(n)
257+
:return: transfer function denominators
258+
:rtype: list of 2-tuples
259+
260+
- ``tf = jointdynamics(qd, q)`` calculates a vector of n continuous-time
261+
transfer functions that represent the transfer function
262+
1/(Js+B) for each joint based on the dynamic parameters of the robot
263+
and the configuration q (n). n is the number of robot joints.
264+
265+
- ``tf = jointdynamics(q, qd)`` as above but include the linearized effects
266+
of Coulomb friction when operating at joint velocity QD (1xN).
267+
"""
268+
269+
tf = []
270+
for j, link in enumerate(self.links):
271+
272+
# compute inertia for this joint
273+
zero = np.zeros((self.n))
274+
qdd = np.zeros((self.n))
275+
qdd[j] = 1
276+
M = self.rne(q, zero, qdd, grav=[0, 0, 0])
277+
J = link.Jm + M[j] / abs(link.G) ** 2
278+
279+
# compute friction
280+
B = link.B
281+
if qd is not None:
282+
# add linearized Coulomb friction at the operating point
283+
if qd > 0:
284+
B += link.Tc[0] / qd[j]
285+
elif qd < 0:
286+
B += link.Tc[1] / qd[j]
287+
tf.append((J, B))
288+
289+
return tf
290+
226291
def friction(self, qd):
227292
"""
228293
tau = friction(qd) calculates the vector of joint friction

roboticstoolbox/robot/SerialLink.py

Lines changed: 39 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from spatialmath.base.argcheck import \
1111
getvector, ismatrix, isscalar, verifymatrix
1212
from spatialmath.base.transforms3d import tr2delta, tr2eul
13-
from spatialmath import SE3
13+
from spatialmath import SE3, Twist3
1414
from scipy.optimize import minimize, Bounds, LinearConstraint
1515
from frne import init, frne, delete
1616
from roboticstoolbox.backend.PyPlot.functions import \
@@ -483,51 +483,7 @@ def isspherical(self):
483483
else:
484484
return False
485485

486-
def payload(self, m, p=np.zeros(3)):
487-
"""
488-
payload(m, p) adds payload mass adds a payload with point mass m at
489-
position p in the end-effector coordinate frame.
490-
491-
payload(m) adds payload mass adds a payload with point mass m at
492-
in the end-effector coordinate frame.
493-
494-
payload(0) removes added payload.
495-
496-
:param m: mass (kg)
497-
:type m: float
498-
:param p: position in end-effector frame
499-
:type p: float ndarray(3,1)
500-
501-
"""
502-
503-
p = getvector(p, 3, out='col')
504-
lastlink = self.links[self.n - 1]
505-
506-
lastlink.m = m
507-
lastlink.r = p
508-
509-
def jointdynamics(self, q, qd):
510-
"""
511-
Transfer function of joint actuator.
512486

513-
tf = jointdynamics(qd, q) calculates a vector of n continuous-time
514-
transfer function objects that represent the transfer function
515-
1/(Js+B) for each joint based on the dynamic parameters of the robot
516-
and the configuration q (n). n is the number of robot joints.
517-
518-
tf = jointdynamics(qd) as above except uses the stored q value of the
519-
robot object.
520-
521-
:param q: The joint angles/configuration of the robot (Optional,
522-
if not supplied will use the stored q values)
523-
:type q: float ndarray(n)
524-
:param qd: The joint velocities of the robot
525-
:type qd: float ndarray(n)
526-
527-
"""
528-
529-
# TODO a tf object implementation?
530-
pass
531487

532488
def isprismatic(self):
533489
"""
@@ -625,35 +581,52 @@ def toradians(self, q):
625581

626582
def twists(self, q=None):
627583
"""
628-
Joint axis twists.
629-
630-
tw, T = twists(q) calculates a vector of Twist objects (n) that
631-
represent the axes of the joints for the robot with joint coordinates
632-
q (n). Also returns T0 which is an SE3 object representing the pose of
633-
the tool.
634-
635-
tw, T = twists() as above except uses the stored q value of the
636-
robot object.
637-
638-
:param q: The joint angles/configuration of the robot (Optional,
639-
if not supplied will use the stored q values)
640-
:type q: float ndarray(n)
584+
Joint axis as twists
641585
586+
:param q: The joint angles/configuration of the robot
587+
:type q: array_like (n)
642588
:return tw: a vector of Twist objects
643589
:rtype tw: float ndarray(n,)
644590
:return T0: Represents the pose of the tool
645591
:rtype T0: SE3
646592
593+
- ``tw, T0 = twists(q)`` calculates a vector of Twist objects (n) that
594+
represent the axes of the joints for the robot with joint coordinates
595+
``q`` (n). Also returns T0 which is an SE3 object representing the pose of
596+
the tool.
597+
598+
- ``tw, T0 = twists()`` as above but the joint coordinates are taken to be
599+
zero.
600+
647601
"""
648602

649-
pass
603+
if q is None:
604+
q = np.zeros((self.n))
650605

651-
# if q is None:
652-
# q = np.copy(self.q)
653-
# else:
654-
# q = getvector(q, self.n)
606+
T = self.fkine_all(q)
607+
tw = Twist3.Alloc(self.n)
608+
if not self.mdh:
609+
# DH case
610+
for j in range(self.n):
611+
if j == 0:
612+
if self.links[j].sigma == 0:
613+
tw[j] = Twist3.R([0, 0, 1], [0, 0, 0]) # revolute
614+
else:
615+
tw[j] = Twist3.P([0, 0, 1]) # prismatic
616+
else:
617+
if self.links[j].sigma == 0:
618+
tw[j] = Twist3.R(T[j-1].a, T[j-1].t) # revolute
619+
else:
620+
tw[j] = Twist3.P(T[j-1].a) # prismatic
621+
else:
622+
# MDH case
623+
for j in range(self.n):
624+
if self.links[j].sigma == 0:
625+
tw[j] = Twist3.R(T[j].a, T[j].t)
626+
else:
627+
tw[j] = Twist3.P(T[j].a, T[j].t)
655628

656-
# TODO Implement this
629+
return tw, T[-1]
657630

658631
def fkine(self, q=None):
659632
'''
@@ -715,10 +688,10 @@ def fkine(self, q=None):
715688

716689
return t
717690

718-
def allfkine(self, q=None):
691+
def fkine_all(self, q=None):
719692
'''
720693
Tall = allfkine(q) evaluates fkine for each joint within a robot and
721-
returns a trajecotry of poses.
694+
returns a sequence of link frame poses.
722695
723696
Tall = allfkine() as above except uses the stored q value of the
724697
robot object.

0 commit comments

Comments
 (0)