rename folders

This commit is contained in:
Zhengyu Peng
2022-01-06 11:25:06 -05:00
parent a31398347b
commit 143671fdb4
26 changed files with 0 additions and 0 deletions

0
software/path tool/fabfile.py vendored Normal file
View File

View File

@ -0,0 +1,48 @@
kLegMountLeftRightX = 29.87
kLegMountOtherX = 22.41
kLegMountOtherY = 55.41
kLegRootToJoint1 = 20.75
kLegJoint1ToJoint2 = 28.0
kLegJoint2ToJoint3 = 42.6
kLegJoint3ToTip = 89.07
SIN30 = 0.5
COS30 = 0.866
SIN45 = 0.7071
COS45 = 0.7071
SIN15 = 0.2588
COS15 = 0.9659
STANDBY_Z = (kLegJoint3ToTip*COS15-kLegJoint2ToJoint3*SIN30)
LEFTRIGHT_X = (kLegMountLeftRightX+kLegRootToJoint1+kLegJoint1ToJoint2+(kLegJoint2ToJoint3*COS30)+kLegJoint3ToTip*SIN15)
OTHER_X = (kLegMountOtherX + (kLegRootToJoint1+kLegJoint1ToJoint2+(kLegJoint2ToJoint3*COS30)+kLegJoint3ToTip*SIN15)*COS45)
OTHER_Y = (kLegMountOtherY + (kLegRootToJoint1+kLegJoint1ToJoint2+(kLegJoint2ToJoint3*COS30)+kLegJoint3ToTip*SIN15)*SIN45)
defaultPosition = (
(OTHER_X, OTHER_Y, -STANDBY_Z),
(LEFTRIGHT_X, 0, -STANDBY_Z),
(OTHER_X, -OTHER_Y, -STANDBY_Z),
(-OTHER_X, -OTHER_Y, -STANDBY_Z),
(-LEFTRIGHT_X, 0, -STANDBY_Z),
(-OTHER_X, OTHER_Y, -STANDBY_Z),
)
mountPosition = (
(kLegMountOtherX, kLegMountOtherY, 0),
(kLegMountLeftRightX, 0, 0),
(kLegMountOtherX, -kLegMountOtherY, 0),
(-kLegMountOtherX, -kLegMountOtherY, 0),
(-kLegMountLeftRightX, 0, 0),
(-kLegMountOtherX, kLegMountOtherY, 0),
)
defaultAngle = (
-45, 0, 45, 135, 180, 225
)
angleLimitation = (
(-45, 45),
(-45, 75),
(-60, 60),
)

View File

@ -0,0 +1,25 @@
import math
import config
pi = math.acos(-1)
def ik(to):
angles = []
x = to[0] - config.kLegRootToJoint1
y = to[1]
angles.append(math.atan2(y, x) * 180 / pi)
x = math.sqrt(x*x + y*y) - config.kLegJoint1ToJoint2
y = to[2]
ar = math.atan2(y, x)
lr2 = x*x + y*y
lr = math.sqrt(lr2)
a1 = math.acos((lr2 + config.kLegJoint2ToJoint3*config.kLegJoint2ToJoint3 - config.kLegJoint3ToTip*config.kLegJoint3ToTip)/(2*config.kLegJoint2ToJoint3*lr))
a2 = math.acos((lr2 - config.kLegJoint2ToJoint3*config.kLegJoint2ToJoint3 + config.kLegJoint3ToTip*config.kLegJoint3ToTip)/(2*config.kLegJoint3ToTip*lr))
angles.append((ar + a1) * 180 / pi)
angles.append(90 - ((a1 + a2) * 180 / pi))
return angles

View File

