Forwarded ROS Services API
Conventions
Content-type & response format
The default response format is application/x-protobuf. Endpoints that support JSON respond with application/json when the request includes Accept: application/json. JSON bodies are generated by serializing the same protobuf message via google::protobuf::util::MessageToJsonString (proto3 JSON mapping — field names are snake_case).
Accept request header | Content-Type response | Body |
|---|---|---|
| (absent) | application/x-protobuf | binary protobuf |
application/x-protobuf | application/x-protobuf | binary protobuf |
application/json | application/json | proto3 JSON |
| (any other) | text/plain | 415 Unsupported Media Type |
Protobuf definitions
Protobuf message definitions are published as part of the @kingsimba/axbot-sdk TypeScript SDK on npm. The .proto source files are available in the axbot-ts-sdk repository. Each endpoint references its own response message.
Service index
| Method | Path | ROS source |
|---|---|---|
GET | /ros/map/overlays | /get_map_overlays (ax_msgs/GetMapOverlays) |
PUT | /ros/map/overlays | /set_map_overlays (ax_msgs/SetMapOverlays) |
GET | /ros/map/traffic_info | /get_traffic_info (ax_msgs/GetTrafficInfo) |
PUT | /ros/map/traffic_info | /set_traffic_info (ax_msgs/SetTrafficInfo) |
GET | /ros/slam/map_image | /slam/get_image (cartographer_ros_msgs/GetMapImage) |
GET | /ros/slam/submaps/{uuid}/{trajectory_id}/{submap_index} | /submap_query_v2 (cartographer_ros_msgs/SubmapQueryV2) |
GET | /ros/rosmaster/topics | ROS master API (getTopics + getSystemState) |
GET | /ros/rosmaster/topics/published_names | ROS master API (getSystemState — publishers only) |
Map Overlays
Reads or replaces the dynamic map overlays as a GeoJSON FeatureCollection. This is a raw JSON endpoint — the Accept header is ignored and the response is always application/json.
Get overlays
Proxies to the /get_map_overlays ROS service (ax_msgs/GetMapOverlays).
Route
GET /ros/map/overlays
Request
No parameters, no request body.
Response
200 application/json — the overlays as a GeoJSON FeatureCollection, passed through verbatim from the service.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[0, 0],
[1, 0],
[1, 1],
[0, 0]
]
]
},
"properties": { "kind": "speed_limit_zone" }
}
]
}
Cache behavior
Cache-Control: no-cache — overlays are dynamic state.
Additional error codes
| Status | Meaning |
|---|---|
500 | map_server returned success = false; body is its message |
Example
curl http://192.168.25.25:8090/ros/map/overlays > overlays.json
Set overlays
Proxies to the /set_map_overlays ROS service (ax_msgs/SetMapOverlays).
Route
PUT /ros/map/overlays
Request
The body is the overlays as a GeoJSON FeatureCollection with Content-Type: application/json. The body is sent verbatim as the overlays string to the ROS service.
Content-Type request header | Body |
|---|---|
application/json | GeoJSON FeatureCollection |
| (any other) | 415 Unsupported Media Type |
Response
200 application/json:
{ "success": true, "message": "" }
Additional error codes
| Status | Meaning |
|---|---|
400 | Malformed request body (invalid JSON) |
415 | Unsupported request Content-Type |
500 | map_server returned success = false; body is its message |
Example
curl -X PUT \
-H "Content-Type: application/json" \
--data-binary @overlays.json \
http://192.168.25.25:8090/ros/map/overlays
SDK usage
import { RobotApi } from "@kingsimba/axbot-sdk/robotApi";
import type { FeatureCollection } from "@kingsimba/axbot-sdk/geojson";
const api = new RobotApi({ apiBase: "http://192.168.25.25:8090" });
// Read the current overlays
const overlays: FeatureCollection = await api.getMapOverlays();
// Replace the overlays
await api.setMapOverlays(overlays);
Traffic Info
Reads or replaces the dynamic traffic info (no-passing zones) of the currently loaded map, as a lightweight JSON document. This is a raw JSON endpoint — the Accept header is ignored and the response is always application/json.
Traffic info is stored separately from Map Overlays: the server converts each zone into a Polygon feature marked properties.trafficInfo = true and appends it to the current overlays. Calling set_map or set_map_overlays discards those generated features.
Get traffic info
Proxies to the /get_traffic_info ROS service (ax_msgs/GetTrafficInfo).
Route
GET /ros/map/traffic_info
Request
No parameters, no request body.
Response
200 application/json — the traffic info JSON document.
{
// Format version; only 1 is supported.
"version": 1,
// UID of the map this traffic info belongs to.
"map_uid": "6246b10c21e1f5ce844af829",
// No-passing zone list, full-replacement semantics.
"no_passing_zones": [
{
// Unique within the list.
"id": "npz-001",
// Vertices as [x, y] pairs in map coordinates, at least 3;
// the ring is closed automatically.
"polygon": [
[1.0, 2.0],
[3.0, 2.0],
[3.0, 5.0],
[1.0, 5.0],
],
// Reserved. Stored but not evaluated in version 1 — zones are always active.
"time_rules": [],
},
],
}
Cache behavior
Cache-Control: no-cache — traffic info is dynamic state.
Additional error codes
| Status | Meaning |
|---|---|
500 | map_server returned success = false; body is its message |
Example
curl http://192.168.25.25:8090/ros/map/traffic_info > traffic_info.json
Set traffic info
Proxies to the /set_traffic_info ROS service (ax_msgs/SetTrafficInfo).
Route
PUT /ros/map/traffic_info
Request
The body is the traffic info JSON document with Content-Type: application/json. The body is sent verbatim as the traffic_info string to the ROS service.
Content-Type request header | Body |
|---|---|
application/json | Traffic info JSON |
| (any other) | 415 Unsupported Media Type |
The call is a full replacement: zones omitted from no_passing_zones are deleted, and an empty array clears every dynamic no-passing zone. map_uid must match the UID of the currently loaded map.
Response
200 application/json:
{ "success": true, "message": "" }
Additional error codes
| Status | Meaning |
|---|---|
400 | Malformed request body (invalid JSON) |
415 | Unsupported request Content-Type |
500 | map_server returned success = false; body is its message |
500 covers validation failures such as a missing map, a map_uid that does not match the currently loaded map, a duplicate zone id, or a polygon with fewer than 3 vertices.
Example
curl -X PUT \
-H "Content-Type: application/json" \
--data-binary @traffic_info.json \
http://192.168.25.25:8090/ros/map/traffic_info
SDK usage
import { RobotApi } from "@kingsimba/axbot-sdk/robotApi";
import type { TrafficInfo } from "@kingsimba/axbot-sdk/robotApiType";
const api = new RobotApi({ apiBase: "http://192.168.25.25:8090" });
// Read the current traffic info
const trafficInfo: TrafficInfo = await api.getTrafficInfo();
// Replace the no-passing zones
trafficInfo.no_passing_zones = [
{
id: "npz-001",
polygon: [
[1.0, 2.0],
[3.0, 2.0],
[3.0, 5.0],
[1.0, 5.0],
],
},
];
await api.setTrafficInfo(trafficInfo);
Submap Query V2
Route
GET /ros/slam/submaps/{uuid}/{trajectory_id}/{submap_index}
Request
| Param | Type | Where | Notes |
|---|---|---|---|
uuid | string | path | Passed through to the ROS request |
trajectory_id | integer | path | Decimal integer |
submap_index | integer | path | Decimal integer |
ver | string | query | Optional; affects cache behavior only |
No request body.
Response
ros_messages.SubmapQueryV2Response — see submap_query.proto and geometry.proto.
Cache behavior
- With
?ver=...:Cache-Control: public, max-age=31536000, immutable - Without
ver:Cache-Control: no-cache+ weakETag - Matching
If-None-Match:304 Not Modified
Additional error codes
| Status | Meaning |
|---|---|
404 | ROS service reported not found |
502 | ROS service call failed |
504 | ROS service was unavailable before timeout |
Example
curl -i \
'http://192.168.25.25:8090/ros/slam/submaps/681dc447472ac49d7b074fa1/12/3?ver=42' \
-o submap_query.pb
SLAM Map Image
Fetches the current SLAM map as a protobuf-encoded PNG image. Proxies to the /slam/get_image ROS service.
Route
GET /ros/slam/map_image
Request
| Param | Type | Where | Notes |
|---|---|---|---|
trajectory_id | integer | query | Optional. Filter by trajectory ID. |
resolution | number | query | Optional. Image resolution in m/pixel. |
new_trajectory_only | boolean | query | Optional. Only submaps from the newest trajectory. |
No request body.
Response
ros_messages.slam.GetMapImageResponse — see slam/map_image.proto and slam/status.proto.
The response includes:
| Field | Type | Notes |
|---|---|---|
origin_x | double | World X-coordinate of the map image origin. |
origin_y | double | World Y-coordinate of the map image origin. |
resolution | double | Map resolution in meters per pixel. |
png_bytes | bytes | PNG-encoded image data. |
status_code | StatusCode | Result status code (see slam/status.proto). |
status_message | string | Human-readable status message. |
Cache behavior
No caching — the map image is dynamic and reflects the current SLAM state.
Additional error codes
| Status | Meaning |
|---|---|
502 | ROS service call failed |
504 | ROS service was unavailable before timeout |
Example
# Fetch as binary protobuf
curl -H "Accept: application/x-protobuf" \
'http://192.168.25.25:8090/ros/slam/map_image' \
-o map_image.pb
# Fetch as JSON
curl -H "Accept: application/json" \
'http://192.168.25.25:8090/ros/slam/map_image' | jq .
{
"origin_x": -8.1,
"origin_y": -4.8,
"resolution": 0.05,
"status_code": "OK",
"status_message": ""
}
SDK usage
import { RobotApi } from "@kingsimba/axbot-sdk/robotApi";
const api = new RobotApi({ apiBase: "http://192.168.25.25:8090" });
const result = await api.getMapImage({ resolution: 0.05 });
if (result) {
const png = new Blob([result.message.png_bytes], { type: "image/png" });
const url = URL.createObjectURL(png);
// use url as <img src> or ImageBitmap source
}
Topic List
Lists all currently published ROS topics with type, publisher count, and subscriber count. Queries the ROS master directly.
Route
GET /ros/rosmaster/topics
Request
No parameters, no request body.
Response
ros_messages.TopicListResponse — repeated TopicInfo (name, type, publisher_count, subscriber_count). Only topics with at least one publisher are included.
See topics.proto.
Cache behavior
Cache-Control: no-cache — topic state is dynamic; no ETags.
Example
# protobuf (default)
curl http://192.168.25.25:8090/ros/rosmaster/topics | protoc --decode_raw
# JSON
curl -H "Accept: application/json" \
http://192.168.25.25:8090/ros/rosmaster/topics | jq .
{
"topics": [
{
"name": "/tf",
"type": "tf2_msgs/TFMessage",
"publisher_count": 1,
"subscriber_count": 3
}
]
}
Published Topic Names
Returns only the names of topics that have at least one publisher.
Route
GET /ros/rosmaster/topics/published_names
Request
No parameters, no request body.
Response
ros_messages.PublishedTopicNamesResponse — repeated names fields.
See topics.proto.
Cache behavior
Cache-Control: no-cache — topic state is dynamic.
Example
# protobuf (default)
curl http://192.168.25.25:8090/ros/rosmaster/topics/published_names | protoc --decode_raw
# JSON
curl -H "Accept: application/json" \
http://192.168.25.25:8090/ros/rosmaster/topics/published_names | jq .
{
"names": ["/tf", "/scan", "/odom"]
}