diff --git a/coverage/axis3-tutorial-web-complete.png b/coverage/axis3-tutorial-web-complete.png index a9b87ad..c9a64f1 100644 Binary files a/coverage/axis3-tutorial-web-complete.png and b/coverage/axis3-tutorial-web-complete.png differ diff --git a/coverage/axis3-tutorial-web-homed.png b/coverage/axis3-tutorial-web-homed.png index 26fe452..0b5e1a9 100644 Binary files a/coverage/axis3-tutorial-web-homed.png and b/coverage/axis3-tutorial-web-homed.png differ diff --git a/coverage/axis3-tutorial-web-manual-verification.report.json b/coverage/axis3-tutorial-web-manual-verification.report.json index 57ae2be..1c292d5 100644 --- a/coverage/axis3-tutorial-web-manual-verification.report.json +++ b/coverage/axis3-tutorial-web-manual-verification.report.json @@ -12,8 +12,8 @@ "entry": { "level": "warning", "source": "rendering", - "text": "[.WebGL-0x26b401184000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels", - "timestamp": 1787548617504.175, + "text": "[.WebGL-0x1540197c000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels", + "timestamp": 1787562371280.121, "url": "http://127.0.0.1:5175/" } } @@ -24,8 +24,8 @@ "entry": { "level": "warning", "source": "rendering", - "text": "[.WebGL-0x26b401184000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels", - "timestamp": 1787548617513.153, + "text": "[.WebGL-0x1540197c000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels", + "timestamp": 1787562371286.231, "url": "http://127.0.0.1:5175/" } } @@ -35,10 +35,10 @@ "params": { "entry": { "level": "error", - "networkRequestId": "747212.33", + "networkRequestId": "759527.32", "source": "network", "text": "Failed to load resource: the server responded with a status of 404 (Not Found)", - "timestamp": 1787548617521.543, + "timestamp": 1787562371287.092, "url": "http://127.0.0.1:5175/favicon.ico" } } @@ -49,8 +49,8 @@ "entry": { "level": "warning", "source": "rendering", - "text": "[.WebGL-0x26b401184000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels", - "timestamp": 1787548617524.14, + "text": "[.WebGL-0x1540197c000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels", + "timestamp": 1787562371299.184, "url": "http://127.0.0.1:5175/" } } @@ -61,8 +61,8 @@ "entry": { "level": "warning", "source": "rendering", - "text": "[.WebGL-0x26b401184000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels (this message will no longer repeat)", - "timestamp": 1787548617533.936, + "text": "[.WebGL-0x1540197c000]GL Driver Message (OpenGL, Performance, GL_CLOSE_PATH_NV, High): GPU stall due to ReadPixels (this message will no longer repeat)", + "timestamp": 1787562371316.08, "url": "http://127.0.0.1:5175/" } } @@ -75,32 +75,32 @@ }, "input_policy": "real browser DOM click events through CDP; real Vite/WASM/Dedicated Worker", "preview_output_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", - "report_sha256": "83171cfcb18f297a3628a4e666611c65af998f8c851cd92845ec703d743a01e1", + "report_sha256": "ac7c2c4785884392c5f3c9c61a97ef8ab6c9290a402ae9a7a3a309e840c6a521", "schema": "axis3-tutorial-web-manual-verification.v1", "screenshots": [ { - "bytes": 112654, + "bytes": 105525, "label": "ready", "path": "coverage/axis3-tutorial-web-ready.png", - "sha256": "8090814b1b5351952822f27d9b5927ae36fa3dd71355eda12127c9525984743f" + "sha256": "9b1a5f583584b5f44efd78f89b787d1a563a87da85f3b056bc59733b6aeb56d4" }, { - "bytes": 145174, + "bytes": 144742, "label": "homed", "path": "coverage/axis3-tutorial-web-homed.png", - "sha256": "127d0ce429d83bf410b7f5461b8223771a1a0374d04ed40a81e005fad8a04fca" + "sha256": "7cf0b93be19773e307e428832f73430b528b6c4323b2d28e2a87849681828056" }, { - "bytes": 144461, + "bytes": 146537, "label": "running", "path": "coverage/axis3-tutorial-web-running.png", - "sha256": "0ed52562d7f5e07f64743ec85fc1db7cc323eb357a075a2dbd688de205a817fb" + "sha256": "c301a8702158dff6204776db2d259f715ecb76b9a388449be559ed86dff29642" }, { - "bytes": 144492, + "bytes": 144270, "label": "complete", "path": "coverage/axis3-tutorial-web-complete.png", - "sha256": "3713af13105514ab8478dcb548d9766361cafb2a3453765e9cc000b1de4ecc78" + "sha256": "71973403dd6f10f560c9c92434cd6a3f71a980c757727ebd5cc3e90aee7c33cf" } ], "states": [ @@ -137,7 +137,7 @@ ], "case_status": "ready to load", "connection": "READY", - "error_text": "TASK_READYTick 0Hash fnv1a64:034bfe70d581f786Startup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationsrunaxis_taskfile_missingstepaxis_taskfile_missingpauseaxis_pause_state_gateresumeaxis_resume_state_gateabortaxis_stop_state_gaterestartaxis_taskfile_missingSource diagnosticsNo startup diagnostics", + "error_text": "NOT_LOADEDTick 0Hash -Startup resourcesNo configuration snapshotDisabled operationsrunaxis_taskfile_missingstepaxis_taskfile_missingpauseaxis_pause_state_gateresumeaxis_resume_state_gateabortaxis_stop_state_gateSource diagnosticsNo startup diagnostics", "footer": "Idle", "href": "http://127.0.0.1:5175/", "label": "ready", @@ -146,7 +146,7 @@ "position": "X0.000 Y0.000 Z0.000", "program_status": "idle", "ready_state": "complete", - "root_html": "
\",\"joint.0.motor-pos-fb\",\"ddt_x.in\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":30,\"command\":\"net\",\"tokens\":[\"Ypos\",\"joint.1.motor-pos-cmd\",\"=>\",\"joint.1.motor-pos-fb\",\"ddt_y.in\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":31,\"command\":\"net\",\"tokens\":[\"Zpos\",\"joint.2.motor-pos-cmd\",\"=>\",\"joint.2.motor-pos-fb\",\"ddt_z.in\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":35,\"command\":\"net\",\"tokens\":[\"Xvel\",\"ddt_x.out\",\"=>\",\"ddt_xv.in\",\"vel_xy.in0\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":36,\"command\":\"net\",\"tokens\":[\"Xacc\",\"<=\",\"ddt_xv.out\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":37,\"command\":\"net\",\"tokens\":[\"Yvel\",\"ddt_y.out\",\"=>\",\"ddt_yv.in\",\"vel_xy.in1\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":38,\"command\":\"net\",\"tokens\":[\"Yacc\",\"<=\",\"ddt_yv.out\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":39,\"command\":\"net\",\"tokens\":[\"Zvel\",\"ddt_z.out\",\"=>\",\"ddt_zv.in\",\"vel_xyz.in0\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":40,\"command\":\"net\",\"tokens\":[\"Zacc\",\"<=\",\"ddt_zv.out\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":43,\"command\":\"net\",\"tokens\":[\"XYvel\",\"vel_xy.out\",\"=>\",\"vel_xyz.in1\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":44,\"command\":\"net\",\"tokens\":[\"XYZvel\",\"<=\",\"vel_xyz.out\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":47,\"command\":\"net\",\"tokens\":[\"estop-loop\",\"iocontrol.0.user-enable-out\",\"iocontrol.0.emc-enable-in\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":49,\"command\":\"loadusr\",\"status\":\"checked\",\"code\":null,\"program\":\"hal_manualtoolchange\",\"capability\":\"SIM-ADAPTER\",\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":50,\"command\":\"net\",\"tokens\":[\"tool-change\",\"iocontrol.0.tool-change\",\"=>\",\"hal_manualtoolchange.change\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":51,\"command\":\"net\",\"tokens\":[\"tool-changed\",\"iocontrol.0.tool-changed\",\"<=\",\"hal_manualtoolchange.changed\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":52,\"command\":\"net\",\"tokens\":[\"tool-number\",\"iocontrol.0.tool-prep-number\",\"=>\",\"hal_manualtoolchange.number\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":53,\"command\":\"net\",\"tokens\":[\"tool-prepare-loopback\",\"iocontrol.0.tool-prepare\",\"=>\",\"iocontrol.0.tool-prepared\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":56,\"command\":\"loadusr\",\"status\":\"checked\",\"code\":null,\"program\":\"./3axis-tutorial\",\"capability\":\"WEB-EQUIV\",\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":59,\"command\":\"net\",\"tokens\":[\"j0\",\"joint.0.pos-fb\",\"=>\",\"3axis-tutorial.jointX\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":60,\"command\":\"net\",\"tokens\":[\"j1\",\"joint.1.pos-fb\",\"=>\",\"3axis-tutorial.jointY\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":61,\"command\":\"net\",\"tokens\":[\"j2\",\"joint.2.pos-fb\",\"=>\",\"3axis-tutorial.jointZ\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":64,\"command\":\"net\",\"tokens\":[\"tool_len\",\"3axis-tutorial.toollength\",\"<=\",\"motion.tooloffset.z\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"},{\"schema\":\"hal-configuration-preflight.v1\",\"line\":65,\"command\":\"net\",\"tokens\":[\"tool_rad\",\"halui.tool.diameter\",\"3axis-tutorial.tooldiameter\"],\"status\":\"checked\",\"code\":null,\"source\":\"linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\",\"resource_id\":\"hal:linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.hal\"}]},\"core\":{\"result\":0},\"status\":\"ready\",\"state_hash\":\"fnv1a64:a7f7c05da5d79f9d\"},\"axis_state\":{\"state\":\"ESTOP\",\"machine_state\":\"ESTOP\",\"operation_state\":\"IDLE\",\"source_task_state\":\"STATE_ESTOP\",\"source_interp_state\":\"INTERP_IDLE\",\"source_mode\":\"MANUAL\",\"states\":[\"ESTOP\",\"ESTOP_RESET\",\"OFF\",\"ON\",\"HOME\",\"IDLE\",\"RUNNING\",\"PAUSED\"]},\"gates\":{\"load\":{\"action\":\"load\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"run\":{\"action\":\"run\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"step\":{\"action\":\"step\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"pause\":{\"action\":\"pause\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"resume\":{\"action\":\"resume\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"abort\":{\"action\":\"abort\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"restart\":{\"action\":\"restart\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"mdi\":{\"action\":\"mdi\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"jogStart\":{\"action\":\"jogStart\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"jogStop\":{\"action\":\"jogStop\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"home\":{\"action\":\"home\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"estop\":{\"action\":\"estop\",\"enabled\":true,\"reason\":\"axis_estop_reset_available\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"recover\":{\"action\":\"recover\",\"enabled\":true,\"reason\":\"axis_recover_available\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"override\":{\"action\":\"override\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"reset\":{\"action\":\"reset\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"spindle\":{\"action\":\"spindle\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"},\"coolant\":{\"action\":\"coolant\",\"enabled\":false,\"reason\":\"axis_fault_active\",\"taskState\":\"ESTOP\",\"interpState\":\"IDLE\"}},\"visual\":{\"schema\":\"axis-visual.v1\",\"pose\":{\"x\":0,\"y\":0,\"z\":0},\"joints\":[0,0,0],\"toolpath\":[{\"id\":1,\"source_line\":5,\"start\":{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":25.4,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":0,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":2,\"source_line\":6,\"start\":{\"x\":25.4,\"y\":25.4,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":25.4,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":38.099999999999994,\"y\":38.099999999999994,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":2,\"turn\":-1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":3,\"source_line\":7,\"start\":{\"x\":25.4,\"y\":25.4,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":25.4,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":25.4,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":4,\"source_line\":8,\"start\":{\"x\":25.4,\"y\":25.4,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":44.449999999999996,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":25.4,\"z\":2.54},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":5,\"source_line\":9,\"start\":{\"x\":25.4,\"y\":44.449999999999996,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":44.449999999999996,\"z\":2.54},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":6,\"source_line\":10,\"start\":{\"x\":25.4,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":35.559999999999995,\"y\":31.75,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":44.449999999999996,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":7,\"source_line\":11,\"start\":{\"x\":35.559999999999995,\"y\":31.75,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":30.479999999999997,\"y\":38.099999999999994,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":35.559999999999995,\"y\":31.75,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":8,\"source_line\":12,\"start\":{\"x\":30.479999999999997,\"y\":38.099999999999994,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":31.75,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":30.479999999999997,\"y\":38.099999999999994,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":9,\"source_line\":13,\"start\":{\"x\":25.4,\"y\":31.75,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":35.559999999999995,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":31.75,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":10,\"source_line\":14,\"start\":{\"x\":35.559999999999995,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":35.559999999999995,\"y\":44.449999999999996,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":35.559999999999995,\"y\":44.449999999999996,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":11,\"source_line\":15,\"start\":{\"x\":35.559999999999995,\"y\":44.449999999999996,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":40.64,\"y\":44.449999999999996,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":35.559999999999995,\"y\":44.449999999999996,\"z\":2.54},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":12,\"source_line\":16,\"start\":{\"x\":40.64,\"y\":44.449999999999996,\"z\":2.54,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":40.64,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":40.64,\"y\":44.449999999999996,\"z\":2.54},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":13,\"source_line\":17,\"start\":{\"x\":40.64,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":45.72,\"y\":38.099999999999994,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":40.64,\"y\":44.449999999999996,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":14,\"source_line\":18,\"start\":{\"x\":45.72,\"y\":38.099999999999994,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":50.8,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":45.72,\"y\":38.099999999999994,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":15,\"source_line\":19,\"start\":{\"x\":50.8,\"y\":44.449999999999996,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":45.72,\"y\":38.099999999999994,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":50.8,\"y\":44.449999999999996,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":16,\"source_line\":20,\"start\":{\"x\":45.72,\"y\":38.099999999999994,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":45.72,\"y\":31.75,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":45.72,\"y\":38.099999999999994,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":17,\"source_line\":21,\"start\":{\"x\":45.72,\"y\":31.75,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":45.72,\"y\":31.75,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":18,\"source_line\":22,\"start\":{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":0,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":0,\"z\":0},\"normal\":{\"x\":0,\"y\":0,\"z\":1},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":19,\"source_line\":23,\"start\":{\"x\":25.4,\"y\":0,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":0,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":38.099999999999994,\"y\":0,\"z\":38.099999999999994},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":2,\"turn\":-1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":20,\"source_line\":24,\"start\":{\"x\":25.4,\"y\":0,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":2.54,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":0,\"z\":25.4},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":21,\"source_line\":25,\"start\":{\"x\":25.4,\"y\":2.54,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":2.54,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":2.54,\"z\":25.4},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":22,\"source_line\":26,\"start\":{\"x\":25.4,\"y\":2.54,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":2.54,\"z\":44.449999999999996},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":23,\"source_line\":27,\"start\":{\"x\":25.4,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":35.559999999999995,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":0,\"z\":44.449999999999996},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":24,\"source_line\":28,\"start\":{\"x\":35.559999999999995,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":30.479999999999997,\"y\":0,\"z\":38.099999999999994,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":35.559999999999995,\"y\":0,\"z\":31.75},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":25,\"source_line\":29,\"start\":{\"x\":30.479999999999997,\"y\":0,\"z\":38.099999999999994,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":25.4,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":30.479999999999997,\"y\":0,\"z\":38.099999999999994},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":26,\"source_line\":30,\"start\":{\"x\":25.4,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":35.559999999999995,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":25.4,\"y\":0,\"z\":31.75},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":27,\"source_line\":31,\"start\":{\"x\":35.559999999999995,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":35.559999999999995,\"y\":2.54,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":35.559999999999995,\"y\":0,\"z\":44.449999999999996},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":28,\"source_line\":32,\"start\":{\"x\":35.559999999999995,\"y\":2.54,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":40.64,\"y\":2.54,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":35.559999999999995,\"y\":2.54,\"z\":44.449999999999996},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":29,\"source_line\":33,\"start\":{\"x\":40.64,\"y\":2.54,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":40.64,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":40.64,\"y\":2.54,\"z\":44.449999999999996},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":30,\"source_line\":34,\"start\":{\"x\":40.64,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":50.8,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":40.64,\"y\":0,\"z\":44.449999999999996},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":31,\"source_line\":35,\"start\":{\"x\":50.8,\"y\":0,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":40.64,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":50.8,\"y\":0,\"z\":44.449999999999996},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":32,\"source_line\":36,\"start\":{\"x\":40.64,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":50.8,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":40.64,\"y\":0,\"z\":31.75},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":33,\"source_line\":37,\"start\":{\"x\":50.8,\"y\":0,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":50.8,\"y\":0,\"z\":31.75},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":34,\"source_line\":38,\"start\":{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":25.4,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":0,\"z\":0},\"normal\":{\"x\":0,\"y\":1,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":35,\"source_line\":39,\"start\":{\"x\":0,\"y\":25.4,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":25.4,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":38.099999999999994,\"z\":38.099999999999994},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":2,\"turn\":-1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":36,\"source_line\":40,\"start\":{\"x\":0,\"y\":25.4,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":2.54,\"y\":25.4,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":25.4,\"z\":25.4},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":37,\"source_line\":41,\"start\":{\"x\":2.54,\"y\":25.4,\"z\":25.4,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":2.54,\"y\":25.4,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":2.54,\"y\":25.4,\"z\":25.4},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":38,\"source_line\":42,\"start\":{\"x\":2.54,\"y\":25.4,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":25.4,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":2.54,\"y\":25.4,\"z\":44.449999999999996},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":39,\"source_line\":43,\"start\":{\"x\":0,\"y\":25.4,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":30.479999999999997,\"z\":38.099999999999994,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":25.4,\"z\":44.449999999999996},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":40,\"source_line\":44,\"start\":{\"x\":0,\"y\":30.479999999999997,\"z\":38.099999999999994,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":35.559999999999995,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":30.479999999999997,\"z\":38.099999999999994},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":41,\"source_line\":45,\"start\":{\"x\":0,\"y\":35.559999999999995,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":30.479999999999997,\"z\":38.099999999999994,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":35.559999999999995,\"z\":44.449999999999996},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":42,\"source_line\":46,\"start\":{\"x\":0,\"y\":30.479999999999997,\"z\":38.099999999999994,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":30.479999999999997,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":30.479999999999997,\"z\":38.099999999999994},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":43,\"source_line\":47,\"start\":{\"x\":0,\"y\":30.479999999999997,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":2.54,\"y\":30.479999999999997,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":30.479999999999997,\"z\":31.75},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":44,\"source_line\":48,\"start\":{\"x\":2.54,\"y\":30.479999999999997,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":2.54,\"y\":40.64,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":2.54,\"y\":30.479999999999997,\"z\":31.75},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":45,\"source_line\":49,\"start\":{\"x\":2.54,\"y\":40.64,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":40.64,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":2.54,\"y\":40.64,\"z\":44.449999999999996},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":46,\"source_line\":50,\"start\":{\"x\":0,\"y\":40.64,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":50.8,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":40.64,\"z\":44.449999999999996},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":47,\"source_line\":51,\"start\":{\"x\":0,\"y\":50.8,\"z\":44.449999999999996,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":40.64,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":50.8,\"z\":44.449999999999996},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":48,\"source_line\":52,\"start\":{\"x\":0,\"y\":40.64,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":50.8,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":40.64,\"z\":31.75},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"},{\"id\":49,\"source_line\":53,\"start\":{\"x\":0,\"y\":50.8,\"z\":31.75,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"end\":{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"center\":{\"x\":0,\"y\":50.8,\"z\":31.75},\"normal\":{\"x\":1,\"y\":0,\"z\":0},\"velocity\":762,\"acceleration\":0,\"motion_type\":1,\"turn\":1,\"source\":\"wasm_interpreter_canonical_motion\"}],\"active_segment_id\":0,\"source\":\"wasm_canonical_motion\"},\"authoritative\":{\"schema\":\"sim_authoritative_runtime.v1\",\"tick\":0,\"status\":\"idle\",\"program_status\":\"idle\",\"kinematics\":{\"type\":\"trivkins\",\"joint_count\":3,\"pose\":{\"x\":0,\"y\":0,\"z\":0},\"joints\":[0,0,0],\"status\":0,\"blocked\":null},\"planner\":{\"next_id\":1,\"queue\":[],\"active\":null,\"active_id\":null,\"progress\":0,\"queue_depth\":0,\"last_error\":0},\"state_hash\":\"fnv1a64:4e24908a983412f4\"},\"motion_authority\":\"wasm\",\"task_authority\":\"wasm_task_canonical\",\"state_hash\":\"fnv1a64:0ef93407e9093297\"},\"motion_authority\":\"wasm\",\"task_authority\":\"wasm_task_canonical\",\"wasm_home_limit\":{\"status\":\"verified\",\"state\":{\"schema\":\"sim_home_limit_state.v1\",\"source\":\"wasm_home_limit\",\"pose\":{\"x\":0,\"y\":0,\"z\":0,\"a\":0,\"b\":0,\"c\":0,\"u\":0,\"v\":0,\"w\":0},\"joints\":[0,0,0],\"joint_count\":3,\"homed\":false,\"home_sequence\":0,\"tick\":0,\"last_error\":0,\"limit_error\":0,\"kinematics_error\":0}},\"axis_state\":{\"state\":\"ESTOP\",\"machine_state\":\"ESTOP\",\"operation_state\":\"IDLE\",\"source_task_state\":\"STATE_ESTOP\",\"source_interp_state\":\"INTERP_IDLE\",\"source_mode\":\"MANUAL\",\"states\":[\"ESTOP\",\"ESTOP_RESET\",\"OFF\",\"ON\",\"HOME\",\"IDLE\",\"RUNNING\",\"PAUSED\"]}}", - "footer": "Error: sim_io_estop", + "error_text": "TASK_READYTick 0Hash fnv1a64:05e87e2994e816e9Startup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationsloadaxis_fault_activerunaxis_fault_activestepaxis_fault_activepauseaxis_fault_activeresumeaxis_fault_activeabortaxis_fault_activerestartaxis_fault_activemdiaxis_fault_activejogStartaxis_fault_activejogStopaxis_fault_activehomeaxis_fault_activeoverrideaxis_fault_activeresetaxis_fault_activespindleaxis_fault_activecoolantaxis_fault_activejogaxis_fault_activeSource diagnosticsNo startup diagnostics", + "footer": "ESTOP blocked: sim_io_estop", "href": "http://127.0.0.1:5175/", "label": "estop", "machine_state": "Machine ESTOP", @@ -183,7 +183,7 @@ ], "case_status": "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini + linuxcnc/configs/nc_files/3dtest.ngc loaded", "connection": "READY", - "error_text": "TASK_READYTick 0Hash fnv1a64:2ef8fd3db1a2565cStartup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationspauseaxis_pause_state_gateresumeaxis_resume_state_gateabortaxis_stop_state_gateSource diagnosticsNo startup diagnostics", + "error_text": "TASK_READYTick 0Hash fnv1a64:a2bf3ff6b3e0bb13Startup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationspauseaxis_pause_state_gateresumeaxis_resume_state_gateabortaxis_stop_state_gateSource diagnosticsNo startup diagnostics", "footer": "IO_RECOVER acknowledged", "href": "http://127.0.0.1:5175/", "label": "power", @@ -206,7 +206,7 @@ ], "case_status": "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini + linuxcnc/configs/nc_files/3dtest.ngc loaded", "connection": "READY", - "error_text": "TASK_READYTick 0Hash fnv1a64:69eb35d2b981cf84Startup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationspauseaxis_pause_state_gateresumeaxis_resume_state_gateabortaxis_stop_state_gateSource diagnosticsNo startup diagnostics", + "error_text": "TASK_READYTick 0Hash fnv1a64:f37b6faa3edb6cd9Startup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationspauseaxis_pause_state_gateresumeaxis_resume_state_gateabortaxis_stop_state_gateSource diagnosticsNo startup diagnostics", "footer": "HOME acknowledged", "href": "http://127.0.0.1:5175/", "label": "homed", @@ -229,7 +229,7 @@ ], "case_status": "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini + linuxcnc/configs/nc_files/3dtest.ngc loaded", "connection": "RUNNING", - "error_text": "TASK_READYTick 41Hash fnv1a64:8cf843955007c133Startup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationsloadaxis_interp_runningrunaxis_interp_runningresumeaxis_resume_state_gaterestartaxis_restart_state_gatemdiaxis_interp_runningjogStartaxis_manual_mode_requiredjogStopaxis_manual_mode_requiredhomeaxis_manual_mode_requiredresetaxis_reset_state_gatespindleaxis_manual_mode_requiredcoolantaxis_manual_mode_requiredjogaxis_manual_mode_requiredSource diagnosticsNo startup diagnostics", + "error_text": "TASK_READYTick 41Hash fnv1a64:c4ef679bda3a005bStartup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationsloadaxis_interp_runningrunaxis_interp_runningresumeaxis_resume_state_gaterestartaxis_restart_state_gatemdiaxis_interp_runningjogStartaxis_manual_mode_requiredjogStopaxis_manual_mode_requiredhomeaxis_manual_mode_requiredresetaxis_reset_state_gatespindleaxis_manual_mode_requiredcoolantaxis_manual_mode_requiredjogaxis_manual_mode_requiredSource diagnosticsNo startup diagnostics", "footer": "PROGRAM_RUN acknowledged", "href": "http://127.0.0.1:5175/", "label": "running", @@ -252,13 +252,13 @@ ], "case_status": "linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.ini + linuxcnc/configs/nc_files/3dtest.ngc loaded", "connection": "RUNNING", - "error_text": "TASK_READYTick 42Hash fnv1a64:d4bd9783adaf8accStartup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationsloadaxis_interp_runningrunaxis_interp_runningresumeaxis_resume_state_gaterestartaxis_restart_state_gatemdiaxis_interp_runningjogStartaxis_manual_mode_requiredjogStopaxis_manual_mode_requiredhomeaxis_manual_mode_requiredresetaxis_reset_state_gatespindleaxis_manual_mode_requiredcoolantaxis_manual_mode_requiredjogaxis_manual_mode_requiredSource diagnosticsNo startup diagnostics", + "error_text": "TASK_READYTick 41Hash fnv1a64:c4ef679bda3a005bStartup resourcesEntrypoint: linuxcnc/configs/sim/axis/vismach/3axis-tutorial/3axis-tutorial.iniResources: 4 resolved / 0 blockedHAL: 37 records / 0 blockedDisabled operationsloadaxis_interp_runningrunaxis_interp_runningresumeaxis_resume_state_gaterestartaxis_restart_state_gatemdiaxis_interp_runningjogStartaxis_manual_mode_requiredjogStopaxis_manual_mode_requiredhomeaxis_manual_mode_requiredresetaxis_reset_state_gatespindleaxis_manual_mode_requiredcoolantaxis_manual_mode_requiredjogaxis_manual_mode_requiredSource diagnosticsNo startup diagnostics", "footer": "PROGRAM_RUN acknowledged", "href": "http://127.0.0.1:5175/", "label": "complete_poll", "machine_state": "Machine ON", "operation_state": "Operation RUNNING", - "position": "X40.640 Y44.450 Z0.000", + "position": "X40.640 Y44.450 Z2.540", "program_status": "running", "ready_state": "complete", "root_html": "
dict[str, Any]: "File", "Machine", "View", "Help", "Simulation case", "Load case", "Manual Control [F3]", "MDI [F5]", "Preview", "DRO", "Run", "Pause", "Step", "Home Axis", "Tool Touch Off", "Spindle", "Coolant", - "Active G-Codes:", "Three.js / authoritative pose", + "Active G-Codes:", "AXIS source program backplot", )} axis_features = ["AXIS-UI-01", "AXIS-UI-02", "AXIS-UI-05", "AXIS-UI-06", "AXIS-UI-07", "AXIS-SHELL-01", "AXIS-MACHINE-01", "AXIS-FILE-01", "AXIS-MACHINE-03", "AXIS-VIEW-01", "AXIS-VIEW-04", "AXIS-EDIT-01", "AXIS-EDIT-03", "AXIS-CTRL-03"] feature_markers = {feature: f'data-axis-feature="{feature}"' in dom for feature in axis_features} diff --git a/web/react/src/App.tsx b/web/react/src/App.tsx index 77e54bb..b9c062c 100644 --- a/web/react/src/App.tsx +++ b/web/react/src/App.tsx @@ -191,8 +191,8 @@ export function App() {
{ setProgramText(DEFAULT_PROGRAM); setPlotCleared(false); }} /> execute("PROGRAM_STEP")} /> execute(programPaused ? "PROGRAM_RESUME" : "PROGRAM_PAUSE")} /> setBlockDelete((value) => !value)} /> setOptionalStop((value) => !value)} /> setZoom((value) => Math.min(2, value + .2))} /> setZoom((value) => Math.max(.5, value - .2))} /> { setView("z"); setRightTab("preview"); }} /> { setView("z2"); setRightTab("preview"); }} /> { setView("x"); setRightTab("preview"); }} /> { setView("y"); setRightTab("preview"); }} /> { setView("y2"); setRightTab("preview"); }} /> { setView("p"); setRightTab("preview"); }} /> setRotateMode((value) => !value)} /> { setPlotCleared(true); setCommandStatus("Live plot cleared"); }} />
Load case{caseStatus}{commandStatus}
-
-
{(["grid", "tool", "path", "live", "limits", "velocity", "offsets", "extents"] as const).map((layer) => )}
+
+
{(["path", "live", "limits", "velocity", "offsets", "extents"] as const).map((layer) => )}
{ setPlotCleared(false); execute("PROGRAM_LOAD", { source: programText, path: "main.ngc" }); }} onRun={runProgram} onStep={() => execute("PROGRAM_STEP")} canLoad={gates.load.enabled} canRun={gates.run.enabled} canStep={gates.step.enabled} currentLine={Number(state.program?.line ?? state.task?.current_line ?? 0) || null} diagnostic={state.error?.code ?? null} />
{taskState}Machine {machineState}Operation {operationState}Tool {toolNumber}{position}{state.error ? `Error: ${state.error.code}` : commandStatus}
diff --git a/web/react/src/ThreeMachineView.tsx b/web/react/src/ThreeMachineView.tsx index 41e2d61..365dcf8 100644 --- a/web/react/src/ThreeMachineView.tsx +++ b/web/react/src/ThreeMachineView.tsx @@ -2,23 +2,22 @@ import { useEffect, useRef } from "react"; import * as THREE from "three"; type ViewMode = "z" | "z2" | "x" | "y" | "y2" | "p"; -type Segment = { id?: number; source_line?: number | null; active?: boolean; rapid?: boolean; start?: Record; end?: Record }; -type Props = { axes: number[]; view?: ViewMode; zoom?: number; rotateMode?: boolean; segments?: Segment[]; showGrid?: boolean; showTool?: boolean; showPath?: boolean; showLive?: boolean; showLimits?: boolean; showVelocity?: boolean; showOffsets?: boolean; showExtents?: boolean }; +type Point = Record; +type Segment = { id?: number; source_line?: number | null; active?: boolean; rapid?: boolean; motion_type?: number; turn?: number; center?: Point; normal?: Point; start?: Point; end?: Point }; +type Props = { axes: number[]; view?: ViewMode; zoom?: number; rotateMode?: boolean; segments?: Segment[]; showPath?: boolean; showLive?: boolean; showLimits?: boolean; showVelocity?: boolean; showOffsets?: boolean; showExtents?: boolean }; -export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = false, segments = [], showGrid = true, showTool = true, showPath = true, showLive = true, showLimits = false, showVelocity = false, showOffsets = false, showExtents = false }: Props) { +export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = false, segments = [], showPath = true, showLive = true, showLimits = false, showVelocity = false, showOffsets = false, showExtents = false }: Props) { const host = useRef(null); - const axesRef = useRef(axes); const viewRef = useRef(view); const zoomRef = useRef(zoom); const rotateRef = useRef(rotateMode); const segmentsRef = useRef(segments); - const layersRef = useRef({ showGrid, showTool, showPath, showLive, showLimits, showVelocity, showOffsets, showExtents }); - axesRef.current = axes; + const layersRef = useRef({ showPath, showLive, showLimits, showVelocity, showOffsets, showExtents }); viewRef.current = view; zoomRef.current = zoom; rotateRef.current = rotateMode; segmentsRef.current = segments; - layersRef.current = { showGrid, showTool, showPath, showLive, showLimits, showVelocity, showOffsets, showExtents }; + layersRef.current = { showPath, showLive, showLimits, showVelocity, showOffsets, showExtents }; useEffect(() => { const element = host.current; @@ -32,43 +31,14 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals renderer.setPixelRatio(Math.min(globalThis.devicePixelRatio || 1, 2)); element.appendChild(renderer.domElement); - const grid = new THREE.GridHelper(8, 16, 0x405765, 0x1e303b); - grid.name = "axis-grid"; - scene.add(grid); - scene.add(new THREE.AxesHelper(2.2)); - const machine = new THREE.Group(); - machine.name = "axis-3axis-tutorial-model"; - const frameMaterial = new THREE.MeshStandardMaterial({ color: 0x7d8b91, roughness: 0.82 }); - const xMaterial = new THREE.MeshStandardMaterial({ color: 0x3d6fc4, roughness: 0.72 }); - const yMaterial = new THREE.MeshStandardMaterial({ color: 0x3f9b69, roughness: 0.72 }); - const zMaterial = new THREE.MeshStandardMaterial({ color: 0xd3ba45, roughness: 0.7 }); - const toolMaterial = new THREE.MeshStandardMaterial({ color: 0xc9e86d, emissive: 0x243200 }); - const sourceScale = 0.01; - const frameAssembly = new THREE.Group(); frameAssembly.name = "frame"; machine.add(frameAssembly); - const base = new THREE.Mesh(new THREE.BoxGeometry(2, 0.2, 5.6), frameMaterial); base.position.set(0, -0.1, 0); frameAssembly.add(base); - const column = new THREE.Mesh(new THREE.BoxGeometry(1.2, 4, 0.6), frameMaterial); column.position.set(0, 2, -2.3); frameAssembly.add(column); - const top = new THREE.Mesh(new THREE.BoxGeometry(1.6, 0.4, 1.2), frameMaterial); top.position.set(0, 4.2, -2.2); frameAssembly.add(top); - const yAssembly = new THREE.Group(); yAssembly.name = "yassembly"; machine.add(yAssembly); - const yBase = new THREE.Mesh(new THREE.BoxGeometry(2, 0.1, 2), yMaterial); yBase.position.set(0, 0.25, 0); yAssembly.add(yBase); - const xAssembly = new THREE.Group(); xAssembly.name = "xassembly"; yAssembly.add(xAssembly); - const xBase = new THREE.Mesh(new THREE.BoxGeometry(10, 0.3, 2), xMaterial); xBase.position.set(0, 0.35, 0); xAssembly.add(xBase); - const work = new THREE.Mesh(new THREE.BoxGeometry(1.4, 0.12, 1.2), new THREE.MeshStandardMaterial({ color: 0x8f9da4, roughness: 0.9 })); - work.position.set(0, 0.56, 0); xAssembly.add(work); - const zAssembly = new THREE.Group(); zAssembly.name = "zassembly"; machine.add(zAssembly); - const zBody = new THREE.Mesh(new THREE.BoxGeometry(0.6, 1.0, 0.9), zMaterial); zBody.position.set(0, 3.4, 0); zAssembly.add(zBody); - const spindle = new THREE.Mesh(new THREE.CylinderGeometry(0.3, 0.3, 1.0, 24), zMaterial); spindle.position.set(0, 2.9, 0); zAssembly.add(spindle); - const cat30 = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.3, 0.35, 20), new THREE.MeshStandardMaterial({ color: 0xd15a52 })); cat30.position.set(0, 2.35, 0); zAssembly.add(cat30); - const tool = new THREE.Mesh(new THREE.ConeGeometry(0.12, 0.8, 16), toolMaterial); tool.position.set(0, 1.85, 0); zAssembly.add(tool); - scene.add(machine); + // AXIS preview is a backplot of the source program. The Vismach solid + // model belongs to the machine view and must not be drawn in this pane. + const axesHelper = new THREE.AxesHelper(2.2); + axesHelper.name = "axis-coordinate-axes"; + scene.add(axesHelper); const pathGroup = new THREE.Group(); pathGroup.name = "axis-toolpath"; scene.add(pathGroup); const livePathGroup = new THREE.Group(); livePathGroup.name = "axis-live-toolpath"; scene.add(livePathGroup); const overlayGroup = new THREE.Group(); overlayGroup.name = "axis-overlays"; scene.add(overlayGroup); - const ambient = new THREE.HemisphereLight(0xc8e4ec, 0x111820, 1.8); - scene.add(ambient); - const key = new THREE.DirectionalLight(0xffffff, 2.2); - key.position.set(3, 6, 4); - scene.add(key); - const resize = () => { const width = Math.max(element.clientWidth, 320); const height = Math.max(element.clientHeight, 280); @@ -81,7 +51,6 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals resize(); let frame = 0; const render = () => { - const [x = 0, y = 0, z = 0] = axesRef.current; const bounds = segmentsRef.current.reduce((box, segment) => { for (const point of [segment.start ?? {}, segment.end ?? {}]) { for (const axis of ["x", "y", "z"] as const) { @@ -94,22 +63,46 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals const span = Math.max(bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, bounds.max.z - bounds.min.z, 1); const scale = Math.min(0.12, 4.2 / span); const center = { x: (bounds.min.x + bounds.max.x) / 2, y: (bounds.min.y + bounds.max.y) / 2, z: (bounds.min.z + bounds.max.z) / 2 }; - xAssembly.position.x = Number(x || 0) * sourceScale; - yAssembly.position.z = Number(y || 0) * sourceScale; - zAssembly.position.y = Number(z || 0) * sourceScale; - grid.visible = layersRef.current.showGrid; - tool.visible = layersRef.current.showTool; + // Keep the live coordinates available for the backplot marker without + // introducing a solid tool or machine mesh into the source preview. pathGroup.visible = layersRef.current.showPath; livePathGroup.visible = layersRef.current.showLive; pathGroup.clear(); livePathGroup.clear(); - const completedMaterial = new THREE.LineBasicMaterial({ color: 0x5c80a0 }); - const liveMaterial = new THREE.LineBasicMaterial({ color: 0x5fc4d8 }); + const completedMaterial = new THREE.LineBasicMaterial({ color: 0xf0f0f0 }); + const liveMaterial = new THREE.LineBasicMaterial({ color: 0xff6666 }); + const traverseMaterial = new THREE.LineBasicMaterial({ color: 0x4d8080 }); + const toView = (point: Point) => new THREE.Vector3( + (Number(point.x ?? 0) - center.x) * scale, + (Number(point.z ?? 0) - center.z) * scale, + (Number(point.y ?? 0) - center.y) * scale, + ); + const arcPoints = (segment: Segment, start: Point, end: Point, centerPoint: Point, normal: Point) => { + const startVector = new THREE.Vector3(Number(start.x ?? 0) - Number(centerPoint.x ?? 0), Number(start.y ?? 0) - Number(centerPoint.y ?? 0), Number(start.z ?? 0) - Number(centerPoint.z ?? 0)); + const endVector = new THREE.Vector3(Number(end.x ?? 0) - Number(centerPoint.x ?? 0), Number(end.y ?? 0) - Number(centerPoint.y ?? 0), Number(end.z ?? 0) - Number(centerPoint.z ?? 0)); + const axis = new THREE.Vector3(Number(normal.x ?? 0), Number(normal.y ?? 0), Number(normal.z ?? 0)); + if (!Number.isFinite(axis.length()) || axis.length() === 0 || startVector.length() === 0) return [toView(start), toView(end)]; + axis.normalize(); + let angle = Math.atan2(axis.dot(startVector.clone().cross(endVector)), startVector.dot(endVector)); + const direction = Number(segment.turn ?? 1) < 0 ? -1 : 1; + if (Math.abs(angle) < 1e-8 && startVector.distanceTo(endVector) < 1e-7) angle = direction * Math.PI * 2; + else if (angle * direction < 0) angle += direction * Math.PI * 2; + const quaternion = new THREE.Quaternion(); + const points: THREE.Vector3[] = []; + for (let index = 0; index <= 32; index += 1) { + const rotated = startVector.clone().applyQuaternion(quaternion.setFromAxisAngle(axis, angle * index / 32)); + points.push(toView({ x: Number(centerPoint.x ?? 0) + rotated.x, y: Number(centerPoint.y ?? 0) + rotated.y, z: Number(centerPoint.z ?? 0) + rotated.z })); + } + return points; + }; for (const segment of segmentsRef.current) { const start = segment.start ?? {}; const end = segment.end ?? {}; - const points = [new THREE.Vector3((Number(start.x ?? 0) - center.x) * scale, (Number(start.z ?? 0) - center.z) * scale, (Number(start.y ?? 0) - center.y) * scale), new THREE.Vector3((Number(end.x ?? 0) - center.x) * scale, (Number(end.z ?? 0) - center.z) * scale, (Number(end.y ?? 0) - center.y) * scale)]; + const points = segment.center && segment.normal && segment.motion_type === 2 + ? arcPoints(segment, start, end, segment.center, segment.normal) + : [toView(start), toView(end)]; const target = segment.active ? livePathGroup : pathGroup; - target.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(points), segment.active ? liveMaterial : completedMaterial)); + const material = segment.active ? liveMaterial : segment.motion_type === 0 || segment.rapid ? traverseMaterial : completedMaterial; + target.add(new THREE.Line(new THREE.BufferGeometry().setFromPoints(points), material)); } if (layersRef.current.showLimits) { const limits = new THREE.LineSegments(new THREE.EdgesGeometry(new THREE.BoxGeometry(5, 2, 3.5)), new THREE.LineBasicMaterial({ color: 0xd87d6c })); @@ -124,7 +117,7 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals else if (selectedView === "y") camera.position.set(0.01, 2, distance); else if (selectedView === "y2") camera.position.set(0.01, 2, -distance); else camera.position.set(6 / Math.max(0.5, zoomRef.current), 5 / Math.max(0.5, zoomRef.current), 7 / Math.max(0.5, zoomRef.current)); - camera.lookAt(0, 1.8, 0); + camera.lookAt(0, 0, 0); scene.rotation.y = rotateRef.current ? (performance.now() / 5000) % (Math.PI * 2) : 0; renderer.render(scene, camera); frame = requestAnimationFrame(render); @@ -133,5 +126,9 @@ export function ThreeMachineView({ axes, view = "p", zoom = 1, rotateMode = fals return () => { cancelAnimationFrame(frame); observer.disconnect(); renderer.dispose(); element.replaceChildren(); }; }, []); - return
Three.js / authoritative pose
; + const [x = 0, y = 0, z = 0] = axes; + const format = (value: number) => Number(value || 0).toFixed(3); + return
+
{`X:   ${format(x)}   DTG X:   ${format(-x)}\nY:   ${format(y)}   DTG Y:   ${format(-y)}\nZ:   ${format(z)}   DTG Z:   ${format(-z)}\nG54 X:   ${format(x)}   G92 X:   0.000\nG54 Y:   ${format(y)}   G92 Y:   0.000\nG54 Z:   ${format(z)}   G92 Z:   0.000\nG54 R:   0.000\nTLO X:   0.000\nTLO Y:   0.000\nTLO Z:   0.000\nVel:   0.000`}
+
; } diff --git a/web/react/src/styles.css b/web/react/src/styles.css index 1d5449e..81976b5 100644 --- a/web/react/src/styles.css +++ b/web/react/src/styles.css @@ -100,10 +100,10 @@ output { font: 12px ui-monospace, monospace; text-align: right; } .mdi-control li button:hover { color: #245d91; text-decoration: underline; } .empty-history { color: var(--muted); } -.axis-preview { display: flex; min-height: 0; flex: 1; padding: 4px; overflow: hidden; background: #101419; } -.three-viewer { position: relative; width: 100%; height: 100%; min-height: 0; flex: 1; overflow: hidden; border: 1px solid #303b43; background: #080e13; } +.axis-preview { display: flex; min-height: 0; flex: 1; padding: 4px; overflow: hidden; background: #000; } +.three-viewer { position: relative; width: 100%; height: 100%; min-height: 0; flex: 1; overflow: hidden; border: 1px solid #303030; background: #000; } .three-viewer canvas { display: block; width: 100%; height: 100%; } -.three-viewer-label { position: absolute; z-index: 1; top: 6px; left: 7px; padding: 2px 5px; color: #c9e86d; background: rgb(8 14 19 / 75%); font: 10px ui-monospace, monospace; pointer-events: none; } +.axis-preview-hud { position: absolute; z-index: 1; top: 11px; left: 34px; margin: 0; color: #f2f2f2; font: 12px/1.45 ui-monospace, monospace; white-space: pre; pointer-events: none; text-shadow: 0 1px #000; } .dro-view { background: #ececec; } .dro-mode-row, .dro-column-headings, .dro-row { display: grid; grid-template-columns: 42px repeat(3, minmax(100px, 1fr)); align-items: center; gap: 9px; } .dro-mode-row { padding: 5px 6px; border-bottom: 1px solid #888; color: #555; font-size: 11px; }