Troubleshooting
Self Test component
(Egret ▸ Utilities, tertiary, type "self test" in the GH search bar
to find it) and a Boolean Toggle wired to its Run input. Toggle
true. The Report output covers most of the checks below: FK / IK roundtrip,
embedded mesh load, joint-limit guard, license state, plugin version.
If Pass = true your install is healthy and the problem is in
the canvas, not the plugin.
Plugin doesn't appear in Grasshopper
- Check the file is at
%AppData%\Grasshopper\Libraries\Egret\Egret.gha. - Right-click the .gha → Properties → if there's an "Unblock" checkbox, tick it.
- Restart Rhino fully (close all instances).
- In Grasshopper, File → Special Folders → Components Folder. Verify the Egret folder is there with the .gha inside.
Components show up but Stage is empty
- Confirm Stage's Robot Meshes output isn't filtered by a downstream component. Right-click the output → Preview should be on.
- Switch viewport display mode to Shaded (right-click viewport label).
- Try dropping a fresh Stage, if you opened an old .gh canvas it might have stale serialization.
- Stage renders the LAST target by default. If no targets are wired into
T, nothing draws, wire a Pose or PTP first.
Code export is capped or blocked on the free tier
- The 30-day full-feature trial has ended and you're on the free tier, which exports up to 25 motion targets per program. Programs above that need a licence. Activate one in the License panel (Stage → double-click → License… button).
- If you've activated and export is still capped, restart Rhino. The codegen components read the license state on each solve but the GH component cache can hold stale text, a recompute fixes it.
- To verify your token is recognized: drop a
Self Testcomponent, run it, look at the "License state" line in the report.
"Invalid signature" when activating a license
- The token doesn't match the public key embedded in your build. Possible causes: (a) you got a token issued against a different version of the keypair (a rotation happened upstream); (b) the token got mangled in copy-paste (newlines, missing characters); (c) you're testing the dev test keypair tokens against a release build that's been rotated.
- Confirm the token starts with
egret-and contains exactly one period (.) between two long base64 segments. - If you're MarshRabbit Robotics rotating the signing keypair:
python tools/verify_embed.pymust print PASS before issuing any tokens.
GH upgrade dialog appears on every canvas open
Expected after any plugin upgrade that adds inputs to components you've wired into. Always click Replace, we only add inputs, never rename or remove, so all existing wires survive.
Real Meshes warning: "meshes unavailable, falling back to stick figure"
- Lite 6: embedded, should always work. If you see this for Lite 6, the .gha is corrupted; reinstall.
- xArm 5/6/7/uFactory 850: also embedded. If you see this, either Real Meshes is off, or the .gha is corrupted; reinstall.
Connect, "connect timed out"
- Bridge process isn't running. Start it with
start_bridge.bat. - Wrong Host / Port. Test with
telnet <host> 65432from this machine. - Bridge is on a remote machine and the firewall blocks port 65432.
Bridge "FAILED on robot init"
- Robot IP is wrong (passed to start_bridge.bat).
- Robot is powered down or on a different subnet.
- xArm SDK not installed:
pip install xarm-python-sdk.
IK warnings on PTP / LIN
- "did not converge", target plane is outside the robot's reach, or the orientation is unreachable in the current joint configuration. Try a different Seed input, or check Workspace for the reach envelope.
- "J<N> out of range", IK found a solution but it violates a joint limit. The solution is clamped; robot may refuse.
- "xArm 5 ... target tilts off vertical", xArm 5 is 4-DOF Cartesian only. Make your target plane have +Z aligned with world Z (or use xArm 6 / Lite 6 instead).
Live arm won't move, Enable says "ready", no error, but nothing happens
If Enable reports ready (mode 0, no fault) and Home or Live Send say they fired, but the arm doesn't move (or only crawls at a fraction of a degree per second), it's almost always one of these:
- Check the Speed input first. A
0speed tells the arm to "move at zero speed", it sits still or crawls at a fraction of a degree per second. An unwired Speed input can default to 0. Wire a sane speed (or rely on the component's default) and try again. This is the most common cause. - Re-toggle Enable. Enable now stops & flushes the controller, then re-arms and waits for it to settle to the ready state before motion is allowed. If a previous run left the arm in a stuck/queued state, a fresh Enable clears it.
- Avoid spamming moves. Firing many discrete moves back-to-back faster than the arm can execute them can leave the controller grinding through a backlog (the "crawl"). Re-toggle Enable to flush, then send one move at a time.
Generated Python script doesn't move the robot
- Confirm
arm.motion_enable(True)ran first, emergency stop state will block subsequent commands. - Check the SDK
codereturn values (script doesn't currently print them, wrap calls with logging if you need to debug). - Some SDK functions require
set_state(0)after errors. The generated header does this on connect; restart the script if mid-run errors get the controller stuck.
Live robot pose doesn't match the Sim / digital twin
If the real arm is consistently offset from Egret's Sim on a single joint by a fixed amount, a 180° offset on J6 is the classic case, the joint's zero is miscalibrated in the controller, not an Egret problem. Egret draws whatever joint angles the controller reports, so the exact same offset also shows up in uFactory Studio.
- The value is the joint's
Tx_offset(offset from the mathematical zero to the mechanical zero), stored on the controller. The xArm Python SDK has no joint-zero-offset call, fix it in uFactory Studio, not in code. - In Studio: Settings ▸ General ▸ Debugging Tools ▸ Joint.
Unlock the axis, jog the joint to the position you want to read as zero, send the
set-zero command
D13 I<n>(e.g.D13 I6for joint 6), then re-enable the joint. This captures the current position as 0. - Power-cycle / re-enable, then verify: command the joint to 0 and confirm the physical arm matches the model. Once corrected at the controller, both uFactory Studio and Egret read correctly, no plugin change needed.
- Caution: this rewrites the joint's calibration. Do one joint at a time, nothing mounted on the flange, area clear. The joint's limit window shifts with the new zero, so re-check that joint's limits afterward.
G-code generated but uFactory Studio rejects it
- Confirm Studio's G-code panel is showing the loaded file content.
- Check for
; ... NOT SUPPORTED ...comments, that's the plugin flagging a command it couldn't translate to uFactory dialect (e.g. WAIT_FOR_DI). Use Python codegen for that flow instead. - Make sure the controller firmware supports the G-code level you're using. Update via uFactory Studio if needed.
Commands succeed but the robot doesn't move
- The arm is in manual / teach mode (mode 2). In mode 2 the
controller accepts motion commands (returns code 0) but ignores them,
the joints are in free-drive. Send
Enable(orSet Mode= 0) to put it back in position control. - uFactory Studio is still connected and holding the mode. If
you used Studio (e.g. to jog or re-home) and left it open, it can keep the arm in
manual mode and override your Grasshopper
Enable. Close Studio, then re-fireEnable. - Quick check: a live
mode 0 / state 1= ready to move;mode 2= manual;state 4= stopped (send Enable).
"No Cartesian targets found, passthrough" from an offset component
Tangential Offset / Tool Axis Offset / Safe Plane operate on
RobotTargets, not raw planes. If you wired Rhino planes straight
in, convert them to targets first, run them through LIN (or
PTP) and feed those in. (All motion components now carry
their TargetPlane, so PTP targets work here too.)
Path samples skipped / "IK did not converge"
- Almost always reach. The Lite 6 reaches ~440 mm from the base; keep your geometry inside ~400 mm (≈90%), right at the edge the arm hits a singularity and IK fails. The diagnostic prints the offending TCP distance.
- The base sits at the world origin and the tool points down by default, so a
target must be reachable with that orientation. Drop a
Workspace Envelopeto see the reachable zone and pull the curve in. - Seed only fixes wrist flips once the path is reachable, it won't recover out-of-reach samples.
Lead-in / lead-out: which component?
- Tangential Offset, leads along the path direction (drag-knife entry, weld lead-in). ⚠ On a non-planar path the tangent can point into the table, watch for sub-floor moves.
- Tool Axis Offset, leads a fixed distance along the
tool axis (e.g.
D=100→ lift 100 mm straight off the work). - Safe Plane, leads to an absolute height (e.g. a plane at Z=150 → retract to a known clear Z).
Where to look for more
- Component reference, every input/output documented.
- uFactory docs, docs.ufactory.cc.
- xArm Python SDK, github.com/xArm-Developer/xArm-Python-SDK.