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>
76 lines
3.3 KiB
C#
76 lines
3.3 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|