Add parametric OpenSCAD designs for the SaltyRover stable 4-wheel variant. Reuses existing 25mm stem, sensor head, and all SaltyLab sensor mounts without modification. Files: - saltyrover_chassis.scad 480×500mm deck, stem collar, FC+Orin standoffs, motor attachment holes, battery tray opening; RENDER deck_2d for waterjet/CNC DXF - rover_motor_mount.scad L-bracket + axle clamp plate per motor; uses caliper-verified axle dims from BOM.md; dropout slot for tool-free motor swap; RENDER bracket_2d for CNC DXF - rover_battery_tray.scad Slide-out tray for 2-4 × 420×88×56mm packs laid flat (low CG); T-slot rails, spring latch - rover_stem_adapter.scad Flange + split clamp locks 25mm stem to deck collar; 550mm stem option for rover height - rover_BOM.md Assembly sequence, fastener table, mass estimate (~13.4kg), height stack diagram Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
219 lines
9.6 KiB
OpenSCAD
219 lines
9.6 KiB
OpenSCAD
// ============================================================
|
||
// saltyrover_chassis.scad — SaltyRover 4-Wheel Base Plate
|
||
// Rev A 2026-03-01 sl-mechanical
|
||
// ============================================================
|
||
// Parametric deck plate for the stable 4-wheel SaltyRover.
|
||
// Low/wide/stable design — reuses sensor head + 25 mm stem.
|
||
//
|
||
// Coordinate convention:
|
||
// Z = 0 deck top face
|
||
// +Y forward
|
||
// +X right (motor side)
|
||
//
|
||
// Battery orientation:
|
||
// Packs laid FLAT (56 mm tall, 420 mm running left-right,
|
||
// 88 mm per pack fore-aft). N packs arranged fore-aft.
|
||
// 2-pack tray: 430 × 186 mm opening.
|
||
// 4-pack tray: 430 × 362 mm opening.
|
||
//
|
||
// Motor positions are at ±TRACK_W/2 (X), ±AXLE_BASE/2 (Y).
|
||
// Motor brackets (rover_motor_mount.scad) bolt to deck edge
|
||
// and extend BRKT_REACH mm outward to hold axle at AXLE_H.
|
||
//
|
||
// RENDER options:
|
||
// "assembly" full deck + phantom batteries + stem stub
|
||
// "deck" deck plate only (review)
|
||
// "deck_2d" floor projection → DXF for waterjet/CNC
|
||
// ============================================================
|
||
|
||
RENDER = "assembly";
|
||
|
||
// ── Deck footprint ────────────────────────────────────────
|
||
ROVER_L = 500.0; // fore-aft (Y)
|
||
ROVER_W = 480.0; // left-right (X) — sized around battery width
|
||
DECK_T = 8.0; // deck thickness
|
||
DECK_R = 15.0; // corner fillet radius
|
||
|
||
// ── Drive geometry (caliper-verified motor data from BOM.md) ──
|
||
TRACK_W = 540.0; // motor axle CL to CL, left-right
|
||
AXLE_BASE = 340.0; // motor axle CL to CL, fore-aft
|
||
AXLE_H = 127.0; // axle CL above ground (10×2.125" wheel, caliper)
|
||
GND_CLR = 50.0; // minimum chassis ground clearance
|
||
|
||
// Height of deck bottom above ground:
|
||
// GND_CLR + battery_tray_floor + battery_height
|
||
BATT_FLOOR_T = 3.0;
|
||
BATT_PACK_H = 56.0; // flat-laid pack height
|
||
DECK_BOT_H = GND_CLR + BATT_FLOOR_T + BATT_PACK_H; // 109 mm
|
||
// Axle above deck top = AXLE_H - (DECK_BOT_H + DECK_T) ≈ +10 mm
|
||
|
||
// ── Battery packs (BOM.md caliper-verified: 420×88×56 mm) ──
|
||
// Laid flat, 420 mm running left-right (X), 88 mm per pack (Y),
|
||
// 56 mm tall (Z). BATT_N packs arranged side-by-side fore-aft.
|
||
BATT_X_DIM = 420.0;
|
||
BATT_Y_DIM = 88.0; // per-pack fore-aft depth
|
||
BATT_N = 2; // packs fore-aft (2 = 176 mm; 4 = 352 mm)
|
||
TRAY_MARGIN = 5.0; // extra margin on each side of tray opening
|
||
|
||
// ── Stem socket (deck centre) ─────────────────────────────
|
||
STEM_BORE = 25.5; // 25 mm tube + 0.5 clearance
|
||
STEM_COLLAR_OD = 50.0;
|
||
STEM_COLLAR_H = 22.0; // raised boss height above deck top
|
||
|
||
// ── FC mount (MAMBA F722S, 30.5×30.5 M3) ─────────────────
|
||
FC_SPACING = 30.5;
|
||
FC_HOLE_D = 3.2;
|
||
FC_STANDOFF_H= 6.0;
|
||
// FC centred forward of battery tray
|
||
FC_X = 0.0;
|
||
FC_Y = ROVER_L/2 - 60.0; // near front edge
|
||
|
||
// ── Jetson Orin NX mount ─────────────────────────────────
|
||
// ⚠ Verify hole pattern against your carrier board.
|
||
// Default: 58×49 mm M3 (same as RPi HAT pattern used on Orin NX cards).
|
||
ORIN_HOLE_X = 58.0;
|
||
ORIN_HOLE_Y = 49.0;
|
||
ORIN_HOLE_D = 3.2;
|
||
ORIN_STANDOFF = 8.0;
|
||
ORIN_X = 0.0;
|
||
ORIN_Y = -(ROVER_L/2 - 55.0); // near rear edge
|
||
|
||
// ── Motor bracket attachment bolt pattern ────────────────
|
||
// 2× M5 bolts through deck edge at each motor corner.
|
||
MOT_BOLT_D = 5.3; // M5 clearance
|
||
MOT_BOLT_SPC = 30.0; // bolt spacing fore-aft at each motor position
|
||
|
||
// ── Lightening holes ──────────────────────────────────────
|
||
LH_D = 55.0;
|
||
|
||
// ── Fasteners ─────────────────────────────────────────────
|
||
M3_D = 3.2;
|
||
M4_D = 4.3;
|
||
M5_D = 5.3;
|
||
|
||
$fn = 64;
|
||
e = 0.01;
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// rounded_plate_2d()
|
||
// ─────────────────────────────────────────────────────────
|
||
module rounded_plate_2d(l, w, r) {
|
||
offset(r=r, $fn=32) offset(r=-r)
|
||
square([l, w], center=true);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// rover_deck()
|
||
// ─────────────────────────────────────────────────────────
|
||
module rover_deck() {
|
||
tray_w = BATT_X_DIM + 2*TRAY_MARGIN; // 430 mm
|
||
tray_l = BATT_Y_DIM * BATT_N + 2*TRAY_MARGIN; // 186 or 362 mm
|
||
|
||
difference() {
|
||
// ── Deck plate ────────────────────────────────
|
||
translate([0, 0, -DECK_T])
|
||
linear_extrude(DECK_T)
|
||
rounded_plate_2d(ROVER_W, ROVER_L, DECK_R);
|
||
|
||
// ── Battery tray opening (centred, through deck) ──
|
||
translate([-tray_w/2, -tray_l/2, -DECK_T - e])
|
||
cube([tray_w, tray_l, DECK_T + 2*e]);
|
||
|
||
// ── Lightening holes ──────────────────────────
|
||
// 3 columns × 2 rows, outside battery opening
|
||
for (hx = [-ROVER_W/4, 0, ROVER_W/4])
|
||
for (hy = [-(tray_l/2 + LH_D/2 + 20),
|
||
(tray_l/2 + LH_D/2 + 20)])
|
||
if (abs(hy) < ROVER_L/2 - LH_D/2 - 10)
|
||
translate([hx, hy, -DECK_T - e])
|
||
cylinder(d=LH_D, h=DECK_T + 2*e);
|
||
|
||
// ── FC mount holes ────────────────────────────
|
||
for (fx=[-FC_SPACING/2, FC_SPACING/2])
|
||
for (fy=[-FC_SPACING/2, FC_SPACING/2])
|
||
translate([FC_X + fx, FC_Y + fy, -DECK_T - e])
|
||
cylinder(d=FC_HOLE_D, h=DECK_T + 2*e);
|
||
|
||
// ── Orin mount holes ──────────────────────────
|
||
for (ox=[-ORIN_HOLE_X/2, ORIN_HOLE_X/2])
|
||
for (oy=[-ORIN_HOLE_Y/2, ORIN_HOLE_Y/2])
|
||
translate([ORIN_X + ox, ORIN_Y + oy, -DECK_T - e])
|
||
cylinder(d=ORIN_HOLE_D, h=DECK_T + 2*e);
|
||
|
||
// ── Motor bracket bolt holes (4 corners × 2 bolts) ──
|
||
for (sx=[-1,1], sy=[-1,1])
|
||
for (by=[-MOT_BOLT_SPC/2, MOT_BOLT_SPC/2])
|
||
translate([sx*ROVER_W/2 - sx*(DECK_T/2 + e),
|
||
sy*AXLE_BASE/2 + by,
|
||
-DECK_T - e])
|
||
rotate([0, 90, 0])
|
||
cylinder(d=MOT_BOLT_D, h=DECK_T + 2*e);
|
||
|
||
// ── Stem bore through deck ────────────────────
|
||
translate([0, 0, -DECK_T - e])
|
||
cylinder(d=STEM_BORE, h=DECK_T + 2*e);
|
||
|
||
// ── Cable routing slots (×2 per side, fore and aft) ──
|
||
for (cy=[-ROVER_L/2 - e, ROVER_L/2 - 16])
|
||
for (cx=[-55, 55])
|
||
translate([cx - 7, cy, -DECK_T - e])
|
||
cube([14, 16, DECK_T + 2*e]);
|
||
}
|
||
|
||
// ── Stem collar (raised boss) ─────────────────────
|
||
difference() {
|
||
cylinder(d=STEM_COLLAR_OD, h=STEM_COLLAR_H);
|
||
translate([0, 0, -e])
|
||
cylinder(d=STEM_BORE, h=STEM_COLLAR_H + 2*e);
|
||
}
|
||
|
||
// ── FC standoff posts (×4) ────────────────────────
|
||
for (fx=[-FC_SPACING/2, FC_SPACING/2])
|
||
for (fy=[-FC_SPACING/2, FC_SPACING/2])
|
||
translate([FC_X + fx, FC_Y + fy, 0])
|
||
cylinder(d=6, h=FC_STANDOFF_H);
|
||
|
||
// ── Orin standoff posts (×4) ──────────────────────
|
||
for (ox=[-ORIN_HOLE_X/2, ORIN_HOLE_X/2])
|
||
for (oy=[-ORIN_HOLE_Y/2, ORIN_HOLE_Y/2])
|
||
translate([ORIN_X + ox, ORIN_Y + oy, 0])
|
||
cylinder(d=6, h=ORIN_STANDOFF);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────
|
||
// Render selector
|
||
// ─────────────────────────────────────────────────────────
|
||
if (RENDER == "assembly") {
|
||
color("Silver", 0.90) rover_deck();
|
||
|
||
// Phantom battery packs (2 × laid flat)
|
||
tray_w = BATT_X_DIM + 2*TRAY_MARGIN;
|
||
tray_l = BATT_Y_DIM * BATT_N + 2*TRAY_MARGIN;
|
||
for (pn = [0 : BATT_N - 1])
|
||
color("Gold", 0.30)
|
||
translate([-BATT_X_DIM/2,
|
||
-BATT_Y_DIM*BATT_N/2 + pn*BATT_Y_DIM,
|
||
-(DECK_T + BATT_FLOOR_T + BATT_PACK_H)])
|
||
cube([BATT_X_DIM, BATT_Y_DIM, BATT_PACK_H]);
|
||
|
||
// Phantom stem stub
|
||
color("Silver", 0.25)
|
||
translate([0, 0, STEM_COLLAR_H])
|
||
cylinder(d=25, h=400);
|
||
|
||
// Motor position markers (spheres at axle CLs)
|
||
axle_z = AXLE_H - (DECK_BOT_H + DECK_T); // above deck top
|
||
for (sx=[-1,1], sy=[-1,1])
|
||
color("Tomato", 0.5)
|
||
translate([sx*TRACK_W/2, sy*AXLE_BASE/2, axle_z])
|
||
sphere(d=20);
|
||
|
||
} else if (RENDER == "deck") {
|
||
rover_deck();
|
||
|
||
} else if (RENDER == "deck_2d") {
|
||
projection(cut=true)
|
||
translate([0, 0, -DECK_T/2])
|
||
rover_deck();
|
||
}
|