|
| 1 | +# MotionView API |
| 2 | +This doc covers what types of data MotionView can consume, what behavior that will lead to, and examples. See also [MVLib](../Guides/MVLib/README.md) for a working implementation example. |
| 3 | + |
| 4 | +### Notes for this doc |
| 5 | +- Anything before the type tag is parsed and removed by MotionView. |
| 6 | +- The type is decided by the first occurrence of a tag in a log. As of MotionView v1.0.0, the following tags are supported: |
| 7 | +```json |
| 8 | +[POSE] # This data is interpreted by MotionView as the current location of the robot. |
| 9 | +[WATCH] # This data is interpreted by MotionView as watch log. |
| 10 | +[LOG] # This data is interpreted by MotionView as a log message |
| 11 | +[WPOINT] # This data is interpreted by MotionView as a waypoint. |
| 12 | +``` |
| 13 | + |
| 14 | + |
| 15 | +### [POSE] Data |
| 16 | +Expected format: |
| 17 | + |
| 18 | +```log |
| 19 | +[POSE],uptime,x,y,theta,l_vel,r_vel |
| 20 | +``` |
| 21 | + |
| 22 | +- `uptime`: The time since the robot booted in milliseconds |
| 23 | +- `x`: The x position of the robot in any supported unit |
| 24 | +- `y`: The y position of the robot in any supported unit |
| 25 | +- `theta`: The angle of the robot in degrees |
| 26 | +- `l_vel`: The velocity of the left drivetrain. Expected to be (±127), however the user can manually set the speed normalization range |
| 27 | +- `r_vel`: Same as `l_vel`, but for the right drivetrain |
| 28 | + |
| 29 | +Example: |
| 30 | + |
| 31 | +```log |
| 32 | +[12.43] [INFO]: [POSE],12342,0,0,90,10,-10 |
| 33 | +``` |
| 34 | + |
| 35 | +Parsed as: |
| 36 | +```json |
| 37 | +{ |
| 38 | + "t": 12432, |
| 39 | + "x": 0, |
| 40 | + "y": 0, |
| 41 | + "theta": 90, |
| 42 | + "l_vel": 10, |
| 43 | + "r_vel": -10 |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +This type of data is used by MotionView to draw the robot. |
| 48 | + |
| 49 | +### [WATCH] Data |
| 50 | +Expected format: |
| 51 | + |
| 52 | +```log |
| 53 | +[WATCH],uptime,level,label,value |
| 54 | +``` |
| 55 | + |
| 56 | +- `uptime`: The time since the robot booted in milliseconds |
| 57 | +- `level`: The log level of the watch (DEBUG, INFO, WARN, ERROR, FATAL) |
| 58 | +- `label`: The label/name of the watch |
| 59 | +- `value`: The value of the watch |
| 60 | + |
| 61 | +Example: |
| 62 | + |
| 63 | +```log |
| 64 | +[12.43] [INFO]: [WATCH],12342,INFO,"Tongue mech state",true |
| 65 | +``` |
| 66 | + |
| 67 | +Parsed as: |
| 68 | +```json |
| 69 | +{ |
| 70 | + "t": 12432, |
| 71 | + "level": "INFO", |
| 72 | + "label": "Tongue mech state", |
| 73 | + "value": "true" |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +MotionView will format the data, and then add the watch to the Watches list of the Viewing mode sidebar. |
| 78 | + |
| 79 | +### [LOG] Data |
| 80 | +Expected format: |
| 81 | + |
| 82 | +```log |
| 83 | +[LOG],uptime,level,message |
| 84 | +``` |
| 85 | + |
| 86 | +- `uptime`: The time since the robot booted in milliseconds |
| 87 | +- `level`: The log level of the log (DEBUG, INFO, WARN, ERROR, FATAL) |
| 88 | +- `message`: The message of the log |
| 89 | + |
| 90 | +The message of the log can contain commas, as anything after the 3rd comma is considered part of the message and parsed as so. |
| 91 | + |
| 92 | +Example: |
| 93 | + |
| 94 | +```log |
| 95 | +[12.43] [INFO]: [LOG],12342,INFO,This is a log message |
| 96 | +``` |
| 97 | + |
| 98 | +Parsed as: |
| 99 | +```json |
| 100 | +{ |
| 101 | + "t": 12432, |
| 102 | + "level": "INFO", |
| 103 | + "message": "This is a log message" |
| 104 | +} |
| 105 | +``` |
| 106 | + |
| 107 | +MotionView will format the data, and then add the log to the Logs list of the Viewing mode sidebar. |
| 108 | + |
| 109 | +### [WPOINT] Data |
| 110 | +Waypoints are stateful. Unlike `[POSE]`, `[WATCH]`, or `[LOG]`, MotionView does not treat each waypoint line as an isolated record. Instead, all `[WPOINT]` lines with the same `id` are grouped into one waypoint object, and MotionView keeps track of that waypoint's current state, event history, field marker, and click-to-jump behavior. |
| 111 | + |
| 112 | +Expected format: |
| 113 | + |
| 114 | +```log |
| 115 | +[WPOINT],uptime,eventType,id,wpointName,params... |
| 116 | +``` |
| 117 | + |
| 118 | +- `uptime`: The time since the robot booted in milliseconds |
| 119 | +- `eventType`: One of `CREATED`, `OFFSET`, `REACHED`, or `TIMEDOUT` |
| 120 | +- `id`: The integer waypoint ID |
| 121 | +- `wpointName`: The human-readable waypoint name. This must not contain commas. |
| 122 | +- `params...`: Event-specific parameters described below |
| 123 | + |
| 124 | +If the line does not contain the required comma structure, MotionView treats it as malformed, ignores it for parsing, and leaves it in the live console with the red error prefix. |
| 125 | + |
| 126 | +#### `CREATED` |
| 127 | + |
| 128 | +Expected format: |
| 129 | + |
| 130 | +```log |
| 131 | +[WPOINT],uptime,CREATED,id,wpointName,targetX,targetY,targetT|NA,timeoutMs|NA,linearTolerance,thetaTolerance|NA,retriggerable |
| 132 | +``` |
| 133 | + |
| 134 | +- `targetX`: Target x position |
| 135 | +- `targetY`: Target y position |
| 136 | +- `targetT`: Target heading in degrees, or `NA` |
| 137 | +- `timeoutMs`: Timeout in milliseconds, or `NA` |
| 138 | +- `linearTolerance`: Linear tolerance |
| 139 | +- `thetaTolerance`: Angular tolerance in degrees, or `NA` |
| 140 | +- `retriggerable`: `0` or `1` |
| 141 | + |
| 142 | +Example: |
| 143 | + |
| 144 | +```log |
| 145 | +[12.32] [INFO]: [WPOINT],12342,CREATED,4,Park Zone,60,0,180,NA,2,5,1 |
| 146 | +``` |
| 147 | + |
| 148 | +Parsed as: |
| 149 | + |
| 150 | +```json |
| 151 | +{ |
| 152 | + "t": 12342, |
| 153 | + "type": "CREATED", |
| 154 | + "id": 4, |
| 155 | + "name": "Park Zone", |
| 156 | + "params": { |
| 157 | + "tarX": 60, |
| 158 | + "tarY": 0, |
| 159 | + "tarT": 180, |
| 160 | + "timeoutMs": null, |
| 161 | + "linearTol": 2, |
| 162 | + "thetaTol": 5, |
| 163 | + "retriggerable": true |
| 164 | + } |
| 165 | +} |
| 166 | +``` |
| 167 | + |
| 168 | +MotionView uses `CREATED` to create or replace the waypoint with that `id`. The waypoint is placed on the field immediately at its target location and remains there until cleared. If the same `id` appears later with a new `CREATED` event, MotionView treats that as a new session for that waypoint and drops the old waypoint state and history. |
| 169 | + |
| 170 | +#### `OFFSET` |
| 171 | + |
| 172 | +Expected format: |
| 173 | + |
| 174 | +```log |
| 175 | +[WPOINT],uptime,OFFSET,id,wpointName,offsetX,offsetY,offsetT|NA,remainingTime|NA |
| 176 | +``` |
| 177 | + |
| 178 | +- `offsetX`: Current x error from the waypoint target |
| 179 | +- `offsetY`: Current y error from the waypoint target |
| 180 | +- `offsetT`: Current angular error, or `NA` |
| 181 | +- `remainingTime`: Remaining timeout in milliseconds, or `NA` |
| 182 | + |
| 183 | +Example: |
| 184 | + |
| 185 | +```log |
| 186 | +[15.80] [INFO]: [WPOINT],15800,OFFSET,4,Park Zone,1.25,-0.50,3.0,420 |
| 187 | +``` |
| 188 | + |
| 189 | +MotionView stores the event in the waypoint's event history and shows it in the sidebar. It does not move the field marker, because field markers always stay at the original target location from `CREATED`. |
| 190 | + |
| 191 | +#### `REACHED` |
| 192 | + |
| 193 | +Expected format: |
| 194 | + |
| 195 | +```log |
| 196 | +[WPOINT],uptime,REACHED,id,wpointName,offsetX,offsetY,offsetT|NA,remainingTime|NA |
| 197 | +``` |
| 198 | + |
| 199 | +Example: |
| 200 | + |
| 201 | +```log |
| 202 | +[16.59] [INFO]: [WPOINT],16585,REACHED,4,Park Zone,0.10,0.00,1.0,150 |
| 203 | +``` |
| 204 | + |
| 205 | +MotionView stores the event and marks the waypoint as reached. For normal waypoints, `REACHED` is terminal and deactivates the waypoint. For retriggerable waypoints (`retriggerable = 1`), `REACHED` does not deactivate the waypoint, so it can continue receiving future `OFFSET` or `REACHED` events. |
| 206 | + |
| 207 | +#### `TIMEDOUT` |
| 208 | + |
| 209 | +Expected format: |
| 210 | + |
| 211 | +```log |
| 212 | +[WPOINT],uptime,TIMEDOUT,id,wpointName,offsetX,offsetY,offsetT|NA,remainingTime|NA |
| 213 | +``` |
| 214 | + |
| 215 | +Example: |
| 216 | + |
| 217 | +```log |
| 218 | +[19.25] [INFO]: [WPOINT],19250,TIMEDOUT,4,Park Zone,4.40,1.20,NA,0 |
| 219 | +``` |
| 220 | + |
| 221 | +MotionView stores the event and always treats `TIMEDOUT` as terminal. This deactivates the waypoint even if it was retriggerable. |
| 222 | + |
| 223 | +#### How MotionView handles waypoint state |
| 224 | + |
| 225 | +- All events are grouped by `id` |
| 226 | +- The field marker is drawn at the target position from the `CREATED` event |
| 227 | +- Active waypoints are shown with the active state pill and active field marker styling |
| 228 | +- Inactive waypoints stay visible on the field, but are greyed out |
| 229 | +- Retriggerable waypoints use the `RETRIGGERABLE` state pill instead of `ACTIVE` or `INACTIVE` |
| 230 | +- If a retriggerable waypoint times out, the `RETRIGGERABLE` state pill uses a dark grey background to reflect that terminal state |
| 231 | +- The sidebar shows all waypoint events in chronological order with `CREATED` at the top |
| 232 | +- The filter menu supports `All`, `Active`, and individual waypoint names |
| 233 | +- Selecting `Active` filters both the sidebar list and field markers to only active waypoints |
| 234 | + |
| 235 | +#### Clicking and jumping behavior |
| 236 | + |
| 237 | +- Clicking a waypoint in the sidebar or on the field selects and highlights that waypoint |
| 238 | +- MotionView jumps to the closest logged pose that occurred while the waypoint was active |
| 239 | +- The active interval is `CREATED.time <= pose.time <= terminalEvent.time` |
| 240 | +- For retriggerable waypoints that have not timed out, the active interval continues indefinitely |
| 241 | +- If there are no poses during the active interval, MotionView highlights the waypoint but does not move the robot |
| 242 | + |
| 243 | +#### Notes |
| 244 | + |
| 245 | +- `NA` values are accepted where shown above and are stored as unset values |
| 246 | +- Fields with unset values are omitted from MotionView's formatted waypoint details |
| 247 | +- Unknown waypoint IDs on non-`CREATED` events are ignored |
| 248 | +- Waypoint names must not contain commas |
0 commit comments