@ -0,0 +1,153 @@
import argparse
import logging
import os
import sys
import config
import kinematics
from path.lib import point_rotate_z, matrix_mul
def collectPath(sub_folder):
scripts = {}
for script_name in [f[:-3] for f in sorted(os.listdir(sub_folder)) if f.endswith('.py') and os.path.isfile(os.path.join(sub_folder, f))]:
module = __import__(script_name)
if not hasattr(module, 'path_generator'):
continue
scripts[script_name] = module.path_generator
return scripts
def show_detail(path, result):
print("path:{}:".format(path))
for i, p in enumerate(result):
print("{:2d} {:5.2f}, {:5.2f}, {:5.2f}".format(i, p[0], p[1], p[2]))
def verify_points(pt):
angles = kinematics.ik(pt)
ok = True
failed = []
for i, angle in enumerate(angles):
if angle < config.angleLimitation[i][0] or angle > config.angleLimitation[i][1]:
ok = False
failed.append((i, angle))
return ok, failed
def verify_path(path, params):
data, mode, _, _ = params
print("Verifying {}...".format(path))
all_ok = True
if mode == "shift":
# data: float[6][N][3]
assert(len(data) == 6)
for i in range(len(data[0])):
for j in range(6):
pt = [config.defaultPosition[j][k] - config.mountPosition[j][k] + data[j][i][k] for k in range(3)]
pt = point_rotate_z(pt, config.defaultAngle[j])
ok, failed = verify_points(pt)
if not ok:
print("{}, {} failed: {}".format(i, j, failed))
all_ok = False
elif mode == "matrix":
# data: np.matrix[N]
for i in range(len(data)):
for j in range(6):
pt = matrix_mul(data[i], config.defaultPosition[j])
for k in range(3):
pt[k] -= config.mountPosition[j][k]
pt = point_rotate_z(pt, config.defaultAngle[j])
ok, failed = verify_points(pt)
if not ok:
print("{}, {} failed: {}".format(i, j, failed))
all_ok = False
return all_ok
def generate_c_body(path, params):
data, mode, dur, entries = params
result = "\nconst Locations {}_paths[] {{\n".format(path)
if mode == "shift":
# data: float[6][N][3]
assert(len(data) == 6)
count = len(data[0])
for i in range(count):
result += " {" + ", ".join(
"{{P{idx}X+({x:.2f}), P{idx}Y+({y:.2f}), P{idx}Z+({z:.2f})}}".format(x=data[j][i][0], y=data[j][i][1], z=data[j][i][2], idx=j+1)
for j in range(6)
) + "},\n"
elif mode == "matrix":
# data: np.matrix[N]
count = len(data)
for i in range(count):
result += " {" + ", \n ".join(
"{{P{idx}X*{e00:.2f} + P{idx}Y*{e01:.2f} + P{idx}Z*{e02:.2f} + {e03:.2f}, P{idx}X*{e10:.2f} + P{idx}Y*{e11:.2f} + P{idx}Z*{e12:.2f} + {e13:.2f}, P{idx}X*{e20:.2f} + P{idx}Y*{e21:.2f} + P{idx}Z*{e22:.2f} + {e23:.2f}}}".format(
e00=data[i].item((0,0)), e01=data[i].item((0,1)), e02=data[i].item((0,2)), e03=data[i].item((0,3)),
e10=data[i].item((1,0)), e11=data[i].item((1,1)), e12=data[i].item((1,2)), e13=data[i].item((1,3)),
e20=data[i].item((2,0)), e21=data[i].item((2,1)), e22=data[i].item((2,2)), e23=data[i].item((2,3)),
idx=j+1)
for j in range(6)
) + "},\n"
else:
raise RuntimeError("Generation mode: {} not supported".format(mode))
result += "};\n"
result += "const int {}_entries[] {{ {} }};\n".format(path, ",".join(str(e) for e in entries))
result += "const MovementTable {name}_table {{{name}_paths, {count}, {dur}, {name}_entries, {ecount} }};".format(name=path, count=count, dur=dur, ecount=len(entries))
return result
def generate_c_def(path):
return """const MovementTable& {name}Table() {{
return {name}_table;
}}""".format(name=path)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='pathTool: generate Hexapod path')
parser.add_argument('--pathDir', metavar='DIR', dest='path_dir', default='path',
help='path script directory (default: {})'.format('path'))
parser.add_argument('--outPath', metavar='PATH', dest='out_path', default='output/movement_table.h',
help='path script directory (default: {})'.format('output/movement_table.h'))
args = parser.parse_args()
sys.path.insert(0, args.path_dir)
# find available path generator
paths = collectPath(args.path_dir)
# generate all paths
results = {path: generator() for path, generator in paths.items()}
# verify all path is within safe angles
verified = [1 for path, data in results.items() if not verify_path(path, data)]
if len(verified) > 0:
print("There were errors, exit...")
else:
# output results
with open(args.out_path, "w") as f:
print("//", file=f)
print("// This file is generated, dont directly modify content...", file=f)
print("//", file=f)
print("namespace {", file=f)
for path, data in results.items():
print(generate_c_body(path, data), file=f)
print("}\n", file=f)
for path in results:
print(generate_c_def(path), file=f)
print("Result written to {}".format(args.out_path))

