Day 4: (Thu Sep 5) Kinematics Etc.¶
Notes for 2019-09-05. See also the Fall 2019 Calendar.
Notes from Day 3¶
Agenda¶
- Administrative - If needed, please fix your post to use the code syntax highlighting as per code formatting in posts 
 
- Assignments 
- In-class - Demos for Exercise: Dynamic Gesture on a Simulated Double Pendulum 
- Brief numpy tutorial. 
- Discussion of two-link kinematics. 
- A few videos. 
- Discussion of common platform ideas. 
 
Videos¶
- SCARA robot demo :https://www.youtube.com/watch?v=k_nHFSdk8Sg 
- SCARA robots demo: https://www.youtube.com/watch?v=4RQiGz-ygsQ 
Lecture code samples¶
NumPy¶
We may use some of the NumPy library for numerical computing, which isn’t part of core Python.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | # Make the numpy library available under the name 'np'.
import numpy as np
# Create a 3-element zero vector (all floating point)
z = np.zeros((3))
print(z)
# Create a 3-element zero vector (integer)
z = np.zeros((3), dtype=np.int)
print(z)
# Create a 3x4 zero matrix (3 rows, 4 columns).
z = np.zeros((3,4))
print(z)
# Create an uninitialized 2x3 matrix (2 rows, 3 columns).
u = np.ndarray((2,3))
print(u)
# Create a 3x3 identity matrix.
I = np.array(((1.0,0,0),(0,1.0,0),(0,0,1.0)))
print(I)
# Create a 3x3 identity matrix.
I = np.eye(3)
print(I)
# Create a random 3-element vector.
R = np.random.rand(3)
print(R)
# Multiply by a scalar.
print(10 * R)
# Vector arithmetic.  The following operate element-by-element.
print(10 * R**2 + R)
print(np.sin(R))
# The same notation provides efficient access to large arrays.
big = np.random.rand(10000)
# Calculate the magnitude of the high-dimensional vector:
magnitude = np.sqrt(np.dot(big,big))
print("Long vector magnitude:", magnitude)
# The same is available as a primitive:
print("Long vector magnitude:", np.linalg.norm(big))
# For more, see https://docs.scipy.org/doc/numpy/reference/routines.linalg.html
 | 
Reference manual items:
And the broader SciPy:
Not to mention more specialized libraries:
Two-Link Forward Kinematics¶
| 1 2 3 4 5 6 7 8 9 10 11 |     def forwardKinematics(self, q):
        """Compute the forward kinematics.  Returns the world-coordinate Cartesian position of the elbow
and endpoint for a given joint angle vector.
        :param q: two-element list or ndarray with [q1, q2] joint angles
        :return: tuple (elbow, end) of two-element ndarrays with [x,y] locations
        """
        elbow = self.origin + np.array((self.l1 * math.sin(q[0]), -self.l1 * math.cos(q[0])))
        end   = elbow + np.array((self.l2 * math.sin(q[0]+q[1]), -self.l2 * math.cos(q[0]+q[1])))
        return elbow, end
 | 
Two-Link Inverse Kinematics¶
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |     def endpointIK(self, target):
        """Compute two inverse kinematics solutions for a target end position.  The
        target is a Cartesian position vector (two-element ndarray) in world coordinates,
        and the result vectors are joint angles as ndarrays [q0, q1].
        If the target is out of reach, returns the closest pose.
        """
        # translate the target vector into body coordinates
        target = target - self.origin
        
        # find the position of the point in polar coordinates
        radiussq = np.dot(target, target)
        radius   = math.sqrt(radiussq)
        # theta is the angle of target point w.r.t. -Y axis, same origin as arm
        theta    = math.atan2(target[0], -target[1]) 
        # use the law of cosines to compute the elbow angle
        #   R**2 = l1**2 + l2**2 - 2*l1*l2*cos(pi - elbow)
        #   both elbow and -elbow are valid solutions
        acosarg = (radiussq - self.l1**2 - self.l2**2) / (-2 * self.l1 * self.l2)
        if acosarg < -1.0:  elbow_supplement = math.pi
        elif acosarg > 1.0: elbow_supplement = 0.0
        else:               elbow_supplement = math.acos(acosarg)
        # use the law of sines to find the angle at the bottom vertex of the triangle defined by the links
        #  radius / sin(elbow_supplement)  = l2 / sin(alpha)
        if radius > 0.0:
            alpha = math.asin(self.l2 * math.sin(elbow_supplement) / radius)
        else:
            alpha = 0.0
            
        #  compute the two solutions with opposite elbow sign
        soln1 = np.array((theta - alpha, math.pi - elbow_supplement))
        soln2 = np.array((theta + alpha, elbow_supplement - math.pi))
        return soln1, soln2
 |