feat: Optional actuator on wrist
This commit is contained in:
parent
7371333a84
commit
ddeaf1194f
|
@ -300,6 +300,8 @@ LINEAR_ACTUATOR_10 = LinearActuator(
|
||||||
back_hole_ext=4.5/2,
|
back_hole_ext=4.5/2,
|
||||||
segment1_length=30.0,
|
segment1_length=30.0,
|
||||||
segment2_length=30.0,
|
segment2_length=30.0,
|
||||||
|
segment1_width=15.0,
|
||||||
|
segment2_width=21.0,
|
||||||
)
|
)
|
||||||
LINEAR_ACTUATOR_HEX_NUT = HexNut(
|
LINEAR_ACTUATOR_HEX_NUT = HexNut(
|
||||||
mass=0.8,
|
mass=0.8,
|
||||||
|
|
|
@ -882,8 +882,8 @@ class ElbowJoint(Model):
|
||||||
|
|
||||||
angle_neutral: float = 30.0
|
angle_neutral: float = 30.0
|
||||||
|
|
||||||
actuator: LinearActuator
|
actuator: Optional[LinearActuator]
|
||||||
flexor: Flexor = None
|
flexor: Optional[Flexor] = None
|
||||||
# Rotates the entire flexor
|
# Rotates the entire flexor
|
||||||
flexor_offset_angle: float = 0
|
flexor_offset_angle: float = 0
|
||||||
# Rotates the surface of the mount
|
# Rotates the surface of the mount
|
||||||
|
@ -893,6 +893,7 @@ class ElbowJoint(Model):
|
||||||
assert self.child_arm_radius > self.disk_joint.radius_housing
|
assert self.child_arm_radius > self.disk_joint.radius_housing
|
||||||
assert self.parent_arm_radius > self.disk_joint.radius_housing
|
assert self.parent_arm_radius > self.disk_joint.radius_housing
|
||||||
self.disk_joint.tongue_length = self.child_arm_radius - self.disk_joint.radius_disk - self.lip_thickness / 2
|
self.disk_joint.tongue_length = self.child_arm_radius - self.disk_joint.radius_disk - self.lip_thickness / 2
|
||||||
|
if self.actuator:
|
||||||
self.flexor = Flexor(
|
self.flexor = Flexor(
|
||||||
actuator=self.actuator,
|
actuator=self.actuator,
|
||||||
motion_span=self.motion_span
|
motion_span=self.motion_span
|
||||||
|
@ -990,8 +991,9 @@ class ElbowJoint(Model):
|
||||||
Cq.Assembly()
|
Cq.Assembly()
|
||||||
.add(self.disk_joint.disk(), name="disk", loc=Cq.Location((0, 0, -dz)))
|
.add(self.disk_joint.disk(), name="disk", loc=Cq.Location((0, 0, -dz)))
|
||||||
.add(self.lip().cut(disk_cut), name="lip", loc=loc_disk.inverse * loc_lip)
|
.add(self.lip().cut(disk_cut), name="lip", loc=loc_disk.inverse * loc_lip)
|
||||||
.add(self.actuator_mount(), name="act", loc=self.actuator_mount_loc(child=True))
|
|
||||||
)
|
)
|
||||||
|
if self.flexor:
|
||||||
|
result.add(self.actuator_mount(), name="act", loc=self.actuator_mount_loc(child=True))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@target(name="parent-lower")
|
@target(name="parent-lower")
|
||||||
|
@ -1040,12 +1042,15 @@ class ElbowJoint(Model):
|
||||||
Cq.Location((0, 0, 0), (0, 1, 0), 90))
|
Cq.Location((0, 0, 0), (0, 1, 0), 90))
|
||||||
.add(connector, name="connector",
|
.add(connector, name="connector",
|
||||||
loc=loc_net_housing.inverse * axial_offset)
|
loc=loc_net_housing.inverse * axial_offset)
|
||||||
.add(self.actuator_mount(),
|
|
||||||
name="act", loc=self.actuator_mount_loc(child=False))
|
|
||||||
#.constrain("housing", "Fixed")
|
#.constrain("housing", "Fixed")
|
||||||
#.constrain("connector", "Fixed")
|
#.constrain("connector", "Fixed")
|
||||||
#.solve()
|
#.solve()
|
||||||
)
|
)
|
||||||
|
if self.flexor:
|
||||||
|
result.add(
|
||||||
|
self.actuator_mount(),
|
||||||
|
name="act",
|
||||||
|
loc=self.actuator_mount_loc(child=False))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@assembly()
|
@assembly()
|
||||||
|
|
|
@ -51,7 +51,7 @@ class WingProfile(Model):
|
||||||
disk_joint=DiskJoint(
|
disk_joint=DiskJoint(
|
||||||
movement_angle=55,
|
movement_angle=55,
|
||||||
),
|
),
|
||||||
hole_diam=6.0,
|
hole_diam=4.0,
|
||||||
angle_neutral=15.0,
|
angle_neutral=15.0,
|
||||||
actuator=LINEAR_ACTUATOR_50,
|
actuator=LINEAR_ACTUATOR_50,
|
||||||
flexor_offset_angle=-15,
|
flexor_offset_angle=-15,
|
||||||
|
@ -65,13 +65,14 @@ class WingProfile(Model):
|
||||||
radius_disk=13.0,
|
radius_disk=13.0,
|
||||||
radius_housing=15.0,
|
radius_housing=15.0,
|
||||||
),
|
),
|
||||||
hole_pos=[10, 20],
|
hole_pos=[10],
|
||||||
lip_length=50,
|
lip_length=30,
|
||||||
child_arm_radius=23.0,
|
child_arm_radius=23.0,
|
||||||
parent_arm_radius=30.0,
|
parent_arm_radius=30.0,
|
||||||
hole_diam=4.0,
|
hole_diam=4.0,
|
||||||
angle_neutral=-30.0,
|
angle_neutral=-30.0,
|
||||||
actuator=LINEAR_ACTUATOR_10,
|
# The left side wrist is too small for an actuator to work
|
||||||
|
actuator=None, #LINEAR_ACTUATOR_10,
|
||||||
))
|
))
|
||||||
# Distance between the two spacers on the elbow, halved
|
# Distance between the two spacers on the elbow, halved
|
||||||
wrist_h2: float = 5.0
|
wrist_h2: float = 5.0
|
||||||
|
@ -90,6 +91,7 @@ class WingProfile(Model):
|
||||||
wrist_rotate: float = -30.0
|
wrist_rotate: float = -30.0
|
||||||
# Position of the elbow axle with 0 being bottom and 1 being top (flipped on the left side)
|
# Position of the elbow axle with 0 being bottom and 1 being top (flipped on the left side)
|
||||||
elbow_axle_pos: float = 0.3
|
elbow_axle_pos: float = 0.3
|
||||||
|
wrist_axle_pos: float = 0.0
|
||||||
|
|
||||||
# False for the right side, True for the left side
|
# False for the right side, True for the left side
|
||||||
flip: bool
|
flip: bool
|
||||||
|
@ -103,9 +105,8 @@ class WingProfile(Model):
|
||||||
self.elbow_axle_pos = 1 - self.elbow_axle_pos
|
self.elbow_axle_pos = 1 - self.elbow_axle_pos
|
||||||
self.elbow_axle_loc = self.elbow_bot_loc * Cq.Location.from2d(0, self.elbow_height * self.elbow_axle_pos)
|
self.elbow_axle_loc = self.elbow_bot_loc * Cq.Location.from2d(0, self.elbow_height * self.elbow_axle_pos)
|
||||||
if self.flip:
|
if self.flip:
|
||||||
self.wrist_axle_loc = self.wrist_bot_loc * Cq.Location.from2d(0, self.wrist_height / 2)
|
self.wrist_axle_pos = 1 - self.wrist_axle_pos
|
||||||
else:
|
self.wrist_axle_loc = self.wrist_bot_loc * Cq.Location.from2d(0, self.wrist_height * self.wrist_axle_pos)
|
||||||
self.wrist_axle_loc = self.wrist_bot_loc
|
|
||||||
|
|
||||||
assert self.elbow_joint.total_thickness < min(self.s1_thickness, self.s2_thickness)
|
assert self.elbow_joint.total_thickness < min(self.s1_thickness, self.s2_thickness)
|
||||||
assert self.wrist_joint.total_thickness < min(self.s2_thickness, self.s3_thickness)
|
assert self.wrist_joint.total_thickness < min(self.s2_thickness, self.s3_thickness)
|
||||||
|
@ -126,7 +127,8 @@ class WingProfile(Model):
|
||||||
"""
|
"""
|
||||||
s3 does not need to duck under s2
|
s3 does not need to duck under s2
|
||||||
"""
|
"""
|
||||||
return self.s1_thickness - 2 * self.panel_thickness
|
extra = 2 * self.panel_thickness if self.flip else 0
|
||||||
|
return self.s1_thickness - 2 * self.panel_thickness - extra
|
||||||
|
|
||||||
@submodel(name="shoulder-joint")
|
@submodel(name="shoulder-joint")
|
||||||
def submodel_shoulder_joint(self) -> Model:
|
def submodel_shoulder_joint(self) -> Model:
|
||||||
|
@ -395,7 +397,7 @@ class WingProfile(Model):
|
||||||
for p in points
|
for p in points
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
def _joint_extension_profile(
|
def _child_joint_extension_profile(
|
||||||
self,
|
self,
|
||||||
axle_loc: Cq.Location,
|
axle_loc: Cq.Location,
|
||||||
radius: float,
|
radius: float,
|
||||||
|
@ -640,8 +642,10 @@ class WingProfile(Model):
|
||||||
return extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
|
return extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
|
||||||
@target(name="profile-s2-bridge", kind=TargetKind.DXF)
|
@target(name="profile-s2-bridge", kind=TargetKind.DXF)
|
||||||
def profile_s2_bridge(self) -> Cq.Workplane:
|
def profile_s2_bridge(self) -> Cq.Workplane:
|
||||||
|
# FIXME: Leave some margin here so we can glue the panels
|
||||||
|
|
||||||
# Generates the extension profile, which is required on both sides
|
# Generates the extension profile, which is required on both sides
|
||||||
profile = self._joint_extension_profile(
|
profile = self._child_joint_extension_profile(
|
||||||
axle_loc=self.wrist_axle_loc,
|
axle_loc=self.wrist_axle_loc,
|
||||||
radius=self.wrist_height * (0.5 if self.flip else 1),
|
radius=self.wrist_height * (0.5 if self.flip else 1),
|
||||||
angle_span=self.wrist_joint.motion_span,
|
angle_span=self.wrist_joint.motion_span,
|
||||||
|
@ -881,24 +885,23 @@ class WingProfile(Model):
|
||||||
if "wrist" in parts:
|
if "wrist" in parts:
|
||||||
angle = self.wrist_joint.motion_span * elbow_wrist_deflection
|
angle = self.wrist_joint.motion_span * elbow_wrist_deflection
|
||||||
result.add(self.wrist_joint.assembly(angle=angle), name="wrist")
|
result.add(self.wrist_joint.assembly(angle=angle), name="wrist")
|
||||||
|
wrist_n_holes = len(self.wrist_joint.hole_pos)
|
||||||
if "s2" in parts and "wrist" in parts:
|
if "s2" in parts and "wrist" in parts:
|
||||||
# Mounted backwards to bend in other direction
|
# Mounted backwards to bend in other direction
|
||||||
|
for i in range(wrist_n_holes):
|
||||||
(
|
(
|
||||||
result
|
result
|
||||||
.constrain("s2/wrist_top?conn0", f"wrist/parent_upper/lip?conn_{tag_bot}0", "Plane")
|
.constrain(f"s2/wrist_top?conn{i}", f"wrist/parent_upper/lip?conn_{tag_bot}{i}", "Plane")
|
||||||
.constrain("s2/wrist_top?conn1", f"wrist/parent_upper/lip?conn_{tag_bot}1", "Plane")
|
.constrain(f"s2/wrist_bot?conn{i}", f"wrist/parent_upper/lip?conn_{tag_top}{i}", "Plane")
|
||||||
.constrain("s2/wrist_bot?conn0", f"wrist/parent_upper/lip?conn_{tag_top}0", "Plane")
|
|
||||||
.constrain("s2/wrist_bot?conn1", f"wrist/parent_upper/lip?conn_{tag_top}1", "Plane")
|
|
||||||
)
|
)
|
||||||
if "s3" in parts:
|
if "s3" in parts:
|
||||||
result.add(self.assembly_s3(), name="s3")
|
result.add(self.assembly_s3(), name="s3")
|
||||||
if "s3" in parts and "wrist" in parts:
|
if "s3" in parts and "wrist" in parts:
|
||||||
|
for i in range(wrist_n_holes):
|
||||||
(
|
(
|
||||||
result
|
result
|
||||||
.constrain("s3/wrist_top?conn0", f"wrist/child/lip?conn_{tag_bot}0", "Plane")
|
.constrain(f"s3/wrist_top?conn{i}", f"wrist/child/lip?conn_{tag_bot}{i}", "Plane")
|
||||||
.constrain("s3/wrist_top?conn1", f"wrist/child/lip?conn_{tag_bot}1", "Plane")
|
.constrain(f"s3/wrist_bot?conn{i}", f"wrist/child/lip?conn_{tag_top}{i}", "Plane")
|
||||||
.constrain("s3/wrist_bot?conn0", f"wrist/child/lip?conn_{tag_top}0", "Plane")
|
|
||||||
.constrain("s3/wrist_bot?conn1", f"wrist/child/lip?conn_{tag_top}1", "Plane")
|
|
||||||
)
|
)
|
||||||
if len(parts) > 1:
|
if len(parts) > 1:
|
||||||
result.solve()
|
result.solve()
|
||||||
|
@ -1095,6 +1098,8 @@ class WingL(WingProfile):
|
||||||
arrow_height: float = 120.0
|
arrow_height: float = 120.0
|
||||||
|
|
||||||
flip: bool = True
|
flip: bool = True
|
||||||
|
elbow_axle_pos: float = 0.4
|
||||||
|
wrist_axle_pos: float = 0.5
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
assert self.wrist_height <= self.shoulder_joint.height
|
assert self.wrist_height <= self.shoulder_joint.height
|
||||||
|
|
Loading…
Reference in New Issue