Mercurial > nkubik
changeset 1:3ad5a7a79c62
Move the IK into python
| author | Radomir Dopieralski <sheep-devel@sheep.art.pl> |
|---|---|
| date | Mon, 13 Oct 2014 23:31:07 +0200 |
| parents | 4f7db939de28 |
| children | e471a59a5658 |
| files | nkubik/leg.h nkubik/leg.ino nkubik/misc.h nkubik/nkubik.ino nkubik/servos.ino robot.py |
| diffstat | 6 files changed, 126 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/nkubik/leg.h Mon Sep 29 21:33:19 2014 +0200 +++ b/nkubik/leg.h Mon Oct 13 23:31:07 2014 +0200 @@ -1,10 +1,18 @@ #ifndef LEG_H #define LEG_H -const unsigned char LEG_HIP[4] = {1, 6, 3, 4}; -const unsigned char LEG_KNEE[4] = {0, 7, 2, 5}; -const char LEG_X[4] = {-1, -1, 1, 1}; -const char LEG_Y[4] = {1, -1, 1, -1}; +/* + * Legs: + * 0 -- front left + * 1 -- front right + * 2 -- hind left + * 3 -- hind right + */ + +const unsigned char LEG_KNEE[4] = {0, 3, 1, 2}; +const unsigned char LEG_HIP[4] = {6, 7, 4, 5}; +const char LEG_X[4] = {1, -1, 1, -1}; +const char LEG_Y[4] = {1, 1, -1, -1}; const double COXA = 38.0; // mm const double TIBIA = 38.0; // mm const double HOME_X = 26.870057685088803;
--- a/nkubik/leg.ino Mon Sep 29 21:33:19 2014 +0200 +++ b/nkubik/leg.ino Mon Oct 13 23:31:07 2014 +0200 @@ -1,4 +1,5 @@ #include "misc.h" +#include "leg.h" double _solve_triangle(double a, double b, double c) { @@ -18,6 +19,8 @@ bool _inverse_kinematics(double x, double y, double *hip, double *knee) { // Calculate angles for knee and ankle, and put them in those variables. // Return true on success, and false if x and y are out of range. + *hip = PI4 - atan2(y, x); + *knee = 0; //asin((_norm(x, y) - COXA)/TIBIA); return true; }
--- a/nkubik/misc.h Mon Sep 29 21:33:19 2014 +0200 +++ b/nkubik/misc.h Mon Oct 13 23:31:07 2014 +0200 @@ -3,6 +3,7 @@ #define NaN (0.0/0.0) const double PI2 = PI / 2; +const double PI4 = PI / 4; const double TAU = PI * 2; #endif
--- a/nkubik/nkubik.ino Mon Sep 29 21:33:19 2014 +0200 +++ b/nkubik/nkubik.ino Mon Oct 13 23:31:07 2014 +0200 @@ -1,15 +1,41 @@ #include "servos.h" -#include "leg.h" -#include "clock.h" void setup() { + Serial.begin(115200); servo_setup(); - Serial.begin(9600); - Serial.println("Started."); } void loop() { - tick(TICK); + do_serial_command(); +} + +int16_t _serial_read_word() { + /* Read two bytes from the serial port and make an int from them. */ + int16_t high = Serial.read(); + int16_t low = Serial.read(); + int16_t value = high << 8 | low; + return value; } + +void do_serial_command() { + static unsigned char serial_command = 0; + /* Read and execute a command from the serial port's buffer. */ + switch (serial_command) { + case 0x00: + /* No command, read one. */ + if (Serial.available() < 1) { return; } + serial_command = Serial.read(); + return; + case 0xff: + /* Move all servos by 1/1000 of radians. */ + if (Serial.available() < SERVOS * 2) { return; } + for (unsigned char servo = 0; servo < SERVOS; ++servo) { + double pos = _serial_read_word(); + servo_move(servo, pos / 1000.0); + } + break; + } + serial_command = 0; +}
--- a/nkubik/servos.ino Mon Sep 29 21:33:19 2014 +0200 +++ b/nkubik/servos.ino Mon Oct 13 23:31:07 2014 +0200 @@ -6,9 +6,10 @@ #define SERVO_FREQ_MIN 600 #define SERVO_FREQ_MAX 2400 -static const unsigned char SERVO_PINS[SERVOS] = { 6, 7, 8, 9, 10, 11, 12, 14}; -static const char SERVO_REVERSE[SERVOS] = { 1, 1, 1, 1, 1, 1, 1, 1}; -static const char SERVO_TRIM[SERVOS] = { 0, 0, 0, 0, 0, 0, 0, 0}; +// Since we have a LED on pin 13, we use pin 5 instead. +static const unsigned char SERVO_PINS[SERVOS] = { 6, 7, 8, 9, 10, 11, 12, 5}; +static const char SERVO_REVERSE[SERVOS] = {1, -1, 1, -1, 1, -1, -1, 1}; +static const char SERVO_TRIM[SERVOS] = {5, 0, 0, 0, 0, 0, 0, 0}; static Servo servos[SERVOS]; @@ -21,7 +22,7 @@ while (rads > TAU) { rads -= TAU; } - while (rads < TAU) { + while (rads < 0) { rads += TAU; } int freq = (SERVO_FREQ_MAX -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/robot.py Mon Oct 13 23:31:07 2014 +0200 @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import math +import struct +import time + +import serial + + +PORT = '/dev/ttyUSB0' + + +def _norm(*args): + return math.sqrt(sum(a**2 for a in args)) + +class Robot(object): + legs = [ + (0, 6, 1, -1), # fl + (3, 7, 1, 1), # fr + (1, 4, -1, -1), # hl + (2, 5, -1, 1), # hr + ] + coxa = 38.0 # mm + tibia = 38.0 # mm + home = 26.870057685088803, 26.870057685088803 + + def __init__(self): + self.serial = serial.Serial(PORT, 115200, timeout=1) + self.positions = [0] * 8 + self.leg_positions = [ + (self.home[0], self.home[1] * self.legs[leg][2]) + for leg in range(4) + ] + + def update(self): + format = '>B' + 'h' * 8 + command = 0xff + positions = [int(pos * 1000) for pos in self.positions] + packet = struct.pack(format, command, *positions) + self.serial.write(packet) + + def move_servo(self, servo, radians=None, degrees=None): + if degrees is not None: + radians = math.radians(degrees) + if radians is not None: + self.positions[servo] = radians + + def move_leg(self, leg, (x, y)): + self.leg_positions[leg] = x, y + y = y * self.legs[leg][2] + hip = math.pi / 4 - math.atan2(y, x) + knee = -math.asin((_norm(x, y) - self.coxa) / self.tibia) + self.move_servo(self.legs[leg][1], hip) + self.move_servo(self.legs[leg][0], knee) + + def move_leg_by(self, leg, (dx, dy)): + x, y = self.leg_positions[leg] + self.move_leg(leg, (x + dx, y + dy)) + + def move_home(self): + for leg in range(4): + self.move_leg(leg, (self.home[0], + self.home[1] * self.legs[leg][2])) + +if __name__ == '__main__': + r = Robot() + r.move_home() + r.update() + for i in range(20): + for leg in range(4): + r.move_leg_by(leg, (-r.legs[leg][3] * 2, 2)) + r.update() + time.sleep(0.2)
