2026: OpenSCAD robot and remote, physical joint limits, model in Unity
hardware/openscad/ rebuilds the broken Fusion models as OpenSCAD: body (top/bottom plate, standoffs, battery bay, switch), legs (coxa bracket, femur link, tibia, horn adapters, TPU socks, servo cables), the whole robot, and the remote (shell, lid, Nextion 3.5", JH-D400X-R4 sticks, 18650 UPS board, IMU, Teensy 4.0, USB-C breakout). Every part was checked by slicing against the original STEP solids; the original's bugs are fixed and listed in PLANNING.md. The robot now uses a hexagon leg layout (corner legs 60 deg round from the mid legs; the corner coxa brackets need turning on their splines). Physical limits from a collision sweep of the model are in Config.h: per-leg coxa limits and LEG_CLEARANCE_MM 56 (a leg is 55.2 mm wide at the joints); the sim API exports them (version 7). sim_smoke passes. Unity loads the model (export_unity.py -> Resources/OpenScadModel, OpenScadModel.cs builds a new rig in place of the old scene's robot). The PCB model's mounting holes now use the exact EasyEDA grid. README shows renders of both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b1c94e4149
commit
91b5b99fd5
42 files changed
+1560
-20
No files matched your search
+75
@@ -0,0 +1,75 @@
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
|
||||
namespace HexapodSim
|
||||
{
|
||||
// Batch-mode check of the OpenSCAD model in Main.unity, without entering
|
||||
// Play mode: builds the model from the DLL's geometry, poses the legs in
|
||||
// the firmware's standing pose and renders the main camera to PNGs.
|
||||
// Unity.exe -batchmode -projectPath . -executeMethod HexapodSim.OpenScadModelSnapshot.Run
|
||||
// -snapshotDir <folder> -quit
|
||||
public static class OpenScadModelSnapshot
|
||||
{
|
||||
public static void Run()
|
||||
{
|
||||
string dir = Arg("-snapshotDir") ?? Path.GetFullPath("Temp/OpenScadSnapshot");
|
||||
Directory.CreateDirectory(dir);
|
||||
EditorSceneManager.OpenScene("Assets/Main.unity");
|
||||
|
||||
Transform chassis = null;
|
||||
foreach (var t in Object.FindObjectsByType<Transform>())
|
||||
if (t.name == "Leg" && t.Find("hip1") != null) { chassis = t.parent; break; }
|
||||
if (chassis == null) { Debug.LogError("[Snapshot] no leg rig in Main.unity"); EditorApplication.Exit(1); return; }
|
||||
|
||||
string dll = Path.GetFullPath(Path.Combine(Application.dataPath, "..", "..", "sim", "build", "hexapod_sim.dll"));
|
||||
HxGeometry g;
|
||||
using (var native = HexapodSimNative.Load(dll)) g = native.Geometry;
|
||||
OpenScadModel.Build(chassis, g, ForwardAxis.NegativeX, 0.1f);
|
||||
|
||||
// Firmware stance: coxa 0, femur -1.2, tibia -98.3 (HexapodSimulation.ApplyJoints).
|
||||
foreach (Transform leg in chassis)
|
||||
{
|
||||
if (leg.name != "Leg" || !leg.gameObject.activeSelf) continue;
|
||||
var hip2 = leg.Find("hip1/Hip2");
|
||||
var knie = leg.Find("hip1/Hip2/Knie");
|
||||
hip2.localRotation = Quaternion.Euler(1.2f, 0, 0);
|
||||
knie.localRotation = Quaternion.Euler(-(-98.3f + 90f), 0, 0);
|
||||
}
|
||||
|
||||
var cam = Camera.main;
|
||||
if (cam == null) cam = new GameObject("SnapshotCamera").AddComponent<Camera>();
|
||||
Vector3 c = chassis.position;
|
||||
Shoot(cam, c + new Vector3(-30, 22, -38), c, Path.Combine(dir, "front_left.png"));
|
||||
Shoot(cam, c + new Vector3(42, 30, 20), c, Path.Combine(dir, "rear_right.png"));
|
||||
Shoot(cam, c + new Vector3(0.01f, 60, 0), c, Path.Combine(dir, "top.png"));
|
||||
Debug.Log("[Snapshot] wrote " + dir);
|
||||
EditorApplication.Exit(0);
|
||||
}
|
||||
|
||||
static void Shoot(Camera cam, Vector3 pos, Vector3 target, string file)
|
||||
{
|
||||
cam.transform.position = pos;
|
||||
cam.transform.LookAt(target);
|
||||
cam.fieldOfView = 45;
|
||||
var rt = new RenderTexture(1280, 900, 24);
|
||||
cam.targetTexture = rt;
|
||||
cam.Render();
|
||||
RenderTexture.active = rt;
|
||||
var tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false);
|
||||
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
|
||||
tex.Apply();
|
||||
File.WriteAllBytes(file, tex.EncodeToPNG());
|
||||
cam.targetTexture = null;
|
||||
RenderTexture.active = null;
|
||||
}
|
||||
|
||||
static string Arg(string name)
|
||||
{
|
||||
var a = System.Environment.GetCommandLineArgs();
|
||||
for (int i = 0; i < a.Length - 1; i++) if (a[i] == name) return a[i + 1];
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user