Robot-side state modules (on_state) reference
Robot-side state modules (on_state) reference
The robot reports its own state to the SDK via the agentsdk.state_request.meta event. Inside
the passive callback you receive:
PassiveCallback.on_state(agent_id, event_id, state_name, state_value)
^^^^^^^^^^ ^^^^^^^^^^^^^^^^
module name module payload (JSON-encoded string)
| Language | Override entry |
|---|---|
| Java | PassiveCallback.onState(agentId, eventId, stateName, stateValue) |
| Python | PassiveCallback.on_state(agent_id, event_id, state_name, state_value) |
⚠️
state_valuemay be a plain string, a number, an object, or an array. Parse withJSONObject.parseObject(stateValue)/json.loads(state_value)when you need structured fields.
This page enumerates every state_name and the field schema of its state_value — 22 modules
total. Each module ships with a JSON sample for direct parsing reference.
Module index
state_name | Topic | Frequency |
|---|---|---|
map_info | Map basics + navigation points | low / event |
map_2d_grid | 2-D occupancy-grid snapshot | very low |
current_location | Current semantic location | event |
robot_pose | Geometric pose | high (capped at 10 Hz) |
planned_path | Current planned path | event |
locomotion_status | Navigation execution state | event |
pnc_status | Planning / control / avoidance summary | event |
task_status | Task state list | event |
exhibit_tasks | Exhibit-tour task list | event |
silisoon | Business mode + state extension | event |
robot_form | Robot form-factor | one-off |
manipulation | Arm / grasp / manipulation status | event |
supported_calligraphy_list | Writable calligraphy characters | one-off |
tts_status | TTS runtime status | event |
vad_status | VAD runtime status | event |
dialog_status | Dialog state machine | event |
action_status | Action / skill task status | event |
listening_status | Listening / wake state | event |
wakeup_behavior_status | Wake-up behaviour override status | event |
vision_perception | Vision perception summary | high (capped at 10 Hz) |
speaker | Current speaker info | event |
settings | On-device toggle panel | event |
map_info
Map basics + navigation points.
| Field | Type | Required | Description |
|---|---|---|---|
map_id | string / number | No | Map ID |
map_name | string | No | Map name |
navi_points | array | No | Navigation point list |
walls | array | No | Wall position list |
infeasible_areas | array | No | Virtual wall position list |
walls / infeasible_areas element:
| Field | Type | Required | Description |
|---|---|---|---|
id | number | Yes | Point ID |
x | number | No | X coordinate |
y | number | No | Y coordinate |
z | number | No | Z coordinate |
navi_points element:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Point name |
id | number | Yes | Point ID |
point_x | number | No | X coordinate |
point_y | number | No | Y coordinate |
JSON sample:
{
"map_id": "MAP_001",
"map_name": "1F Lobby",
"navi_points": [
{ "name": "reception", "id": 1, "point_x": 1.2, "point_y": 3.4 },
{ "name": "pantry", "id": 2, "point_x": 5.6, "point_y": 7.8 }
],
"walls": [
{ "id": 101, "x": 0.0, "y": 0.0, "z": 0.0 },
{ "id": 102, "x": 10.0, "y": 0.0, "z": 0.0 }
],
"infeasible_areas": [
{ "id": 201, "x": 2.5, "y": 3.0, "z": 0.0 }
]
}
map_2d_grid
2-D occupancy-grid snapshot — published infrequently: only on map switch, version bump, first
full sync, or after receiving session.input_status_info.sync.
Recommended encoding:
- Raw layout:
int8 raw - Compression:
zstd - Text wrapping:
base64 - Combined
encoding:int8_zstd_base64
| Field | Type | Required | Description |
|---|---|---|---|
map_id | string / number | Yes | Map ID |
map_name | string | No | Map name |
version | string | No | Map version |
frame | string | No | Frame, e.g. map |
width | number | Yes | Grid width (cells) |
height | number | Yes | Grid height (cells) |
resolution | number | Yes | metres / cell |
origin | object | Yes | Origin with x / y / yaw |
encoding | string | Yes | Prefer int8_zstd_base64; int8_raw for debugging |
data | string | No | Compressed + base64-encoded grid bytes; may be omitted if transport.mode=resource_ref |
data_md5 | string | No | Map content digest |
compression | object | No | Bulk-data compression metadata |
transport | object | No | Bulk-data transport metadata |
compression:
| Field | Type | Required | Description |
|---|---|---|---|
raw_layout | string | No | e.g. int8_row_major |
algorithm | string | No | Prefer zstd |
binary_encoding | string | No | Prefer base64 |
transport:
| Field | Type | Required | Description |
|---|---|---|---|
mode | string | No | inline / chunked / resource_ref |
resource_uri | string | No | Map URI when using resource_ref mode |
chunk_index | number | No | Chunk index, starting from 0 |
chunk_count | number | No | Total chunk count |
JSON sample:
{
"map_id": "MAP_001",
"map_name": "1F Lobby",
"version": "v2",
"frame": "map",
"width": 1024,
"height": 1024,
"resolution": 0.05,
"origin": { "x": -25.6, "y": -25.6, "yaw": 0.0 },
"encoding": "int8_zstd_base64",
"data": "KLUv/QBYDQAA...<base64>...",
"data_md5": "9e107d9d372bb6826bd81d3542a419d6",
"compression": {
"raw_layout": "int8_row_major",
"algorithm": "zstd",
"binary_encoding": "base64"
},
"transport": { "mode": "inline" }
}
current_location
Current semantic location (high-frequency geometric pose goes to robot_pose).
| Field | Type | Required | Description |
|---|---|---|---|
location_name | string | No | Location name |
location_coordinate | string | No | Coordinate string, recommended "x,y" |
orientation | number / null | No | Heading angle (degrees recommended) |
floor | string / number | No | Floor |
building | string | No | Building / venue |
The SDK's compatibility shim
current_location.uploadaccepts both{"current_location": {...}}and the bare{"location_name": "..."}.
JSON sample:
{
"location_name": "reception",
"location_coordinate": "1.2,3.4",
"orientation": 90,
"floor": "1F",
"building": "HQ Tower"
}
robot_pose
Current geometric pose.
| Field | Type | Required | Description |
|---|---|---|---|
map_id | string / number | No | Owning map ID |
frame | string | No | map / odom / ... |
x | number | Yes | X coordinate |
y | number | Yes | Y coordinate |
z | number | No | Z coordinate |
yaw | number | Yes | Yaw (radians recommended) |
pitch | number | No | Pitch |
roll | number | No | Roll |
quaternion | object | No | Quaternion |
linear_velocity | object | No | Linear velocity |
angular_velocity | object | No | Angular velocity |
timestamp_ms | number | No | Sample timestamp |
High-frequency geometric state — the SDK's
input_status_infoupload layer caps per-module output at 10 Hz by default. The cap only throttles outbound traffic; the local cache always retains the most recent write.
JSON sample:
{
"map_id": "MAP_001",
"frame": "map",
"x": 1.234,
"y": 5.678,
"z": 0.0,
"yaw": 1.5708,
"pitch": 0.0,
"roll": 0.0,
"quaternion": { "w": 0.7071, "x": 0.0, "y": 0.0, "z": 0.7071 },
"linear_velocity": { "x": 0.3, "y": 0.0, "z": 0.0 },
"angular_velocity": { "x": 0.0, "y": 0.0, "z": 0.1 },
"timestamp_ms": 1774828800210
}
planned_path
Current planned path; replace the whole array on each update, never merge point-by-point.
| Field | Type | Required | Description |
|---|---|---|---|
path_id | string | No | Path ID |
map_id | string / number | No | Owning map ID |
frame | string | No | Frame |
planner | string | No | Planner name |
planning_status | string | Yes | running / ready / replanned / blocked / failed |
start_pose | object | No | Start pose |
target_pose | object | No | Target pose |
path_points | array | Yes | Path points |
total_length_m | number | No | Total length |
remaining_length_m | number | No | Remaining length |
eta_sec | number | No | ETA in seconds |
updated_at_ms | number | No | Last update timestamp |
JSON sample:
{
"path_id": "path_001",
"map_id": "MAP_001",
"frame": "map",
"planner": "global_planner_v2",
"planning_status": "running",
"start_pose": { "x": 0.0, "y": 0.0, "yaw": 0.0 },
"target_pose": { "x": 10.0, "y": 5.0, "yaw": 1.5708 },
"path_points": [
{ "x": 0.0, "y": 0.0 },
{ "x": 2.5, "y": 1.2 },
{ "x": 5.0, "y": 2.5 },
{ "x": 7.5, "y": 3.8 },
{ "x": 10.0, "y": 5.0 }
],
"total_length_m": 11.18,
"remaining_length_m": 8.94,
"eta_sec": 30,
"updated_at_ms": 1774828800210
}
locomotion_status
Current navigation execution status.
| Field | Type | Required | Description |
|---|---|---|---|
motion_task_id | string / number | No | Motion task ID |
task_name | string | No | Task name |
task_type | string | No | Fixed to navigation for the first phase |
state | string | Yes | waiting / running / paused / completed / failed |
target_x | number | No | Target X |
target_y | number | No | Target Y |
target_z | number | No | Target Z |
start_time_ms | number | No | Start time |
estimated_completion_ms | number | No | ETA timestamp |
timestamp_ms | number | No | Update time |
trace_id | string | No | Trace ID |
error_message | string | No | Error reason |
JSON sample:
{
"motion_task_id": "nav_001",
"task_name": "Go to pantry",
"task_type": "navigation",
"state": "running",
"target_x": 10.0,
"target_y": 5.0,
"target_z": 0.0,
"start_time_ms": 1774828800000,
"estimated_completion_ms": 1774828830000,
"timestamp_ms": 1774828810000,
"trace_id": "trace_abc123",
"error_message": ""
}
pnc_status
Planning / control / avoidance summary.
| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | running / path_block / start_replan / replan_timeout / task_finish / task_error |
detail | string | No | Short prose summary for cloud dashboards |
JSON sample:
{
"status": "path_block",
"detail": "Static obstacle ahead, replanning"
}
task_status
Task state list. Value type: array<object>.
| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | running / idle / pause, etc. |
task_name | string | Yes | Human-readable task name |
task_id | string / number | No | Task ID |
task_type | string | No | Task type, e.g. navigation / calligraphy |
message | string | No | Status message |
updated_at_ms | number | No | Last update time |
Even with a single task, send an array (length
1). For "no task but sync explicitly", send[{"state":"idle","task_name":""}].
JSON sample:
[
{
"state": "running",
"task_name": "Navigate to pantry",
"task_id": "nav_001",
"task_type": "navigation",
"message": "in progress",
"updated_at_ms": 1774828810000
}
]
exhibit_tasks
Extension module already used by aimrt_agent for exhibit-tour task lists. Value type: array.
| Field | Type | Required | Description |
|---|---|---|---|
task_name | string | Yes | Tour task name |
task_id | string / number | Yes | Tour task ID |
points | array<object> | No | Associated points |
points element:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Point name |
id | string / number | Yes | Point ID |
Updated by whole-array replacement on TE task list change. Business extension, not part of the first-phase navigation recommended set, but actively used in agent.
JSON sample:
[
{
"task_name": "HQ Tour Route A",
"task_id": "exhibit_001",
"points": [
{ "name": "reception", "id": 1 },
{ "name": "showroom", "id": 2 },
{ "name": "pantry", "id": 3 }
]
},
{
"task_name": "R&D Tour Route B",
"task_id": "exhibit_002",
"points": [
{ "name": "engineering office", "id": 4 },
{ "name": "lab", "id": 5 }
]
}
]
silisoon
Extension module written by the SDK compatibility shim waiter.silisoon.status_upload.
| Field | Type | Required | Description |
|---|---|---|---|
mode | number | Yes | Business mode: 1=interaction / 2=silisoon / 3=grasp |
silisoon_status | number | Yes | Business state: 1=delivering / 2=idle |
JSON sample:
{
"mode": 2,
"silisoon_status": 1
}
robot_form
Extension module written by the SDK compatibility shim robot.body_info.upload. Value type: string.
Example values:
"two-legged"/"four-legged"/"wheeled". The SDK writes the rawformfield straight intostatus_info.robot_form.
JSON sample (bare string):
"wheeled"
Note:
state_valuehere is a bare string, not an object. Java readsstateValuedirectly; Python usesstate_valueas-is — nojson.loadsneeded.
manipulation
Arm / grasp / manipulation capability status.
| Field | Type | Required | Description |
|---|---|---|---|
is_on | boolean | Yes | Whether the manipulation capability is currently enabled / available |
mode | string | No | Optional run mode, e.g. pick / place / assist |
updated_at_ms | number | No | Last update time |
JSON sample:
{
"is_on": true,
"mode": "pick",
"updated_at_ms": 1774828810000
}
supported_calligraphy_list
List of supported calligraphy characters. Value type: array<string>.
Useful for exposing capabilities in calligraphy / education / interaction demos. Update by whole-array replacement.
JSON sample:
["福", "禄", "寿", "喜", "hello", "happy new year"]
tts_status
TTS runtime snapshot.
| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | idle / begin / playing / finished / interrupted / failed |
item_id | string | No | Unique ID of this utterance |
event_id | string | No | Related dialog event ID |
text | string | No | Text being spoken |
domain | string | No | Domain marker — common values: • task_master — system-level utterances, priority l4–l8, rule-based• omnissdk / agent — utterances from the interaction layer (normal dialog / active flows) |
priority | number | No | Utterance priority |
error_msg | string | No | Failure reason |
in_queue_item_ids | array<string> | No | Remaining queued utterance IDs |
updated_at_ms | number | No | Last update time |
JSON sample:
{
"state": "playing",
"item_id": "item_tts_001",
"event_id": "event_dialog_001",
"text": "Sure, here is the announcement.",
"domain": "agent",
"priority": 5,
"error_msg": "",
"in_queue_item_ids": ["item_tts_002", "item_tts_003"],
"updated_at_ms": 1774828810000
}
vad_status
VAD runtime snapshot.
| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | bos / continue / eos / bos_timeout / finish |
event_id | string | No | Related dialog event ID |
updated_at_ms | number | No | Last update time |
JSON sample:
{
"state": "eos",
"event_id": "event_dialog_001",
"updated_at_ms": 1774828810000
}
dialog_status
Dialog status snapshot — covers both before and after quit_voice.
| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | idle / wake_up / waiting_asr / waiting_dm / processing_local / processing_remote / interrupted / finish |
event_id | string | No | Current dialog event ID |
before_quit_voice | boolean | No | Whether this is the last stable state before quit_voice |
source | string | No | Source, e.g. sdk_dialog_manager / agent_controller |
updated_at_ms | number | No | Last update time |
quit_voiceitself is a control event, not a state module.
JSON sample:
{
"state": "waiting_dm",
"event_id": "event_dialog_001",
"before_quit_voice": false,
"source": "sdk_dialog_manager",
"updated_at_ms": 1774828810000
}
action_status
Action / skill / running-task snapshot.
| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | idle / running / pause / completed / failed |
tag | string | No | Action tag, e.g. write / navigation / grasp |
task_name | string | No | Task name |
task_id | string / number | No | Task ID |
message | string | No | Status message |
updated_at_ms | number | No | Last update time |
Multiple concurrent tasks may be sent as an array.
JSON sample (single task):
{
"state": "running",
"tag": "write",
"task_name": "Write 福",
"task_id": "action_001",
"message": "stroke 3/5 in progress",
"updated_at_ms": 1774828810000
}
JSON sample (multi-task array):
[
{ "state": "running", "tag": "navigation", "task_name": "Go to A", "task_id": "nav_001", "updated_at_ms": 1774828810000 },
{ "state": "running", "tag": "tts", "task_name": "Explain A","task_id": "tts_001","updated_at_ms": 1774828810000 }
]
listening_status
On-device listening state.
| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | listening / non_wakeup_silent |
wakeup_state | string | Yes | already_wake_up / idle |
event_id | string | No | Current dialog / wake event ID |
source | string | No | Source, e.g. sdk_wakeup_manager |
updated_at_ms | number | No | Last update time |
listening— woken up; in listening / interaction statenon_wakeup_silent— not woken up; idle or quiet-monitoring
JSON sample:
{
"state": "listening",
"wakeup_state": "already_wake_up",
"event_id": "status_nav_001",
"source": "sdk_wakeup_manager",
"updated_at_ms": 1774828800210
}
wakeup_behavior_status
Wake-up behaviour override status — reports whether the cloud-sent agentsdk.flow wake-up
behaviour override has taken effect.
| Field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | active / expired / cleared / failed |
flow_id | string | No | Flow that triggered the override |
request_event_id | string | No | agentsdk.flow.*.request event ID that triggered the override |
ttl_ms | number | No | Keep-alive duration, default 30000 |
expires_at_ms | number | No | Local expiry timestamp |
interrupt_current_interaction | boolean | No | Whether the new wake should interrupt the current interaction |
behavior | object | No | Currently effective override; same shape as the dispatched setting.wakeup_behavior.behavior. Empty object or omitted = listen-only |
error_msg | string | No | Failure reason when state=failed |
source | string | No | Source, e.g. agentsdk.flow / agent_controller |
updated_at_ms | number | No | Last update time |
Notes:
- This module describes the state of the cloud-pushed wake-up behaviour override, not the KWS engine itself.
- On expiry, send
state=expiredand restore the default wake-up behaviour. - A new override may replace a still-live previous one.
behavior={}or omittedbehaviormeans listen-only is in effect.
JSON sample (full behaviour active):
{
"state": "active",
"flow_id": "flow_mock_demo_001",
"request_event_id": "event_wakeup_behavior_001",
"ttl_ms": 30000,
"expires_at_ms": 1774828830210,
"interrupt_current_interaction": true,
"behavior": {
"tts": { "text": "I'm here, go ahead" },
"emoticon": { "id": 103, "times": 1 },
"motion": { "id": [10226] }
},
"source": "agentsdk.flow",
"updated_at_ms": 1774828800210
}
JSON sample (listen-only):
{
"state": "active",
"flow_id": "flow_mock_demo_001",
"request_event_id": "event_wakeup_listen_only_001",
"ttl_ms": 30000,
"expires_at_ms": 1774828830210,
"interrupt_current_interaction": false,
"behavior": {},
"source": "agentsdk.flow",
"updated_at_ms": 1774828800210
}
vision_perception
Vision perception summary snapshot, optionally carrying image-relative geometry.
| Field | Type | Required | Description |
|---|---|---|---|
perception_mode | string | No | Current mode, e.g. full / only_face |
greeting_in_dialog | boolean | No | Whether full-duplex greetings are allowed |
streams | object | No | Per-stream summary keyed by stream_id |
aggregate | object | Yes | Stable cross-stream aggregated summary |
updated_at_ms | number | No | Last update time |
streams.<stream_id> recommended fields:
| Field | Type | Required | Description |
|---|---|---|---|
image_size | object | No | Original image size {width, height} |
person_count | number | Yes | Persons in this stream |
tracked_person_count | number | Yes | Stably-tracked persons in this stream |
known_face_ids | array<string> | No | Recognised face IDs in this stream |
gesture_labels | array<string> | No | Gesture labels seen in this stream |
action_labels | array<string> | No | Action labels seen in this stream |
persons | array<object> | No | Per-person geometry + pose details |
persons[] recommended fields:
| Field | Type | Required | Description |
|---|---|---|---|
track_id | number | No | Stable track ID |
global_id | string | No | Cross-cut aggregation ID |
face_uid | string | No | Recognised face ID |
identity_category | string | No | recognized_known / recognized_unknown / unspecified |
body | object | No | Body box, keypoints, hand/head boxes, body & head pose |
face | object | No | Face box, raw detection box, 5-point landmarks, face pose |
gestures | array<object> | No | Per-body gestures + normalised hand ROI |
actions | array<object> | No | Action recognition results |
aggregate recommended fields:
| Field | Type | Required | Description |
|---|---|---|---|
person_count | number | Yes | Persons currently in view |
tracked_person_count | number | Yes | Stably-tracked persons |
known_face_ids | array<string> | No | Recognised face IDs |
unknown_face_count | number | No | Visible but unrecognised faces |
facing_face_count | number | No | Faces facing the camera |
gesture_labels | array<string> | No | Active gesture labels |
action_labels | array<string> | No | Active action labels |
Geometry conventions:
- All
*_box_norm/keypoints_norm/landmarks_normuse coordinates normalised to image width and height. - Rectangle shape:
{x, y, w, h, cx, cy}with components typically in[0, 1]. - Keypoint shape:
{index, x, y, score}. - Pose may come from
face.yaw/pitch/rollorbody.head_pose.
Notes:
- The module carries normalised detection boxes / keypoints / pose alongside the summary.
- Capped at 10 Hz by default to avoid flooding the link with high-frequency geometry.
- Raw images and the full
PerceptionAggregateVieware not uploaded. - For finer-grained instantaneous notifications, pair with the custom event
vision.perception.event.
JSON sample:
{
"perception_mode": "full",
"greeting_in_dialog": true,
"streams": {
"front_cam": {
"image_size": { "width": 1280, "height": 720 },
"person_count": 2,
"tracked_person_count": 2,
"known_face_ids": ["face_uid001"],
"gesture_labels": ["wave"],
"action_labels": [],
"persons": [
{
"track_id": 1,
"global_id": "g_1",
"face_uid": "face_uid001",
"identity_category": "recognized_known",
"face": {
"box_norm": { "x": 0.29, "y": 0.17, "w": 0.05, "h": 0.11, "cx": 0.32, "cy": 0.22 },
"yaw": 4.8, "pitch": -2.1, "roll": 0.9
}
}
]
}
},
"aggregate": {
"person_count": 2,
"tracked_person_count": 2,
"known_face_ids": ["face_uid001"],
"unknown_face_count": 1,
"facing_face_count": 1,
"gesture_labels": ["wave"],
"action_labels": []
},
"updated_at_ms": 1774828810000
}
speaker
Current speaker information.
| Field | Type | Required | Description |
|---|---|---|---|
event_id | string | No | Related dialog event ID |
order | string | No | Ordering for multi-speaker scenarios, e.g. left_to_right |
image_size | object | No | Current-frame image size {width, height} |
speaker_id | string | No | Speaker ID (often matches persons[*].face_uid) |
doa | number | No | DOA estimate |
persons | array<object> | Yes | Candidate list |
persons[] fields:
| Field | Type | Required | Description |
|---|---|---|---|
face_uid | string | No | Face ID |
identity_category | string | No | recognized_known / recognized_unknown / unspecified |
user_name | string | No | User name |
user_desc | string | No | User description / note |
face | object | No | Same shape as vision_perception.persons[].face |
age | number | No | Estimated age |
gender | number | No | 0 = female / 1 = male |
JSON sample:
{
"event_id": "event_xxx",
"order": "left_to_right",
"image_size": { "width": 1280, "height": 720 },
"speaker_id": "face_uid001",
"doa": 60,
"persons": [
{
"face_uid": "face_uid001",
"identity_category": "recognized_known",
"user_name": "Zhang San",
"user_desc": "Employee #001, founding member",
"face": {
"box_norm": { "x": 0.2891, "y": 0.1667, "w": 0.0547, "h": 0.1111, "cx": 0.3164, "cy": 0.2222 },
"detected_box_norm": { "x": 0.2875, "y": 0.1639, "w": 0.0578, "h": 0.1167, "cx": 0.3164, "cy": 0.2222 },
"landmarks_norm": [
{ "index": 0, "x": 0.3023, "y": 0.2056 },
{ "index": 1, "x": 0.3305, "y": 0.2042 },
{ "index": 2, "x": 0.3164, "y": 0.2222 }
],
"yaw": 4.8,
"pitch": -2.1,
"roll": 0.9,
"facing_camera": true
},
"age": 14,
"gender": 0
}
]
}
settings
On-device toggle panel — every sub-field is essentially a bool.
| Field | Type | Required | Description |
|---|---|---|---|
greeting_in_dialog | bool | No | Whether full-duplex greetings are enabled |
JSON sample:
{
"greeting_in_dialog": true
}
Consuming on the business side
Minimal handler skeletons:
Python
import json
from linksoul_agentsdk.passive import Asr2LlmCallback
class MyCb(Asr2LlmCallback):
def on_state(self, agent_id, event_id, state_name, state_value):
if state_name == "robot_pose":
pose = json.loads(state_value)
print(f"x={pose['x']} y={pose['y']} yaw={pose['yaw']}")
elif state_name == "tts_status":
tts = json.loads(state_value)
if tts["state"] == "finished":
... # TTS finished
elif state_name == "robot_form":
# robot_form is a bare string — no json.loads needed
print(f"form = {state_value}")
def on_request(self, *a, **k):
...
Java
import com.alibaba.fastjson2.JSONObject;
@Override
public void onState(String agentId, String eventId, String stateName, String stateValue) {
switch (stateName) {
case "robot_pose" -> {
JSONObject pose = JSONObject.parseObject(stateValue);
log.info("x={} y={} yaw={}", pose.getDouble("x"), pose.getDouble("y"), pose.getDouble("yaw"));
}
case "tts_status" -> {
JSONObject tts = JSONObject.parseObject(stateValue);
if ("finished".equals(tts.getString("state"))) {
// ...
}
}
case "robot_form" -> log.info("form = {}", stateValue);
default -> { /* ignore */ }
}
}
Key points:
state_valueis not always a JSON object —robot_formis a bare string,supported_calligraphy_listisarray<string>,task_status/exhibit_tasksarearray<object>. Check the module spec on this page before parsing.- Frequency-sensitive:
robot_poseandvision_perceptionare capped per module at 10 Hz; don't run heavy I/O insideon_state. - Whole-array replacement:
planned_path/exhibit_tasks/supported_calligraphy_listetc. are replaced as full arrays — never merge point-by-point. - Explicit empty state: to signal "no task, but synced", send
task_status = [{"state":"idle","task_name":""}].