View File

@ -0,0 +1 @@
../../../hexapod7697/src/hexapod/movement_table.h

View File

View File

@ -0,0 +1,17 @@
from collections import deque
from lib import semicircle_generator
g_steps = 20
g_radius = 25
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
path = semicircle_generator(g_radius, g_steps, reverse=True)
mir_path = deque(path)
mir_path.rotate(halfsteps)
return [path, mir_path, path, mir_path, path, mir_path, ], "shift", 20, (0, halfsteps)

View File

@ -0,0 +1,27 @@
from collections import deque
from lib import semicircle2_generator
g_steps = 20
y_radius = 20
z_radius = 80
x_radius = 30
z_shift = -30
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
rpath = [(x, y, z + z_shift) for x, y, z in semicircle2_generator(g_steps, y_radius, z_radius, x_radius)]
lpath = [(x, y, z + z_shift) for x, y, z in semicircle2_generator(g_steps, y_radius, z_radius, -x_radius)]
mir_rpath = deque(rpath)
mir_rpath.rotate(halfsteps)
mir_lpath = deque(lpath)
mir_lpath.rotate(halfsteps)
return [rpath, mir_rpath, rpath, mir_lpath, lpath, mir_lpath, ], "shift", 30, (0, halfsteps)

View File

@ -0,0 +1,19 @@
from collections import deque
from lib import semicircle_generator
g_steps = 20
g_radius = 25
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
path = semicircle_generator(g_radius, g_steps)
mir_path = deque(path)
mir_path.rotate(halfsteps)
return [path, mir_path, path, mir_path, path, mir_path, ], "shift", 20, (0, halfsteps)

View File

@ -0,0 +1,25 @@
from collections import deque
from lib import semicircle2_generator
g_steps = 20
y_radius = 50
z_radius = 30
x_radius = 10
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
rpath = semicircle2_generator(g_steps, y_radius, z_radius, x_radius)
lpath = semicircle2_generator(g_steps, y_radius, z_radius, -x_radius)
mir_rpath = deque(rpath)
mir_rpath.rotate(halfsteps)
mir_lpath = deque(lpath)
mir_lpath.rotate(halfsteps)
return [rpath, mir_rpath, rpath, mir_lpath, lpath, mir_lpath, ], "shift", 20, (0, halfsteps)

View File

