Robot parts: Initial commit
This commit is contained in:
parent
1bed3f2a39
commit
40d53ac1ba
|
@ -0,0 +1,187 @@
|
|||
import boxes
|
||||
|
||||
__all__ = [
|
||||
"RobotArg",
|
||||
"RobotArmMM",
|
||||
"RobotArmMm",
|
||||
"RobotArmUU",
|
||||
"RobotArmUu",
|
||||
"RobotArmMu",
|
||||
]
|
||||
|
||||
class RobotArg:
|
||||
|
||||
def __init__(self, includenone=False):
|
||||
self.robotarms = [
|
||||
(name, globals()[name].__doc__[23:]) for name in __all__
|
||||
if name.startswith("RobotArm")]
|
||||
if includenone:
|
||||
self.robotarms[0:0] = [("none", "")]
|
||||
|
||||
def __call__(self, arg):
|
||||
return str(arg)
|
||||
|
||||
def choices(self):
|
||||
return [name for name, descr in self.robotarms]
|
||||
|
||||
def html(self, name, default):
|
||||
options = "\n".join(
|
||||
("""<option value="%s"%s>%s %s</option>""" %
|
||||
(name, ' selected="selected"' if name == default else "",
|
||||
name, descr) for name, descr in self.robotarms))
|
||||
return """<select name="%s" size="1">\n%s</select>\n""" % (name, options)
|
||||
|
||||
|
||||
class _RobotArm:
|
||||
|
||||
def __init__(self, boxes, servo, servo2=None):
|
||||
self.boxes = boxes
|
||||
self.servo = servo
|
||||
self.servo2 = servo2 or servo
|
||||
|
||||
def __getattr__(self, name):
|
||||
"""Hack for easy access of Boxes methods"""
|
||||
return getattr(self.boxes, name)
|
||||
|
||||
class RobotArmMM(_RobotArm):
|
||||
"""Robot arm segment with two parallel servos"""
|
||||
def __call__(self, length, move=None):
|
||||
t = self.thickness
|
||||
w = self.servo.height
|
||||
l = max(self.servo.length * 2, length + 2*self.servo.axle_pos)
|
||||
|
||||
th = max(2 * t + l, 2*w + 4*t + self.spacing)
|
||||
tw = 5 * (w + 2*self.thickness + self.spacing)
|
||||
|
||||
if self.move(tw, th, move, True):
|
||||
return
|
||||
|
||||
self.rectangularWall(w, l, "FfFf", callback=[
|
||||
lambda:self.servo.top(w/2), None,
|
||||
lambda:self.servo.top(w/2)], move="right")
|
||||
self.rectangularWall(w, l, "FfFf", callback=[
|
||||
lambda:self.servo.bottom(w/2), None,
|
||||
lambda:self.servo.bottom(w/2)], move="right")
|
||||
self.rectangularWall(w, l, "FFFF", move="right")
|
||||
self.rectangularWall(w, l, "FFFF", move="right")
|
||||
self.rectangularWall(w, w, "ffff", callback=[
|
||||
lambda:self.servo.front(w/2)], move="up")
|
||||
self.rectangularWall(w, w, "ffff", callback=[
|
||||
lambda:self.servo.front(w/2)], move="")
|
||||
|
||||
self.move(tw, th, move)
|
||||
|
||||
class RobotArmMm(_RobotArm):
|
||||
"""Robot arm segment with two orthogonal servos"""
|
||||
def __call__(self, length, move=None):
|
||||
t = self.thickness
|
||||
w = self.servo.height
|
||||
w2 = self.servo2.height
|
||||
l = max(self.servo.length * 2, length + 2*self.servo.axle_pos)
|
||||
|
||||
th = max(2 * self.thickness + l, w + w2 + 4*t + self.spacing)
|
||||
tw = 5 * (max(w, w2) + 2*self.thickness + self.spacing)
|
||||
|
||||
if self.move(tw, th, move, True):
|
||||
return
|
||||
|
||||
self.rectangularWall(w2, l, "FfFf", callback=[
|
||||
lambda:self.servo.top(w2/2)], move="right")
|
||||
self.rectangularWall(w2, l, "FfFf", callback=[
|
||||
lambda:self.servo.bottom(w2/2)], move="right")
|
||||
self.rectangularWall(w, l, "FFFF", callback=[
|
||||
None, None, lambda:self.servo2.top(w/2)], move="right")
|
||||
self.rectangularWall(w, l, "FFFF", callback=[
|
||||
None, None, lambda:self.servo2.bottom(w/2)], move="right")
|
||||
self.rectangularWall(w2, w, "ffff", callback=[
|
||||
lambda:self.servo.front(w2/2)], move="up")
|
||||
self.rectangularWall(w, w2, "ffff", callback=[
|
||||
lambda:self.servo2.front(w/2)], move="")
|
||||
|
||||
self.move(tw, th, move)
|
||||
|
||||
class RobotArmUU(_RobotArm):
|
||||
"""Robot arm segment with two parallel sets of hinge knuckles"""
|
||||
def __call__(self, length, move=None):
|
||||
t = self.thickness
|
||||
w = self.servo.hinge_width()
|
||||
l = max(4*self.thickness, length - 2*t - 2*self.servo.height)
|
||||
|
||||
th = max(2 * self.servo._edges["m"].spacing() + l,
|
||||
2*w + 4*t + self.spacing)
|
||||
tw = 5 * (w + 2*self.thickness + self.spacing)
|
||||
|
||||
if self.move(tw, th, move, True):
|
||||
return
|
||||
|
||||
iw = (0, 3, 4, 7)
|
||||
e = self.servo.edges
|
||||
self.rectangularWall(w, l, e("mFmF"), ignore_widths=iw, move="right")
|
||||
self.rectangularWall(w, l, e("MFMF"), ignore_widths=iw, move="right")
|
||||
self.rectangularWall(w, l, "FfFf", move="right")
|
||||
self.rectangularWall(w, l, "FfFf", move="right")
|
||||
self.rectangularWall(w, w, "ffff", callback=[
|
||||
lambda: self.hole(w/2, w/2, 6)], move="up")
|
||||
self.rectangularWall(w, w, "ffff", callback=[
|
||||
lambda: self.hole(w/2, w/2, 6)], move="")
|
||||
|
||||
self.move(tw, th, move)
|
||||
|
||||
class RobotArmUu(_RobotArm):
|
||||
"""Robot arm segment with two orthogonal sets of hinge knuckles"""
|
||||
def __call__(self, length, move=None):
|
||||
t = self.thickness
|
||||
w = self.servo.hinge_width()
|
||||
w2 = self.servo2.hinge_width()
|
||||
l = max(4*self.thickness, length - 2*t - 2*self.servo.height)
|
||||
|
||||
th = max(self.thickness + self.servo._edges["m"].spacing() + l,
|
||||
2*w + self.thickness + 4 * self.edges["f"].spacing())
|
||||
tw = 5 * (w + 2*self.thickness + self.spacing)
|
||||
|
||||
if self.move(tw, th, move, True):
|
||||
return
|
||||
iw = (3, 4)
|
||||
e = self.servo.edges
|
||||
self.rectangularWall(w2, l, e("nfFf"), move="right")
|
||||
self.rectangularWall(w2, l, e("NfFf"), move="right")
|
||||
self.rectangularWall(w, l, e("FFmF"), ignore_widths=iw, move="right")
|
||||
self.rectangularWall(w, l, e("FFMF"), ignore_widths=iw, move="right")
|
||||
self.rectangularWall(w2, w, "ffff", callback=[
|
||||
lambda: self.hole(w2/2, w/2, 6)], move="up")
|
||||
self.rectangularWall(w2, w, "ffff", callback=[
|
||||
lambda: self.hole(w2/2, w/2, 6)], move="")
|
||||
|
||||
self.move(tw, th, move)
|
||||
|
||||
class RobotArmMu(_RobotArm):
|
||||
"""Robot arm segment with a servo and an orthogonal sets of hinge knuckles"""
|
||||
def __call__(self, length, move=None):
|
||||
t = self.thickness
|
||||
w = self.servo.height
|
||||
w2 = self.servo2.hinge_width()
|
||||
l = max(self.servo.length, length + self.servo.axle_pos - self.servo.height - t)
|
||||
|
||||
th = max(t + l + self.servo2._edges["m"].spacing(),
|
||||
w + w2 + self.thickness + 4 * self.edges["f"].spacing())
|
||||
tw = 5 * (w + 2*self.thickness + self.spacing)
|
||||
|
||||
if self.move(tw, th, move, True):
|
||||
return
|
||||
|
||||
e = self.servo2.edges
|
||||
iw = (3, 4)
|
||||
self.rectangularWall(w2, l, "FfFf", callback=[
|
||||
lambda:self.servo.top(w2/2)], move="right")
|
||||
self.rectangularWall(w2, l, "FfFf", callback=[
|
||||
lambda:self.servo.bottom(w2/2)], move="right")
|
||||
self.rectangularWall(w, l, e("FFmF"), ignore_widths=iw, move="right")
|
||||
self.rectangularWall(w, l, e("FFMF"), ignore_widths=iw, move="right")
|
||||
self.rectangularWall(w2, w, "ffff", callback=[
|
||||
lambda:self.servo.front(w2/2)], move="up")
|
||||
self.rectangularWall(w2, w, "ffff", callback=[
|
||||
lambda: self.hole(w2/2, w/2, 6)], move="")
|
||||
|
||||
self.move(tw, th, move)
|
||||
|
||||
# class RobotArmMU(_RobotArm):
|
|
@ -0,0 +1,120 @@
|
|||
import boxes.vectors
|
||||
import math
|
||||
|
||||
class EyeEdge(boxes.edges.FingerHoleEdge):
|
||||
|
||||
char = "m"
|
||||
|
||||
def __init__(self, boxes, servo, fingerHoles=None, driven=False,
|
||||
outset=False, **kw):
|
||||
self.servo = servo
|
||||
self.outset = outset
|
||||
self.driven = driven
|
||||
super(EyeEdge, self).__init__(boxes, fingerHoles, **kw)
|
||||
|
||||
def __call__(self, length, bedBolts=None, bedBoltSettings=None, **kw):
|
||||
t = self.fingerHoles.settings.thickness
|
||||
dist = self.fingerHoles.settings.edge_width
|
||||
|
||||
pos_axle = self.servo.hinge_depth()
|
||||
self.ctx.save()
|
||||
self.hole(length/2.0, -pos_axle,
|
||||
self.servo.axle/2.0 if self.driven else
|
||||
self.servo.servo_axle/2.0)
|
||||
if self.outset:
|
||||
self.fingerHoles(t, self.thickness / 2, length-2*t, 0)
|
||||
else:
|
||||
self.fingerHoles(0, self.thickness / 2, length, 0)
|
||||
self.ctx.restore()
|
||||
r = self.servo.servo_axle * 2
|
||||
a, l = boxes.vectors.tangent(length/2, pos_axle, r)
|
||||
angle = math.degrees(a)
|
||||
self.polyline(0, -angle, l, (2*angle, r), l, -angle, 0)
|
||||
|
||||
def startwidth(self):
|
||||
return self.fingerHoles.settings.thickness
|
||||
|
||||
def margin(self):
|
||||
return self.servo.hinge_depth() + self.fingerHoles.settings.thickness + self.servo.servo_axle * 2
|
||||
|
||||
def buildEdges(boxes, servo, chars="mMnN"):
|
||||
result = {}
|
||||
for n, char in enumerate(chars):
|
||||
e = EyeEdge(boxes, servo, outset=(n<2), driven=(n % 2))
|
||||
e.char = char
|
||||
result[char] = e
|
||||
return result
|
||||
|
||||
class ServoArg:
|
||||
|
||||
def __init__(self, includenone=False):
|
||||
self.servos = ["Servo9g"]
|
||||
if includenone:
|
||||
self.robotarms[0:0] = ["none"]
|
||||
|
||||
def __call__(self, arg):
|
||||
return str(arg)
|
||||
|
||||
def choices(self):
|
||||
return [name for name, descr in self.robotarms]
|
||||
|
||||
def html(self, name, default):
|
||||
options = "\n".join(
|
||||
("""<option value="%s"%s>%s</option>""" %
|
||||
(name, ' selected="selected"' if name == default else "",
|
||||
name) for name in self.servos))
|
||||
return """<select name="%s" size="1">\n%s</select>\n""" % (name, options)
|
||||
|
||||
|
||||
class Servo:
|
||||
def __init__(self, boxes, axle=3):
|
||||
self.boxes = boxes
|
||||
self.axle = axle
|
||||
self._edges = buildEdges(boxes, self)
|
||||
|
||||
def edges(self, edges):
|
||||
return [self._edges.get(e, e) for e in edges]
|
||||
|
||||
class Servo9g(Servo):
|
||||
|
||||
height = 22.5
|
||||
length = 28.0 # one tab in the wall
|
||||
width = 12.0
|
||||
axle_pos = 6.0
|
||||
servo_axle = 4.6 # 6.9 for servo arm
|
||||
|
||||
def top(self, x=0.0, y=0.0, angle=90.0):
|
||||
self.boxes.moveTo(x, y, angle)
|
||||
self.boxes.hole(6, 0, 6)
|
||||
self.boxes.hole(12, 0, 3)
|
||||
|
||||
def bottom(self, x=0.0, y=0.0, angle=90.0):
|
||||
self.boxes.moveTo(x, y, angle)
|
||||
self.boxes.hole(6, 0, self.axle/2.0)
|
||||
|
||||
def front(self, x=0.0, y=0.0, angle=90.0):
|
||||
self.boxes.moveTo(x, y, angle)
|
||||
self.boxes.rectangularHole(5.4, 0, 2.4, 12)
|
||||
self.boxes.rectangularHole(17, 0, 4, 16)
|
||||
|
||||
def hinge_width(self):
|
||||
return self.height + self.boxes.thickness + 4.5
|
||||
|
||||
def hinge_depth(self):
|
||||
return self.height # XXX
|
||||
|
||||
class Servo9gt(Servo9g):
|
||||
height = 35
|
||||
|
||||
def top(self, x=0.0, y=0.0, angle=90.0):
|
||||
self.boxes.moveTo(x, y, angle)
|
||||
self.boxes.hole(6, 0, 6)
|
||||
self.boxes.hole(12, 0, 5)
|
||||
|
||||
def bottom(self, x=0.0, y=0.0, angle=90.0):
|
||||
self.boxes.moveTo(x, y, angle)
|
||||
self.boxes.hole(6, 0, self.axle)
|
||||
|
||||
def front(self, x=0.0, y=0.0, angle=90.0):
|
||||
self.boxes.moveTo(x, y, angle)
|
||||
self.boxes.rectangularHole(5.4, 0, 2.4, 12)
|
Loading…
Reference in New Issue