diff --git a/dev/hex/hex.py b/dev/hex/hex.py new file mode 100755 index 0000000..17f05dd --- /dev/null +++ b/dev/hex/hex.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +############################################## +# The MIT License (MIT) +# Copyright (c) 2016 Kevin Walchko +# see LICENSE for full details +############################################## +# Simple robot + +from multiped import Engine +from multiped import TripodGait + +class Robot(object): + """ + This is a simple class that binds the others together. You could make it + a base class for something fancier. + """ + def __init__(self, data, legType, servoType): + """ + Constructor. + Engine - commands the leg servos to move + gait - Ideally there are several types of gaits for different + walking/running situations. If you don't give it an dict + of gaits, then the default is just the standard + DiscreteRippleGait. + The gaits need to know: + - how high to pick up a leg + - what the neutral leg position is (where is the foot + located when just standing?) + """ + self.engine = Engine(data, servoType) + self.kinematics = legType(data) + + neutral = self.kinematics.getNeutralPos() + + if 'gaits' in data: + self.gaits = data['gaits'] + else: + self.gaits = { + 'crawl': DiscreteRippleGait(65.0, neutral) + } + + + +params = { + +} + +robot = Robot() diff --git a/dev/hex/test.py b/dev/hex/test.py index 2285f4c..7c0fd48 100755 --- a/dev/hex/test.py +++ b/dev/hex/test.py @@ -1,32 +1,68 @@ #!/usr/bin/env python3 -from robot import Tripod -from params import spider -from pprint import pprint -import matplotlib.pyplot as plt -from mpl_toolkits.mplot3d import Axes3D -import numpy as np +from multiped.gait import TripodGait +from multiped.engine import Engine +from pyservos.ax12 import AX12 -fig = plt.figure() -ax = fig.add_subplot(111, projection='3d') +t = TripodGait() +# ans = t.command(1,0,0,0) -t = Tripod(spider["neutral"], 25, 20) +# print(ans) -# pprint(t.gait) -gait = t.gait +""" +parameter file: +{ + "legs": { + 0: { + "linkLengths": [coxa, femur, tibia], # mm + "servoOffsets": [s0, s1, s2], # radians + "servoLimits": [(min,max), (min,max), (min, max)] # radians + "ids": [4,5,6] # servo ID numbers + } + } +} +""" +params = { + "legs": { + 0: { + "linkLengths": [50, 65, 68], # mm + "servoOffsets": [0, 0, 0], # deg + "servoLimits": [(0,300), (0,300), (0, 300)], # deg + "ids": [1,2,3] # servo ID numbers + }, + 1: { + "linkLengths": [50, 65, 68], # mm + "servoOffsets": [0, 0, 0], # deg + "servoLimits": [(0,300), (0,300), (0, 300)], # deg + "ids": [4,5,6] # servo ID numbers + }, + 2: { + "linkLengths": [50, 65, 68], # mm + "servoOffsets": [0, 0, 0], # deg + "servoLimits": [(0,300), (0,300), (0, 300)], # deg + "ids": [7,8,9] # servo ID numbers + }, + 3: { + "linkLengths": [50, 65, 68], # mm + "servoOffsets": [0, 0, 0], # deg + "servoLimits": [(0,300), (0,300), (0, 300)], # deg + "ids": [10,11,12] # servo ID numbers + }, + 4: { + "linkLengths": [50, 65, 68], # mm + "servoOffsets": [0, 0, 0], # deg + "servoLimits": [(0,300), (0,300), (0, 300)], # deg + "ids": [13,14,15] # servo ID numbers + }, + 5: { + "linkLengths": [50, 65, 68], # mm + "servoOffsets": [0, 0, 0], # deg + "servoLimits": [(0,300), (0,300), (0, 300)], # deg + "ids": [16,17,18] # servo ID numbers + }, + } +} -m = 'h' -for leg, c, i in zip(gait, ['b','g','r','c','m','y'],[1,2,3,4,5,6]): - x = [n[0] for n in leg] + [leg[0][0]] - y = [n[1] for n in leg] + [leg[0][1]] - z = [n[2] for n in leg] + [leg[0][2]] - ax.plot(x[:1],y[:1],z[:1],marker="h",c="k",markersize=15) - ax.plot(x,y,z,"-h",c=c,label=f"Leg {i}: {len(x)} pts") - -ax.set_xlabel('X [mm]') -ax.set_ylabel('Y [mm]') -ax.set_zlabel('Z [mm]') -ax.legend() -# ax.set_aspect('equal', 'box') - -plt.show() +# e = Engine(params, None, AX12) +# e.setGait(TripodGait) +# e.move(1,0,0,0) diff --git a/dev/hex/params.py b/dev/hex_sim/params.py similarity index 100% rename from dev/hex/params.py rename to dev/hex_sim/params.py diff --git a/dev/hex/robot.py b/dev/hex_sim/robot.py similarity index 98% rename from dev/hex/robot.py rename to dev/hex_sim/robot.py index 033bdfa..307001c 100644 --- a/dev/hex/robot.py +++ b/dev/hex_sim/robot.py @@ -12,7 +12,6 @@ class Tripod: def __init__(self, neutral, stride, count): self.gait = self.build_forward(neutral, stride, count) self.orientations = [-30, -90, -120, 120, 90, 30] - self. def build_stride(self, n, dist, steps): """ @@ -72,7 +71,7 @@ def rotate_z(self, stride, angle, offset): def gait_world(self): ret = [] - for i in range(6): + # for i in range(6): return ret diff --git a/dev/hex_sim/test.py b/dev/hex_sim/test.py new file mode 100755 index 0000000..2285f4c --- /dev/null +++ b/dev/hex_sim/test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +from robot import Tripod +from params import spider +from pprint import pprint +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +import numpy as np + +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') + +t = Tripod(spider["neutral"], 25, 20) + +# pprint(t.gait) +gait = t.gait + +m = 'h' +for leg, c, i in zip(gait, ['b','g','r','c','m','y'],[1,2,3,4,5,6]): + x = [n[0] for n in leg] + [leg[0][0]] + y = [n[1] for n in leg] + [leg[0][1]] + z = [n[2] for n in leg] + [leg[0][2]] + ax.plot(x[:1],y[:1],z[:1],marker="h",c="k",markersize=15) + ax.plot(x,y,z,"-h",c=c,label=f"Leg {i}: {len(x)} pts") + +ax.set_xlabel('X [mm]') +ax.set_ylabel('Y [mm]') +ax.set_zlabel('Z [mm]') +ax.legend() +# ax.set_aspect('equal', 'box') + +plt.show() diff --git a/docs/gait/pics/walking-2-legs.gif b/docs/gait/pics/biped-robot.gif similarity index 100% rename from docs/gait/pics/walking-2-legs.gif rename to docs/gait/pics/biped-robot.gif diff --git a/docs/gait/pics/1-copvyx36cnhwyrvculwn-g1.gif b/docs/gait/pics/biped.gif similarity index 100% rename from docs/gait/pics/1-copvyx36cnhwyrvculwn-g1.gif rename to docs/gait/pics/biped.gif diff --git a/docs/gait/pics/robotics-05-00013-g009.png b/docs/gait/pics/quadruped.png similarity index 100% rename from docs/gait/pics/robotics-05-00013-g009.png rename to docs/gait/pics/quadruped.png diff --git a/docs/jupyter/gait.ipynb b/docs/jupyter/gait.ipynb new file mode 100644 index 0000000..db8bc6e --- /dev/null +++ b/docs/jupyter/gait.ipynb @@ -0,0 +1,250 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "from multiped.gait import TripodGait" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import pyplot as plt\n", + "from math import pi, cos, sin, atan2" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [], + "source": [ + "tri = TripodGait()" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [], + "source": [ + "ft = tri.command(1,0,0,0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "def plot_feet(ft):\n", + " def plot_foot(o,i):\n", + " x = [v[0] for v in o]\n", + " y = [v[1] for v in o]\n", + " z = [v[2] for v in o]\n", + " plt.subplot(3,2,i)\n", + " plt.plot(x, label='x');\n", + " plt.plot(y, label='y');\n", + " plt.plot(z, label='z');\n", + " plt.grid(True);\n", + "# plt.axis(\"equal\")\n", + " plt.legend();\n", + " for i, leg in enumerate([1,6,2,5,3,4]):\n", + " plot_foot(ft[leg-1], i+1)\n", + " \n", + "plot_feet(ft)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "def plot_feet(ft):\n", + " def plot_foot(o,i):\n", + " x = [v[0] for v in o]\n", + " y = [v[1] for v in o]\n", + " z = [v[2] for v in o]\n", + " plt.subplot(3,2,i)\n", + " plt.plot(x, y);\n", + " plt.plot(x[0],y[0],\"og\")\n", + " plt.plot(x[-1],y[-1],\"Xr\")\n", + " plt.axis(\"equal\")\n", + " plt.grid(True);\n", + "\n", + " for i, leg in enumerate([1,6,2,5,3,4]):\n", + " plot_foot(ft[leg-1], i+1)\n", + " \n", + "plot_feet(ft)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "def plot_foot(o):\n", + " x = [v[0] for v in o]\n", + " y = [v[1] for v in o]\n", + " z = [v[2] for v in o]\n", + " plt.plot(x, y);\n", + " plt.grid(True);\n", + " \n", + "plot_foot(ft[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "150.00000000000003" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "5*pi/6*180/pi" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "59.99999999999999" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pi/3*180/pi" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'>' not supported between instances of 'list' and 'int'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0ma\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m4\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m>\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: '>' not supported between instances of 'list' and 'int'" + ] + } + ], + "source": [ + "a=[1,2,3,4,5,6]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/jupyter/kinematics-R3.ipynb b/docs/jupyter/kinematics-R3.ipynb new file mode 100644 index 0000000..7f88136 --- /dev/null +++ b/docs/jupyter/kinematics-R3.ipynb @@ -0,0 +1,730 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AX-12A Hexapod Kinematics\n", + "\n", + "Kevin Walchko, Phd\n", + "\n", + "25 Feb 2020\n", + "\n", + "-----------\n", + "\n", + "\"Creative
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.\n", + "\n", + "---\n", + "\n", + "**Still in development**\n", + "\n", + "- **Coxa:** hip segment which moves left/right in red\n", + "- **Femur:** blue segment\n", + "- **Tibia:** yellow segment" + ] + }, + { + "cell_type": "code", + "execution_count": 183, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "\n", + "import numpy as np\n", + "from matplotlib import pyplot as plt\n", + "# from sympy import symbols, sin, cos, pi, simplify\n", + "# from math import cos, sin, pi, atan2, sqrt, acos\n", + "import math" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Forward Kinematics\n", + "\n", + "The [modified DH parameters](https://en.wikipedia.org/wiki/Denavit%E2%80%93Hartenberg_parameters#Modified_DH_parameters) are:\n", + "\n", + "\n", + "| i |$a_i$ | $\\alpha_i$ | $d_i$ | $\\theta_i$ |\n", + "|---|:------|:-----------|:------|:-----------|\n", + "| 1 | body | 0 | 0 | $\\theta_1$ |\n", + "| 2 | coxa | 90 | 0 | $\\theta_2$ |\n", + "| 3 | femur | 0 | 0 | $\\theta_3$ |\n", + "| 4 | tibia | 90 | 0 | 0 |\n", + "\n", + "- $a_i$: **link length** in mm from $Z_{i-1}$ to $Z_i$ along $X_i$\n", + "- $\\alpha_i$: **twist angle** between $Z_{i-1}$ and $Z_i$ measured about $X_i$\n", + "- $d_i$: **offset distance** between $X_{i-1}$ and $X_i$ along $Z_i$\n", + "- $\\theta_i$: **rotation angle** between $X_{i-1}$ and $X_i$ measured about $Z_i$\n", + "\n", + "| Link | Name | mm |\n", + "|-------|--------|----|\n", + "| $L_1$ | coxa | 50 |\n", + "| $L_2$ | femur | 65 |\n", + "| $L_3$ | tibia | 68 |" + ] + }, + { + "cell_type": "code", + "execution_count": 169, + "metadata": {}, + "outputs": [], + "source": [ + "from sympy import symbols, sin, cos, pi, simplify\n", + "def makeT(a, alpha, d, theta):\n", + " # create a modified DH homogenious matrix\n", + " return np.array([\n", + " [ cos(theta), -sin(theta), 0, a],\n", + " [sin(theta)*cos(alpha), cos(theta)*cos(alpha), -sin(alpha), -d*sin(alpha)],\n", + " [sin(theta)*sin(alpha), cos(theta)*sin(alpha), cos(alpha), d*cos(alpha)],\n", + " [ 0, 0, 0, 1]\n", + " ])\n", + "\n", + "def simplifyT(tt):\n", + " \"\"\"\n", + " This goes through each element of a matrix and tries to simplify it.\n", + " \"\"\"\n", + " ret = []\n", + " for row in tt:\n", + " m = []\n", + " for col in row:\n", + " m.append(simplify(col))\n", + " ret.append(m[:])\n", + " return np.array(ret)\n", + "\n", + "def subs(tt, m):\n", + " \"\"\"\n", + " This allows you to simplify the trigonomic mess that kinematics can\n", + " create and also substitute in some inputs in the process\n", + " \n", + " Yes, this is basically the same as above. I could combine these into 1\n", + " function, but I wanted to beclearer on what I am doing.\n", + " \"\"\"\n", + " ret = tt.copy()\n", + " for i, row in enumerate(tt):\n", + " for j, col in enumerate(row):\n", + " try:\n", + " ret[i,j] = col.subs(m)\n", + " except:\n", + " ret[i,j] = simplify(col)\n", + " return ret" + ] + }, + { + "cell_type": "code", + "execution_count": 170, + "metadata": {}, + "outputs": [], + "source": [ + "t1, t2, t3 = symbols('t1 t2 t3')\n", + "l1, l2, l3 = symbols('l1 l2 l3')" + ] + }, + { + "cell_type": "code", + "execution_count": 171, + "metadata": {}, + "outputs": [], + "source": [ + "# a, alpha, d, theta\n", + "T1 = makeT(0, 0, 0, t1)\n", + "T2 = makeT(l1, pi/2, 0, t2)\n", + "T3 = makeT(l2, 0, 0, t3)\n", + "T4 = makeT(l3, pi/2, 0, 0)" + ] + }, + { + "cell_type": "code", + "execution_count": 172, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "T1 = [[cos(t1) -sin(t1) 0 0]\n", + " [sin(t1) cos(t1) 0 0]\n", + " [0 0 1 0]\n", + " [0 0 0 1]]\n", + "T2 = [[cos(t2) -sin(t2) 0 l1]\n", + " [0 0 -1 0]\n", + " [sin(t2) cos(t2) 0 0]\n", + " [0 0 0 1]]\n", + "T3 = [[cos(t3) -sin(t3) 0 l2]\n", + " [sin(t3) cos(t3) 0 0]\n", + " [0 0 1 0]\n", + " [0 0 0 1]]\n", + "T4 = [[1 0 0 l3]\n", + " [0 0 -1 0]\n", + " [0 1 0 0]\n", + " [0 0 0 1]]\n" + ] + } + ], + "source": [ + "print('T1 = ', T1)\n", + "print('T2 = ', T2)\n", + "print('T3 = ', T3)\n", + "print('T4 = ', T4)" + ] + }, + { + "cell_type": "code", + "execution_count": 173, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "T = [[(-sin(t2)*sin(t3) + cos(t2)*cos(t3))*cos(t1) sin(t1)\n", + " (sin(t2)*cos(t3) + sin(t3)*cos(t2))*cos(t1)\n", + " (l1 - l3*sin(t2)*sin(t3) + (l2 + l3*cos(t3))*cos(t2))*cos(t1)]\n", + " [(-sin(t2)*sin(t3) + cos(t2)*cos(t3))*sin(t1) -cos(t1)\n", + " (sin(t2)*cos(t3) + sin(t3)*cos(t2))*sin(t1)\n", + " (l1 - l3*sin(t2)*sin(t3) + (l2 + l3*cos(t3))*cos(t2))*sin(t1)]\n", + " [sin(t2)*cos(t3) + sin(t3)*cos(t2) 0 sin(t2)*sin(t3) - cos(t2)*cos(t3)\n", + " l3*sin(t3)*cos(t2) + (l2 + l3*cos(t3))*sin(t2)]\n", + " [0 0 0 1]]\n" + ] + } + ], + "source": [ + "T = T1.dot(T2.dot(T3.dot(T4)))\n", + "print('T = ', T)" + ] + }, + { + "cell_type": "code", + "execution_count": 174, + "metadata": {}, + "outputs": [], + "source": [ + "Tf = simplify(T)" + ] + }, + { + "cell_type": "code", + "execution_count": 175, + "metadata": {}, + "outputs": [ + { + "data": { + "text/latex": [ + "$\\displaystyle \\left[\\begin{matrix}\\cos{\\left(t_{1} \\right)} \\cos{\\left(t_{2} + t_{3} \\right)} & \\sin{\\left(t_{1} \\right)} & \\sin{\\left(t_{2} + t_{3} \\right)} \\cos{\\left(t_{1} \\right)} & \\left(l_{1} + l_{2} \\cos{\\left(t_{2} \\right)} + l_{3} \\cos{\\left(t_{2} + t_{3} \\right)}\\right) \\cos{\\left(t_{1} \\right)}\\\\\\sin{\\left(t_{1} \\right)} \\cos{\\left(t_{2} + t_{3} \\right)} & - \\cos{\\left(t_{1} \\right)} & \\sin{\\left(t_{1} \\right)} \\sin{\\left(t_{2} + t_{3} \\right)} & \\left(l_{1} + l_{2} \\cos{\\left(t_{2} \\right)} + l_{3} \\cos{\\left(t_{2} + t_{3} \\right)}\\right) \\sin{\\left(t_{1} \\right)}\\\\\\sin{\\left(t_{2} + t_{3} \\right)} & 0 & - \\cos{\\left(t_{2} + t_{3} \\right)} & l_{2} \\sin{\\left(t_{2} \\right)} + l_{3} \\sin{\\left(t_{2} + t_{3} \\right)}\\\\0 & 0 & 0 & 1\\end{matrix}\\right]$" + ], + "text/plain": [ + "[[cos(t1)*cos(t2 + t3), sin(t1), sin(t2 + t3)*cos(t1), (l1 + l2*cos(t2) + l3*cos(t2 + t3))*cos(t1)], [sin(t1)*cos(t2 + t3), -cos(t1), sin(t1)*sin(t2 + t3), (l1 + l2*cos(t2) + l3*cos(t2 + t3))*sin(t1)], [sin(t2 + t3), 0, -cos(t2 + t3), l2*sin(t2) + l3*sin(t2 + t3)], [0, 0, 0, 1]]" + ] + }, + "execution_count": 175, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "Tf" + ] + }, + { + "cell_type": "code", + "execution_count": 176, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "position x: (l1 + l2*cos(t2) + l3*cos(t2 + t3))*cos(t1)\n", + "position y: (l1 + l2*cos(t2) + l3*cos(t2 + t3))*sin(t1)\n", + "position z: l2*sin(t2) + l3*sin(t2 + t3)\n" + ] + } + ], + "source": [ + "print('position x: {}'.format(Tf[0,3]))\n", + "print('position y: {}'.format(Tf[1,3]))\n", + "print('position z: {}'.format(Tf[2,3]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Math" + ] + }, + { + "cell_type": "code", + "execution_count": 180, + "metadata": {}, + "outputs": [], + "source": [ + "leg = (50,65,68)" + ] + }, + { + "cell_type": "code", + "execution_count": 181, + "metadata": {}, + "outputs": [], + "source": [ + "from math import cos, sin, pi, atan2, sqrt, acos\n", + "def forward(t1,t2,t3, links, degrees=True):\n", + " l1,l2,l3 = links\n", + " \n", + " if degrees:\n", + " t1 *= pi/180\n", + " t2 *= pi/180\n", + " t3 *= pi/180\n", + " \n", + " x = (l1 + l2*cos(t2) + l3*cos(t2 + t3))*cos(t1)\n", + " y = (l1 + l2*cos(t2) + l3*cos(t2 + t3))*sin(t1)\n", + " z = l2*sin(t2) + l3*sin(t2 + t3)\n", + " return (x,y,z)" + ] + }, + { + "cell_type": "code", + "execution_count": 182, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(115.31727983645297, 115.31727983645295, -48.08326112068523)" + ] + }, + "execution_count": 182, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "forward(45,0,-45, leg)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Inverse Kinematics\n", + "\n", + "![](http://mathworld.wolfram.com/images/eps-gif/LawofCosines_1000.gif)\n", + "\n", + "\n", + "## Law of Cosines\n", + "\n", + "$$\n", + "a^2 = b^2 + c^2 - 2bc \\cos(A) \\rightarrow \\cos(A)=\\frac{-a^2+b^2+c^2}{2bc}\\\\\n", + "b^2 = a^2 + c^2 - 2ac \\cos(B) \\rightarrow \\cos(B)=\\frac{a^2-b^2+c^2}{2ac}\\\\\n", + "c^2 = a^2 + b^2 - 2ab \\cos(C) \\rightarrow \\cos(C)=\\frac{a^2+b^2-c^2}{2ab}\n", + "$$\n", + "\n", + "- [Wolfram: law of cosines](http://mathworld.wolfram.com/LawofCosines.html)\n", + "- [Cosine law calculator](https://www.calculatorsoup.com/calculators/geometry-plane/triangle-law-of-cosines.php)\n", + "\n", + "## Law of Sines\n", + "\n", + "$$\n", + "\\frac{a}{\\sin(A)} = \\frac{b}{\\sin(B)} = \\frac{c}{\\sin(C)}\n", + "$$" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "metadata": {}, + "outputs": [], + "source": [ + "def cosinelaw(a,b,c):\n", + " # cos(g) = (a^2+b^2-c^2)/2ab\n", + " return acos((a**2+b**2-c**2)/(2*a*b))\n", + "\n", + "def inverse(x,y,z, links, degrees=True):\n", + " \"\"\"\n", + " Azimuth angle is between x and w and lies in the x-y plane\n", + " \n", + " ^ x\n", + " w |\n", + " \\ |\n", + " l1 \\ |\n", + " \\ |\n", + " \\|\n", + " <----------+ (z is out of the page - right hand rule)\n", + " y\n", + " \n", + " Most of the leg moves in the plane defined by w-z\n", + " \n", + " ^ z l3\n", + " | o-----o\n", + " | / \\ l4\n", + " | / l2 E\n", + " | /\n", + " +--o-------------> w\n", + " l1\n", + " \n", + " l1: coxa\n", + " l2: femur\n", + " l3: tibia\n", + " \n", + " All joint angles returned are in degrees: (t1, t2, t3)\n", + " \"\"\"\n", + " # mm\n", + " l1,l2,l3 = links\n", + " \n", + " w = sqrt(x**2+y**2) - l1\n", + " d = sqrt(w**2+z**2)\n", + " \n", + " t1 = atan2(y,x)\n", + " t2 = atan2(z,w)+cosinelaw(l2,d,l3)\n", + " t3 = cosinelaw(l2,l3,d)-pi\n", + " \n", + " if degrees:\n", + " t1 *= 180/pi\n", + " t2 *= 180/pi\n", + " t3 *= 180/pi\n", + " \n", + " return (t1,t2,t3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test\n", + "\n", + "Let's test that both the forward and inverse kinematics agree ... and they should. The errors are printed below. Please note, that 0 and 360 degrees are the same thing. " + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": {}, + "outputs": [], + "source": [ + "# def testAng(a1,a2,a3):\n", + "# # all angles in degrees\n", + " \n", + "# print('*'*25)\n", + " \n", + "# f=forward(a1,a2,a3)\n", + "# print('Pts FK:', f)\n", + " \n", + "# f = f + (180+(a2+a3),)\n", + "# print('debug', f)\n", + "# i=inverse(*f)\n", + "# print('Angles IK [deg]:', i)\n", + " \n", + "# print('Delta Angles:')\n", + "# err = []\n", + "# for a,b in zip([a1,a2,a3,a4],i):\n", + "# err.append(a-b)\n", + " \n", + "# print(' a1:{:.2f} a2:{:.2f} a3:{:.2f} a4:{:.2f}'.format(err[0],err[1],err[2], err[3]))\n", + "\n", + "def testPos(x,y,z, links):\n", + " # a,y,z in mm\n", + " # o in deg measured from the floor, so if the leg is straight down, then o = 90 deg\n", + " \n", + " print('*'*25)\n", + " \n", + " i=inverse(x,y,z,links)\n", + " print('Angles IK [deg]:', i)\n", + " \n", + " f=forward(i[0], i[1], i[2], links)\n", + " print('Pts FK:', f)\n", + " \n", + " print('Delta Angles:')\n", + " err = []\n", + " for a,b in zip([x,y,z],f):\n", + " err.append(a-b)\n", + " \n", + " print(' x:{:.2f} y:{:.2f} z:{:.2f}'.format(err[0],err[1],err[2]))" + ] + }, + { + "cell_type": "code", + "execution_count": 160, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "*************************\n", + "Angles IK [deg]: (0.0, 2.555727551856687, -38.48183952164615)\n", + "Pts FK: (170.0, 0.0, -36.999999999999986)\n", + "Delta Angles:\n", + " x:0.00 y:0.00 z:-0.00\n", + "*************************\n", + "Angles IK [deg]: (0.0, 60.355608437273524, -116.53340171223132)\n", + "Pts FK: (120.00000000000001, 0.0, 7.105427357601002e-15)\n", + "Delta Angles:\n", + " x:-0.00 y:0.00 z:-0.00\n", + "*************************\n", + "Angles IK [deg]: (0.0, 82.61930045217325, -154.05417582934723)\n", + "Pts FK: (80.0, 0.0, -1.4210854715202004e-14)\n", + "Delta Angles:\n", + " x:0.00 y:0.00 z:0.00\n" + ] + } + ], + "source": [ + "testPos(170,0,-37, leg)\n", + "testPos(120,0,0, leg)\n", + "testPos(80,0,0, leg)" + ] + }, + { + "cell_type": "code", + "execution_count": 153, + "metadata": {}, + "outputs": [], + "source": [ + "# testAng(0,0,0,0)\n", + "# testAng(0,45,-45,-90)\n", + "# testAng(0,0,-90,0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Plot Leg Locations\n", + "\n", + "Let's get a visual of what is going on when we command a leg to a 3d location. The command is:\n", + "\n", + "```python\n", + "plotLeg(x,y,z,orientation)\n", + "```\n", + "\n", + "The *orientation* is the tarsus (foot) angle between the ground plane and the tarsus. Thus, if the tarsus is pointing straight down, the angle is 90 degrees. This is measured from the floor to the tarsus link." + ] + }, + { + "cell_type": "code", + "execution_count": 163, + "metadata": {}, + "outputs": [], + "source": [ + "def rplot(t1, t2, t3, links, degrees=True):\n", + " \"\"\"Given the 3 joint angles (in rads), plot the arm in the x-y and w-z planes\n", + " \n", + " x = (d2 + l1*cos(t2) + l2*cos(t2 + t3))*cos(t1)\n", + " y = (d2 + l1*cos(t2) + l2*cos(t2 + t3))*sin(t1)\n", + " z = l1*sin(t2) + l2*sin(t2 + t3)\n", + " \"\"\"\n", + " l1,l2,l3 = links\n", + "\n", + " ptsx = [0]\n", + " ptsy = [0]\n", + " \n", + " if degrees:\n", + " t1 *= pi/180\n", + " t2 *= pi/180\n", + " t3 *= pi/180\n", + " \n", + " \n", + " # our definition is reverse or these joints\n", + " # link 1\n", + " x0 = l1\n", + " y0 = 0\n", + " ptsx.append(x0)\n", + " ptsy.append(y0)\n", + " \n", + " # link 2\n", + " x1 = x0 + l2*cos(t2)\n", + " y1 = y0 + l2*sin(t2)\n", + " ptsx.append(x1)\n", + " ptsy.append(y1)\n", + " \n", + " # link 3\n", + " x2 = x1 + l3*cos(t2 + t3)\n", + " y2 = y1 + l3*sin(t2 + t3)\n", + " ptsx.append(x2)\n", + " ptsy.append(y2)\n", + " \n", + " plt.subplot(1,2,1,projection='polar')\n", + " plt.plot([0, t1], [0, 1.0])\n", + " plt.grid(True)\n", + " plt.title('Azimuth Angle (x-y plane)\\n')\n", + " \n", + " plt.subplot(1,2,2)\n", + " plt.plot(ptsx, ptsy, 'b-', marker='o')\n", + " plt.axis('equal')\n", + " plt.grid(True)\n", + " plt.title('w-z Plane') \n", + "\n", + "def plotLeg(x, y, z, links):\n", + " \"\"\"Given a point (in inches) and orientation (in rads), this calculates\n", + " the joint angles, then uses those angles to calculate the forward solution\n", + " and prints out the error. It also plots the arm.\n", + " \"\"\"\n", + " angles = inverse(x, y, z, links)\n", + " angles = list(angles)\n", + " \n", + " for i, a in enumerate(angles):\n", + " if a > 180:\n", + " angles[i] = -360 + a\n", + " \n", + " a,b,c = angles\n", + " print(f'Angles: {a:.2f} {b:.2f} {c:.2f}')\n", + " \n", + " print(f'w-z plane (w,z): {sqrt(x**2 + y**2):.2f} {z:.2f}')\n", + "\n", + " rplot(a,b,c,links)" + ] + }, + { + "cell_type": "code", + "execution_count": 164, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Angles: 0.00 25.26 -66.39\n", + "w-z plane (w,z): 160.00 -17.00\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotLeg(160,0,-17, leg)" + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Angles: -45.00 25.38 -111.66\n", + "w-z plane (w,z): 113.14 -40.00\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotLeg(80,-80,-40, leg)" + ] + }, + { + "cell_type": "code", + "execution_count": 166, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Angles: 0.00 -1.92 -92.26\n", + "w-z plane (w,z): 110.00 -70.00\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotLeg(110,0,-70, leg)" + ] + }, + { + "cell_type": "code", + "execution_count": 167, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Angles: 0.00 82.62 -154.05\n", + "w-z plane (w,z): 80.00 0.00\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plotLeg(80,0,0, leg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/misc/walking-robots-pdfs/Spider robot kinematics.pdf b/docs/misc/walking-robots-pdfs/Spider robot kinematics.pdf deleted file mode 100644 index c3d9bbd..0000000 Binary files a/docs/misc/walking-robots-pdfs/Spider robot kinematics.pdf and /dev/null differ diff --git a/docs/ncomms14494.pdf b/docs/misc/walking-robots-pdfs/climbing-hexapods.pdf similarity index 100% rename from docs/ncomms14494.pdf rename to docs/misc/walking-robots-pdfs/climbing-hexapods.pdf diff --git a/docs/99d15da9cde98069e24b3dc07218d472dc42.pdf b/docs/misc/walking-robots-pdfs/hex-with-4dof-legs.pdf similarity index 100% rename from docs/99d15da9cde98069e24b3dc07218d472dc42.pdf rename to docs/misc/walking-robots-pdfs/hex-with-4dof-legs.pdf diff --git a/docs/6360dff3ca1b8f5eafb436bc8855ff49250d.pdf b/docs/misc/walking-robots-pdfs/modelling-hexapod.pdf similarity index 100% rename from docs/6360dff3ca1b8f5eafb436bc8855ff49250d.pdf rename to docs/misc/walking-robots-pdfs/modelling-hexapod.pdf diff --git a/multiped/__init__.py b/multiped/__init__.py index 688e001..7de9670 100644 --- a/multiped/__init__.py +++ b/multiped/__init__.py @@ -19,5 +19,4 @@ __author__ = 'Kevin J. Walchko' __license__ = 'MIT' -# __version__ = '0.5.0' __version__ = version("multiped") diff --git a/multiped/alt/control.py b/multiped/alt/control.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/multiped/alt/control.py @@ -0,0 +1 @@ + diff --git a/multiped/alt/gait.py b/multiped/alt/gait.py new file mode 100644 index 0000000..df7dab0 --- /dev/null +++ b/multiped/alt/gait.py @@ -0,0 +1,163 @@ +from math import sin, cos, pi +import numpy as np +import time + +class Vector: + __data = None + + def __init__(self, x=0,y=0,z=0): + self.__data = [x,y,z] + + def __index__(self, i): + return self.__data[i] + + @property + def x(self): + return self.__data[0] + @x.setter + def x(self, x): + self.__data[0] = x + + @property + def y(self): + return self.__data[1] + @y.setter + def y(self, y): + self.__data[1] = y + + @property + def z(self): + return self.__data[2] + @z.setter + def z(self, z): + self.__data[2] = z + +class Foot: + position = None + orientation = 0 # yaw only + cycle = 0 + + def __init__(self, x=0, y=0, z=0, theta=0, cycle=0): + self.position = Vector(x,y,z) + self.orientation = theta + self.cycle = cycle + +class Twist: + linear = Vector() + angular = Vector() + +class Pose2D: + x = 0 + y = 0 + theta = 0 + + + + +class Gait: + def __init__(self): + self.cycle_period = 25 + + # tripod + self.gait_factor = 1.0 + # self.cycle_leg_number = [1,0,1,0,1,0] # Leg gait order (grouping) ['RR', 'RM', 'RF', 'LR', 'LM', 'LF'] + self.last_time = time.monotonic() + self.cycle_length = ?? # config + self.leg_lift_height = 50 # config + + self.feet = [ + Foot(cycle=1), + Foot(cycle=0), + Foot(cycle=1), + Foot(cycle=0), + Foot(cycle=1), + Foot(cycle=0) + ] + + self.lpf = Pose2D() + + def cyclePeriod(self, base, gait_vel): + period_height = sin(self.cycle_period*pi/self.cycle_length) + + current_time = time.monotonic() + dt = current_time - self.last_time + self.last_time = current_time + + gait_vel.linear.x = pi*base.x / cycle_length * period_height * (1/dt) + gait_vel.linear.y = -pi*base.y / cycle_length * period_height * (1/dt) + gait_vel.angular.z = pi*base.theta * period_height * (1/dt) + + for i, foot in enumerate(self.feet): + if foot.cycle == 0: + period_distance = cos( self.cycle_period * pi / self.cycle_length) + foot.position.x = base.x * period_distance + foot.position.y = base.y * period_distance + foot.position.z = leg_lift_height * period_height + foot.orientation = base.theta * period_distance + elif foot.cycle == 1: + period_distance = cos( self.cycle_period * pi / self.cycle_length) + foot.position.x = -base.x * period_distance + foot.position.y = -base.y * period_distance + foot.position.z = 0 + foot.orientation = -base.theta * period_distance + + def gaitCycle(self, cmd_vel, gait_vel): + base = Pose2D() + base.x = cmd_vel.linear.x / pi * cycle_length + base.y = cmd_vel.linear.y / pi * cycle_length + base.theta = cmd_vel.angular.z / pi * cycle_length + + # Low pass filter on the values to avoid jerky movements due to rapid value changes + smooth_base = self.lpf + smooth_base.x = base.x * 0.05 + ( smooth_base.x * ( 1.0 - 0.05 ) ); + smooth_base.y = base.y * 0.05 + ( smooth_base.y * ( 1.0 - 0.05 ) ); + smooth_base.theta = base.theta * 0.05 + ( smooth_base.theta * ( 1.0 - 0.05 ) ); + + if abs(self.lpf.x) > 0.001 or abs(self.lpf.y) > 0.001 or abs(self.lpf.theta) > 0.0043: + self.is_travelling = True + else: + self.is_travelling = False + + # check if in non-rest position + + if self.is_travelling is True or in_cycle is True: + self.cyclePeriod(self.lpf, gait_vel) + self.cycle_period += 1 + else: + self.cycle_period = 0 + + if self.cycle_period == self.cycle_length: + self.cycle_period = 0 + + # switch sequence on the foot cycle + for foot in self.feet: + if foot.cycle == 0: + foot.cycle = 1 + else: + foot.cycle = 0 + + + + + + + + + + + + + + + + + + + + + + + + + +## diff --git a/multiped/alt/ik.py b/multiped/alt/ik.py new file mode 100644 index 0000000..123d150 --- /dev/null +++ b/multiped/alt/ik.py @@ -0,0 +1,75 @@ +############################################# +# The MIT License (MIT) +# Copyright (c) 2016 Kevin Walchko +# see LICENSE for full details +############################################## + +# import numpy as np +from math import sin, cos, acos, atan2, sqrt, pi, fabs +# from math import radians as d2r +# from math import degrees as r2d +from .utils import constrain +from .utils import cosinelaw +from .utils import rad2deg, deg2rad + +# def sq(x): +# return x*x + +class Leg3: + """ + parameter file: + { + "legs": { + 0: { + "linkLengths": [coxa, femur, tibia], # mm + "servoOffsets": [s0, s1, s2], # radians + "servoLimits": [(min,max), (min,max), (min, max)] # radians + "ids": [4,5,6] # servo ID numbers + } + } + } + """ + def __init__(self, params): + self.linkLengths = params["linkLengths"] + self.servoOffsets = list(deg2rad*x for x in params["servoOffsets"]) + self.servoLimits = list((deg2rad*a, deg2rad*b) for a,b in params["servoLimits"]) + self.ids = params["ids"] + + def forward(self, t1,t2,t3, deg=True): + """ + Forward kinematics of the leg where angles a,b,c can be degrees [default] + or radians. Output is in the same units as the link lengths. + """ + l1,l2,l3 = self.linkLengths + + if degrees: + t1 *= deg2rad + t2 *= deg2rad + t3 *= deg2rad + + x = (l1 + l2*cos(t2) + l3*cos(t2 + t3))*cos(t1) + y = (l1 + l2*cos(t2) + l3*cos(t2 + t3))*sin(t1) + z = l2*sin(t2) + l3*sin(t2 + t3) + return (x,y,z) + + def inverse(self, x,y,z, degrees=False): + """ + Given a point in 3D space (x,y,z), this returns the joint angles in + radians [default] or degrees as a tuple (theta1, theta2, theta3). + """ + # mm + l1,l2,l3 = self.linkLengths + + w = sqrt(x**2+y**2) - l1 + d = sqrt(w**2+z**2) + + t1 = atan2(y,x) + t2 = atan2(z,w)+cosinelaw(l2,d,l3) + t3 = cosinelaw(l2,l3,d)-pi + + if degrees: + t1 *= rad2deg + t2 *= rad2deg + t3 *= rad2deg + + return (t1,t2,t3) diff --git a/multiped/bin/__init__.py b/multiped/bin/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/multiped/bin/get_leg_angles.py b/multiped/bin/get_leg_angles.py deleted file mode 100644 index c9ca6c7..0000000 --- a/multiped/bin/get_leg_angles.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python - -############################################## -# The MIT License (MIT) -# Copyright (c) 2017 Kevin Walchko -# see LICENSE for full details -############################################## - -from __future__ import print_function, division -from pyxl320 import ServoSerial -from pyxl320.Packet import le, makeReadPacket -import argparse -import simplejson as json - - -def writeToFile(data, filename='data.json'): - with open(filename, 'w') as outfile: - json.dump(data, outfile) - - -DESCRIPTION = """ -Returns the angles of servos -""" - - -def handleArgs(): - parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('port', help='serial port or \'dummy\' for testing', type=str) - parser.add_argument('-j', '--json', help='save info to a json file, you must supply a file name: --json my_file.json', type=str) - - args = vars(parser.parse_args()) - return args - - -def getInfo(pkt): - ID = pkt[4] - angle = float((pkt[10] << 8) + pkt[9])/1023 - angle *= 300.0 - return ID, angle - - -def getSingle(ID, ser): - pkt = makeReadPacket(ID, 37, le(2)) - # print('made packet:', pkt) - ID = None - angle = None - - ans = ser.sendPkt(pkt) - if ans: - ans = ans[0] - ID, angle = getInfo(ans) - - return angle - - -def main(): - args = handleArgs() - port = args['port'] - - s = ServoSerial(port=port) - s.open() - - ids = range(1, 13) - - resp = {} - for k in ids: - resp[k] = None - - # as more servos add up, I might need to increase the cnt number??? - for i in ids: - angle = getSingle(i, s) - resp[i] = angle - - cnt = 10 - while cnt: - cnt = 0 - for k, v in resp.items(): - # search through and find servos w/o responses (i.e., None) - if v is None: - cnt += 1 # found a None - angle = getSingle(k, s) - resp[k] = angle - - print('') - print('Servos: 1 - 12') - print('All angles are in {}'.format('degrees')) - print(' {:>13} | {:>13} | {:>13} | {:>13} |'.format('Leg 1', 'Leg 2', 'Leg 3', 'Leg 4')) - print(' {:>4} | {:6} | {:>4} | {:6} | {:>4} | {:6} | {:>4} | {:6} |'.format('ID', 'Angle', 'ID', 'Angle', 'ID', 'Angle', 'ID', 'Angle')) - print('-' * 65) - # for k, v in resp.items(): - # if v is None: - # print('{:4} | {}'.format(k, 'unknown')) - # else: - # print('{:4} | {:6.2f}'.format(k, v)) - for i in range(1, 4): - print(' {:4} | {:6.2f} | {:4} | {:6.2f} | {:4} | {:6.2f} | {:4} | {:6.2f}'.format(i, resp[i], i+3, resp[i+3], i+6, resp[i+6], i+9, resp[i+9])) - print('-' * 65) - print('') - - if args['json']: - print('Saving servo angle info to {}'.format(args['json'])) - writeToFile(resp, args['json']) - - s.close() - - -if __name__ == '__main__': - main() diff --git a/multiped/bin/get_leg_info.py b/multiped/bin/get_leg_info.py deleted file mode 100644 index ab3bf77..0000000 --- a/multiped/bin/get_leg_info.py +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env python - -############################################## -# The MIT License (MIT) -# Copyright (c) 2017 Kevin Walchko -# see LICENSE for full details -############################################## - -from __future__ import print_function, division -from pyxl320 import ServoSerial -from pyxl320.Packet import le, makeReadPacket -import argparse -import simplejson as json -from serial import SerialException -import sys -from quadruped.packetDecoder import PacketDecoder - - -def writeToFile(data, filename='data.json'): - with open(filename, 'w') as outfile: - json.dump(data, outfile) - - -def pktToDict(p): - # print('pkt', pkt) - # print('len(pkt)', len(pkt)) - ans = {} - ans['ID'] = p.id - ans['Present Position'] = p.angle() - ans['Present Voltage'] = p.voltage() - ans['Present Load'] = '{:>5.1f}% {}'.format(*p.load()) - ans['Present Temperature'] = p.temperature(PacketDecoder.F) - ans['Hardware Error Status'] = p.hw_error() - - return ans - - -DESCRIPTION = """ -Returns limited info for each leg servo. - -./get_leg_info.py /dev/tty.usbserial-AL034G2K -Opened /dev/tty.usbserial-AL034G2K @ 1000000 - -Servos: 1 - 12 --------------------------------------------------- -Servo: 1 HW Error: 0 -Position [deg]: 139.6 Load: 0.0% CCW -Voltage [V] 7.0 Temperature [F]: 80.6 --------------------------------------------------- -Servo: 2 HW Error: 0 -Position [deg]: 178.9 Load: 4.5% CW -Voltage [V] 7.1 Temperature [F]: 86.0 --------------------------------------------------- -Servo: 3 HW Error: 0 -Position [deg]: 119.1 Load: 0.0% CCW -Voltage [V] 7.1 Temperature [F]: 80.6 --------------------------------------------------- -Servo: 4 HW Error: 0 -Position [deg]: 146.6 Load: 0.8% CCW -Voltage [V] 7.3 Temperature [F]: 80.6 --------------------------------------------------- -Servo: 5 HW Error: 0 -Position [deg]: 275.4 Load: 0.8% CCW -Voltage [V] 7.1 Temperature [F]: 80.6 --------------------------------------------------- -Servo: 6 HW Error: 0 -Position [deg]: 104.1 Load: 0.0% CCW -Voltage [V] 7.3 Temperature [F]: 82.4 --------------------------------------------------- -Servo: 7 HW Error: 0 -Position [deg]: 163.9 Load: 0.0% CCW -Voltage [V] 7.2 Temperature [F]: 80.6 --------------------------------------------------- -Servo: 8 HW Error: 0 -Position [deg]: 279.5 Load: 0.0% CCW -Voltage [V] 7.1 Temperature [F]: 80.6 --------------------------------------------------- -Servo: 9 HW Error: 0 -Position [deg]: 100.3 Load: 0.0% CCW -Voltage [V] 7.1 Temperature [F]: 84.2 --------------------------------------------------- -Servo: 10 HW Error: 0 -Position [deg]: 156.3 Load: 0.0% CCW -Voltage [V] 7.1 Temperature [F]: 82.4 --------------------------------------------------- -Servo: 11 HW Error: 0 -Position [deg]: 280.6 Load: 0.0% CCW -Voltage [V] 7.2 Temperature [F]: 80.6 --------------------------------------------------- -Servo: 12 HW Error: 0 -Position [deg]: 97.7 Load: 0.0% CCW -Voltage [V] 7.1 Temperature [F]: 84.2 --------------------------------------------------- -""" - - -def handleArgs(): - parser = argparse.ArgumentParser(description=DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('port', help='serial port or \'dummy\' for testing', type=str) - parser.add_argument('-j', '--json', metavar='FILENAME', help='save info to a json file: --json my_file.json', type=str) - - args = vars(parser.parse_args()) - return args - - -def getSingle(ID, ser): - pkt = makeReadPacket(ID, 37, le(50-37+1)) - # print('made packet:', pkt) - - ans = ser.sendPkt(pkt) - if ans: - ans = ans[0] - pd = PacketDecoder(ans, 37) # data packet starts at register 37 - # pd.printPacket() - if pd.checkError(): - raise Exception('Crap!') - ans = pktToDict(pd) - else: - ans = None - - return ans - - -def printServo(s): - print('-'*50) - print('Servo: {} \t\tHW Error: {}'.format(s['ID'], s['Hardware Error Status'])) - print('Position [deg]: {:5.1f} Load: {}'.format(s['Present Position'], s['Present Load'])) - print('Voltage [V] {:4.1f} Temperature [F]: {:5.1f}'.format(s['Present Voltage'], s['Present Temperature'])) - - -def main(): - args = handleArgs() - port = args['port'] - - s = ServoSerial(port=port) - - # open serial port - try: - s.open() - except SerialException as e: - print('-'*20) - print(sys.argv[0], 'encountered an error') - print(e) - exit(1) - - ids = range(1, 13) - - resp = {} - for k in ids: - resp[k] = None - - # get servo data - try: - for i in ids: - data = getSingle(i, s) - resp[i] = data - except Exception as e: - print(e) - exit(1) - - cnt = 10 - while cnt: - cnt = 0 - for k, v in resp.items(): - # search through and find servos w/o responses (i.e., None) - if v is None: - cnt += 1 # found a None - ans = getSingle(k, s) - resp[k] = ans - - print('') - print('Servos: 1 - 12') - for i in range(1, 13): - printServo(resp[i]) - print('-' * 50) - print('') - - if args['json']: - print('Saving servo angle info to {}'.format(args['json'])) - writeToFile(resp, args['json']) - - s.close() - - -if __name__ == '__main__': - main() diff --git a/multiped/engine.py b/multiped/engine.py index 9659e5d..17d15fc 100644 --- a/multiped/engine.py +++ b/multiped/engine.py @@ -3,77 +3,41 @@ # Copyright (c) 2016 Kevin Walchko # see LICENSE for full details ############################################## - -from __future__ import print_function -from __future__ import division -from pyservos import ServoSerial -from pyservos import Packet -# from pyservos import ServoTypes -from pyservos.packet import angle2int -from pyservos.utils import le -from multiped.Servo import Servo +# from pyservos.utils import angle2int +from multiped.kinematics3 import Leg3 import time - -debug = True +from colorama import Fore +from pprint import pprint +from math import pi -def dprint(s): - global debug - if debug: - print(s) +def printError(e): + print(f"{Fore.RED}*** {e} ***{Fore.RESET}") +def printWarn(w): + print(f"{Fore.YELLOW}*** {w} ***{Fore.RESET}") -def calc_rpm(da, wait): - """ - Given an angular delta and a wait time, calculate the rpm needed to achieve +def printInfo(i): + print(f">>{Fore.CYAN} {i} {Fore.RESET}") - [Join Mode] - 0 ~ 1,023(0x3FF) can be used, and the unit is about 0.111rpm. - If it is set to 0, it means the maximum rpm of the motor is used - without controlling the speed. If it is 1023, it is about 114rpm. - For example, if it is set to 300, it is about 33.3 rpm. +def pprintInfo(i): + print(f">>{Fore.CYAN}") + pprint(i) + print(f"{Fore.RESET}", end="") - AX12 max rmp is 59 (max speed 532) - rev min 360 deg deg - --- ------- ------- = 6 ---- - min 60 sec rev sec - rpm = abs(new_angle - old_angle)/(0.111 * wait * 6) - """ - return int(abs(da)/(0.111*wait*6)) +class DummySerial: + enable = True + def write(self, pkt): + if not self.enable: + return -def calc_wait(da, speed): - """ - Given an angular delta and the speed (servo counts), calculate the how long - to wait for the servo to complete the movement - - [Join Mode] - 0 ~ 1,023(0x3FF) can be used, and the unit is about 0.111rpm. - If it is set to 0, it means the maximum rpm of the motor is used - without controlling the speed. If it is 1023, it is about 114rpm. - For example, if it is set to 300, it is about 33.3 rpm. - - AX12 max rmp is 59 (max speed 532) - rev min 360 deg deg - --- ------- ------- = 6 ---- - min 60 sec rev sec - - da deg - wait = ---------------------------------------- - rpm 360 deg min - 0.111 --- * speed_cnt * ------- * ------ - cnt rev 60 sec - - wait = abs(new_angle - old_angle)/(0.111 * speed * 6) - """ - try: - w = abs(da)/(0.111*speed*6) - except ZeroDivisionError: - w = 1 - print("*** calc_wait() div error: {}".format(speed)) + print(f">>{Fore.CYAN} serial.write[{len(pkt)}]: {Fore.YELLOW}[",end="") + for p in pkt: + print(int(p),end=",") + print(f"]{Fore.RESET}") - return w class Engine(object): @@ -81,194 +45,356 @@ class Engine(object): This class holds the serial port and talks to the hardware. Other classes ( e.g., gait, legs and servos) do the calculations for walking. """ - + current_move = None last_move = None + gait = None + serial = None + packet = None + legs = [0]*6 - def __init__(self, data, servoType): + def __init__(self, data, serialPort, packet): """ - data: serial port to use, if none, then use dummy port - servoType: AX12 or XL320 or other servo type - curr_pos: current leg position - bcm_pin: which gpio pin is used for the comm - { - 0: [(t0,t1,t2,t3,speed), ...] - 1: [...] - ... - 3: [...] - } + data: various info + serialPort: serial port object """ - if 'bcm_pin' in data: - bcm_pin = data['bcm_pin'] - else: - bcm_pin = None - - # self.wait = wait - # determine serial port - # default to fake serial port - if 'serialPort' in data: - try: - self.serial = ServoSerial(data['serialPort'], pi_pin=bcm_pin) - print('Using servo serial port: {}'.format(data['serialPort'])) - self.serial.open() - - except Exception as e: - print(e) - print('Engine::init(): bye ...') - exit(1) + self.serial = serialPort + if self.serial: + self.serial.open() else: - print('*** Using dummy serial port!!! ***') - self.serial = ServoSerial('dummy') - # raise Exception('No serial port given') - - # handle servos ... how does it know how many servos??? - self.servos_up = {} # check servos are operating - self.servos = [] - for ID, seg in enumerate(['coxa', 'femur', 'tibia', 'tarsus']): - length, offset = data[seg] - self.servos.append(Servo(ID, offset)) - # resp = self.pingServo(ID) # return: (T/F, servo_angle) - # self.servos[ID] = resp[0] - # curr_angle[ID] = - # for s, val in self.servos.items(): - # if val is False: - # print("*** Engine.__init__(): servo[{}] has failed".format(s)) - - self.packet = Packet(servoType) - - # keep track of last location, this is servo angle space - # self.last_move = { - # 0: curr_pos[0][0], - # 1: curr_pos[1][0], - # 2: curr_pos[2][0], - # 3: curr_pos[3][0] - # } - self.last_move = self.getCurrentAngles() - - def getCurrentAngles(self): - """ - Returns the current angles for all servos in DH space as a dictionary. - angles = { - 0: [0.0, 130.26, -115.73, -104.52], - 1: [0.0, 130.26, -115.73, -104.52], - 2: [0.0, 130.26, -115.73, -104.52], - 3: [0.0, 130.26, -115.73, -104.52], - } - - FIXME: actually query the servos and get there angles in DH space - """ - angles = { - 0: [0.0, 130.26, -115.73, -104.52], - 1: [0.0, 130.26, -115.73, -104.52], - 2: [0.0, 130.26, -115.73, -104.52], - 3: [0.0, 130.26, -115.73, -104.52], - } - return angles - - def DH2Servo(self, angle, num): - return self.servos[num].DH2Servo(angle) - - def moveLegsGait4(self, legs): + self.serial = DummySerial() + self.serial.enable = False + + self.packet = packet() + + try: + for leg in range(6): + self.legs[leg] = Leg3(data["legs"][leg]) + except Exception as e: + # print(f"{Fore.RED}*** {e} ***{Fore.RESET}") + printError(e) + raise + + def setGait(self, gait): + self.gait = gait() + + def wait(self, start): """ - gait or sequence? - speed = 1 - 1023 (scalar, all servos move at same rate) - { step 0 step 1 ... - 0: [(t1,t2,t3,t4,speed), (t1,t2,t3,t4,speed), ...] # leg0 - 2: [(t1,t2,t3,t4,speed), (t1,t2,t3,t4,speed), ...] # leg2 - ... - } where t=theta - NOTE: each leg needs the same number of steps and servos per leg - WARNING: these angles are in servo space [0-300 deg] - - [Join Mode] - 0 ~ 1,023(0x3FF) can be used, and the unit is about 0.111rpm. - If it is set to 0, it means the maximum rpm of the motor is used - without controlling the speed. If it is 1023, it is about 114rpm. - For example, if it is set to 300, it is about 33.3 rpm. - - AX12 max rmp is 59 (max speed 532) - rev min 360 deg deg - --- ------- ------- = 6 ---- - min 60 sec rev sec - - sleep time = | (new_angle - old_angle) /(0.111 * min_speed * 6) | + This will wait until the farthest move is done """ - # get the keys and figure out some stuff - keys = list(legs.keys()) # which legs are we moving - numSteps = len(legs[keys[0]]) # how many steps in the cycle - numServos = len(legs[keys[0]][0])-1 # how many servos per leg, -1 because speed there - - # if self.last_move is None: - # # assume we just turned on and was in the sit position - # # need a better solution - # self.last_move = { - # 0: legs[0][0], - # 1: legs[1][0], - # 2: legs[2][0], - # 3: legs[3][0] - # } - - # curr_move = {} - # for each step in legs - for step in range(numSteps): - # dprint("\nStep[{}]===============================================".format(step)) - data = [] - - # find max time we have to wait for all 4 legs to reach their end - # point. - max_wait = 0 - for legNum in keys: - angles = legs[legNum][step][:4] - speed = legs[legNum][step][4] - # print(" speed", speed) - for a, oa in zip(angles, self.last_move[legNum][:4]): - da = abs(a-oa) - w = calc_wait(da, speed) - # print(" calc_wait: {:.3f}".format(w)) - # print("calc_wait: {}".format(w)) - max_wait = w if w > max_wait else max_wait - - # print(">> found wait", max_wait, " speed:", speed) - - servo_speeds = [100,125,150,200] - - # for legNum in [0,3,1,2]: - for legNum in keys: - # dprint(" leg[{}]--------------".format(legNum)) - leg_angles_speed = legs[legNum][step] - # print(leg_angles_speed) - angles = leg_angles_speed[:4] # 4 servo angles - speed = leg_angles_speed[4] - # print("Speed:", speed, "wait", max_wait) - - for i, DH_angle in enumerate(angles): - # oldangle = self.last_move[legNum][i] - # due to rounding errors, to ensure the other servers finish - # BEFORE time.sleep(max_wait) ends, the the function it - # has less time - # spd = calc_rpm((angle - oldangle), 0.9*max_wait) - # now that i am scaling the spd parameter above, I sometimes - # exceed the original speed number, so saturate it if - # necessary - # spd = spd if spd <= speed else speed - # sl, sh = le(spd) - sl, sh = le(servo_speeds[i]) - servo_angle = self.DH2Servo(DH_angle, i) - al, ah = angle2int(servo_angle) # angle - data.append([legNum*numServos + i+1, al, ah, sl, sh]) # ID, low angle, high angle, low speed, high speed - # data.append([legNum*numServos + i+1, al, ah]) # ID, low angle, high angle, low speed, high speed - - self.last_move[legNum] = leg_angles_speed - - pkt = self.packet.makeSyncWritePacket(self.packet.base.GOAL_POSITION, data) + diff = [0]*18 + for i, (a, b) in enumerate(zip(self.current_move, self.last_move)): + diff[i] = abs(a - b) + mag = max(diff) + speed = 180/pi*1023/300*1/1207.14 # FIXME: this is wrong + + stop = time.time() + delay = mag*speed + dt = stop - start + + # if we haven't taken too much time already, sleep, else return + if delay > dt: + time.sleep(delay - dt) + # printInfo(f"engin.wait(): {1000*delay-dt:.2f} msec") + else: + # print(f"{Fore.RED}Too quick on engine.wait() {Fore.RESET}") + printError("Too quick on engine.wait()") + + self.last_move = self.current_move.copy() + + def move(self, x, y, z, theta): + # get the foot (x,y,z) locations for one cycle + feet = self.gait.command(x,y,z,theta) + pprintInfo(feet[0]) + info = [0]*18 # [[ID, angle], [ID, angle], ...] + if self.current_move is None: + self.current_move = [pi*0.5]*18 + if self.last_move is None: + self.last_move = self.current_move.copy() + + for step in range(len(feet[0])): + start = time.time() + for leg in range(6): + angles = self.legs[leg].inverse(*feet[leg][step]) # (angle, angle, angle) + ids = self.legs[leg].ids + for id, angle in zip(ids, angles): + info[id-1] = (id,) + tuple(angle2int(angle)) # data for servo sync write + self.current_move[id-1] = angle # calc wait time + + # printInfo(self.current_move) + pkt = self.packet.makeSyncWritePacket(self.packet.GOAL_POSITION, info) self.serial.write(pkt) - dprint("sent serial packet leg: {}".format(legNum)) - data = [] - print('max_wait', max_wait) - time.sleep(max_wait) + self.wait(start) # wait for motors to complete move + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # def moveLegsGait(self, legs): + # """ + # gait or sequence? + # speed = 1 - 1023 (scalar, all servos move at same rate) + # { step 0 step 1 ... + # 0: [(t1,t2,t3,t4,speed), (t1,t2,t3,t4,speed), ...] # leg0 + # 2: [(t1,t2,t3,t4,speed), (t1,t2,t3,t4,speed), ...] # leg2 + # ... + # } where t=theta + # NOTE: each leg needs the same number of steps and servos per leg + # WARNING: these angles are in servo space [0-300 deg] + # + # [Join Mode] + # 0 ~ 1,023(0x3FF) can be used, and the unit is about 0.111rpm. + # If it is set to 0, it means the maximum rpm of the motor is used + # without controlling the speed. If it is 1023, it is about 114rpm. + # For example, if it is set to 300, it is about 33.3 rpm. + # + # AX12 max rmp is 59 (max speed 532) + # rev min 360 deg deg + # --- ------- ------- = 6 ---- + # min 60 sec rev sec + # + # sleep time = | (new_angle - old_angle) /(0.111 * min_speed * 6) | + # """ + # # get the keys and figure out some stuff + # keys = list(legs.keys()) # which legs are we moving + # numSteps = len(legs[keys[0]]) # how many steps in the cycle + # numServos = len(legs[keys[0]][0])-1 # how many servos per leg, -1 because speed there + # + # # if self.last_move is None: + # # # assume we just turned on and was in the sit position + # # # need a better solution + # # self.last_move = { + # # 0: legs[0][0], + # # 1: legs[1][0], + # # 2: legs[2][0], + # # 3: legs[3][0] + # # } + # + # # curr_move = {} + # # for each step in legs + # for step in range(numSteps): + # # dprint("\nStep[{}]===============================================".format(step)) + # data = [] + # + # # find max time we have to wait for all 4 legs to reach their end + # # point. + # max_wait = 0 + # for legNum in keys: + # angles = legs[legNum][step][:4] + # speed = legs[legNum][step][4] + # # print(" speed", speed) + # for a, oa in zip(angles, self.last_move[legNum][:4]): + # da = abs(a-oa) + # w = calc_wait(da, speed) + # # print(" calc_wait: {:.3f}".format(w)) + # # print("calc_wait: {}".format(w)) + # max_wait = w if w > max_wait else max_wait + # + # # print(">> found wait", max_wait, " speed:", speed) + # + # servo_speeds = [100,125,150,200] + # + # # for legNum in [0,3,1,2]: + # for legNum in keys: + # # dprint(" leg[{}]--------------".format(legNum)) + # leg_angles_speed = legs[legNum][step] + # # print(leg_angles_speed) + # angles = leg_angles_speed[:4] # 4 servo angles + # speed = leg_angles_speed[4] + # # print("Speed:", speed, "wait", max_wait) + # + # for i, DH_angle in enumerate(angles): + # # oldangle = self.last_move[legNum][i] + # # due to rounding errors, to ensure the other servers finish + # # BEFORE time.sleep(max_wait) ends, the the function it + # # has less time + # # spd = calc_rpm((angle - oldangle), 0.9*max_wait) + # # now that i am scaling the spd parameter above, I sometimes + # # exceed the original speed number, so saturate it if + # # necessary + # # spd = spd if spd <= speed else speed + # # sl, sh = le(spd) + # sl, sh = le(servo_speeds[i]) + # servo_angle = self.DH2Servo(DH_angle, i) + # al, ah = angle2int(servo_angle) # angle + # data.append([legNum*numServos + i+1, al, ah, sl, sh]) # ID, low angle, high angle, low speed, high speed + # # data.append([legNum*numServos + i+1, al, ah]) # ID, low angle, high angle, low speed, high speed + # + # self.last_move[legNum] = leg_angles_speed + # + # pkt = self.packet.makeSyncWritePacket(self.packet.base.GOAL_POSITION, data) + # self.serial.write(pkt) + # dprint("sent serial packet leg: {}".format(legNum)) + # data = [] + # print('max_wait', max_wait) + # time.sleep(max_wait) + # + # # time.sleep(1) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - # time.sleep(1) +# def calc_rpm(da, wait): +# """ +# Given an angular delta and a wait time, calculate the rpm needed to achieve +# +# [Join Mode] +# 0 ~ 1,023(0x3FF) can be used, and the unit is about 0.111rpm. +# If it is set to 0, it means the maximum rpm of the motor is used +# without controlling the speed. If it is 1023, it is about 114rpm. +# For example, if it is set to 300, it is about 33.3 rpm. +# +# AX12 max rmp is 59 (max speed 532) +# rev min 360 deg deg +# --- ------- ------- = 6 ---- +# min 60 sec rev sec +# +# rpm = abs(new_angle - old_angle)/(0.111 * wait * 6) +# """ +# return int(abs(da)/(0.111*wait*6)) +# def calc_wait(da, speed): +# """ +# Given an angular delta and the speed (servo counts), calculate the how long +# to wait for the servo to complete the movement +# +# [Join Mode] +# 0 ~ 1,023(0x3FF) can be used, and the unit is about 0.111rpm. +# If it is set to 0, it means the maximum rpm of the motor is used +# without controlling the speed. If it is 1023, it is about 114rpm. +# For example, if it is set to 300, it is about 33.3 rpm. +# +# AX12 max rmp is 59 (max speed 532) +# rev min 360 deg deg +# --- ------- ------- = 6 ---- +# min 60 sec rev sec +# +# da deg +# wait = ---------------------------------------- +# rpm 360 deg min +# 0.111 --- * speed_cnt * ------- * ------ +# cnt rev 60 sec +# +# wait = abs(new_angle - old_angle)/(0.111 * speed * 6) +# """ +# try: +# w = abs(da)/(0.111*speed*6) +# except ZeroDivisionError: +# w = 1 +# print("*** calc_wait() div error: {}".format(speed)) +# +# return w # def pprint(self, i, step): # print('***', i, '*'*25) diff --git a/multiped/gait.py b/multiped/gait.py index de6e529..6495530 100644 --- a/multiped/gait.py +++ b/multiped/gait.py @@ -4,45 +4,224 @@ # see LICENSE for full details ############################################## -from __future__ import print_function -from __future__ import division from math import cos, sin, sqrt, pi +from multiped.utils import constrain, Rz +import numpy as np + + +class TripodGait: + case = (1,2,1,2,1,2) + home = np.array([60,0,-50]) + body = (0,0,0) + + def compute_strides(self,commandedX,commandedY,commandedZ, commandedR): + # compute stride lengths + self.strideX = 90*commandedX + self.strideY = 90*commandedY + self.strideR = pi/4*commandedR # was 35 + + # compute rotation trig + self.sinRotZ = sin(self.strideR) + self.cosRotZ = cos(self.strideR) + + # print(f">> stride: {self.strideX} {self.strideY} {self.strideR}") + # print(f">> rot: {self.sinRotZ} {self.cosRotZ}\n") + + def compute_amplitudes(self): + # compute total distance from center of body to toe + totalX = self.home[0] + self.body[0] + totalY = self.home[1] + self.body[1] + + # compute rotational offset + rotOffsetX = totalY*self.sinRotZ + totalX*self.cosRotZ - totalX + rotOffsetY = totalY*self.cosRotZ - totalX*self.sinRotZ - totalY + + # compute X and Y amplitude and constrain to prevent legs from crashing into each other + amplitudeX = (self.strideX + rotOffsetX)/2.0 + amplitudeY = (self.strideY + rotOffsetY)/2.0 + amplitudeX = constrain(amplitudeX,-50,50) + amplitudeY = constrain(amplitudeY,-50,50) + + # compute Z amplitude + step_height_multiplier = 1.0 + if (abs(self.strideX + rotOffsetX) > abs(self.strideY + rotOffsetY)): + amplitudeZ = step_height_multiplier * (self.strideX + rotOffsetX) / 4.0 + else: + amplitudeZ = step_height_multiplier * (self.strideY + rotOffsetY) / 4.0 + + return amplitudeX,amplitudeY,amplitudeZ + + def command(self, commandedX, commandedY, commandedZ, commandedR): + """ + Given a command, this returns an array of movments for one cycle + + return: + feet = { + 0: [(x0,y0,z0), (x1,y1,z1), ... (xn,yn,zn)] # leg0, all foot locations for one cycle + 1: [...] + ... + 5: [...] + } + """ + min_cmd = 0.1 + if((abs(commandedX) < min_cmd) or (abs(commandedY) < min_cmd) and (abs(commandedR) > 360)): + return None + + feet = { + 0: [], 1: [], 2: [], 3: [], 4: [], 5: [], + } + + case = ((1,2,1,2,1,2),(2,1,2,1,2,1)) + + for s in (0,1): + self.case = case[s] + max_step = 12 + for i in range(max_step): + steps = self.one_time_step(commandedX, commandedY, commandedZ, commandedR, i/max_step) + for leg in range(6): + feet[leg].append(steps[leg]) + + # print(f">> feet0: {feet[0]}") + return feet + + + def one_time_step(self, commandedX, commandedY, commandedZ, commandedR, dstep): + # print(f">> step: {dstep}") + ret = [0]*6 + self.compute_strides(commandedX, commandedY, commandedZ, commandedR) + amplitudeX,amplitudeY,amplitudeZ = self.compute_amplitudes() + # print(f">> Amp: {amplitudeX} {amplitudeY} {amplitudeZ}") + # numTicks = int(duration / FRAME_TIME_MS / 2.0) # total ticks divided into the two cases + # rot = [-pi/6, -pi/2, -5*pi/6,5*pi/6, pi/2, pi/6] + rot = [-pi/6, -pi/2, -5*pi/6, 5*pi/6+pi, pi/2+pi, pi/6+pi] + for leg_num in [0,1,2,3,4,5]: + # amplitudeX,amplitudeY,amplitudeZ = self.compute_amplitudes() + # print(f">> Amp: {amplitudeX} {amplitudeY} {amplitudeZ}") + if self.case[leg_num] == 1: # move foot forward (raise and lower) + # ret[leg_num] = [0,0,0] + # ret[leg_num][0] = self.home[0] - amplitudeX*cos(pi*dstep) + # ret[leg_num][1] = self.home[1] - amplitudeY*cos(pi*dstep) + # ret[leg_num][2] = self.home[2] + abs(amplitudeZ)*sin(pi*dstep) + # if (dstep >= 1.0): + # self.case[leg_num] = 2 + angle = rot[leg_num] + R = Rz(angle) + m = np.array([ + - amplitudeX*cos(pi*dstep), + - amplitudeY*cos(pi*dstep), + abs(amplitudeZ)*sin(pi*dstep) + ]) + ft = R @ (self.home + m) + ret[leg_num] = ft + + elif self.case[leg_num] == 2: # move foot back (on the ground) + # ret[leg_num] = [0,0,0] + # ret[leg_num][0] = self.home[0] + amplitudeX*cos(pi*dstep) + # ret[leg_num][1] = self.home[1] + amplitudeY*cos(pi*dstep) + # ret[leg_num][2] = self.home[2] + # if (dstep >= 1.0): + # self.case[leg_num] = 1 + angle = rot[leg_num] + R = Rz(angle) + m = np.array([ + + amplitudeX*cos(pi*dstep), + + amplitudeY*cos(pi*dstep), + 0 + ]) + ft = R @ (self.home + m) + ret[leg_num] = ft + + # print(f">> feet: {ret}") + return ret + + + + + + + + + + + + + + + + + + + + -debug = False -def rot_z_tuple(t, c): - """ - t - theta [radians] - c - [x,y,z] - return - (x,y,z) tuple rotated about z-axis - """ - ans = ( - c[0]*cos(t)-c[1]*sin(t), - c[0]*sin(t)+c[1]*cos(t), - c[2] - ) - return ans -# make a static method in Gait? Nothing else uses it -def rot_z(t, c): - """ - t - theta [radians] - c - [x,y,z] - return - [x,y,z] numpy array rotated about z-axis - """ - ans = [ - c[0]*cos(t)-c[1]*sin(t), - c[0]*sin(t)+c[1]*cos(t), - c[2] - ] - return ans + + + + + + + + + + + + + + + + + + + + + + + + + + +# debug = False +# +# +# def rot_z_tuple(t, c): +# """ +# t - theta [radians] +# c - [x,y,z] +# return - (x,y,z) tuple rotated about z-axis +# """ +# ans = ( +# c[0]*cos(t)-c[1]*sin(t), +# c[0]*sin(t)+c[1]*cos(t), +# c[2] +# ) +# +# return ans +# +# +# # make a static method in Gait? Nothing else uses it +# def rot_z(t, c): +# """ +# t - theta [radians] +# c - [x,y,z] +# return - [x,y,z] numpy array rotated about z-axis +# """ +# ans = [ +# c[0]*cos(t)-c[1]*sin(t), +# c[0]*sin(t)+c[1]*cos(t), +# c[2] +# ] +# +# return ans + # class Tripod: # def __init__(self, neutral, forward, back, count): # self.build_forward() @@ -57,198 +236,198 @@ def rot_z(t, c): # return tri -class Gait(object): - """ - Base class for gaits. Gait only plan all foot locations for 1 complete cycle - of the gait. - - Like to add center of mass (CM) compensation, so we know the CM is always - inside the stability triangle. - - Gait knows: - - how many legs - - leg stride (neutral position) - """ - # these are the offsets of each leg - legOffset = [0, 6, 3, 9] - # frame rotations for each leg - # cmrot = [pi/4, -pi/4, -3*pi/4, 3*pi/4] - # frame = [-pi/4, pi/4, 3*pi/4, -3*pi/4] # this seem to work better ... wtf? - frame = [pi/4, -pi/4, -3*pi/4, 3*pi/4] - moveFoot = None - rest = None - scale = 50.0 - - def __init__(self, rest): - # the resting or idle position/orientation of a leg - self.rest = rest - - def command(self, cmd): - """ - Send a command to the quadruped - cmd: [x, y, rotation about z-axis], the x,y is a unit vector and - rotation is in radians - """ - x, y, rz = cmd - d = sqrt(x**2+y**2) - - # handle no movement command ... do else where? - if d <= 0.1 and abs(rz) < 0.1: - x = y = 0.0 - rz = 0.0 - return None - # commands should be unit length, oneCyle scales it - elif 0.1 < d: - x /= d - y /= d - else: - return None - - angle_limit = pi/2 - if rz > angle_limit: - rz = angle_limit - elif rz < -angle_limit: - rz = -angle_limit - - return self.oneCycle_alt(x, y, rz) - - def oneCycle_alt(self, x, y, rz): - raise NotImplementedError('*** Gait: wrong function, this is base class! ***') - - -class DiscreteRippleGait(Gait): - """ - Discrete 12 step gait - """ - steps = 0 - - def __init__(self, height, rest): - """ - height: added to z - rest: the neutral foot position - """ - Gait.__init__(self, rest) - # self.phi = [8/8, 7/8, 1/8, 0/8, 1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8, 8/8] - self.phi = [10/10, 5/10, 0/10, 1/10, 2/10, 3/10, 4/10, 5/10, 6/10, 7/10, 8/10, 9/10] - self.setLegLift(height) - self.steps = len(self.phi) - - def setLegLift(self, lift): - # legs lift in the sequence: 0, 3, 1, 2 - # 0 1 2 3 4 5 6 7 8 9 10 11 - self.z = [0.0, lift, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # leg height - - def eachLeg(self, index, cmd): - """ - interpolates the foot position of each leg - cmd: - linear (mm) - angle (rads) - """ - rest = self.rest - i = index - phi = self.phi[i] - xx, yy, rzz = cmd - - # rotational commands ----------------------------------------------- - angle = rzz/2-rzz*phi - rest_rot = rot_z(-angle, rest) - - # create new move command - move = [ - xx/2 - phi*xx, - yy/2 - phi*yy, - self.z[i] - ] - - # new foot position: newpos = rot + move ---------------------------- - # newpos = linear_movement + angular_movement - # newpos = move + rest_rot - newpos = [0, 0, 0] - newpos[0] = move[0] + rest_rot[0] - newpos[1] = move[1] + rest_rot[1] - newpos[2] = move[2] + rest_rot[2] - - # print('New [](x,y,z): {:.2f}\t{:.2f}\t{:.2f}'.format(newpos[0], newpos[1], newpos[2])) - return newpos - - def move_cg(self, leg, off, pt, leg_lift): - """ - There is a pattern of which direction to shift based on which leg you - are trying to move and which leg is lifted (not currently providing - support for the robot) - leg - leg number - off - offset in mm to shift cm - leg_lift - which leg is moving through the air currently - - lift 0: x-d 1: y-d 2: x+d 3: y+d - y+d x-d y-d x+d - x+d y+d x-d y-d - y-d x+d y+d x-d - pattern: always x y x y (alternate) - always - + + - - """ - axis = [0, 1, 0, 1] # 0=x, 1=y componets of 3d point - offset = [-off, off, off, -off] # either adding or subtracting offset from point - ia = axis[(leg+leg_lift) % 4] # us mod to rotate through each of these indexes - io = (leg-leg_lift) % 4 - pt[ia] += offset[io] # shift point - return pt - # if leg == 0: - # if leg_lift == 0: pt[0] -= offset # x-d - # elif leg_lift == 1: pt[1] += offset # y+d - # elif leg_lift == 2: pt[0] += offset # x+d - # elif leg_lift == 3: pt[1] -= offset # y-d - # elif leg == 0: - # if leg_lift == 0: pt[1] -= offset # x-d - # elif leg_lift == 1: pt[0] -= offset # y+d - # elif leg_lift == 2: pt[1] += offset # x+d - # elif leg_lift == 3: pt[0] += offset # y-d - - - def oneCycle(self, x, y, rz): - """ - direction of travel x, y (2D plane) or rotation about z-axis - Returns 1 complete cycle for all 4 feet (x,y,z) - """ - - # check if x, y, rz is same as last time commanded, if so, return - # the last cycle response, else, calculate a new response - # ??? - - scale = self.scale - cmd = (scale*x, scale*y, rz) - ret = { - 0: [], - 1: [], - 2: [], - 3: [] - } # 4 leg foot positions for the entire 12 count cycle is returned - - # iteration, there are 12 steps in gait cycle, add a 13th so all feet - # are on the ground at the end, otherwise one foot is still in the air - leg_lift = [0,0,0,3,3,3,1,1,1,2,2,2] - for i in range(0, self.steps): - for legNum in [0, 1, 2, 3]: # order them diagonally - rcmd = rot_z_tuple(self.frame[legNum], cmd) - index = (i + self.legOffset[legNum]) % self.steps - pos = self.eachLeg(index, rcmd) # move each leg appropriately - # print('Foot[{}]: {:.2f} {:.2f} {:.2f}'.format(legNum, *(pos))) - - # shift cg - # fist and last shouldn't move cg?? - # pos = self.move_cg(legNum, 40, pos, leg_lift[i]) - - ret[legNum].append(pos) - - if debug: - print("=[Gait.py]===============================") - for legNum in [0, 1, 2, 3]: - print('Leg[{}]---------'.format(legNum)) - for i, pt in enumerate(ret[legNum]): - print(' {:2}: {:7.2f} {:7.2f} {:7.2f}'.format(i, *pt)) - - return ret +# class Gait(object): +# """ +# Base class for gaits. Gait only plan all foot locations for 1 complete cycle +# of the gait. +# +# Like to add center of mass (CM) compensation, so we know the CM is always +# inside the stability triangle. +# +# Gait knows: +# - how many legs +# - leg stride (neutral position) +# """ +# # these are the offsets of each leg +# legOffset = [0, 6, 3, 9] +# # frame rotations for each leg +# # cmrot = [pi/4, -pi/4, -3*pi/4, 3*pi/4] +# # frame = [-pi/4, pi/4, 3*pi/4, -3*pi/4] # this seem to work better ... wtf? +# frame = [pi/4, -pi/4, -3*pi/4, 3*pi/4] +# moveFoot = None +# rest = None +# scale = 50.0 +# +# def __init__(self, rest): +# # the resting or idle position/orientation of a leg +# self.rest = rest +# +# def command(self, cmd): +# """ +# Send a command to the quadruped +# cmd: [x, y, rotation about z-axis], the x,y is a unit vector and +# rotation is in radians +# """ +# x, y, rz = cmd +# d = sqrt(x**2+y**2) +# +# # handle no movement command ... do else where? +# if d <= 0.1 and abs(rz) < 0.1: +# x = y = 0.0 +# rz = 0.0 +# return None +# # commands should be unit length, oneCyle scales it +# elif 0.1 < d: +# x /= d +# y /= d +# else: +# return None +# +# angle_limit = pi/2 +# if rz > angle_limit: +# rz = angle_limit +# elif rz < -angle_limit: +# rz = -angle_limit +# +# return self.oneCycle_alt(x, y, rz) +# +# def oneCycle_alt(self, x, y, rz): +# raise NotImplementedError('*** Gait: wrong function, this is base class! ***') +# +# +# class DiscreteRippleGait(Gait): +# """ +# Discrete 12 step gait +# """ +# steps = 0 +# +# def __init__(self, height, rest): +# """ +# height: added to z +# rest: the neutral foot position +# """ +# Gait.__init__(self, rest) +# # self.phi = [8/8, 7/8, 1/8, 0/8, 1/8, 2/8, 3/8, 4/8, 5/8, 6/8, 7/8, 8/8] +# self.phi = [10/10, 5/10, 0/10, 1/10, 2/10, 3/10, 4/10, 5/10, 6/10, 7/10, 8/10, 9/10] +# self.setLegLift(height) +# self.steps = len(self.phi) +# +# def setLegLift(self, lift): +# # legs lift in the sequence: 0, 3, 1, 2 +# # 0 1 2 3 4 5 6 7 8 9 10 11 +# self.z = [0.0, lift, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # leg height +# +# def eachLeg(self, index, cmd): +# """ +# interpolates the foot position of each leg +# cmd: +# linear (mm) +# angle (rads) +# """ +# rest = self.rest +# i = index +# phi = self.phi[i] +# xx, yy, rzz = cmd +# +# # rotational commands ----------------------------------------------- +# angle = rzz/2-rzz*phi +# rest_rot = rot_z(-angle, rest) +# +# # create new move command +# move = [ +# xx/2 - phi*xx, +# yy/2 - phi*yy, +# self.z[i] +# ] +# +# # new foot position: newpos = rot + move ---------------------------- +# # newpos = linear_movement + angular_movement +# # newpos = move + rest_rot +# newpos = [0, 0, 0] +# newpos[0] = move[0] + rest_rot[0] +# newpos[1] = move[1] + rest_rot[1] +# newpos[2] = move[2] + rest_rot[2] +# +# # print('New [](x,y,z): {:.2f}\t{:.2f}\t{:.2f}'.format(newpos[0], newpos[1], newpos[2])) +# return newpos +# +# def move_cg(self, leg, off, pt, leg_lift): +# """ +# There is a pattern of which direction to shift based on which leg you +# are trying to move and which leg is lifted (not currently providing +# support for the robot) +# leg - leg number +# off - offset in mm to shift cm +# leg_lift - which leg is moving through the air currently +# +# lift 0: x-d 1: y-d 2: x+d 3: y+d +# y+d x-d y-d x+d +# x+d y+d x-d y-d +# y-d x+d y+d x-d +# pattern: always x y x y (alternate) +# always - + + - +# """ +# axis = [0, 1, 0, 1] # 0=x, 1=y componets of 3d point +# offset = [-off, off, off, -off] # either adding or subtracting offset from point +# ia = axis[(leg+leg_lift) % 4] # us mod to rotate through each of these indexes +# io = (leg-leg_lift) % 4 +# pt[ia] += offset[io] # shift point +# return pt +# # if leg == 0: +# # if leg_lift == 0: pt[0] -= offset # x-d +# # elif leg_lift == 1: pt[1] += offset # y+d +# # elif leg_lift == 2: pt[0] += offset # x+d +# # elif leg_lift == 3: pt[1] -= offset # y-d +# # elif leg == 0: +# # if leg_lift == 0: pt[1] -= offset # x-d +# # elif leg_lift == 1: pt[0] -= offset # y+d +# # elif leg_lift == 2: pt[1] += offset # x+d +# # elif leg_lift == 3: pt[0] += offset # y-d +# +# +# def oneCycle(self, x, y, rz): +# """ +# direction of travel x, y (2D plane) or rotation about z-axis +# Returns 1 complete cycle for all 4 feet (x,y,z) +# """ +# +# # check if x, y, rz is same as last time commanded, if so, return +# # the last cycle response, else, calculate a new response +# # ??? +# +# scale = self.scale +# cmd = (scale*x, scale*y, rz) +# ret = { +# 0: [], +# 1: [], +# 2: [], +# 3: [] +# } # 4 leg foot positions for the entire 12 count cycle is returned +# +# # iteration, there are 12 steps in gait cycle, add a 13th so all feet +# # are on the ground at the end, otherwise one foot is still in the air +# leg_lift = [0,0,0,3,3,3,1,1,1,2,2,2] +# for i in range(0, self.steps): +# for legNum in [0, 1, 2, 3]: # order them diagonally +# rcmd = rot_z_tuple(self.frame[legNum], cmd) +# index = (i + self.legOffset[legNum]) % self.steps +# pos = self.eachLeg(index, rcmd) # move each leg appropriately +# # print('Foot[{}]: {:.2f} {:.2f} {:.2f}'.format(legNum, *(pos))) +# +# # shift cg +# # fist and last shouldn't move cg?? +# # pos = self.move_cg(legNum, 40, pos, leg_lift[i]) +# +# ret[legNum].append(pos) +# +# if debug: +# print("=[Gait.py]===============================") +# for legNum in [0, 1, 2, 3]: +# print('Leg[{}]---------'.format(legNum)) +# for i, pt in enumerate(ret[legNum]): +# print(' {:2}: {:7.2f} {:7.2f} {:7.2f}'.format(i, *pt)) +# +# return ret # def oneCycle2(self, x, y, rz): diff --git a/multiped/jsonFile.py b/multiped/jsonFile.py index f33e2c2..1b50f00 100644 --- a/multiped/jsonFile.py +++ b/multiped/jsonFile.py @@ -10,71 +10,71 @@ class FileStorageError(Exception): - pass + pass class jsonFile(object): - """ - Store your API keys or other params in a json/yaml file and then import them - with this class. You can also pass a dictionary to this and create a json/yaml - file storage. All key/value pairs are stored in a dictionary called db. - """ - db = None + """ + Store your API keys or other params in a json/yaml file and then import them + with this class. You can also pass a dictionary to this and create a json/yaml + file storage. All key/value pairs are stored in a dictionary called db. + """ + db = None - def read(self, fname): - """ - Reads a Json file - in: file name - out: length of file, dictionary - """ - try: - with open(fname, 'r') as f: - data = json.load(f) + def read(self, fname): + """ + Reads a Json file + in: file name + out: length of file, dictionary + """ + try: + with open(fname, 'r') as f: + data = json.load(f) - self.db = data - return len(self.db), data - except IOError: - raise FileStorageError('Could not open {0!s} for reading'.format((fname))) + self.db = data + return len(self.db), data + except IOError: + raise FileStorageError('Could not open {0!s} for reading'.format((fname))) - def write(self, fname, data=None): - """ - Writes a Json file - """ - try: - if data is None: - data = self.db + def write(self, fname, data=None): + """ + Writes a Json file + """ + try: + if data is None: + data = self.db - with open(fname, 'w') as f: - json.dump(data, f) + with open(fname, 'w') as f: + json.dump(data, f) - except IOError: - raise FileStorageError('Could not open {0!s} for writing'.format((fname))) + except IOError: + raise FileStorageError('Could not open {0!s} for writing'.format((fname))) - def __getitem__(self, keyName): - if keyName in self.db: - return self.db[keyName] - else: - return None + def __getitem__(self, keyName): + if keyName in self.db: + return self.db[keyName] + else: + return None - def __str__(self): - s = [] - for k, v in db.items(): - s.append(str(k) + ': ' + str(v) + '\n') - return ''.join(s) + def __str__(self): + s = [] + for k, v in db.items(): + s.append(str(k) + ': ' + str(v) + '\n') + return ''.join(s) - def __repr__(self): - print(self.__str__()) + def __repr__(self): + print(self.__str__()) - def clear(self): - self.db = None + def clear(self): + self.db = None # # if __name__ == '__main__': -# fs = jsonFile() -# fs.read('walkingeye.json') -# # db = fs.db +# fs = jsonFile() +# fs.read('walkingeye.json') +# # db = fs.db # -# print('serialPort', fs['serialPort']) -# print('') +# print('serialPort', fs['serialPort']) +# print('') # -# print(fs) +# print(fs) diff --git a/multiped/kinematics3.py b/multiped/kinematics3.py index 9cc26c2..a835348 100644 --- a/multiped/kinematics3.py +++ b/multiped/kinematics3.py @@ -1,9 +1,101 @@ -# #!/usr/bin/env python -# ############################################## -# # The MIT License (MIT) -# # Copyright (c) 2016 Kevin Walchko -# # see LICENSE for full details -# ############################################## +############################################## +# The MIT License (MIT) +# Copyright (c) 2016 Kevin Walchko +# see LICENSE for full details +############################################## + +# import numpy as np +from math import sin, cos, acos, atan2, sqrt, pi, fabs +# from math import radians as d2r +# from math import degrees as r2d +from .utils import constrain +from .utils import cosinelaw +from .utils import rad2deg, deg2rad + +# def sq(x): +# return x*x + +class Leg3: + """ + parameter file: + { + "legs": { + 0: { + "linkLengths": [coxa, femur, tibia], # mm + "servoOffsets": [s0, s1, s2], # radians + "servoLimits": [(min,max), (min,max), (min, max)] # radians + "ids": [4,5,6] # servo ID numbers + } + } + } + """ + def __init__(self, params): + self.linkLengths = params["linkLengths"] + self.servoOffsets = list(deg2rad*x for x in params["servoOffsets"]) + self.servoLimits = list((deg2rad*a, deg2rad*b) for a,b in params["servoLimits"]) + self.ids = params["ids"] + + def forward(self, t1,t2,t3, deg=True): + """ + Forward kinematics of the leg where angles a,b,c can be degrees [default] + or radians. Output is in the same units as the link lengths. + """ + l1,l2,l3 = self.linkLengths + + if degrees: + t1 *= deg2rad + t2 *= deg2rad + t3 *= deg2rad + + x = (l1 + l2*cos(t2) + l3*cos(t2 + t3))*cos(t1) + y = (l1 + l2*cos(t2) + l3*cos(t2 + t3))*sin(t1) + z = l2*sin(t2) + l3*sin(t2 + t3) + return (x,y,z) + + def inverse(self, x,y,z, degrees=False): + """ + Given a point in 3D space (x,y,z), this returns the joint angles in + radians [default] or degrees as a tuple (theta1, theta2, theta3). + """ + # mm + l1,l2,l3 = self.linkLengths + + w = sqrt(x**2+y**2) - l1 + d = sqrt(w**2+z**2) + + t1 = atan2(y,x) + t2 = atan2(z,w)+cosinelaw(l2,d,l3) + t3 = cosinelaw(l2,l3,d)-pi + + if degrees: + t1 *= rad2deg + t2 *= rad2deg + t3 *= rad2deg + + return (t1,t2,t3) + + + + + + + + + + + + + + + + + + + + + + + # # from __future__ import print_function # from __future__ import division @@ -19,180 +111,180 @@ # # # class LegException(Exception): -# pass +# pass # # # class Leg3(object): -# """ -# """ -# # these are fixed by the 3D printing, not changing -# coxaLength = 45.0 -# tibiaLength = 55.0 -# femurLength = 104.0 -# s_limits = [ -# [-90, 90], # set limits -# [-90, 90], -# [-150, 0] -# ] -# s_offsets = [150, 150, 150+90] # angle offsets to line up with fk -# -# sit_raw = (150, 270, 100) -# stand_raw = (150, 175, 172) -# sit_angles = None -# stand_angles = None -# -# def __init__(self, channels): -# """ -# Each leg has 3 servos/channels -# """ -# if not len(channels) == 3: -# raise LegException('len(channels) != 3') -# -# Servo.bulkServoWrite = True -# -# # angle offsets to line up with fk -# self.servos = [] -# for i in range(0, 3): -# self.servos.append(Servo(channels[i])) -# self.servos[i].setServoLimits(self.s_offsets[i], *self.s_limits[i]) -# -# self.sit_angles = self.convertRawAngles(*self.sit_raw) -# initAngles = self.convertRawAngles(*self.stand_raw) -# self.stand_angles = initAngles -# self.foot0 = self.fk(*initAngles) # rest/idle position of the foot/leg -# -# def __del__(self): -# pass -# -# def sit(self): -# self.moveFootAngles(*self.sit_angles) -# -# def stand(self): -# self.moveFootAngles(*self.stand_angles) -# -# def convertRawAngles(self, a, b, c): -# return (a-self.s_offsets[0], b-self.s_offsets[1], c-self.s_offsets[2]) -# -# def fk(self, a, b, g): -# """ -# Forward kinematics of the leg, note, angle are all degrees -# """ -# Lc = self.coxaLength -# Lf = self.femurLength -# Lt = self.tibiaLength -# -# a = d2r(a) -# b = d2r(b) -# g = d2r(g) -# -# foot = [ -# (Lc + Lf*cos(b) + Lt*cos(b + g))*cos(a), -# (Lc + Lf*cos(b) + Lt*cos(b + g))*sin(a), -# Lf*sin(b) + Lt*sin(b + g) -# ] -# -# # return np.array(foot) -# return foot -# -# def ik(self, x, y, z): -# """ -# Calculates the inverse kinematics from a given foot coordinate (x,y,z)[mm] -# and returns the joint angles[degrees] -# -# Reference (there are typos) -# https://tote.readthedocs.io/en/latest/ik.html -# -# If the foot (x,y,z) is in a position that does not produce a result (some -# numeric error or invalid foot location), the this returns None. -# """ -# # try: -# Lc = self.coxaLength -# Lf = self.femurLength -# Lt = self.tibiaLength -# -# if sqrt(x**2 + y**2) < Lc: -# print('too short') -# return None -# # elif z > 0.0: -# # return None -# -# a = atan2(y, x) -# f = sqrt(x**2 + y**2) - Lc -# # b1 = atan2(z, f) # takes into account quadrent, z is neg -# -# # you have different conditions depending if z is pos or neg -# if z < 0.0: -# b1 = atan2(f, fabs(z)) -# else: -# b1 = atan2(z, f) -# -# d = sqrt(f**2 + z**2) # <--- -# -# # print('ik pos: {} {} {}'.format(x,y,z)) -# # print('d: {:.3f} f: {:.3f}'.format(d,f)) -# # print('Lc Lf Lt: {} {} {}'.format(Lc,Lf,Lt)) -# # print('num: {:.3f}'.format(Lf**2 + d**2 - Lt**2)) -# # print('den: {:.3f}'.format(2.0 * Lf * d)) -# # print('acos: {:.2f}'.format((Lf**2 + d**2 - Lt**2) / (2.0 * Lf * d))) -# -# guts = ((Lf**2 + d**2 - Lt**2) / (2.0 * Lf * d)) -# if 1.0 < guts or guts < -1.0: -# print('acos crap!: {:.3f} {:.3f} {:.3f} guts: {:.3f}'.format(x, y, z, guts)) -# return None -# b2 = acos((Lf**2 + d**2 - Lt**2) / (2.0 * Lf * d)) # issues? -# b = b1 + b2 -# g = acos((Lf**2 + Lt**2 - d**2) / (2.0 * Lf * Lt)) -# -# # FIXES ################################### -# g -= pi # fix to align fk and ik frames -# -# if z < 0.0: -# b -= pi/2 # -# ############################################## -# # print('b1 b2: {:.2f} {:.2f}'.format(r2d(b1), r2d(b2))) -# # print('ik angles: {:.2f} {:.2f} {:.2f}'.format(r2d(a), r2d(b), r2d(g))) -# return r2d(a), r2d(b), r2d(g) # coxaAngle, femurAngle, tibiaAngle -# -# # except Exception as e: -# # print('ik error:', e) -# # raise e -# -# def moveFoot(self, x, y, z): -# """ -# Attempts to move it's foot to coordinates [x,y,z] -# """ -# try: -# # a, b, c = self.ik(x, y, z) # inverse kinematics -# # angles = [a, b, c] -# angles = self.ik(x, y, z) # inverse kinematics -# # return angles -# if angles is None: -# print('something bad') -# return -# # print('angles: {:.2f} {:.2f} {:.2f}'.format(*angles)) -# for i, servo in enumerate(self.servos): -# # print('i, servo:', i, servo) -# angle = angles[i] -# # print('servo {} angle {}'.format(i, angle)) -# servo.angle = angle -# return angles -# -# except Exception as e: -# print (e) -# raise -# -# def moveFootAngles(self, a, b, c): -# """ -# Attempts to move it's foot to coordinates [x,y,z] -# """ -# try: -# for servo, angle in zip(self.servos, (a, b, c)): -# servo.angle = angle -# -# except Exception as e: -# print('Leg::moveFootAngles() error:', e) -# raise -# -# # def reset(self): -# # # self.angles = self.resting_position -# # self.move(*self.foot0) +# """ +# """ +# # these are fixed by the 3D printing, not changing +# coxaLength = 45.0 +# tibiaLength = 55.0 +# femurLength = 104.0 +# s_limits = [ +# [-90, 90], # set limits +# [-90, 90], +# [-150, 0] +# ] +# s_offsets = [150, 150, 150+90] # angle offsets to line up with fk +# +# sit_raw = (150, 270, 100) +# stand_raw = (150, 175, 172) +# sit_angles = None +# stand_angles = None +# +# def __init__(self, channels): +# """ +# Each leg has 3 servos/channels +# """ +# if not len(channels) == 3: +# raise LegException('len(channels) != 3') +# +# Servo.bulkServoWrite = True +# +# # angle offsets to line up with fk +# self.servos = [] +# for i in range(0, 3): +# self.servos.append(Servo(channels[i])) +# self.servos[i].setServoLimits(self.s_offsets[i], *self.s_limits[i]) +# +# self.sit_angles = self.convertRawAngles(*self.sit_raw) +# initAngles = self.convertRawAngles(*self.stand_raw) +# self.stand_angles = initAngles +# self.foot0 = self.fk(*initAngles) # rest/idle position of the foot/leg +# +# def __del__(self): +# pass +# +# def sit(self): +# self.moveFootAngles(*self.sit_angles) +# +# def stand(self): +# self.moveFootAngles(*self.stand_angles) +# +# def convertRawAngles(self, a, b, c): +# return (a-self.s_offsets[0], b-self.s_offsets[1], c-self.s_offsets[2]) +# +# def fk(self, a, b, g): +# """ +# Forward kinematics of the leg, note, angle are all degrees +# """ +# Lc = self.coxaLength +# Lf = self.femurLength +# Lt = self.tibiaLength +# +# a = d2r(a) +# b = d2r(b) +# g = d2r(g) +# +# foot = [ +# (Lc + Lf*cos(b) + Lt*cos(b + g))*cos(a), +# (Lc + Lf*cos(b) + Lt*cos(b + g))*sin(a), +# Lf*sin(b) + Lt*sin(b + g) +# ] +# +# # return np.array(foot) +# return foot +# +# def ik(self, x, y, z): +# """ +# Calculates the inverse kinematics from a given foot coordinate (x,y,z)[mm] +# and returns the joint angles[degrees] +# +# Reference (there are typos) +# https://tote.readthedocs.io/en/latest/ik.html +# +# If the foot (x,y,z) is in a position that does not produce a result (some +# numeric error or invalid foot location), the this returns None. +# """ +# # try: +# Lc = self.coxaLength +# Lf = self.femurLength +# Lt = self.tibiaLength +# +# if sqrt(x**2 + y**2) < Lc: +# print('too short') +# return None +# # elif z > 0.0: +# # return None +# +# a = atan2(y, x) +# f = sqrt(x**2 + y**2) - Lc +# # b1 = atan2(z, f) # takes into account quadrent, z is neg +# +# # you have different conditions depending if z is pos or neg +# if z < 0.0: +# b1 = atan2(f, fabs(z)) +# else: +# b1 = atan2(z, f) +# +# d = sqrt(f**2 + z**2) # <--- +# +# # print('ik pos: {} {} {}'.format(x,y,z)) +# # print('d: {:.3f} f: {:.3f}'.format(d,f)) +# # print('Lc Lf Lt: {} {} {}'.format(Lc,Lf,Lt)) +# # print('num: {:.3f}'.format(Lf**2 + d**2 - Lt**2)) +# # print('den: {:.3f}'.format(2.0 * Lf * d)) +# # print('acos: {:.2f}'.format((Lf**2 + d**2 - Lt**2) / (2.0 * Lf * d))) +# +# guts = ((Lf**2 + d**2 - Lt**2) / (2.0 * Lf * d)) +# if 1.0 < guts or guts < -1.0: +# print('acos crap!: {:.3f} {:.3f} {:.3f} guts: {:.3f}'.format(x, y, z, guts)) +# return None +# b2 = acos((Lf**2 + d**2 - Lt**2) / (2.0 * Lf * d)) # issues? +# b = b1 + b2 +# g = acos((Lf**2 + Lt**2 - d**2) / (2.0 * Lf * Lt)) +# +# # FIXES ################################### +# g -= pi # fix to align fk and ik frames +# +# if z < 0.0: +# b -= pi/2 # +# ############################################## +# # print('b1 b2: {:.2f} {:.2f}'.format(r2d(b1), r2d(b2))) +# # print('ik angles: {:.2f} {:.2f} {:.2f}'.format(r2d(a), r2d(b), r2d(g))) +# return r2d(a), r2d(b), r2d(g) # coxaAngle, femurAngle, tibiaAngle +# +# # except Exception as e: +# # print('ik error:', e) +# # raise e +# +# def moveFoot(self, x, y, z): +# """ +# Attempts to move it's foot to coordinates [x,y,z] +# """ +# try: +# # a, b, c = self.ik(x, y, z) # inverse kinematics +# # angles = [a, b, c] +# angles = self.ik(x, y, z) # inverse kinematics +# # return angles +# if angles is None: +# print('something bad') +# return +# # print('angles: {:.2f} {:.2f} {:.2f}'.format(*angles)) +# for i, servo in enumerate(self.servos): +# # print('i, servo:', i, servo) +# angle = angles[i] +# # print('servo {} angle {}'.format(i, angle)) +# servo.angle = angle +# return angles +# +# except Exception as e: +# print (e) +# raise +# +# def moveFootAngles(self, a, b, c): +# """ +# Attempts to move it's foot to coordinates [x,y,z] +# """ +# try: +# for servo, angle in zip(self.servos, (a, b, c)): +# servo.angle = angle +# +# except Exception as e: +# print('Leg::moveFootAngles() error:', e) +# raise +# +# # def reset(self): +# # # self.angles = self.resting_position +# # self.move(*self.foot0) diff --git a/multiped/robot.py b/multiped/robot.py index 72ad200..b261900 100644 --- a/multiped/robot.py +++ b/multiped/robot.py @@ -1,46 +1,44 @@ #!/usr/bin/env python - -############################################## -# The MIT License (MIT) -# Copyright (c) 2016 Kevin Walchko -# see LICENSE for full details -############################################## -# Simple robot - -from __future__ import print_function -from __future__ import division -from multiped import Engine -from multiped import DiscreteRippleGait -# import time -########################## - - -class Robot(object): - """ - This is a simple class that binds the others together. You could make it - a base class for something fancier. - """ - def __init__(self, data, legType, servoType): - """ - Constructor. - Engine - commands the leg servos to move - gait - Ideally there are several types of gaits for different - walking/running situations. If you don't give it an dict - of gaits, then the default is just the standard - DiscreteRippleGait. - The gaits need to know: - - how high to pick up a leg - - what the neutral leg position is (where is the foot - located when just standing?) - """ - self.engine = Engine(data, servoType) - self.kinematics = legType(data) - - neutral = self.kinematics.getNeutralPos() - - if 'gaits' in data: - self.gaits = data['gaits'] - else: - self.gaits = { - 'crawl': DiscreteRippleGait(65.0, neutral) - } +# +# ############################################## +# # The MIT License (MIT) +# # Copyright (c) 2016 Kevin Walchko +# # see LICENSE for full details +# ############################################## +# # Simple robot +# +# from multiped import Engine +# # from multiped import DiscreteRippleGait +# # import time +# ########################## +# +# +# class Robot(object): +# """ +# This is a simple class that binds the others together. You could make it +# a base class for something fancier. +# """ +# def __init__(self, data, legType, servoType): +# """ +# Constructor. +# Engine - commands the leg servos to move +# gait - Ideally there are several types of gaits for different +# walking/running situations. If you don't give it an dict +# of gaits, then the default is just the standard +# DiscreteRippleGait. +# The gaits need to know: +# - how high to pick up a leg +# - what the neutral leg position is (where is the foot +# located when just standing?) +# """ +# self.engine = Engine(data, servoType) +# self.kinematics = legType(data) +# +# neutral = self.kinematics.getNeutralPos() +# +# if 'gaits' in data: +# self.gaits = data['gaits'] +# else: +# self.gaits = { +# 'crawl': DiscreteRippleGait(65.0, neutral) +# } diff --git a/multiped/servo.py b/multiped/servo.py index 5082b41..0803ad7 100644 --- a/multiped/servo.py +++ b/multiped/servo.py @@ -5,23 +5,23 @@ ############################################## -class Servo(object): - """ - Servo hold the parameters of a servo, it doesn't talk to real servos. This - class does the conversion between DH angles to real servo angles - """ - - def __init__(self, ID, offset=150): - self.offset = offset - # self.minAngle = minmax[0] # DH space - # self.maxAngle = minmax[1] # DH space - self.id = ID - - def DH2Servo(self, angle): - """ - Sets the servo angle and clamps it between [limitMinAngle, limitMaxAngle]. - """ - sangle = angle+self.offset - if sangle > 300 or sangle < 0: - raise Exception('{} angle out of range DH[-150,150]: {:.1f} Servo[0,300]: {:.1f} deg'.format(self.id, angle, sangle)) - return sangle +# class Servo(object): +# """ +# Servo hold the parameters of a servo, it doesn't talk to real servos. This +# class does the conversion between DH angles to real servo angles +# """ +# +# def __init__(self, ID, offset=150): +# self.offset = offset +# # self.minAngle = minmax[0] # DH space +# # self.maxAngle = minmax[1] # DH space +# self.id = ID +# +# def DH2Servo(self, angle): +# """ +# Sets the servo angle and clamps it between [limitMinAngle, limitMaxAngle]. +# """ +# sangle = angle+self.offset +# if sangle > 300 or sangle < 0: +# raise Exception('{} angle out of range DH[-150,150]: {:.1f} Servo[0,300]: {:.1f} deg'.format(self.id, angle, sangle)) +# return sangle diff --git a/multiped/utils.py b/multiped/utils.py new file mode 100644 index 0000000..958bd5c --- /dev/null +++ b/multiped/utils.py @@ -0,0 +1,25 @@ +from math import acos, pi +import numpy as np + +rad2deg = 180/pi +deg2rad = pi/180 + +def constrain(angle, min, max): + angle = angle if angle > min else min + angle = angle if angle < max else max + return angle + +def cosinelaw(a,b,c): + # cos(g) = (a^2+b^2-c^2)/2ab + return acos((a**2+b**2-c**2)/(2*a*b)) + +def Rz(a, degrees=False): + if degrees: + a *= deg2rad + ca = np.cos(a) + sa = np.sin(a) + return np.array( + [[ ca, sa, 0], + [-sa, ca, 0], + [ 0, 0, 1]] + ) diff --git a/pyproject.toml b/pyproject.toml index 8454733..91ec526 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ pyservos = ">=2.0.1" simplejson = "*" [tool.poetry.dev-dependencies] -pytest = "^5.2" +pytest = "*" # mypy = "*" # [mypy-pi_servo_serial] diff --git a/readme.md b/readme.md index b3b972c..0288891 100755 --- a/readme.md +++ b/readme.md @@ -62,8 +62,8 @@ to run. This software talks to both the XL-320 and AX-12A servos from Robotis. Here is *sort* of the layout of the code: ``` - cmd 3d pts DH angles servo packet -robot --> gait -----> legs --------> engine -----------> servos + cmd 3d foot pts servo angles servo packet +robot --> gait -----------> legs ----------> engine -----------> servos ``` - **Robot(data):**