Mercurial > Kubik
changeset 141:999894826513
move leg to separate module
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Wed, 06 Aug 2014 18:10:24 +0200 |
| parents | e7adf29e5d6d |
| children | b5c06cc9e0fc |
| files | kubik.py |
| diffstat | 1 files changed, 3 insertions(+), 104 deletions(-) [+] |
line wrap: on
line diff
--- a/kubik.py Thu Jul 31 17:07:08 2014 +0200 +++ b/kubik.py Wed Aug 06 18:10:24 2014 +0200 @@ -1,31 +1,8 @@ -import math - import serial -import maestro import pygame - -def _solve_triangle(a, b, c): - """Calculate an angle of a triangle using the law of cosines.""" - a, b, c = abs(a), abs(b), abs(c) - if a + b < c or a + c < b or b + c < a: - raise ValueError("Impossible triangle: %r, %r, %r" % (a, b, c)) - cos = float(a ** 2 + b ** 2 - c ** 2) / (2 * a * b) - return math.acos(cos) - - -def _length(a, b): - """Calculate the length of a vector.""" - return math.sqrt(a ** 2 + b ** 2) - - -def _normalize_degrees(angle): - """Convert an angle to range +-180 degree range.""" - while angle > 180: - angle -= 360 - while angle < -180: - angle += 360 - return angle +import maestro +import leg class HipServo(maestro.Servo): @@ -51,11 +28,7 @@ max_degrees = 136 -class Leg(object): - """A signle leg, containing 3 servos: hip, knee and ankle, and three - connections between them: coxa, femur and tibia. - """ - +class Leg(leg.Leg): # Lengths of leg segments, in mm coxa = 16.0 # between the hip and the knee femur = 50.0 # between the knee and the ankle @@ -63,80 +36,6 @@ base = 45.0, 45.0 # from the center of body home = 45.0, 45.0, -35.0 - def __init__(self, hip, knee, ankle, front=True): - self.hip = hip - self.knee = knee - self.ankle = ankle - self.front = front - if self.front: - self.y_direction = 1 - else: - self.y_direction = -1 - self.hip_offset = -45 * self.y_direction - self.home = ( - self.home[0], self.home[1] * self.y_direction, self.home[2]) - self.position = list(self.home) - - def __repr__(self): - return "<Leg (%r, %r, %r)>" % ( - self.position[0], - self.position[1], - self.position[2], - ) - - def __iter__(self): - """Iterate over all joints.""" - return iter([self.hip, self.knee, self.ankle]) - - def _inverse_kinematics(self, (x, y, z)): - """Calculate the 3 angles of the leg, in radians.""" - f = _length(x, y) - self.coxa - d = min(self.femur + self.tibia, _length(f, z)) - hip = math.atan2(y, x) - knee = _solve_triangle(self.femur, d, self.tibia) - math.atan2(-z, f) - ankle = _solve_triangle(self.femur, self.tibia, d) - knee = _normalize_degrees(-math.degrees(knee)) - ankle = _normalize_degrees(math.degrees(ankle) - 90) - hip = _normalize_degrees(math.degrees(hip) + self.hip_offset) - return hip, knee, ankle - - def move_to(self, position): - """Move the foot to the specified point. - - If any of the coordinates is None, no movement will be done in that - axis. - """ - position = list(position) - for i, coord in enumerate(position): - if coord is None: - position[i] = self.position[i] - self.position = position - - def move_by(self, (dx, dy, dz)): - """Move the foot by the specified amount.""" - x, y, z = self.position - self.move_to((x + dx, y + dy, z + dz)) - - def rotate(self, degrees): - """Rotate the leg around the center of the body horizontally.""" - radians = math.radians(degrees * self.y_direction) - x, y, z = self.position - bx = self.base[0] + x - by = self.base[1] + y * self.y_direction - r = _length(bx, by) - a = math.atan2(bx, by) - rx = r * math.sin(a + radians) - self.base[0] - ry = r * math.cos(a + radians) - self.base[1] - self.move_to((rx, ry * self.y_direction, None)) - - def update(self, shift): - dx, dy, dz = shift - x, y, z = self.position - hip, knee, ankle = self._inverse_kinematics((x + dx, y + dy, z + dz)) - self.hip.move_degrees(hip) - self.knee.move_degrees(knee) - self.ankle.move_degrees(ankle) - class Robot(object): def __init__(self):
