302 lines
11 KiB
Python
302 lines
11 KiB
Python
"""Tests for the standard-parts library bearing assemblies."""
|
|
|
|
import inspect
|
|
import json
|
|
import unittest
|
|
|
|
import simplecadapi as scad
|
|
|
|
|
|
class TestStdBearingSurface(unittest.TestCase):
|
|
def test_preferred_nested_std_export_surface(self):
|
|
assembly = scad.std.bearing.make_ball_bearing_rassembly(
|
|
8.0,
|
|
22.0,
|
|
7.0,
|
|
3.5,
|
|
7,
|
|
0.05,
|
|
0.0,
|
|
"bearing_surface_test",
|
|
)
|
|
|
|
self.assertIsInstance(assembly, scad.Assembly)
|
|
|
|
def test_public_bearing_factories_follow_make_rtype_naming(self):
|
|
factory_names = [
|
|
name for name in scad.std.bearing.__all__
|
|
if callable(getattr(scad.std.bearing, name, None))
|
|
]
|
|
|
|
self.assertGreater(len(factory_names), 0)
|
|
for name in factory_names:
|
|
self.assertTrue(name.startswith("make_"), name)
|
|
self.assertIn("_r", name, name)
|
|
|
|
def test_ball_bearing_signature_has_no_keyword_only_separator(self):
|
|
signature = inspect.signature(scad.std.bearing.make_ball_bearing_rassembly)
|
|
|
|
self.assertNotIn(
|
|
inspect.Parameter.KEYWORD_ONLY,
|
|
{parameter.kind for parameter in signature.parameters.values()},
|
|
)
|
|
|
|
|
|
class TestBallBearingAssembly(unittest.TestCase):
|
|
def test_basic_ball_bearing_assembly(self):
|
|
with scad.GraphSession() as session:
|
|
bearing = scad.std.bearing.make_ball_bearing_rassembly(
|
|
8.0,
|
|
22.0,
|
|
7.0,
|
|
3.5,
|
|
7,
|
|
0.05,
|
|
0.05,
|
|
"bearing_basic_test",
|
|
30.0,
|
|
)
|
|
preview = scad.make_compound_from_assembly_rcompound(bearing)
|
|
model_json = scad.export_model_json(session)
|
|
|
|
meta = bearing.get_metadata("std.bearing.ball_bearing")
|
|
self.assertEqual(meta["ball_count"], 7)
|
|
self.assertEqual(meta["outer_component_id"], "outer_ring")
|
|
self.assertEqual(meta["inner_component_id"], "inner_ring")
|
|
self.assertEqual(len(meta["ball_component_ids"]), 7)
|
|
self.assertIn("ball_00", meta["ball_component_ids"])
|
|
|
|
self.assertEqual(
|
|
bearing.component_ids(),
|
|
(
|
|
"outer_ring",
|
|
"inner_ring",
|
|
"ball_00",
|
|
"ball_01",
|
|
"ball_02",
|
|
"ball_03",
|
|
"ball_04",
|
|
"ball_05",
|
|
"ball_06",
|
|
),
|
|
)
|
|
self.assertEqual(bearing.constraint_ids(), ("inner_outer_revolute",))
|
|
self.assertEqual(bearing.connector_ids(), ("outer_axis", "inner_axis"))
|
|
self.assertEqual(bearing.grounded_component_ids, ())
|
|
constraint = bearing.get_constraint("inner_outer_revolute")
|
|
self.assertEqual(constraint.constraint_kind, "revolute")
|
|
self.assertEqual(constraint.connector_a.component_id, "outer_ring")
|
|
self.assertEqual(constraint.connector_b.component_id, "inner_ring")
|
|
self.assertEqual(constraint.connector_a.connector_id, "axis")
|
|
self.assertEqual(constraint.connector_b.connector_id, "axis")
|
|
self.assertEqual(constraint.drive_angle_degrees, 30.0)
|
|
|
|
outer_part = bearing.get_component("outer_ring").item
|
|
inner_part = bearing.get_component("inner_ring").item
|
|
ball_part = bearing.get_component("ball_00").item
|
|
self.assertEqual(outer_part.connector_ids(), ("axis",))
|
|
self.assertEqual(inner_part.connector_ids(), ("axis",))
|
|
self.assertEqual(ball_part.connector_ids(), ())
|
|
self.assertGreater(outer_part.body.get_volume(), 0.0)
|
|
self.assertGreater(inner_part.body.get_volume(), 0.0)
|
|
|
|
outer_ring_meta = outer_part.body.get_metadata("std.bearing.ring")
|
|
inner_ring_meta = inner_part.body.get_metadata("std.bearing.ring")
|
|
ball_radius = meta["ball_diameter"] / 2.0
|
|
self.assertAlmostEqual(
|
|
outer_ring_meta["inner_radius"],
|
|
meta["ball_pitch_radius"] + ball_radius * 0.75,
|
|
)
|
|
self.assertAlmostEqual(
|
|
inner_ring_meta["outer_radius"],
|
|
meta["ball_pitch_radius"] - ball_radius * 0.75,
|
|
)
|
|
self.assertLess(outer_ring_meta["raceway_mouth_z"], outer_ring_meta["groove_radius"])
|
|
self.assertLess(inner_ring_meta["raceway_mouth_z"], inner_ring_meta["groove_radius"])
|
|
|
|
from OCP.BRepAdaptor import BRepAdaptor_Surface
|
|
from OCP.GeomAbs import GeomAbs_Sphere, GeomAbs_Torus
|
|
|
|
self.assertTrue(
|
|
any(
|
|
BRepAdaptor_Surface(face.wrapped).GetType() == GeomAbs_Torus
|
|
for face in outer_part.body.get_faces()
|
|
)
|
|
)
|
|
self.assertTrue(
|
|
any(
|
|
BRepAdaptor_Surface(face.wrapped).GetType() == GeomAbs_Torus
|
|
for face in inner_part.body.get_faces()
|
|
)
|
|
)
|
|
self.assertTrue(
|
|
all(
|
|
BRepAdaptor_Surface(face.wrapped).GetType() == GeomAbs_Sphere
|
|
for face in ball_part.body.get_faces()
|
|
)
|
|
)
|
|
|
|
self.assertEqual(len(preview.get_solids()), 9)
|
|
self.assertGreater(preview.get_volume(), 0.0)
|
|
self.assertTrue(scad.measure_constraint_residual_rconstraintresidual(
|
|
bearing,
|
|
"inner_outer_revolute",
|
|
).within_tolerance)
|
|
|
|
payload = json.loads(model_json)
|
|
ops = [node["op"] for node in payload["graph"]["nodes"]]
|
|
self.assertIn("make_sphere_rsolid", ops)
|
|
self.assertEqual(ops.count("make_three_point_arc_redge"), 2)
|
|
self.assertEqual(ops.count("make_revolve_rsolid"), 2)
|
|
self.assertIn("make_revolute_constraint_rassembly", ops)
|
|
self.assertEqual(ops.count("make_forward_connector_rassembly"), 2)
|
|
self.assertIn("make_compound_from_assembly_rcompound", ops)
|
|
stdlib_nodes = [
|
|
node
|
|
for node in payload["graph"]["nodes"]
|
|
if node["op"] != "make_compound_from_assembly_rcompound"
|
|
]
|
|
self.assertTrue(all("topo_delta" not in node for node in stdlib_nodes))
|
|
|
|
def test_inferred_ball_count_is_recorded(self):
|
|
bearing = scad.std.bearing.make_ball_bearing_rassembly(
|
|
8.0,
|
|
22.0,
|
|
7.0,
|
|
3.5,
|
|
)
|
|
meta = bearing.get_metadata("std.bearing.ball_bearing")
|
|
|
|
self.assertGreaterEqual(meta["ball_count"], 3)
|
|
self.assertEqual(len(meta["ball_component_ids"]), meta["ball_count"])
|
|
|
|
def test_external_constraints_can_bind_to_internal_connectors(self):
|
|
bearing = scad.std.bearing.make_ball_bearing_rassembly(
|
|
8.0,
|
|
22.0,
|
|
7.0,
|
|
3.5,
|
|
7,
|
|
0.05,
|
|
0.0,
|
|
"bearing_bind_test",
|
|
)
|
|
|
|
shaft = scad.make_cylinder_rsolid(
|
|
radius=3.8,
|
|
height=14.0,
|
|
bottom_face_center=(0.0, 0.0, -7.0),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
shaft_part = scad.make_part_rpart("shaft", shaft)
|
|
top_face = max(
|
|
shaft.get_faces(),
|
|
key=lambda face: face.get_center().z if face.get_normal_at().z > 0.7 else -999.0,
|
|
)
|
|
shaft_axis = scad.make_face_connector_rconnector("axis", top_face)
|
|
shaft_part = scad.add_connector_rpart(shaft_part, shaft_axis)
|
|
bearing = scad.add_component_rassembly(
|
|
bearing,
|
|
shaft_part,
|
|
component_id="shaft",
|
|
placement=scad.identity_placement_rplacement(),
|
|
)
|
|
bearing = scad.add_fixed_constraint_rassembly(
|
|
bearing,
|
|
"shaft_to_inner_ring",
|
|
scad.make_connector_ref_rconnectorref("inner_ring", "axis"),
|
|
scad.make_connector_ref_rconnectorref("shaft", "axis"),
|
|
)
|
|
bearing = scad.ground_component_rassembly(
|
|
assembly=bearing,
|
|
component_id="outer_ring",
|
|
)
|
|
bearing = scad.solve_assembly_constraints_rassembly(bearing, strict=False)
|
|
|
|
self.assertIn("shaft", bearing.component_ids())
|
|
self.assertTrue(scad.measure_constraint_residual_rconstraintresidual(
|
|
bearing,
|
|
"shaft_to_inner_ring",
|
|
).within_tolerance)
|
|
|
|
def test_parent_assembly_can_bind_to_bearing_forwarded_connectors(self):
|
|
bearing = scad.std.bearing.make_ball_bearing_rassembly(
|
|
8.0,
|
|
22.0,
|
|
7.0,
|
|
3.5,
|
|
7,
|
|
0.05,
|
|
0.0,
|
|
"bearing_parent_bind_test",
|
|
)
|
|
shaft = scad.make_cylinder_rsolid(
|
|
radius=3.8,
|
|
height=14.0,
|
|
bottom_face_center=(0.0, 0.0, -7.0),
|
|
axis=(0.0, 0.0, 1.0),
|
|
)
|
|
shaft_part = scad.make_part_rpart("parent_bind_shaft", shaft)
|
|
top_face = max(
|
|
shaft.get_faces(),
|
|
key=lambda face: face.get_center().z if face.get_normal_at().z > 0.7 else -999.0,
|
|
)
|
|
shaft_axis = scad.make_face_connector_rconnector("axis", top_face)
|
|
shaft_part = scad.add_connector_rpart(shaft_part, shaft_axis)
|
|
parent = scad.make_assembly_rassembly("bearing_parent_bind_asm")
|
|
parent = scad.add_component_rassembly(
|
|
parent,
|
|
shaft_part,
|
|
component_id="shaft",
|
|
placement=scad.identity_placement_rplacement(),
|
|
)
|
|
parent = scad.add_component_rassembly(
|
|
parent,
|
|
bearing,
|
|
component_id="bearing",
|
|
placement=scad.identity_placement_rplacement(),
|
|
)
|
|
parent = scad.ground_component_rassembly(parent, "shaft")
|
|
parent = scad.add_fixed_constraint_rassembly(
|
|
parent,
|
|
"shaft_to_bearing_inner_axis",
|
|
scad.make_connector_ref_rconnectorref("shaft", "axis"),
|
|
scad.make_connector_ref_rconnectorref("bearing", "inner_axis"),
|
|
)
|
|
parent = scad.solve_assembly_constraints_rassembly(parent)
|
|
|
|
self.assertTrue(scad.measure_constraint_residual_rconstraintresidual(
|
|
parent,
|
|
"shaft_to_bearing_inner_axis",
|
|
).within_tolerance)
|
|
|
|
def test_invalid_params(self):
|
|
with self.assertRaises(Exception):
|
|
scad.std.bearing.make_ball_bearing_rassembly(22.0, 8.0, 7.0, 3.5)
|
|
with self.assertRaises(Exception):
|
|
scad.std.bearing.make_ball_bearing_rassembly(8.0, 22.0, 3.0, 3.5)
|
|
with self.assertRaises(Exception):
|
|
scad.std.bearing.make_ball_bearing_rassembly(8.0, 22.0, 7.0, 8.0)
|
|
with self.assertRaises(Exception):
|
|
scad.std.bearing.make_ball_bearing_rassembly(
|
|
8.0,
|
|
22.0,
|
|
7.0,
|
|
3.5,
|
|
100,
|
|
)
|
|
with self.assertRaises(Exception):
|
|
scad.std.bearing.make_ball_bearing_rassembly(
|
|
8.0,
|
|
22.0,
|
|
7.0,
|
|
3.5,
|
|
7,
|
|
0.05,
|
|
2.0,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|