Mechanical design: rigorous proof-out + vendor tender package - #107
Conversation
… torque proof First slice of the mechanical-design proof-out. Establishes the single-source-of- truth parameter set (params.py) with sourced/derived/assumed provenance tags, the SI units layer, the common BudgetResult type, and the exemplar axis-torque budget. The torque proof already lands the boldest result: MN78 counterweight-FREE needs 49.9 Nm at RA vs the CSF-32 127 Nm rating (SF 2.5) and 26.5 Nm at DEC vs 70 Nm (SF 2.6) — deleting the ~9 kg of counterweights is quantitatively feasible, the same principle the ZWO AM5 / RST-135 exploit. 5/5 tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKZMQ755R7q38SKqJsCQsg
…nerated report Completes the rigorous mechanical-design proof-out. Turns the repo's asserted-but- uncomputed design into 11 first-principles budgets (torque, stiffness, dynamics, encoder tracking, balance, bearings, wind, pier, thermal, enclosure, power), each a calc module + pytest asserting its margin. A weighted-Pugh trade study runs the selection permutations with a sensitivity pass, parametric OpenSCAD + an SVG preview fill the empty CAD appendix, and report.py generates MECHANICAL_DESIGN.md from the calculator (a diff-test forbids drift). 121/121 tests green. Honest tally: 6 PASS / 5 FAIL — the FAILs are real findings the repo's prose hid: - stiffness 43.5" vs 5": the deep-groove 6008/6006 bearings (not the walls) are 98% of the error -> angular-contact 7008/7006 pairs required. - tracking: baseline dual-encoder chain 5.02" RMS vs 1" -> on-axis high-res absolute encoder REQUIRED (proposed ring reaches 0.54"). - survival wind: 9.2 kN roof uplift, SF 0.19 -> hold-down anchors mandatory (unspecced). - thermal: 22 K diurnal swing walks focus ~10x depth-of-focus -> temp-comp focuser. - off-grid power: 12 V pack 3.3 h vs 10 h night -> 48 V pack (13.4 h) or DGX duty-cycle. Selected build banks two won bold picks (counterweight-FREE GEM, active-thermal roof) plus the mandatory on-axis encoder; keeps baselines where they already pass. Every input tagged sourced/derived/assumed; the three governing voids the repo omits (survival wind, snow, seismic) are filled as labelled assumptions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKZMQ755R7q38SKqJsCQsg
Foundation of the vendor tender package that turns the proven mechanical design into biddable fabrication documents. Additive under design/mechanical/tender/; does not touch the proof-out modules. - gen/partspec.py: parts registry (single source of truth) — 30 line items across BP-01..05, every fabricated dimension traced to calc/params.py; the 5 proof-out remediations baked in (angular-contact 7008/7006, on-axis absolute encoder, 4x wind hold-down anchors, temp-comp focuser, 48 V pack); counterweight flagged optional for the CW-free build; stock masses computed. - gen/bom.py: master_bom.csv, cut_list.csv (dual mm/in), cots_schedule.csv. - gen/drawing.py: 15 dimensioned SVG control drawings (Y14.1 title block, dual units, material/finish/tolerance blocks, "ISSUED FOR BID / FOR PE REVIEW"). - gen/xlsx_export.py: Excel BOM workbook (needs openpyxl; CSVs are source of truth). - gen/htmlset.py: print-to-PDF drawing set bundling all 15 sheets. - tests/test_tender.py: 6 consistency gates (full-spec, BOM coverage, cut/COTS split, remediations-present/baseline-absent, well-formed drawings, PE-gate flag). Bid-package SOWs (BP-00..05) + adversarial QA land in a follow-up commit. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKZMQ755R7q38SKqJsCQsg
Vendor-grade tender documents authored against the parts registry (one stream per package). All dual-unit (mm [in]), standards cited by number, dimensions pulled from partspec.py (no invented numbers), headed "ISSUED FOR BID / FOR PE REVIEW". - BP-00 master dossier: instructions to bidders, general SOW, standards register, drawing register, inspection/test plan, pricing/bid form, T&Cs, index with bid-in-parts-or-whole guidance + roll-off/turret-variant appendix. - BP-01 mount machining: CNC 6061-T6, H7 bearing seats (ISO 286) sized for the angular-contact 7008/7006 remediation, Type III anodize (MIL-A-8625F), GD&T (ASME Y14.5), CMM acceptance. - BP-02 turned parts: 303 SS spindles/shaft, journals to fit 7008/7006, passivation. - BP-03 pier & foundation: RC pier (ACI 318/301), rebar + anchor (F1554), galv top plate — with the PE-STAMP GATE stated prominently. BP-04 roll-off roof, BP-05 COTS schedule, and vendor DOCX/XLSX land next. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKZMQ755R7q38SKqJsCQsg
Completes the vendor tender package and applies the adversarial-QA fixes. New bid packages: - BP-04 roll-off roof "disappearing turret": welded steel (AWS D1.1, symbols per A2.4), box-track rail run = 2x roof length, gate-operator drive sized to the 235 N move force, MANDATORY 4x wind hold-down anchors + snow interlock; weld map + acceptance; PE-stamp gate stated. - BP-05 COTS schedule: harmonic drives, angular-contact 7008/7006, on-axis absolute encoder, motors/drivers, temp-comp focuser, rail/drive/roofing, 48 V pack, consolidated fastener schedule; remediations vs optional (counterweights) marked. QA fixes (all real findings from the adversarial review): - partspec: corrected BP-04 roof-steel over-count — NW-RR-001/002/003 now carry per-piece length x piece qty (purlins 52.2 kg not 261; rails 89.7 kg not 179). - drawing.py: only dual-format true linear dimensions; counts/angles/f'c/torque no longer rendered as "mm [in]" (fixed 7 of 15 sheets). - docs: 43.3" -> 43.5" to match the 8 mm-wall selected configuration everywhere. Vendor deliverables (generated from calc/params.py): - bom/NIGHTWATCH_tender_BOM.xlsx (Excel BOM/cut-list/COTS) - drawings/DRAWING_SET.html (print-to-PDF set of all 15 control drawings) - docs/NIGHTWATCH_tender_RFQ.docx (whole tender as one Word RFQ) - tender/README.md index. Full suite: 127 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SKZMQ755R7q38SKqJsCQsg
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c26cb55. Configure here.
| res.add("-- tilt (35 mph gust) --", 0.0, "", "") | ||
| res.add("OTA drag @ 35 mph", f_wind, "N", "from wind.py") | ||
| res.add("Pier tip deflection", delta * 1e6, "um", "F L^3/3EI") | ||
| res.add("Pier pointing tilt", tilt, "arcsec", "tip slope F L^2/2EI") |
There was a problem hiding this comment.
Pier tilt note mismatches formula
Medium Severity
evaluate() sets pier pointing tilt to pier_tilt_arcsec(F) plus an extra moment term F·h_head·L/(EI), but the budget line note and assumptions still describe only tip slope F·L²/(2EI). The published value (~0.70″) matches the sum, not the labeled formula (~0.33″), so hand checks and downstream docs can disagree with the calculator.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c26cb55. Configure here.
| def shaft_mass_kg(cw: P.CounterweightSystem = P.COUNTERWEIGHTS) -> float: | ||
| """Mass of the solid 303-SS counterweight shaft = rho * A * L. DERIVED.""" | ||
| area = math.pi / 4.0 * cw.shaft_dia_m ** 2 | ||
| return cw.material.rho * area * cw.shaft_len_m |
There was a problem hiding this comment.
Duplicate counterweight shaft mass
Low Severity
shaft_mass_kg in balance.py and counterweight_shaft_mass_kg in pier.py both compute 303-SS shaft mass from rho·A·L on P.COUNTERWEIGHTS. Two copies of the same derived value risk diverging if one path is updated later.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c26cb55. Configure here.
| f_rock = rocking_mode_hz(ota, ra_h, dec_h) | ||
|
|
||
| # Governing = lowest of every mode/mass case we examined. | ||
| f_governing = min(f_bounce_free, f_bounce_cw, f_rock) |
There was a problem hiding this comment.
Rocking mode ignores counterweight mass
Low Severity
evaluate() takes the governing first mode as the minimum of CW-free bounce, counterweighted bounce, and rocking modes, but rocking_mode_hz() always uses payload-only inertia while the counterweighted bounce case includes 12.5 kg of weights. The compared modes do not use the same modal mass.
Reviewed by Cursor Bugbot for commit c26cb55. Configure here.


Summary
Turns the proven mechanical design (PR #105) into an official, modular vendor tender package under
design/mechanical/tender/— documents a machine shop, turning shop, steel fabricator, and concrete contractor can bid on and build, in parts or whole. Every number is generated from the validatedcalc/params.py(single source of truth); a consistency test suite guards it. 127/127 tests pass.Based on
design/mechanical-proveoutso the diff is tender-only; retarget tomainafter #105 merges.Type of Change
design/mechanical/tender/)What's in it
Generators (source → vendor docs), all driven by
calc/params.py:gen/partspec.py— parts registry: 30 line items across BP-01…05, dims traced to params, the 5 proof-out remediations baked in, stock masses computed.gen/bom.py→master_bom.csv,cut_list.csv(dual mm/in),cots_schedule.csv.gen/drawing.py→ 15 dimensioned control drawings (SVG, ASME Y14.1 title block, dual units, material/finish/tolerance blocks).gen/xlsx_export.py→ Excel BOM workbook ·gen/htmlset.py→ print-to-PDF drawing set ·gen/docx_export.py→ whole tender as one Word RFQ.Bid packages — one per trade (biddable in parts or whole):
Follows the real standards vendors expect — MIL-STD-31000A (TDP), ASME Y14.5 GD&T + Y14.1 title blocks, AWS A2.4/D1.1/D1.2 welding, MIL-A-8625F anodize, ACI 318 foundation, ISO 286 H7/js6 fits — and bakes in all five proof-out remediations (angular-contact 7008/7006 bearings, on-axis absolute encoder, 4× wind hold-down anchors, temp-comp focuser, 48 V pack).
Safety Checklist
Testing
pytest design/mechanical/tests/→ 127 passed (incl. 6 tender consistency gates: dims trace to registry; BOM ↔ cut-list ↔ drawings agree; remediations present, deep-groove baseline absent; well-formed drawings; PE-gate flagged).Documentation
tender/README.mdindex +BP-00master dossier; every doc headed "ISSUED FOR BID / FOR PE REVIEW — NOT FOR CONSTRUCTION."Additional Notes
Issued for bid / PE review, not for construction: BP-03 pier and BP-04 roof are structural (ASCE 7 wind/snow/seismic) and require a licensed PE stamp before construction — stated prominently, not replaced. Values the design doesn't yet fix (weld/member sizing, rail/drive product, GD&T values, surface-finish Ra) are marked ASSUMED design-intent — bidder/PE to confirm, never presented as final. Left as draft for your review.
🤖 Generated with Claude Code
Generated by Claude Code
Note
Low Risk
Documentation and design-calculator additions only; no changes to observatory runtime, safety interlocks, or firmware. Main risk is engineering assumptions (wind, snow, DGX power) being treated as build truth without PE/vendor validation.
Overview
Adds a computed mechanical design under
design/mechanical/: a single SI source of truth incalc/params.py, eleven proof modules (torque, stiffness, dynamics, encoder tracking, balance, bearings, wind, pier, thermal, enclosure roof drive/snow, night power) that each return a sharedBudgetResult, and a regeneratedMECHANICAL_DESIGN.mdwired throughcalc/report.pywithtest_report.pyso narrative numbers cannot drift from code.The report documents resolved repo contradictions (MN76 vs MN78, encoder PPR, bearing type), fills assumed survival wind/snow/seismic loads, and states blunt outcomes—six proofs pass, five fail (bearing-limited pointing deflection, baseline encoder ~5″ RMS vs 1″ target, roof uplift without anchors, passive thermal focus, 12 V off-grid autonomy)—with remediations and a weighted trade-study / v1–v2 roadmap.
Phase D CAD adds OpenSCAD housings, pier adapter, counterweight shaft, and
assembly.scad, plussvg_preview.pyand committedpreview_assembly.svgdriven live fromparams.py(test_cad.py).Reviewed by Cursor Bugbot for commit c26cb55. Bugbot is set up for automated code reviews on this repo. Configure here.