Architecture at a glance
The idea: voice → text → a JSON plan → each step is checked against the commands the rover actually understands → the rover executes it. The model reasons; a fixed contract controls the motion. Cyberwave runs the listening nodes (Audio Track, Audio Assistant) on the device and the thinking nodes in the cloud — you don’t wire that split yourself.Prerequisites
- A UGV Beast twin with its UGV Beast Controller (teleop) policy assigned. See the UGV Beast get-started.
- A microphone twin that streams audio (this is your voice input).
- Familiarity with the Workflow editor and the node catalog.
Step 1: Create the workflow
Create a new workflow (name it UGV Rover Voice Agent) and add both twins to it: the microphone twin (audio in) and the UGV Beast twin (the rover to drive). You’ll wire nine nodes left to right. Each node’s inputs are set in the inspector — some are fixed values (# tab), some reference another node’s output using the
</> expression tab with {node-name.output} syntax.
Step 2: Capture the voice — Audio Track → Audio Assistant
Audio Track (the trigger) listens to the microphone and emits short audio clips.
Audio Assistant trims that stream down to actual speech (voice-activity
detection), so the transcriber isn’t fed silence.
Speak into the mic and open Executions — a run should fire, and Audio
Assistant should show
is_speaking: true with a captured speech segment.Step 3: Transcribe — Call Model (speech-to-text)
Add a Call Model node and pick a speech-to-text model (e.g. Faster Whisper Small EN for English).
Output:
result = the transcript, e.g. "back up a little, then turn left".
Step 4: Plan — Call Model (planner)
Add a second Call Model node and pick a capable cloud LLM or VLM (e.g. GPT-5.4, Gemini 3 Pro, or Claude). This node turns the sentence into a strict JSON driving plan. Set the Prompt to expression mode (</>) and paste the planner prompt
below. The last line pulls in the live transcript with {call-model.result}.
Planner prompt (copy into the Prompt expression field)
Planner prompt (copy into the Prompt expression field)
Leave Image URL empty. It’s for pictures, not text — the transcript belongs
in the prompt. (Wire Image URL to a camera frame only if you want a vision
variant.)
result = the JSON plan as text.
Step 5: Read the plan — JSON Parser
Add a JSON Parser to turn the plan text into structured data.
LLM fix repairs the occasional chatty wrapper (
"Sure, here's...") around the
JSON so parsing doesn’t fail.
Step 6: Know the rover’s vocabulary — Twin
Add a Twin node pointing at the UGV Beast. It reports the exact commands the rover accepts — the safe vocabulary you’ll match against.
Output used later:
control_actuations (e.g. move_forward, move_backward,
turn_left, turn_right, stop).
Step 7: Run each step — Loop
Add a Loop so the plan’s steps execute one at a time.
The loop exposes
{loop.item} (the current step) and {loop.index} each pass.
Step 8: Guardrail — Fuzzy Matcher
Wire Loop → Fuzzy Matcher. This snaps the model’s word ("backward") to the
rover’s real command ("move_backward"), and returns empty if nothing is close —
so a bad transcription can’t drive the rover.
Outputs:
matched (the real command), match (true/false), score.
Step 9: Drive — Virtual Controller
Wire Fuzzy Matcher → Virtual Controller. This publishes the matched command to the rover. Use Virtual Controller (not Send Controller Command) because it accepts a dynamic command that changes every step.Motion duration. Virtual Controller has no duration field, so how long each
command drives is governed by the UGV Beast Controller policy. Test a single
forward in simulation (Step 10) and confirm the rover moves briefly and
stops. If it keeps going, add an explicit stop step between moves.Step 10: Test in simulation
Switch the toolbar to SIMULATE — your voice is real, but the rover drives as a 3D twin in the viewer, so nothing physical can go wrong.- Confirm the mic twin is streaming and the Beast is visible in the viewer.
- Say a single command: “move forward for three seconds.”
- Open Executions → latest run and walk the nodes:
Then work through progressively harder commands:
For “back up a little, then turn left” the Loop runs twice, Fuzzy Matcher
returns
move_backward then turn_left, and the twin reverses then turns in
the viewer.Troubleshooting
Step 11: Go live
Once simulation is clean, switch the toolbar to LIVE to drive the physical Beast. The graph is unchanged — only the target flips.The one idea to take away
The model never controls speed, and never sends a command directly to the rover. It only chooses a direction and a duration, and every command is validated against the rover’s real vocabulary before it moves. That’s what makes an LLM safe to put in a robot’s control loop: the model reasons, a fixed contract acts.Next steps
The SDK version
Build the same agent in Python with the Cyberwave SDK.
Workflow nodes
Every node used here, with inputs, outputs, and where it runs.
Workflows reference
Triggers, the editor, and running in sim or live.
Add a camera (vision)
Wire a camera frame into the planner for obstacle-aware driving.