Part of Phase 2 sensor mount designs for SaltyBot 25 mm mast. Files added: chassis/sensor_head.scad — split collar (25 mm OD stem) + octagonal platform chassis/rplidar_mount.scad — anti-vibration ring for RPLIDAR A1M8 (Ø58 mm BC) chassis/realsense_mount.scad — RealSense D435i arm bracket, 10° tilt, 1/4-20 nut chassis/imx219_mount.scad — 4× IMX219 radial arms, 10° tilt, CSI ribbon slot chassis/sensor_head_assembly.md — assembly diagram + fastener BOM + print settings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
162 lines
7.9 KiB
OpenSCAD
162 lines
7.9 KiB
OpenSCAD
// ============================================================
|
||
// sensor_head.scad — Sensor Head Platform Rev A 2026-02-28
|
||
// Agent: sl-mechanical
|
||
// ============================================================
|
||
// Clamps to 25 mm OD vertical stem (top of mast).
|
||
// Platform hosts:
|
||
// • RPLIDAR A1M8 — centred, topmost
|
||
// • RealSense D435i — front arm, 10° down tilt
|
||
// • 4× IMX219 cameras — radial arms, 90° apart, 10° down
|
||
//
|
||
// RENDER options:
|
||
// "assembly" 3-D exploded-ish view (default)
|
||
// "collar_front" front collar half for slicing (print 2)
|
||
// "collar_rear" rear collar half for slicing
|
||
// "platform_2d" flat projection → DXF
|
||
// ============================================================
|
||
|
||
RENDER = "assembly";
|
||
|
||
// ── Stem ─────────────────────────────────────────────────────
|
||
STEM_OD = 25.0; // actual stem OD (mm)
|
||
STEM_BORE = 25.4; // collar bore (+ 0.4 mm clearance for FDM)
|
||
|
||
// ── Collar ───────────────────────────────────────────────────
|
||
COL_OD = 52.0; // outer diameter
|
||
COL_H = 36.0; // height
|
||
COL_BOLT_X = 19.0; // M4 clamping bolt CL from stem axis
|
||
COL_BOLT_D = 4.5; // M4 clearance hole
|
||
COL_NUT_W = 7.0; // M4 hex nut A/F
|
||
COL_NUT_H = 3.4; // M4 hex nut thickness
|
||
|
||
// ── Platform ─────────────────────────────────────────────────
|
||
PLAT_OD = 120.0; // octagonal platform, across-flats ≈ OD
|
||
PLAT_H = 8.0; // plate thickness
|
||
PLAT_Z = COL_H; // platform bottom sits atop collar
|
||
|
||
// ── RPLIDAR bolt circle ───────────────────────────────────────
|
||
RPL_BC = 58.0; // M3 hole bolt circle diameter
|
||
RPL_HOLE_D = 3.3; // M3 clearance
|
||
RPL_RECESS_D = 72.0; // alignment lip diameter (body + 2 mm clearance)
|
||
RPL_RECESS_H = 1.5; // recess depth
|
||
|
||
// ── Sensor arm attachment holes ───────────────────────────────
|
||
// RealSense arm: 2× M4 holes at X = +ARM_R, Y = ±ARM_DY_RS
|
||
ARM_R = 50.0; // radial distance from stem CL
|
||
ARM_DY_RS = 18.0; // half-spacing for RealSense pair
|
||
// IMX219 arms: 4 × 2 M4 holes at each 90° cardinal, tangential offset ±ARM_DY_CAM
|
||
ARM_DY_CAM = 9.0; // half-spacing for IMX219 pair
|
||
|
||
ARM_HOLE_D = 4.5; // M4 clearance
|
||
|
||
$fn = 64;
|
||
e = 0.01;
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// collar_half(side)
|
||
// side = "front" (+Y) | "rear" (-Y)
|
||
// Print flat-face-down (mating face on build plate).
|
||
// ─────────────────────────────────────────────────────────────
|
||
module collar_half(side = "front") {
|
||
difference() {
|
||
// ── Body: D-shaped half-cylinder ─────────────────────
|
||
intersection() {
|
||
cylinder(d = COL_OD, h = COL_H);
|
||
translate([-COL_OD/2, (side == "front") ? 0 : -COL_OD/2, 0])
|
||
cube([COL_OD, COL_OD/2, COL_H]);
|
||
}
|
||
|
||
// ── Stem bore ────────────────────────────────────────
|
||
translate([0, 0, -e])
|
||
cylinder(d = STEM_BORE, h = COL_H + 2*e);
|
||
|
||
// ── M4 clamping bolt clearance holes (Y direction) ───
|
||
for (bx = [-COL_BOLT_X, COL_BOLT_X]) {
|
||
translate([bx, (side == "front") ? COL_OD/2 : 0, COL_H/2])
|
||
rotate([90, 0, 0])
|
||
cylinder(d = COL_BOLT_D, h = COL_OD/2 + e);
|
||
}
|
||
|
||
// ── M4 hex nut pockets (rear half only) ──────────────
|
||
if (side == "rear") {
|
||
for (bx = [-COL_BOLT_X, COL_BOLT_X]) {
|
||
translate([bx, -(COL_OD/4 + e), COL_H/2])
|
||
rotate([90, 0, 0])
|
||
cylinder(d = COL_NUT_W / cos(30), h = COL_NUT_H + e, $fn = 6);
|
||
}
|
||
}
|
||
|
||
// ── M4 set screw — height / rotation lock (front half) ─
|
||
if (side == "front") {
|
||
translate([0, COL_OD/2, COL_H * 0.72])
|
||
rotate([90, 0, 0])
|
||
cylinder(d = COL_BOLT_D, h = COL_OD/2 - STEM_BORE/2 + e);
|
||
}
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// platform()
|
||
// ─────────────────────────────────────────────────────────────
|
||
module platform() {
|
||
difference() {
|
||
// ── Octagonal disc ───────────────────────────────────
|
||
cylinder(d = PLAT_OD, h = PLAT_H, $fn = 8);
|
||
|
||
// ── Stem passage ─────────────────────────────────────
|
||
translate([0, 0, -e])
|
||
cylinder(d = STEM_BORE, h = PLAT_H + 2*e);
|
||
|
||
// ── RPLIDAR alignment recess (top face) ──────────────
|
||
translate([0, 0, PLAT_H - RPL_RECESS_H])
|
||
cylinder(d = RPL_RECESS_D, h = RPL_RECESS_H + e);
|
||
|
||
// ── RPLIDAR M3 bolt holes — 58 mm BC ─────────────────
|
||
for (a = [45, 135, 225, 315])
|
||
translate([RPL_BC/2 * cos(a), RPL_BC/2 * sin(a), -e])
|
||
cylinder(d = RPL_HOLE_D, h = PLAT_H + 2*e);
|
||
|
||
// ── RealSense arm M4 holes — front (+X), ±ARM_DY_RS ──
|
||
for (dy = [-ARM_DY_RS, ARM_DY_RS])
|
||
translate([ARM_R, dy, -e])
|
||
cylinder(d = ARM_HOLE_D, h = PLAT_H + 2*e);
|
||
|
||
// ── IMX219 arm M4 holes — 4 × cardinal, ±ARM_DY_CAM ─
|
||
// Tangential perpendicular for angle a: (sin(a), -cos(a))
|
||
for (a = [0, 90, 180, 270])
|
||
for (s = [-1, 1])
|
||
translate([
|
||
ARM_R * cos(a) + s * ARM_DY_CAM * sin(a),
|
||
ARM_R * sin(a) - s * ARM_DY_CAM * cos(a),
|
||
-e
|
||
])
|
||
cylinder(d = ARM_HOLE_D, h = PLAT_H + 2*e);
|
||
|
||
// ── Lightening pockets — between arm attachment holes ─
|
||
for (a = [45, 135, 225, 315])
|
||
translate([(PLAT_OD/2 - 22) * cos(a),
|
||
(PLAT_OD/2 - 22) * sin(a), -e])
|
||
cylinder(d = 20, h = PLAT_H + 2*e);
|
||
}
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Render selector
|
||
// ─────────────────────────────────────────────────────────────
|
||
if (RENDER == "assembly") {
|
||
color("SkyBlue", 0.9) collar_half("front");
|
||
color("DodgerBlue", 0.9) mirror([0, 1, 0]) collar_half("rear");
|
||
color("Silver", 0.85) translate([0, 0, PLAT_Z]) platform();
|
||
|
||
} else if (RENDER == "collar_front") {
|
||
collar_half("front");
|
||
|
||
} else if (RENDER == "collar_rear") {
|
||
collar_half("rear");
|
||
|
||
} else if (RENDER == "platform_2d") {
|
||
projection(cut = true)
|
||
translate([0, 0, -(PLAT_Z + PLAT_H / 2)])
|
||
platform();
|
||
}
|