"""EL01 lab tests for hwe/core/arm.py (step 6). These build real CAD, so they take a few seconds."""importmathimportunittestfrom_implimportloadfromhwe.unitsimportQ_arm_mod=load("arm")WORKED=dict(length=Q_(100,"mm"),width=Q_(12,"mm"),thickness=Q_(5,"mm"),pad_size=Q_(28,"mm"),motor_hole_spacing=Q_(16,"mm"),motor_hole_diameter=Q_(3.2,"mm"),center_hole_diameter=Q_(8,"mm"),frame_hole_diameter=Q_(3.2,"mm"),frame_hole_inset=Q_(6,"mm"),frame_hole_pitch=Q_(16,"mm"))OTHER=dict(length=Q_(0.13,"m"),width=Q_(1.4,"cm"),thickness=Q_(4,"mm"),pad_size=Q_(30,"mm"),motor_hole_spacing=Q_(19,"mm"),motor_hole_diameter=Q_(3.2,"mm"),center_hole_diameter=Q_(9,"mm"),frame_hole_diameter=Q_(3.2,"mm"),frame_hole_inset=Q_(7,"mm"),frame_hole_pitch=Q_(20,"mm"))defhand_volume_mm3(p):"""The test's own geometry, in plain millimetres (independent of your code)."""mm={k:v.to("mm").mfork,vinp.items()}L,w,t,a=mm["length"],mm["width"],mm["thickness"],mm["pad_size"]area=L*w+a*a-(a/2)*wholes=math.pi/4*(4*mm["motor_hole_diameter"]**2+mm["center_hole_diameter"]**2+2*mm["frame_hole_diameter"]**2)returnt*(area-holes)classStep6Arm(unittest.TestCase):@classmethoddefsetUpClass(cls):cls.worked=arm_mod.arm(**WORKED)cls.other=arm_mod.arm(**OTHER)deftest_hand_volume_of_the_worked_arm(self):# 5 x (100x12 + 28x28 - 14x12 - pi/4 (4x3.2^2 + 8^2 + 2x3.2^2)) = 8587.398 mm^3v=arm_mod.arm_volume_by_hand(**WORKED).to("mm^3").mself.assertAlmostEqual(v,hand_volume_mm3(WORKED),delta=1e-6)self.assertAlmostEqual(v,8587.398,delta=1e-3)deftest_hand_volume_mixed_units(self):self.assertAlmostEqual(arm_mod.arm_volume_by_hand(**OTHER).to("mm^3").m,hand_volume_mm3(OTHER),delta=1e-6)deftest_cad_volume_matches_hand_geometry(self):self.assertAlmostEqual(self.worked.volume,hand_volume_mm3(WORKED),delta=1e-6*hand_volume_mm3(WORKED))deftest_cad_volume_matches_with_other_units(self):# 0.13 m and 1.4 cm must reach build123d as 130 mm and 14 mmself.assertAlmostEqual(self.other.volume,hand_volume_mm3(OTHER),delta=1e-6*hand_volume_mm3(OTHER))deftest_bounding_box(self):# x from 0 to length + pad/2 = 114; y spans the pad, 28; z spans the thickness, 5 (mm)size=self.worked.bounding_box().sizeself.assertAlmostEqual(size.X,114.0,delta=1e-6)self.assertAlmostEqual(size.Y,28.0,delta=1e-6)self.assertAlmostEqual(size.Z,5.0,delta=1e-6)deftest_frame_end_starts_at_x_zero(self):box=self.worked.bounding_box()self.assertAlmostEqual(box.min.X,0.0,delta=1e-6)self.assertAlmostEqual(box.min.Z,0.0,delta=1e-6)deftest_one_solid_with_seven_holes(self):self.assertEqual(len(self.worked.solids()),1)holes=[fforfinself.worked.faces()iff.geom_type.name=="CYLINDER"]self.assertEqual(len(holes),7)deftest_motor_holes_are_on_the_pattern(self):# Each motor hole's axis is 8 mm (half of 16) from the motor centre (100, 0) in x and in y.# A hole's wall is a cylinder; the centre of its bounding box lies on the hole's axis.frombuild123dimportCenterOfcentres=[]forfinself.worked.faces():iff.geom_type.name=="CYLINDER":c=f.center(CenterOf.BOUNDING_BOX)centres.append((round(c.X,3),round(c.Y,3)))forx,yin[(92.0,-8.0),(92.0,8.0),(108.0,-8.0),(108.0,8.0),(100.0,0.0),(6.0,0.0),(22.0,0.0)]:self.assertIn((x,y),centres)if__name__=="__main__":unittest.main()