forgecad 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{AdminPage-DwYHz72L.js → AdminPage-DcCnj0qo.js} +1 -1
- package/dist/assets/{BenchmarkPage-a9_f-1US.js → BenchmarkPage-BVEpJSVk.js} +1 -1
- package/dist/assets/{BlogPage-DodHpvmf.js → BlogPage-DHaGP50_.js} +1 -1
- package/dist/assets/{DocsPage-B5LePEuj.js → DocsPage-CDoxHkz8.js} +33 -2
- package/dist/assets/{EditorApp-QXsAISLR.js → EditorApp-BJ0Dloyh.js} +174 -35
- package/dist/assets/{EmbedViewer-DdEHGUMU.js → EmbedViewer-CRKZbY0y.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-yhhOodbf.js → LandingPageProofDriven-BxHkYRE7.js} +1 -1
- package/dist/assets/{LegalPage-5RbKRGYK.js → LegalPage-B-u6FrVv.js} +1 -1
- package/dist/assets/{PricingPage-E3Rma7aV.js → PricingPage-CzpZ6-Ce.js} +1 -1
- package/dist/assets/{SettingsPage-BJZcM97j.js → SettingsPage-CIZSSAd0.js} +1 -1
- package/dist/assets/{app-CE3sYcV7.css → app-CjsbDlb7.css} +143 -0
- package/dist/assets/{app-DSYrDg0V.js → app-DaTMg3nH.js} +612 -120
- package/dist/assets/cli/{render-ZMHR9HkV.js → render-DPf4AYJK.js} +38 -16
- package/dist/assets/{evalWorker-DbNs7Dkp.js → evalWorker-CjZZWRWW.js} +1428 -1038
- package/dist/assets/{jointPose-DO6mnXn_.js → jointPose-DzQOViQH.js} +1 -1
- package/dist/assets/{manifold-BGlQBBH9.js → manifold-BYlzU521.js} +1 -1
- package/dist/assets/{manifold-fy2MV7K1.js → manifold-DgXo0T5P.js} +2 -2
- package/dist/assets/{manifold-BU-tJwQh.js → manifold-K1SkarlQ.js} +1 -1
- package/dist/assets/{reportWorker-DO6hcQbh.js → reportWorker-B9nWwSrB.js} +1402 -1012
- package/dist/assets/{scalar-sampling-budget-o90NSNmF.js → scalar-sampling-budget-prBw_s8t.js} +2139 -1749
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +2 -2
- package/dist/docs-raw/CLI.md +18 -3
- package/dist/docs-raw/generated/assembly.md +70 -5
- package/dist/docs-raw/generated/concepts.md +16 -2
- package/dist/docs-raw/generated/core.md +9 -2
- package/dist/docs-raw/generated/lib.md +1 -1
- package/dist/docs-raw/generated/output.md +14 -43
- package/dist/docs-raw/generated/runtime-names.md +4 -4
- package/dist/docs-raw/guides/simready-quickstart.md +171 -0
- package/dist/docs-raw/simulation-workflow.md +273 -0
- package/dist/index.html +2 -2
- package/dist/sitemap.xml +25 -13
- package/dist-cli/{check-compiler-JTVBITCR.js → check-compiler-II7NLPAB.js} +1 -1
- package/dist-cli/{check-query-propagation-3FFLSMVN.js → check-query-propagation-7462TR3R.js} +1 -1
- package/dist-cli/{chunk-OAN5T4XD.js → chunk-UWTJCGXF.js} +1455 -722
- package/dist-cli/forgecad.js +2994 -529
- package/dist-skill/CONTEXT.md +94 -55
- package/dist-skill/docs/API/core/concepts.md +1 -1
- package/dist-skill/docs/CLI.md +18 -3
- package/dist-skill/docs/generated/assembly.md +66 -5
- package/dist-skill/docs/generated/core.md +9 -2
- package/dist-skill/docs/generated/lib.md +1 -1
- package/dist-skill/docs/generated/output.md +14 -43
- package/dist-skill/docs/generated/runtime-names.md +4 -4
- package/examples/robotics/README.md +46 -0
- package/examples/robotics/scout-cam-rover-simready/README.md +119 -0
- package/examples/robotics/scout-cam-rover-simready/lib/dims.js +140 -0
- package/examples/robotics/scout-cam-rover-simready/main.forge.js +343 -0
- package/examples/robotics/scout-cam-rover-simready/parts/body.forge.js +304 -0
- package/examples/robotics/scout-cam-rover-simready/parts/chassis.forge.js +320 -0
- package/examples/robotics/scout-cam-rover-simready/parts/hardware.forge.js +21 -0
- package/examples/robotics/scout-cam-rover-simready/parts/turret.forge.js +70 -0
- package/examples/robotics/scout-cam-rover-simready/parts/wheel.forge.js +116 -0
- package/examples/robotics/simready-asset-crate.forge.js +79 -0
- package/examples/robotics/simready-diff-drive-rover.forge.js +141 -0
- package/examples/robotics/simready-parallel-gripper.forge.js +102 -0
- package/package.json +1 -1
|
@@ -26,10 +26,10 @@ Point2D, Points, polygon, polygonVertices, port, Product, ProductPanelBuilder, P
|
|
|
26
26
|
ProductSkin, ProductSkinBuilder, ProductStationBuilder, ProductSurfaceBuilder, ProductSurfaceRef, projectToPlane, queueMicrotask, rect
|
|
27
27
|
Rectangle2D, robotExport, roundedRect, Route3D, scene, Sculpt, sdf, SdfShape
|
|
28
28
|
selectEdge, selectEdges, self, setActiveBackend, setImmediate, setInterval, setTimeout, Shape
|
|
29
|
-
ShapeGroup, sheetMetal, SheetMetalPart, sheetStock, Sketch, sketchToDxf, sketchToSvg
|
|
30
|
-
SolvedAssembly, spec, sphere, spline2d, stroke, Surface, SurfaceBody
|
|
31
|
-
sweep, text2d, textWidth, torus, toShape, Transform, union
|
|
32
|
-
variableSweep, verify, Viewport, window, Wood
|
|
29
|
+
ShapeGroup, sheetMetal, SheetMetalPart, sheetStock, Sim, Sketch, sketchToDxf, sketchToSvg
|
|
30
|
+
slot, SolvedAssembly, spec, sphere, spline2d, stroke, Surface, SurfaceBody
|
|
31
|
+
SurfaceMembers, sweep, text2d, textWidth, torus, toShape, Transform, union
|
|
32
|
+
union2d, variableSweep, verify, Viewport, window, Wood
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
`showLabels` is also a runtime global, but it is not part of the top-level collision check. Avoid reusing it unless you intentionally want a local value with that name.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Robotics And SimReady Examples
|
|
2
|
+
|
|
3
|
+
These examples show the current ForgeCAD simulation contract: physical parts use `Sim.body(...)`, joints carry drive intent, and the returned assembly finishes with `withSimulation(...)`.
|
|
4
|
+
|
|
5
|
+
Run commands from the ForgeCAD repo root with the local CLI:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
node dist-cli/forgecad.js check simready examples/robotics/simready-diff-drive-rover.forge.js
|
|
9
|
+
node dist-cli/forgecad.js export mjcf examples/robotics/simready-diff-drive-rover.forge.js --output /tmp/forgecad-rover-mjcf
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Examples
|
|
13
|
+
|
|
14
|
+
| Example | File | What It Proves |
|
|
15
|
+
|---------|------|----------------|
|
|
16
|
+
| Diff-drive rover | `simready-diff-drive-rover.forge.js` | Robot-body profile, wheel contact surfaces, velocity drives, and diff-drive controller metadata |
|
|
17
|
+
| Parallel gripper | `simready-parallel-gripper.forge.js` | Prismatic joints, passive dynamics, and gripper contact-surface metadata |
|
|
18
|
+
| Asset crate | `simready-asset-crate.forge.js` | One-part asset assembly with physical material, collider, and grasp-ready contact metadata |
|
|
19
|
+
| Scout cam rover | `scout-cam-rover-simready/main.forge.js` | Larger copied robot with MJCF, SDF, URDF, MuJoCo smoke motion, starter Gym env, balance training, and push playback |
|
|
20
|
+
|
|
21
|
+
## Minimum Workflow
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
node dist-cli/forgecad.js run examples/robotics/simready-diff-drive-rover.forge.js
|
|
25
|
+
node dist-cli/forgecad.js check simready examples/robotics/simready-diff-drive-rover.forge.js
|
|
26
|
+
node dist-cli/forgecad.js export mjcf examples/robotics/simready-diff-drive-rover.forge.js --output /tmp/forgecad-rover-mjcf
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The MJCF export writes a runnable MuJoCo package with `scene.xml`, `manifest.json`, `simready-manifest.json`, and starter Python scripts.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cd /tmp/forgecad-rover-mjcf
|
|
33
|
+
uv run --python 3.11 --with mujoco --with pillow python scripts/smoke_control.py --render-gif drive.gif
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The smaller examples are meant to be readable API references. The Scout example is the end-to-end simulator workflow.
|
|
37
|
+
|
|
38
|
+
## Picking The Right Example
|
|
39
|
+
|
|
40
|
+
Use `simready-diff-drive-rover.forge.js` when you want the smallest robot that proves the full controller/export path.
|
|
41
|
+
|
|
42
|
+
Use `simready-parallel-gripper.forge.js` when you care about manipulators, fingertips, or grasp-readiness metadata.
|
|
43
|
+
|
|
44
|
+
Use `simready-asset-crate.forge.js` when the object is not a robot but still needs physical material, collision, and contact metadata.
|
|
45
|
+
|
|
46
|
+
Use `scout-cam-rover-simready/` when you want MuJoCo scripts, generated package structure, GIF output, and a realistic source-authored robot example.
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Scout Cam Rover SimReady Example
|
|
2
|
+
|
|
3
|
+
This is a copied, source-authored simulation version of the personal Scout Cam Rover model. The `.forge.js` file returns the normal assembly, and the same assembly carries the simulation contract through `withSimulation(...)`.
|
|
4
|
+
|
|
5
|
+
## What Is Sim-Ready Here
|
|
6
|
+
|
|
7
|
+
- Every assembly part has `Sim.body(...)` metadata with mass, physical material, and collision intent.
|
|
8
|
+
- The TPU tires expose connector-based wheel contact surfaces through `Sim.contact.wheelSurface("tread")`.
|
|
9
|
+
- The two wheel joints have velocity drive intent through `Sim.drive.velocity(...)`.
|
|
10
|
+
- The root assembly uses `withSimulation(...)` with a `Sim.controller.diffDrive(...)` controller.
|
|
11
|
+
- SDF export emits a Gazebo Sim DiffDrive plugin that listens on `/model/scout_cam_rover/cmd_vel`.
|
|
12
|
+
|
|
13
|
+
## Local Checks
|
|
14
|
+
|
|
15
|
+
Run from the ForgeCAD repo root:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
node dist-cli/forgecad.js run examples/robotics/scout-cam-rover-simready/main.forge.js
|
|
19
|
+
node dist-cli/forgecad.js check simready examples/robotics/scout-cam-rover-simready/main.forge.js
|
|
20
|
+
node dist-cli/forgecad.js export mjcf examples/robotics/scout-cam-rover-simready/main.forge.js --output /tmp/scout-cam-rover-mjcf
|
|
21
|
+
node dist-cli/forgecad.js export sdf examples/robotics/scout-cam-rover-simready/main.forge.js --output /tmp/scout-cam-rover-sdf
|
|
22
|
+
node dist-cli/forgecad.js export urdf examples/robotics/scout-cam-rover-simready/main.forge.js --output /tmp/scout-cam-rover-urdf
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The MJCF package is written to:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
/tmp/scout-cam-rover-mjcf/scout_cam_rover.xml
|
|
29
|
+
/tmp/scout-cam-rover-mjcf/scene.xml
|
|
30
|
+
/tmp/scout-cam-rover-mjcf/scripts/gym_env.py
|
|
31
|
+
/tmp/scout-cam-rover-mjcf/scripts/smoke_control.py
|
|
32
|
+
/tmp/scout-cam-rover-mjcf/scripts/train_balance.py
|
|
33
|
+
/tmp/scout-cam-rover-mjcf/scripts/play_balance.py
|
|
34
|
+
/tmp/scout-cam-rover-mjcf/simready-manifest.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The SDF package is written to:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
/tmp/scout-cam-rover-sdf/models/scout_cam_rover/model.sdf
|
|
41
|
+
/tmp/scout-cam-rover-sdf/simready-manifest.json
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The URDF package is written to:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
/tmp/scout-cam-rover-urdf/scout_cam_rover.urdf
|
|
48
|
+
/tmp/scout-cam-rover-urdf/simready-manifest.json
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Moving It In A Simulator
|
|
52
|
+
|
|
53
|
+
The fastest local path is MuJoCo. The MJCF export includes a runnable scene and a package-local smoke controller that discovers the exported actuator names from `manifest.json`.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd /tmp/scout-cam-rover-mjcf
|
|
57
|
+
uv run --python 3.11 --with mujoco --with pillow python scripts/smoke_control.py --render-gif drive.gif
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
That command compiles the generated `scene.xml`, commands the wheel velocity actuators, prints a motion summary, and writes `/tmp/scout-cam-rover-mjcf/drive.gif`.
|
|
61
|
+
The generated smoke controller calibrates the diff-drive motor signs inside MuJoCo before it commands semantic forward/turn/reverse motion, so mirrored wheel axes do not require hand-flipped script edits.
|
|
62
|
+
|
|
63
|
+
The MJCF package also includes a small Gymnasium control lab and starter balance trainer:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
cd /tmp/scout-cam-rover-mjcf
|
|
67
|
+
uv run --python 3.11 --with mujoco --with numpy --with gymnasium --with pillow python scripts/train_balance.py --render-gif balance.gif --fps 10
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
That writes `policies/balance_linear.json` and `balance.gif`. The trainer is intentionally editable Python boilerplate: ForgeCAD wires the model, actuators, calibrated diff-drive semantics, and observation plumbing; the reward, policy class, curriculum, and RL library choice stay outside the CAD API.
|
|
71
|
+
The GIF duration is controlled by both the simulated `--seconds` value and the rendered `--fps`; 10 FPS maps to a clean 100 ms GIF frame delay in common viewers.
|
|
72
|
+
|
|
73
|
+
After training, push the policy with an external force pulse:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
cd /tmp/scout-cam-rover-mjcf
|
|
77
|
+
uv run --python 3.11 --with mujoco --with numpy --with gymnasium --with pillow python scripts/play_balance.py \
|
|
78
|
+
--policy policies/balance_linear.json \
|
|
79
|
+
--push-y 1 \
|
|
80
|
+
--push-at 2 \
|
|
81
|
+
--push-duration 0.15 \
|
|
82
|
+
--render-gif balance_push.gif \
|
|
83
|
+
--fps 10
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`play_balance.py` applies the pulse through MuJoCo's root-body external force array and prints the final tilt, survival time, frame count, and approximate GIF duration.
|
|
87
|
+
|
|
88
|
+
If your desktop supports MuJoCo's GLFW viewer, you can also open the generated scene:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
uv run --python 3.11 --with mujoco python -m mujoco.viewer --mjcf=/tmp/scout-cam-rover-mjcf/scene.xml
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Gazebo Sim is the SDF path, because ForgeCAD's SDF exporter already emits a DiffDrive plugin for the `Sim.controller.diffDrive(...)` metadata.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
export GZ_SIM_RESOURCE_PATH=/tmp/scout-cam-rover-sdf/models:${GZ_SIM_RESOURCE_PATH}
|
|
98
|
+
gz sim empty.sdf
|
|
99
|
+
gz service -s /world/empty/create \
|
|
100
|
+
--reqtype gz.msgs.EntityFactory \
|
|
101
|
+
--reptype gz.msgs.Boolean \
|
|
102
|
+
--timeout 300 \
|
|
103
|
+
--req 'sdf_filename: "/tmp/scout-cam-rover-sdf/models/scout_cam_rover/model.sdf", name: "scout_cam_rover"'
|
|
104
|
+
gz topic -t /model/scout_cam_rover/cmd_vel \
|
|
105
|
+
-m gz.msgs.Twist \
|
|
106
|
+
-p 'linear: {x: 0.15}, angular: {z: 0.0}'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Those commands require Gazebo Sim to be installed on the host. This repo check does not execute Gazebo, Isaac Sim, MuJoCo, or any physics engine.
|
|
110
|
+
|
|
111
|
+
## Important Physics Caveat
|
|
112
|
+
|
|
113
|
+
This robot is a two-wheel self-balancing rover. The exported DiffDrive controller can command the wheel joints, and the generated MuJoCo package includes a starter balance trainer, but the policy itself is simulator-side code. In a real physics project, the model usually needs one of these next:
|
|
114
|
+
|
|
115
|
+
- A quick demo stabilizer: add a caster, skid, or temporary roll/pitch constraint so basic drive motion is inspectable.
|
|
116
|
+
- A faithful robot controller: add IMU feedback and a balance PID/LQR loop that commands the wheel velocity or torque.
|
|
117
|
+
- A simulator integration layer: connect the exported model to ROS 2 control, Gazebo systems, Isaac controllers, PufferLib, MJX, or another MuJoCo actuator/controller stack.
|
|
118
|
+
|
|
119
|
+
Without that controller or stabilizer, the wheels can move but the body may fall over.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Scout cam rover — shared dimension tree (pure data/math, no geometry).
|
|
2
|
+
// World frame: Z up, ground z=0, axle along X at z=AXLE_Z, front of robot faces -Y.
|
|
3
|
+
// All printed-part interfaces derive from these numbers; change here, not in parts.
|
|
4
|
+
|
|
5
|
+
function compute(p) {
|
|
6
|
+
const wall = p.wall; // printed shell wall thickness
|
|
7
|
+
|
|
8
|
+
// ---- drive line / wheels --------------------------------------------------
|
|
9
|
+
const tireOD = p.wheelOD; // outer diameter incl. TPU tire
|
|
10
|
+
const tireThk = 5; // radial
|
|
11
|
+
const tireW = 14;
|
|
12
|
+
const rimOD = tireOD - 2 * tireThk;
|
|
13
|
+
const rimID = rimOD - 12; // rim band 6 thick radially
|
|
14
|
+
const rimW = 14;
|
|
15
|
+
const axleZ = tireOD / 2;
|
|
16
|
+
|
|
17
|
+
// N20 micro gearmotor (purchased): body 12 wide x 10 tall, 24 long incl gearbox,
|
|
18
|
+
// D-shaft d3 x 9.5 with 2.5 flat.
|
|
19
|
+
const motor = {
|
|
20
|
+
w: 12, h: 10, len: 24, // gearbox front face = mating plane
|
|
21
|
+
shaftD: 3, shaftFlat: 2.5, shaftLen: 9.5,
|
|
22
|
+
noseBossD: 4, noseBossL: 1.2, // small ring around shaft exit
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// ---- chassis tub ----------------------------------------------------------
|
|
26
|
+
const tub = {
|
|
27
|
+
w: 70, d: 72, h: 52, z0: axleZ - 26, // base z (world) — axle centered in tub height
|
|
28
|
+
cornerR: 6,
|
|
29
|
+
wall: wall,
|
|
30
|
+
floorT: 2.8,
|
|
31
|
+
postSq: 12, postInset: 6, // corner posts receiving the shell plugs
|
|
32
|
+
sideScrewZ: 47, // tub-local height of the 4 horizontal shell screws
|
|
33
|
+
};
|
|
34
|
+
tub.axleZl = axleZ - tub.z0; // axle height in tub-local Z
|
|
35
|
+
|
|
36
|
+
// motor pod (printed, black): hides shaft exit, wheel hub runs inside its bore
|
|
37
|
+
const pod = {
|
|
38
|
+
od: 34, len: 14, boreD: 24,
|
|
39
|
+
screwR: 14.0, screwN: 3, // M2 from inside tub through the wall into pod bosses
|
|
40
|
+
pilotD: 1.7, wallClearD: 1.9, pilotDepth: 6,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// wheel hub geometry (wheel-local: z=0 bore mouth face, +Z outward)
|
|
44
|
+
const hub = {
|
|
45
|
+
bossD: 20,
|
|
46
|
+
bossL: 14, // reaches from inside pod bore out to the spoke web
|
|
47
|
+
boreD: 3.2, boreFlat: 2.65, boreDepth: 9,
|
|
48
|
+
faceHoleN: 5, faceHoleD: 2.6, faceHoleR: 6,
|
|
49
|
+
};
|
|
50
|
+
const web = { t: 6, z0: hub.bossL }; // spoke web axial band (wheel-local)
|
|
51
|
+
const rim = { z0: web.z0 - (rimW - web.t) / 2 }; // rim band centered on web
|
|
52
|
+
// wheel-local Z of bore mouth maps to world |x| = tub.w/2 + 1.5 (mouth sits 1.5 outside the wall,
|
|
53
|
+
// inside the pod bore). Pod outer face at tub.w/2 + pod.len.
|
|
54
|
+
const wheelMouthX = tub.w / 2 + 1.5;
|
|
55
|
+
|
|
56
|
+
// battery: 2x18650 holder (purchased) mounted vertically on the body shell rear
|
|
57
|
+
// inner wall — high mass is correct for an inverted-pendulum self-balancer.
|
|
58
|
+
const batt = { w: 70, h: 42, d: 21, mountHoleSpan: 50, zc: 38 }; // zc = shell-local center
|
|
59
|
+
|
|
60
|
+
// service door in the tub front wall (exposes driver / IMU / wiring bay)
|
|
61
|
+
const door = {
|
|
62
|
+
openW: 44, openH: 22, zc: 19, // tub-local opening, center height
|
|
63
|
+
panelW: 54, panelH: 34, panelT: 2.0,
|
|
64
|
+
plugT: 2.2, slop: 0.3, // plug per-side clearance into opening
|
|
65
|
+
recess: 1.0, recessSlop: 0.4,
|
|
66
|
+
screwDX: 23.5, screwDZ: 13.5, // screw offsets from door center
|
|
67
|
+
pilotD: 1.7, screwHeadD: 3.8, bossD: 6, bossLen: 7,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// electronics in the tub bay (purchased modules on printed floor posts)
|
|
71
|
+
const boards = {
|
|
72
|
+
standoffH: 4,
|
|
73
|
+
drv: { w: 16, d: 18, t: 1.6, x: -12, y: -22.5 }, // DRV8833 dual H-bridge
|
|
74
|
+
buck: { w: 22, d: 17, t: 1.6, x: 7.6, y: -22.5 }, // MP1584 5V buck
|
|
75
|
+
mpu: { w: 16.5, d: 21.5, t: 1.6, x: 0, y: 3 }, // MPU6050 IMU (mid-bay)
|
|
76
|
+
};
|
|
77
|
+
const sw = { w: 13, h: 9, t: 9, plateW: 15, plateH: 11, plateT: 1.8, zc: 14 }; // rocker, rear wall
|
|
78
|
+
|
|
79
|
+
// ---- body shell (upper cube) ---------------------------------------------
|
|
80
|
+
const body = {
|
|
81
|
+
w: 84, d: 92, h: 88, cornerR: 13,
|
|
82
|
+
yOff: -4, // shell center sits 4mm toward the front of the tub center
|
|
83
|
+
topT: 3.0,
|
|
84
|
+
plugSq: 8, plugL: 9.7, socketSq: 8.3, socketDepth: 10, // 4 corner plugs into tub posts
|
|
85
|
+
plugInsetX: 10, plugInsetY: 10, // plug centers from tub inner corners
|
|
86
|
+
};
|
|
87
|
+
// neck + ring on top of shell (printed as part of shell)
|
|
88
|
+
const neck = { od: 44, h: 14, boreD: 36, ringOD: 50, ringH: 4 };
|
|
89
|
+
|
|
90
|
+
// camera (front face of shell, shell-local: centered XY, base z=0)
|
|
91
|
+
const cam = {
|
|
92
|
+
zc: 52, // lens center height above shell base
|
|
93
|
+
recessD: 44, recessDepth: 1.0,
|
|
94
|
+
holeD: 26,
|
|
95
|
+
screwR: 18.5, screwN: 4, pilotD: 1.7, screwStartDeg: 0,
|
|
96
|
+
bezelOD: 43.4, bezelID: 28, bezelT: 3.4, // proud of face by bezelT - recessDepth
|
|
97
|
+
cowlD: 27.8, cowlT: 3.0, apertureD: 9.5,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// ESP32-CAM (purchased): PCB 27 x 40.5 x 1.6, lens barrel d8 x 6.5 on front
|
|
101
|
+
const esp = { pcbW: 27, pcbH: 40.5, pcbT: 1.6, barrelD: 8, barrelL: 6.5, compT: 3.0 };
|
|
102
|
+
|
|
103
|
+
// side vents: skewed recessed panel + 5 vertical through slots, both side faces
|
|
104
|
+
const vent = {
|
|
105
|
+
n: 5, slotW: 4.5, slotL: 36, pitch: 11,
|
|
106
|
+
recessDepth: 0.8, skewDZ: 14, // rear edge of band this much higher than front
|
|
107
|
+
yc: 3, zc: 56, bandW: 58, bandH: 52, // band center (shell-local y/z) and size
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// SG90 servo (purchased) hung under a bridge bar across the neck-bore opening.
|
|
111
|
+
// Servo-local frame: z=0 at the tab TOP plane (mates upward against the bosses);
|
|
112
|
+
// spline axis at local x=0.
|
|
113
|
+
const servo = {
|
|
114
|
+
bodyW: 23, bodyD: 12.4, bodyDown: 19, bodyUp: 4.5, // body extent below/above tab plane
|
|
115
|
+
bodyXc: -5.6, // body center offset so the spline sits at x=0
|
|
116
|
+
tabSpan: 32.4, tabT: 2.5, tabHoleXa: -13.75, tabHoleXb: 13.75, // relative to body center
|
|
117
|
+
towerH: 4.6, towerD: 11.8, splineD: 4.8, splineH: 3.2,
|
|
118
|
+
hornD: 20.6, hornT: 1.8, hornHubD: 7.4, // round horn pressed on the spline
|
|
119
|
+
tabPlaneZ: 78.2, // shell-local height of the tab plane
|
|
120
|
+
bossSq: 8, // printed bosses hanging from the bridge bar
|
|
121
|
+
};
|
|
122
|
+
const bridge = { w: 10, holeD: 13 }; // bar left across the neck-bore wall opening
|
|
123
|
+
|
|
124
|
+
// turret (printed black) rides the servo horn through the neck bore
|
|
125
|
+
const turret = {
|
|
126
|
+
baseD: 40, baseH: 5, lugN: 4, lugW: 5, lugT: 2, lugH: 2.4,
|
|
127
|
+
barrelD: 34, barrelH: 15, capD: 37, capH: 3,
|
|
128
|
+
colD: 14, colHubD: 25, colHubH: 5, colLen: 12.5, // column reaches the horn through the neck
|
|
129
|
+
socketD: 21.2, socketDepth: 2.0,
|
|
130
|
+
gapAboveNeck: 1.2, // running gap between turret base underside and neck ring top
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
wall, axleZ, tireOD, tireThk, tireW, rimOD, rimID, rimW,
|
|
135
|
+
motor, tub, pod, hub, web, rim, wheelMouthX,
|
|
136
|
+
batt, door, boards, sw, body, neck, cam, esp, vent, servo, bridge, turret,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = { compute };
|