From 0520ac90c128b44ea5bc8a033da9edfd73584153 Mon Sep 17 00:00:00 2001 From: Marius Unsel Date: Thu, 15 May 2025 02:39:43 +0200 Subject: [PATCH] inital commit --- README.md | 9 + SyncGrips.ipynb | 845 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 854 insertions(+) create mode 100644 README.md create mode 100644 SyncGrips.ipynb diff --git a/README.md b/README.md new file mode 100644 index 0000000..d40009c --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# CAD Files for Syncgrips BLE enabled Paralletes + +You can start a Docker container with the environment for creating CAD models using python and `build123d`. It spawns a jupyter notebook with integrated 3D renderer. + +```bash +docker run -it --rm -v :/home/cq -p 8888:8888 bwalter42/jupyter_cadquery:3.5.2 +``` + + diff --git a/SyncGrips.ipynb b/SyncGrips.ipynb new file mode 100644 index 0000000..59fae3e --- /dev/null +++ b/SyncGrips.ipynb @@ -0,0 +1,845 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "a0a9f44b-e8bc-49c4-b44d-4c327e51e6e8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting auto display for cadquery Workplane and Shape\n" + ] + } + ], + "source": [ + "import timeit\n", + "tic = timeit.default_timer()\n", + "\n", + "import cadquery as cq\n", + "from build123d import *\n", + "\n", + "from jupyter_cadquery import (\n", + " versions,\n", + " show, PartGroup, Part, \n", + " get_viewer, close_viewer, get_viewers, close_viewers, open_viewer, set_defaults, get_defaults, open_viewer,\n", + " get_pick,\n", + ")\n", + "from jupyter_cadquery.ocp_utils import webcol_to_cq\n", + "\n", + "from jupyter_cadquery.replay import replay, enable_replay, disable_replay\n", + "close_viewers()\n", + "set_defaults(\n", + " cad_width=640, \n", + " height=480, \n", + " viewer=\"syncgrips\"\n", + ")\n", + "cv = open_viewer(\"syncgrips\",\n", + " anchor=\"right\", \n", + " glass=True, \n", + " theme=\"dark\",\n", + " tools=True) # sets default viewer\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "13eee041-c6d5-4734-aedb-768b0be31bc4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "100% ⋮————————————————————————————————————————————————————————————⋮ (3/3) 1.10s\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sensor_width = 35\n", + "wall_thickness = 3\n", + "\n", + "w1 = sensor_width + 2* wall_thickness #sensor casing\n", + "w2 = 150 #sensor center \n", + "h = 85 # total height\n", + "h1 = 20 # sensor casing height\n", + "h2 = 12\n", + "h3 = 35# sensor casing + mpu height\n", + "r = 25 #grip radius\n", + "r1 = 8\n", + "locs = ((0,h+10), (-10,h-10),(10,h-10)) #locations of screws\n", + "handle_len = w2+w1-20-6\n", + "\n", + "\n", + "with BuildPart() as slim_cutout:\n", + " with BuildSketch(Plane.XY.offset(12)) as slim_sk:\n", + " Polygon((w2/2+10,50),(w2/2-w1+10,0),\\\n", + " (0,0),(0,60),(60,90),\\\n", + " align=Align.MIN)\n", + " mirror(about=Plane.YZ)\n", + " extrude(amount=-30)\n", + " chamfer(length=12, length2=20, objects=slim_cutout.edges().group_by(Axis.Z)[-1])\n", + "\n", + "slim_cutout2 = (Rotation(0,180,0)*Location((0,0,-w1))*slim_cutout.part)\n", + "\n", + "with BuildPart() as slim_cutout_mpu:\n", + " with BuildSketch(Plane.XY.offset(12)) as slim_sk_mpu:\n", + " with Locations((-w2/2-10,0)):\n", + " Polygon((w2/2-w1+10,0),(w2/2+10,50),\\\n", + " (60,90),(0,60),(-60,90),\\\n", + " (-w2/2-10,35),(-w2/2-w1/2+55,35),(-w2/2-w1/2+55,0),\n", + " align=Align.MIN)\n", + " #mirror(about=Plane.YZ)\n", + " raw_slim_cutout_mpu = extrude(amount=-30)\n", + " chamfer(length=12, length2=20, objects=slim_cutout_mpu.edges().group_by(Axis.Z)[-1][2])\n", + " chamfer(length2=12, length=20, objects=slim_cutout_mpu.edges().group_by(Axis.Z)[-1][2])\n", + " chamfer(length2=12, length=20, objects=slim_cutout_mpu.edges().group_by(Axis.Z)[-1][6])\n", + " chamfer(length2=12, length=10, objects=slim_cutout_mpu.edges().group_by(Axis.Z)[-1][2])\n", + "\n", + "with BuildPart() as slim_cutout2_mpu:\n", + " add(Location((0,0,47))*raw_slim_cutout_mpu)\n", + " chamfer(length=12, length2=20, objects=slim_cutout2_mpu.edges().group_by(Axis.Z)[0][2])\n", + " chamfer(length2=12, length=20, objects=slim_cutout2_mpu.edges().group_by(Axis.Z)[0][2])\n", + " chamfer(length2=12, length=20, objects=slim_cutout2_mpu.edges().group_by(Axis.Z)[0][6])\n", + " chamfer(length2=12, length=10, objects=slim_cutout2_mpu.edges().group_by(Axis.Z)[0][2])\n", + "\n", + "with BuildPart() as inner_cutout:\n", + " with BuildSketch(Plane.XY.offset(w1-10)) as handle_sk:\n", + " with Locations((0,h)):\n", + " Circle(r*2.4)\n", + " extrude(amount=30)\n", + " \n", + "with BuildPart() as screwholes:\n", + " with BuildSketch() as screwholes_sk:\n", + " with Locations(*locs):\n", + " Circle(1.5)\n", + " extrude(amount=12)\n", + " with BuildSketch() as screwholes_sk1:\n", + " with Locations(*locs):\n", + " Circle(3)\n", + " extrude(amount=2)\n", + " \n", + "r_sens = 6\n", + " \n", + "with BuildPart() as sensor_cutout:\n", + " with BuildSketch(Plane.XZ) as sensor_sk1:\n", + " d = 0\n", + " with Locations((w2/2+d,w1/2),(-w2/2-d,w1/2)):\n", + " Rectangle(sensor_width-4, sensor_width-4)\n", + " sensor_space = extrude(amount=-14)\n", + " faces = (sensor_space.edges().group_by(Axis.Y)[-1] | Axis.Z)\n", + " chamfer(objects=faces, length=6)\n", + " \n", + " with BuildSketch(Plane.XZ) as sensor_sk:\n", + " with Locations((w2/2,w1/2),(-w2/2,w1/2)):\n", + " RectangleRounded(sensor_width, sensor_width, r_sens)\n", + " extrude(amount=-10)\n", + " \n", + " \n", + "with BuildPart() as snapfit_cutout:\n", + " d = 2\n", + " l = 10\n", + " hc=3\n", + " with BuildSketch(Plane.XY.offset(w1/2-l/2)) as snap_sk:\n", + " with Locations((w2/2+w1/2-1.5*d,hc),(-w2/2-w1/2+1.5*d,hc)):\n", + " Rectangle(d, d, rotation=45)\n", + " extrude(amount=l)\n", + " \n", + "\n", + "with BuildPart() as cable_paths:\n", + " with BuildSketch(Plane.XZ) as sensor_sk:\n", + " with Locations((w2/2-w1/2+2,w1/2),(-w2/2+w1/2-2,w1/2)):\n", + " Rectangle(2, 4)\n", + " extrude(amount=-12)\n", + " \n", + "with BuildPart() as cable_paths_mpu:\n", + " with BuildSketch(Plane.XZ) as sensor_sk:\n", + " with Locations((w2/2-w1/2+2,w1/2)):\n", + " Rectangle(2, 4)\n", + " extrude(amount=-12)\n", + " with BuildSketch(Plane.XZ) as sensor_sk:\n", + " with Locations((-w2/2+w1/2-2,w1/2)):\n", + " Rectangle(2, 4)\n", + " extrude(amount=-22)\n", + " \n", + "with BuildPart() as tunnels: \n", + " with BuildLine() as tunnel_right:\n", + " Spline((w2/2-w1/2+1,8.5,w1/2),(0,h-r+3,w1/2), tangents=((-0.1,0.05,0),(0,1,0)))\n", + " with BuildSketch(Plane.YZ.offset(w2/2-w1/2+1)) as tunnel_hole:\n", + " with Locations((8.5, w1/2)):\n", + " Circle(3)\n", + " tunnel = sweep(path=tunnel_right, mode=Mode.ADD)\n", + " mirror(objects=tunnel, about=Plane.YZ)\n", + "\n", + "with BuildPart() as tunnels_mpu: \n", + " with BuildLine() as tunnel_right:\n", + " Spline((-w2/2-w1/2+54, h3-15+1.5, w1/2),(0, h-r+3, w1/2), tangents=((0.1,0.05,0),(0,1,0)))\n", + " with BuildSketch(Plane.YZ.offset(-w2/2-w1/2+54)) as tunnel_mpu_r_hole:\n", + " with Locations((h3-15+1.5, w1/2)):\n", + " Circle(3)\n", + " tunnel = sweep(path=tunnel_right, mode=Mode.ADD)\n", + " with BuildLine() as tunnel_left:\n", + " Spline((w2/2-w1/2,8.5,w1/2),(0,h-r+3,w1/2), tangents=((-0.1,0.05,0),(0,1,0)))\n", + " with BuildSketch(Plane.YZ.offset(w2/2-w1/2+1)) as tunnel_mpu_l_hole:\n", + " with Locations((8.5, w1/2)):\n", + " Circle(3)\n", + " sweep(path=tunnel_left, mode=Mode.ADD)\n", + " \n", + "mpu_width = 28\n", + "mpu_len = 53\n", + "mpu_h = 15\n", + "with BuildPart() as mpu_cutout:\n", + " lift = 20\n", + " with BuildSketch(Plane.XZ.offset(-h3-lift)) as mpu_sk:\n", + " with Locations((-w2/2-w1/2+mpu_len/2+2, w1/2)):\n", + " RectangleRounded(mpu_len,28, 4)\n", + " extrude(amount=lift+mpu_h)\n", + " \n", + "with BuildPart() as mpu_standoff:\n", + " standoff_len = 10\n", + " x = -(w2/2+w1/2-mpu_len-1)\n", + " y1 = w1/2-mpu_width/2+standoff_len/2\n", + " y2 = w1/2+mpu_width/2-standoff_len/2\n", + " with BuildSketch(Plane.XZ.offset(-h3+mpu_h)) as standoff_sk:\n", + " with Locations((x, y1),\\\n", + " (x, y2)):\n", + " Rectangle(2,standoff_len)\n", + " extrude(amount=-7)\n", + " \n", + "with BuildPart() as grip:\n", + " with BuildSketch() as base_sk:\n", + " Polygon((w2/2+w1/2,0),(w2/2-w1/2,0),\\\n", + " (w2/2-w1/2-20,h2),(0,h2),(0,h+2.3*r),\\\n", + " (w2/2-w1/2, h1+10),(w2/2+w1/2, h1),\\\n", + " align=Align.MIN)\n", + " mirror(about=Plane.YZ)\n", + " fillet(radius=r,objects=base_sk.vertices().group_by(Axis.Y)[-1])\n", + " fillet(radius=r*2,objects=base_sk.vertices().group_by(Axis.Y)[3])\n", + " fillet(radius=10,objects=base_sk.vertices().group_by(Axis.Y)[2])\n", + " fillet(radius=2*r,objects=base_sk.vertices().group_by(Axis.Y)[1])\n", + " extrude(amount=w1)\n", + " fillet(radius=r1, objects=grip.edges().group_by(Axis.Z)[0].sort_by(Axis.Y)[-1])\n", + " with BuildSketch(Plane.XY.offset(10)) as pole_cutout:\n", + " with Locations((0,h)):\n", + " Circle(r+0.5)\n", + " extrude(amount=100, mode=Mode.SUBTRACT)\n", + " fillet(radius=r1, objects=grip.edges().group_by(Axis.Y)[-6])\n", + " fillet(radius=r1, objects=grip.edges().group_by(Axis.X)[0].sort_by(Axis.Z)[-1])\n", + " add(screwholes,mode=Mode.SUBTRACT)\n", + " add(sensor_cutout,mode=Mode.SUBTRACT)\n", + " add(cable_paths, mode=Mode.SUBTRACT)\n", + " add(slim_cutout,mode=Mode.SUBTRACT)\n", + " add(slim_cutout2,mode=Mode.SUBTRACT)\n", + " add(tunnels,mode=Mode.SUBTRACT)\n", + " add(inner_cutout,mode=Mode.SUBTRACT)\n", + " add(snapfit_cutout, mode=Mode.SUBTRACT)\n", + " \n", + "with BuildPart() as grip_mpu:\n", + " with BuildSketch() as base_sk:\n", + " with Locations((-w2/2-w1/2,0)):\n", + " Polygon((w2/2+w1/2,0),(w2/2-w1/2,0),\\\n", + " (w2/2-w1/2-20,h2),(-w2/2+w1/2+20,h2),(-w2/2+w1/2,0),(-w2/2-w1/2,0),\\\n", + " (-w2/2-w1/2,h3),(-w2/2-w1/2+55,h3+1),\\\n", + " #(-r,h),\\\n", + " (-6.5,h+2.77*r),\\\n", + " #(r,h),\\\n", + " (w2/2-w1/2, h1+10),(w2/2+w1/2, h1),\\\n", + " \n", + " align=Align.MIN)\n", + " #mirror(about=Plane.YZ)\n", + " fillet(radius=r,objects=base_sk.vertices().group_by(Axis.Y)[-1])\n", + " fillet(radius=r,objects=base_sk.vertices().group_by(Axis.Y)[5])\n", + " fillet(radius=r*2,objects=base_sk.vertices().group_by(Axis.Y)[3])\n", + " fillet(radius=10,objects=base_sk.vertices().group_by(Axis.Y)[2])\n", + " fillet(radius=2*r,objects=base_sk.vertices().group_by(Axis.Y)[1])\n", + " extrude(amount=w1)\n", + " #\n", + " with BuildSketch(Plane.XY.offset(10)) as pole_cutout:\n", + " with Locations((0,h)):\n", + " Circle(r+.5)\n", + " extrude(amount=100, mode=Mode.SUBTRACT)\n", + " fillet(radius=r1, objects=grip_mpu.edges().sort_by(Axis.Y)[-7])\n", + " fillet(radius=r1, objects=grip_mpu.edges().sort_by(Axis.Y)[-6])\n", + " fillet(radius=r1, objects=grip_mpu.edges().group_by(Axis.Z)[0].sort_by(Axis.Y)[-1])\n", + " fillet(radius=r1, objects=grip_mpu.edges().group_by(Axis.Z)[-1].sort_by(Axis.Y)[-1])\n", + " add(screwholes, mode=Mode.SUBTRACT)\n", + " add(sensor_cutout, mode=Mode.SUBTRACT)\n", + " add(cable_paths_mpu, mode=Mode.SUBTRACT)\n", + " add(slim_cutout_mpu, mode=Mode.SUBTRACT)\n", + " add(slim_cutout2_mpu, mode=Mode.SUBTRACT)\n", + " add(tunnels_mpu, mode=Mode.SUBTRACT)\n", + " #usb slot\n", + " with BuildSketch(Plane.YZ.offset(-w2/2-w1/2)) as usb_sk:\n", + " with Locations((h3-6, w1/2)):\n", + " SlotCenterToCenter(6,4, rotation=90)\n", + " extrude(amount=10, mode=Mode.SUBTRACT)\n", + " add(mpu_cutout,mode=Mode.SUBTRACT)\n", + " add(inner_cutout,mode=Mode.SUBTRACT)\n", + " add(mpu_standoff)\n", + " add(snapfit_cutout, mode=Mode.SUBTRACT)\n", + "\n", + " \n", + "with BuildPart() as nut_m3_slot:\n", + " with BuildSketch() as base_sk:\n", + " sw = 3.3\n", + " RegularPolygon(sw,6)\n", + " with Locations((50,0)):\n", + " RegularPolygon(sw,6)\n", + " make_hull()\n", + " extrude(amount=3)\n", + "\n", + "with BuildPart() as handle:\n", + " with BuildSketch(Plane.XY.offset(10)) as handle_sk:\n", + " with Locations((0,h)):\n", + " Circle(r)\n", + " extrude(amount=handle_len)\n", + " with BuildSketch(Plane.XY.offset(10)) as screwholes_sk:\n", + " with Locations(*locs):\n", + " Circle(1.5)\n", + " extrude(amount=30, mode=Mode.SUBTRACT)\n", + " with BuildSketch(Plane.XY.offset(10+handle_len)) as screwholes_sk:\n", + " with Locations(*locs):\n", + " Circle(1.5)\n", + " extrude(amount=-30, mode=Mode.SUBTRACT)\n", + " # add tunnel\n", + " with BuildLine(Plane.YZ) as tnl:\n", + " rr=10\n", + " j = JernArc((h-r-0.5,w1/2), (1,0), arc_size=90, radius=rr)\n", + " l = Line(j@1, j@1+(0,handle_len-w1/2-2*rr))\n", + " JernArc(l@1, (0,1), arc_size=90, radius=rr)\n", + " with BuildSketch(Plane.XZ.offset(-h+r+0.5)) as tunnel_hole:\n", + " with Locations((0, w1/2)):\n", + " Circle(3)\n", + " sweep(path=tnl, mode=Mode.SUBTRACT)\n", + " # add nut slots \n", + " with Locations((0,10+h,20), (0,10+h, handle_len),\\\n", + " (10,h-10,20), (10,h-10, handle_len)):\n", + " add(nut_m3_slot, mode=Mode.SUBTRACT)\n", + " with Locations((0,10+h,20), (0,10+h, handle_len),\\\n", + " (10,h-10,20), (10,h-10, handle_len)):\n", + " add(nut_m3_slot, mode=Mode.SUBTRACT)\n", + " with Locations((-10,h-10,20), (-10,h-10, handle_len)):\n", + " add(Rotation(0,0,180)*nut_m3_slot.part, mode=Mode.SUBTRACT)\n", + " \n", + " \n", + "grip = Rotation(0,180,0)*Location((0,0,-handle_len-20))*grip.part\n", + "#show(grip_mpu, tunnels_mpu, transparent=True,reset_camera=False) \n", + "#show(grip,transparent=True,reset_camera=False)\n", + "#show(grip_mpu,mpu_standoff, transparent=True, reset_camera=False)\n", + "#show(grip, inner_cutout, transparent=True,reset_camera=False)\n", + "#show(tunnel_hole,tnl,grip_mpu,Rotation(0,180,0)*Location((0,0,-handle_len-20))*grip.part, handle,transparent=True,reset_camera=False)\n", + "show( grip, grip_mpu, handle,transparent=True, reset_camera=False)\n", + "#show(slim_cutout_mpu, reset_camera=False)\n", + "#show(grip, sensor_cutout, tunnel_right,transparent=True,reset_camera=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "ce464618-0d41-45ab-b17b-9ec93350721e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "100% ⋮————————————————————————————————————————————————————————————⋮ (2/2) 0.06s\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "with BuildPart() as sensorfoot_housing:\n", + " with BuildSketch(Plane.XZ) as housing_sk:\n", + " with Locations((w2/2, w1/2)):\n", + " RectangleRounded(sensor_width-0.0, sensor_width-0.0, r_sens+0.5)\n", + "\n", + " extrude(amount=-6)\n", + " add(Location((-0.25,0,0))*snapfit_cutout.part)\n", + " opening=sensorfoot_housing.faces().sort_by(Axis.Y)[-1]\n", + " \n", + " offset(amount=-1, openings=opening, side=Side.RIGHT)\n", + " \n", + " with Locations((w2/2,-2,w1/2)):\n", + " Cone(bottom_radius=15, top_radius=12, height=6, rotation=(90,0,0), mode=Mode.SUBTRACT)\n", + " with Locations((w2/2-sensor_width/2, 6, w1/2)):\n", + " Box(7,10,7, mode=Mode.SUBTRACT)\n", + " \n", + "\n", + "with BuildPart() as sensorfoot_bbox:\n", + " with BuildSketch(Plane.XZ) as housing_sk:\n", + " with Locations((w2/2, w1/2)):\n", + " RectangleRounded(sensor_width-4, sensor_width-4, r_sens+0.5)\n", + " extrude(amount=20, both=True)\n", + " \n", + "x_sens = 14.25\n", + "with BuildPart() as sensorfoot:\n", + " with Locations((w2/2,-1.5,w1/2)):\n", + " Cone(bottom_radius=15, top_radius=12, height=6, rotation=(90,0,0), mode=Mode.ADD)\n", + " with Locations((w2/2,2.5,w1/2)):\n", + " Cone(bottom_radius=10, top_radius=15, height=2, rotation=(90,0,0), mode=Mode.ADD)\n", + " with Locations((w2/2-sensor_width/2+x_sens, 3.5, w1/2)):\n", + " Box(12,5,30, mode=Mode.SUBTRACT)\n", + " with Locations((w2/2-sensor_width/2+x_sens, 0, w1/2)):\n", + " Cone(bottom_radius=3, top_radius=2, height=2, rotation=(90,0,0), mode=Mode.SUBTRACT)\n", + " \n", + " #with Locations((w2/2-sensor_width/2+x_sens,2,w1/2)):\n", + " # Box(11,2,30)\n", + " with Locations((w2/2-sensor_width/2+5,2,w1/2), (w2/2+sensor_width/2-5,2,w1/2)):\n", + " Box(3,2,30)\n", + " add(sensorfoot_bbox, mode=Mode.INTERSECT)\n", + " \n", + "\n", + "\n", + "show( sensorfoot, sensorfoot_housing,transparent=True,reset_camera=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "03be83e0-4493-44b5-b38a-85c8007838c5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "100% ⋮————————————————————————————————————————————————————————————⋮ (2/2) 0.07s\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "with BuildPart() as mpu_cover:\n", + " lift = 20\n", + " th = 1.\n", + " with BuildSketch(Plane.XZ.offset(-h3)) as mpu_sk:\n", + " with Locations((-w2/2-w1/2+mpu_len/2+2, w1/2)):\n", + " RectangleRounded(mpu_len,28, 4)\n", + " extrude(amount=1)\n", + " with BuildSketch(mpu_cover.faces().sort_by(Axis.Y)[0]) as stand_sk:\n", + " with Locations((0,-14+th/2), (0,14-th/2)):\n", + " Rectangle(20,th)\n", + " extrude(amount=14)\n", + " buttonlocs = ((-mpu_len/2+5,-t), (-mpu_len/2+5,t))\n", + " with BuildSketch(mpu_cover.faces().sort_by(Axis.Y)[-1]) as holes_sk:\n", + " t = 9\n", + " rr = 2\n", + " dd = 6\n", + " ddd = 0.4\n", + " with Locations(*buttonlocs):\n", + " with Locations((1,0)):\n", + " RectangleRounded(dd+4,dd,rr)\n", + " RectangleRounded(dd+4-ddd,dd-ddd,rr-ddd/2, mode=Mode.SUBTRACT)\n", + " with Locations((5,0)):\n", + " Rectangle(6,2, mode=Mode.SUBTRACT)\n", + " extrude(amount=-2, mode=Mode.SUBTRACT)\n", + " with BuildSketch(mpu_cover.faces().sort_by(Axis.Y)[-1]) as buttons_sk:\n", + " with Locations(*buttonlocs):\n", + " RectangleRounded(5,5,1.5)\n", + " extrude(amount=-5)\n", + " with BuildSketch(mpu_cover.faces().sort_by(Axis.Y)[-1]) as buttons_sk:\n", + " with Locations((2.5,0)):\n", + " Rectangle(32.5,19)\n", + " extrude(amount=-3, mode=Mode.SUBTRACT)\n", + " \n", + " \n", + "show(grip_mpu,mpu_cover,transparent=True,reset_camera=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "id": "8d3ecdf0-94b8-4e65-95f9-785784f7cf57", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "assert False\n", + "foldername = \"SyncGripSTEP/\"\n", + "export_step(sensorfoot.part,foldername+\"sensorfoot.step\")\n", + "export_step(sensorfoot_housing.part,foldername+\"sensorfoot-housing.step\")\n", + "export_step(grip,foldername+\"grip.step\")\n", + "export_step(grip_mpu.part,foldername+\"grip-mpu.step\")\n", + "export_step(handle.part,foldername+\"handle.step\")\n", + "export_step(mpu_cover.part, foldername+\"mpu_cover.step\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ec1e400-2779-4f43-94c5-07a8d18c0023", + "metadata": {}, + "outputs": [], + "source": [ + "with BuildPart() as nut_m3:\n", + " with BuildSketch() as base_sk:\n", + " RegularPolygon(3.005,6)\n", + " extrude(amount=2.4)\n", + " chamfer(nut_m3.edges(), length=0.2)\n", + " Cylinder(1.5,6, mode=Mode.SUBTRACT)\n", + " \n", + "\n", + " \n", + " \n", + "show(nut_m3, nut_m3_slot, transparent=True, reset_camera=False)" + ] + }, + { + "cell_type": "markdown", + "id": "1693d74f-3a6d-4206-91cd-51f126a8285d", + "metadata": {}, + "source": [ + "# export SVG" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "id": "09205ef3-d30d-4da8-a2f0-0f82e397b7cd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING, exporting non-planar shape to 2D format.\n", + " This is probably not what you want.\n", + " 1820 points found outside the XY plane.\n" + ] + } + ], + "source": [ + "foldername = \"SyncGripSVG/\"\n", + "\n", + "fullgrip = Compound(children=[grip, grip_mpu.part, handle.part])\n", + "grips = (Location((-200,0,0))*mirror(fullgrip, about=Plane.YZ)) + (Location((200,0,0))*Rotation(0,0,0)*fullgrip)\n", + "\n", + "\n", + "exporter = ExportSVG(unit= Unit.MM, \\\n", + " scale= 1, \\\n", + " margin= 0, \\\n", + " fit_to_stroke= True, \\\n", + " precision = 6, \\\n", + " fill_color= None, \\\n", + " line_weight = 0.09)\n", + "exporter.add_layer(\"Layer 1\", fill_color=(0, 0, 0), line_color=(255, 255, 255))\n", + "exporter.add_shape(grip, layer=\"Layer 1\")\n", + "exporter.write(foldername+\"grip.svg\")" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "id": "38da9b1c-8880-4ba2-abef-f9ae0bb3ddb5", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def drawSVG(part,view_port_origin, filename):\n", + " visible, hidden = part.project_to_viewport(view_port_origin, viewport_up=(0,1,0))\n", + " max_dimension = max(*Compound(children=visible + hidden).bounding_box().size)\n", + " exporter = ExportSVG(scale=100 / max_dimension,\\\n", + " fill_color=(12,12,12),\n", + " line_weight=1)\n", + " exporter.add_layer(\"Visible\",\\\n", + " line_weight=0.3,\\\n", + " fill_color=None,\\\n", + " line_color=(75,75,75))\n", + " exporter.add_layer(\"Hidden\", \\\n", + " line_color=(144,44,77), \\\n", + " line_weight=0.2,\\\n", + " line_type=LineType.ISO_DOT)\n", + " exporter.add_shape(visible, layer=\"Visible\")\n", + " #exporter.add_shape(hidden, layer=\"Hidden\")\n", + " exporter.write(foldername+filename+\".svg\")" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "id": "068bc1c1-0d80-43cc-8773-e0aaba5a3772", + "metadata": {}, + "outputs": [], + "source": [ + "view_port_origin=(-200, 85, 250)\n", + "fullgrip = Compound(children=[grip, grip_mpu.part, handle.part])\n", + "drawSVG(fullgrip,view_port_origin, \"fullgrip\")" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "id": "fa7fbea4-6725-4b48-aca0-748084e43833", + "metadata": {}, + "outputs": [], + "source": [ + "view_port_origin=(w2/2, 90, -100)\n", + "#sensorfoot_explode = Compound(children=[Location((0,30,0))*sensorfoot.part, sensorfoot_housing.part])\n", + "sensorfoot_normal = Location((0,0,70))*Compound(children=[sensorfoot.part, sensorfoot_housing.part])\n", + "#drawout = Compound(children=[sensorfoot_explode, sensorfoot_normal])\n", + "drawSVG(sensorfoot_normal, view_port_origin, \"sensorfoot\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5e75454-c676-4ba7-9c4b-156cfe07c475", + "metadata": {}, + "outputs": [], + "source": [ + "rf = 30.5/2 # radius of a flask\n", + "nrows = 2\n", + "ncols = 3\n", + "\n", + "t = 2 # wall thickness\n", + "ti = 0.4 # wall thickness inbetween flasks\n", + "df = rf * 2 + ti\n", + "flask_locs = list((i*df,j*df) for i in range(ncols) for j in range(nrows))\n", + "\n", + "w = ncols*df-ti+2*t\n", + "d = nrows*df-ti+2*t\n", + "h = 25\n", + "\n", + "dd = rf+0.2\n", + "cuts_locs = list(((i+0.5)*df, j) for i in range(ncols-1) for j in [-rf-t-dd, d-rf-t+dd])\n", + "cuts1_locs = list((j,(i+0.5)*df) for i in range(nrows-1) for j in [-rf-t-dd, w-rf-t+dd])\n", + "\n", + "\n", + "with BuildPart() as flasks_case:\n", + " with BuildSketch() as case_sk:\n", + " with Locations((-rf-t,-rf-t)):\n", + " RectangleRounded(w, d, rf+t, align=Align.MIN)\n", + " with Locations(*cuts_locs):\n", + " Circle(rf+t, mode=Mode.SUBTRACT)\n", + " with Locations(*cuts1_locs):\n", + " Circle(rf+t, mode=Mode.SUBTRACT)\n", + " \n", + " \n", + " extrude(amount=h) \n", + " fillet(flasks_case.edges()|Axis.Z,radius=rf)\n", + " with BuildSketch() as flasks_sk:\n", + " with Locations(*flask_locs):\n", + " Circle(rf) \n", + " extrude(amount=h-t, mode=Mode.SUBTRACT)\n", + " with BuildSketch() as inner_sk:\n", + " with Locations((-rf+t, -rf+t )):\n", + " RectangleRounded(w-4*t, d-4*t, rf, align=Align.MIN)\n", + " extrude(amount=h-t-8, mode=Mode.SUBTRACT)\n", + " fillet(flasks_case.edges().sort_by(Axis.Z)[0], radius=1)\n", + " \n", + "show(flasks_case, reset_camera=False)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "316a54b1-f07f-4b7c-88d2-288ee0f45306", + "metadata": {}, + "outputs": [], + "source": [ + "flasks_case.part.export_step(\"flasks.step\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "864538fc-57f4-4c15-bf15-7e76b5b0b5d4", + "metadata": {}, + "outputs": [], + "source": [ + "from math import sin, cos, asin,pi\n", + "\n", + "def arcd(y):\n", + " return 2*asin(y*0.5)\n", + "\n", + "def secant_phi(length, radius):\n", + " # calculates tht angle of a secant on a circle\n", + " # with given length and the radius of a circle\n", + " return arcd(length/radius)\n", + "\n", + "dt = 2 # how thick the holder should be\n", + "ds = 6 # how big the step at the end of the gripper should be\n", + "r1 = 15.25-dt # the radius of the hole of the weight plate\n", + "h1 = 22 # the height of the gripper\n", + "\n", + "\n", + "dphi = 15./180.*pi # degree of flex\n", + "# how big do i need to make the radius so when it is flexed, \n", + "# the original radius and angle is reached?\n", + "# when flexed, both grippers should be parallel\n", + "phi_flexed_cutout = secant_phi(r1*2 , r)\n", + "phi_flexed = 2*pi - phi_flexed_cutout\n", + "phi_unflexed = phi_flexed - dphi\n", + "# now we need the circumfence of that arc and the new radius\n", + "circ_flexed = 2*(phi_flexed)*r\n", + "r_unflexed = circ_flexed/(2*(phi_unflexed))\n", + "\n", + "r2 = r_unflexed / 2.0\n", + "phi0 = ((2*pi- phi_flexed)/2) - pi/2\n", + "\n", + "p1 = (r_unflexed * cos( phi0), r_unflexed * sin( phi0))\n", + "p2 = (p1[0] +h1*sin(dphi), p1[1]-h1*cos(dphi))\n", + "p3 =(p2[0] + ds *cos(dphi), p2[1]+ ds *sin(dphi))\n", + "\n", + "\n", + "with BuildPart() as calibration_plate_gripper:\n", + " with BuildSketch() as profile_sketch:\n", + " with BuildLine() as line_builder:\n", + " #a = CenterArc(center=(0,0),\\\n", + " # radius=r_unflexed, \\\n", + " # start_angle=phi0, \\\n", + " # arc_size=circ_flexed/2)\n", + " RadiusArc((0,r_unflexed), p1, r_unflexed)\n", + " line = Polyline(\\\n", + " p1,\\\n", + " p2,\\\n", + " p3,\\\n", + " close=False)\n", + " \n", + " \n", + " ##line1 = fillet(radius=6,objects=line.vertices())\n", + " w = offset(amount=dt, side=Side.LEFT) \n", + " \n", + " \n", + " make_face()\n", + " extrude(amount=7)\n", + " mirror(about=Plane.YZ)\n", + " \n", + " \n", + "show(calibration_plate_gripper, Cylinder(25,100),reset_camera=False, transparent=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9cf1c8e8-adff-4fb0-8453-73e5dbd54c8f", + "metadata": {}, + "outputs": [], + "source": [ + "foldername = \"SyncGripSTEP/\"\n", + "\n", + "calibration_plate_gripper.part.export_step(foldername+\"calibration_plate_gripper.step\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "32b7d490-319f-4aa7-8fa4-056bad961d6f", + "metadata": {}, + "outputs": [], + "source": [ + "phi_unflexed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "669af16d-c398-4e9c-a048-5da88fc54efc", + "metadata": {}, + "outputs": [], + "source": [ + "phi_flexed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb1e25ab-df4d-41a3-b5da-f2952efb8d32", + "metadata": {}, + "outputs": [], + "source": [ + "phi0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a5fd2ce3-b39f-4668-89d5-d1810172cdca", + "metadata": {}, + "outputs": [], + "source": [ + "circ_flexed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7f02d3a1-4bf3-4dce-ab79-e8cc97ccdf06", + "metadata": {}, + "outputs": [], + "source": [ + "offset?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee4e8291-b51d-403a-a589-e48a0710e77c", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}