@ -0,0 +1,118 @@
from collections import deque
import math
import numpy as np
pi = math.acos(-1)
def semicircle_generator(radius, steps, reverse=False):
assert (steps % 4) == 0
halfsteps = int(steps/2)
step_angle = pi / halfsteps
result = []
# first half, move backward (only y change)
for i in range(halfsteps):
result.append((0, radius - i*radius*2/(halfsteps), 0))
# second half, move forward in semicircle shape (y, z change)
for i in range(halfsteps):
angle = pi - step_angle*i
y = radius * math.cos(angle)
z = radius * math.sin(angle)
result.append((0, y, z))
result = deque(result)
result.rotate(int(steps/4))
if reverse:
result = deque(reversed(result))
result.rotate(1)
return result
def semicircle2_generator(steps, y_radius, z_radius, x_radius, reverse=False):
assert (steps % 4) == 0
halfsteps = int(steps/2)
step_angle = pi / halfsteps
result = []
# first half, move backward (only y change)
for i in range(halfsteps):
result.append((0, y_radius - i*y_radius*2/(halfsteps), 0))
# second half, move forward in semicircle shape (y, z change)
for i in range(halfsteps):
angle = pi - step_angle*i
y = y_radius * math.cos(angle)
z = z_radius * math.sin(angle)
x = x_radius * math.sin(angle)
result.append((x, y, z))
result = deque(result)
result.rotate(int(steps/4))
if reverse:
result = deque(reversed(result))
result.rotate(1)
return result
def get_rotate_x_matrix(angle):
angle = angle * pi / 180
return np.matrix([
[1, 0, 0, 0],
[0, math.cos(angle), -math.sin(angle), 0],
[0, math.sin(angle), math.cos(angle), 0],
[0, 0, 0, 1],
])
def get_rotate_y_matrix(angle):
angle = angle * pi / 180
return np.matrix([
[math.cos(angle), 0, math.sin(angle), 0],
[0, 1, 0, 0],
[-math.sin(angle), 0, math.cos(angle), 0],
[0, 0, 0, 1],
])
def get_rotate_z_matrix(angle):
angle = angle * pi / 180
return np.matrix([
[math.cos(angle), -math.sin(angle), 0, 0],
[math.sin(angle), math.cos(angle), 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
])
def matrix_mul(m, pt):
ptx = list(pt) + [1]
return list((m * np.matrix(ptx).T).T.flat)[:-1]
def point_rotate_x(pt, angle):
ptx = list(pt) + [1]
return list((get_rotate_x_matrix(angle) * np.matrix(ptx).T).T.flat)[:-1]
def point_rotate_y(pt, angle):
ptx = list(pt) + [1]
return list((get_rotate_y_matrix(angle) * np.matrix(ptx).T).T.flat)[:-1]
def point_rotate_z(pt, angle):
ptx = list(pt) + [1]
return list((get_rotate_z_matrix(angle) * np.matrix(ptx).T).T.flat)[:-1]
def path_rotate_x(path, angle):
return [point_rotate_x(p, angle) for p in path]
def path_rotate_y(path, angle):
return [point_rotate_y(p, angle) for p in path]
def path_rotate_z(path, angle):
return [point_rotate_z(p, angle) for p in path]
if __name__ == '__main__':
pt = [0, 1, 0]
print(point_rotate_z(pt, 270))

View File

@ -0,0 +1,42 @@
from collections import deque
import math
from lib import get_rotate_x_matrix as get_matrix
g_steps = 20
swing_angle = 15
y_radius = 15
def path_generator():
assert (g_steps % 4) == 0
quarter = int(g_steps/4)
pi = math.acos(-1)
result = []
step_angle = swing_angle / quarter
step_offset = y_radius / quarter
for i in range(quarter):
m = get_matrix(swing_angle - i*step_angle)
m[1,3] = -i * step_offset
result.append(m)
for i in range(quarter):
m = get_matrix(-i*step_angle)
m[1,3] = -y_radius + i * step_offset
result.append(m)
for i in range(quarter):
m = get_matrix(i*step_angle-swing_angle)
m[1,3] = i * step_offset
result.append(m)
for i in range(quarter):
m = get_matrix(i*step_angle)
m[1,3] = y_radius-i * step_offset
result.append(m)
return result, "matrix", 50, (0, quarter*2)

View File

@ -0,0 +1,42 @@
from collections import deque
import math
from lib import get_rotate_y_matrix as get_matrix
g_steps = 20
swing_angle = 15
x_radius = 15
def path_generator():
assert (g_steps % 4) == 0
quarter = int(g_steps/4)
pi = math.acos(-1)
result = []
step_angle = swing_angle / quarter
step_offset = x_radius / quarter
for i in range(quarter):
m = get_matrix(swing_angle - i*step_angle)
m[0,3] = -i * step_offset
result.append(m)
for i in range(quarter):
m = get_matrix(-i*step_angle)
m[0,3] = -x_radius + i * step_offset
result.append(m)
for i in range(quarter):
m = get_matrix(i*step_angle-swing_angle)
m[0,3] = i * step_offset
result.append(m)
for i in range(quarter):
m = get_matrix(i*step_angle)
m[0,3] = x_radius-i * step_offset
result.append(m)
return result, "matrix", 50, (0, quarter*2)

View File

@ -0,0 +1,25 @@
from collections import deque
import math
from lib import get_rotate_x_matrix, get_rotate_y_matrix
g_steps = 20
z_lift = 4.5
xy_radius = 1
def path_generator():
pi = math.acos(-1)
result = []
step_angle = 2*pi / g_steps
for i in range(g_steps):
x = xy_radius * math.cos(i*step_angle)
y = xy_radius * math.sin(i*step_angle)
m = get_rotate_y_matrix(math.atan2(x, z_lift)*180/pi) * get_rotate_x_matrix(math.atan2(y, z_lift)*180/pi)
result.append(m)
return result, "matrix", 50, range(g_steps)

View File

@ -0,0 +1,20 @@
from collections import deque
from lib import semicircle_generator
from lib import path_rotate_z
g_steps = 20
g_radius = 25
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
path = semicircle_generator(g_radius, g_steps)
path = path_rotate_z(path, 90) # shift 90 degree to make the path "left" shift
mir_path = deque(path)
mir_path.rotate(halfsteps)
return [path, mir_path, path, mir_path, path, mir_path, ], "shift", 20, (0, halfsteps)

View File

@ -0,0 +1,20 @@
from collections import deque
from lib import semicircle_generator
from lib import path_rotate_z
g_steps = 20
g_radius = 25
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
path = semicircle_generator(g_radius, g_steps)
path = path_rotate_z(path, 270) # shift 270 degree to make the path "right" shift
mir_path = deque(path)
mir_path.rotate(halfsteps)
return [path, mir_path, path, mir_path, path, mir_path, ], "shift", 20, (0, halfsteps)

View File

@ -0,0 +1,27 @@
from collections import deque
from lib import semicircle_generator
from lib import path_rotate_z
g_steps = 20
g_radius = 25
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
path = semicircle_generator(g_radius, g_steps)
mir_path = deque(path)
mir_path.rotate(halfsteps)
return [
path_rotate_z(path, 45),
path_rotate_z(mir_path, 0),
path_rotate_z(path, 315),
path_rotate_z(mir_path, 225),
path_rotate_z(path, 180),
path_rotate_z(mir_path, 135),
], "shift", 20, (0, halfsteps)

View File

@ -0,0 +1,27 @@
from collections import deque
from lib import semicircle_generator
from lib import path_rotate_z
g_steps = 20
g_radius = 25
def path_generator():
assert (g_steps % 4) == 0
halfsteps = int(g_steps/2)
path = semicircle_generator(g_radius, g_steps)
mir_path = deque(path)
mir_path.rotate(halfsteps)
return [
path_rotate_z(path, 45+180),
path_rotate_z(mir_path, 0+180),
path_rotate_z(path, 315+180),
path_rotate_z(mir_path, 225+180),
path_rotate_z(path, 180+180),
path_rotate_z(mir_path, 135+180),
], "shift", 20, (0, halfsteps)

View File

@ -0,0 +1,35 @@
from collections import deque
import math
from lib import get_rotate_x_matrix, get_rotate_z_matrix
g_steps = 20
raise_angle = 3
twist_x_angle = 20
twise_y_angle = 12
def path_generator():
assert (g_steps % 4) == 0
result = []
quarter = int(g_steps / 4)
step_x_angle = twist_x_angle / quarter
step_y_angle = twise_y_angle / quarter
m = get_rotate_x_matrix(raise_angle)
for i in range(quarter):
result.append(m * get_rotate_z_matrix(i*step_x_angle) * get_rotate_x_matrix(i*step_y_angle))
for i in range(quarter):
result.append(m * get_rotate_z_matrix((quarter-i)*step_x_angle) * get_rotate_x_matrix((quarter-i)*step_y_angle))
for i in range(quarter):
result.append(m * get_rotate_z_matrix(-i*step_x_angle) * get_rotate_x_matrix(i*step_y_angle))
for i in range(quarter):
result.append(m * get_rotate_z_matrix((-quarter+i)*step_x_angle) * get_rotate_x_matrix((quarter-i)*step_y_angle))
return result, "matrix", 50, [0, 10]