score-back/openwiki/rpc-protocol.md
Artur Mukhamadiev b8d8272f76 docs(openwiki): automate recurring documentation updates
- Add scheduled OpenWiki regeneration and pull-request workflow
- Refresh generated wiki metadata, navigation, and source documentation
- Add Doxygen configuration and ignore generated documentation output
- Publish OpenWiki guidance for Codex and Claude agents

TG-3 #ready-for-test
2026-08-27 15:15:45 +03:00

7.8 KiB
Raw Blame History

type, title, description, tags
type title description tags
Protocol RPC Protocol JSON-RPC 2.0 wire protocol over TCP — request/response formats, error codes, all RPC methods (get-stereo-calibration, get-image-pair, get-available-methods, legacy methods), and handler registration.
rpc
json-rpc
protocol
api
wire-format

RPC Protocol

JSON-RPC 2.0

The server implements JSON-RPC 2.0 over TCP with length-prefixed framing (see Architecture → Wire framing).

Batch requests are not supported — only single request objects are processed.

Request format

{
  "jsonrpc": "2.0",
  "method": "<method_name>",
  "params": {},
  "id": <integer|string>
}

The params field is accepted but currently ignored by all implemented methods. The id field is required; requests without it receive a -32600 Invalid Request error.

Success response

{
  "jsonrpc": "2.0",
  "result": <method_specific_result>,
  "id": <matching_request_id>
}

Error response

{
  "jsonrpc": "2.0",
  "error": {
    "code": <integer>,
    "message": "<string>"
  },
  "id": <matching_request_id>
}

Error codes

Code Meaning When
-32700 Parse error Request is not valid JSON
-32600 Invalid Request Missing jsonrpc, method, or id fields, or jsonrpc != "2.0"
-32601 Method not found No handler registered for the requested method name
-32000 Server error Handler threw an exception

Known issue: Non-object JSON (arrays, strings, numbers, null) causes a nlohmann::json::type_error instead of a clean -32600 response. See tests/test_rpc_edge_cases.cpp.

Source: src/rpc_server.cppRpcServer::process() and create_error().

Methods

get-stereo-calibration

Returns full stereo rig calibration: intrinsics for both cameras, stereo rotation and translation, and sensor resolution. Called once by CloudPointClient::connect().

Request:

{"jsonrpc": "2.0", "method": "get-stereo-calibration", "id": 1}

Response:

{
  "left":  { "camera_matrix": [9 doubles], "dist_coeffs": [5 doubles] },
  "right": { "camera_matrix": [9 doubles], "dist_coeffs": [5 doubles] },
  "rotation":    [9 doubles],
  "translation": [3 doubles],
  "image_size":  { "width": 640, "height": 480 }
}

All matrices are row-major. camera_matrix is the 3×3 intrinsic matrix; rotation is the 3×3 left-to-right rotation (OpenCV convention); translation is in metres. Calibration arrays are plain JSON doubles — not Base64.

Test mock defaults: fx=fy=800, cx=320, cy=240, zero distortion, R=I, T=[-0.06, 0, 0], 640×480.


get-image-pair

Returns a synchronised stereo frame as two base64-encoded images. Called on each CloudPointClient::compute_cloud().

Request:

{"jsonrpc": "2.0", "method": "get-image-pair", "id": 2}

Response:

{
  "frame": 42,
  "left":  { "width": 640, "height": 480, "type": "BGR", "data": "<base64>" },
  "right": { "width": 640, "height": 480, "type": "BGR", "data": "<base64>" }
}

data is Base64-encoded raw pixel bytes (standard alphabet, no line breaks). type is "BGR" (3 ch), "RGBA" (4 ch), or "DEPTH" (1 ch float32). Unity must flip GPU readback vertically before encoding (wire format is top-left-origin row-major).

DTOs: StereoCalibrationDto and ImagePairDto in include/cloud_point_rpc/rpc_dto.hpp. Decoded client-side via Base64RPCCoder.


get-available-methods

Returns the names of all methods registered on the server. Auto-registered in the RpcServer constructor — not added by the application. Useful for client-side discovery.

Request:

{"jsonrpc": "2.0", "method": "get-available-methods", "id": 5}

Response:

{"jsonrpc": "2.0", "result": ["get-available-methods", "get-stereo-calibration", "get-image-pair"], "id": 5}

Result is a JSON array of method-name strings, including get-available-methods itself. Tested in tests/test_integration.cpp (ClientRetrieveRemoteMethods).

Source: src/rpc_server.cppRpcServer::RpcServer() constructor; get_method_names().


get-intrinsic-params (legacy)

Retrieves left-camera intrinsic parameters as a flat 3×3 matrix (row-major, 9 doubles). Not used by CloudPointClient; kept for backward compatibility.

Request:

{"jsonrpc": "2.0", "method": "get-intrinsic-params", "id": 3}

Response:

{"jsonrpc": "2.0", "result": [fx, 0, cx, 0, fy, cy, 0, 0, 1], "id": 3}

Result: 9 plain JSON doubles. Not Base64.

get-extrinsic-params (legacy)

Retrieves left-camera extrinsic matrix as a flat 4×4 matrix (row-major, 16 doubles). Not used by CloudPointClient; kept for backward compatibility.

Request:

{"jsonrpc": "2.0", "method": "get-extrinsic-params", "id": 4}

Response:

{"jsonrpc": "2.0", "result": [16 doubles], "id": 4}

Result: 16 plain JSON doubles. Not Base64.

get-cloud-point

Retrieves the current field-of-view point cloud.

Request:

{"jsonrpc": "2.0", "method": "get-cloud-point", "id": 3}

Response:

{"jsonrpc": "2.0", "result": {"width": int, "height": int, "data": <base64-encoded-array>}, "id": 3}

Result type: matrix WxH (list of [x, y, z] points), Base64-encoded.

Note

: The standalone mock server (server_main.cpp) returns these as raw JSON arrays (not Base64-encoded) via Service. The Base64 encoding is expected to be implemented on the Unity side per API.md.

Handler registration

Handlers are registered with RpcServer::register_method(). Two forms exist:

C++ handler

rpc_server.register_method("get-intrinsic-params", [&](const json& params) {
    return service.get_intrinsic_params();  // returns vector<double>
});

The handler returns std::variant<nlohmann::json, std::string>. If a json is returned, it is placed directly in the result field. If a std::string is returned, it is placed as-is.

C callback handler

rpc_string* my_callback(rpc_string* params_json) {
    // params_json->s contains the JSON params as a string
    // return a result string (JSON or raw)
    return crpc_str_create("result_data", 11);
}

rpc_server.register_method("my-method", my_callback);

The C callback receives the JSON params as a string in rpc_string->s. The return value's string is parsed as JSON if possible; otherwise it is used as a raw string in the result field.

Source: src/rpc_server.cppregister_method(name, callback_t) overload.

Base64 encoding

include/cloud_point_rpc/rpc_coder.hpp, src/rpc_coder.cpp

  • Base64RPCCoder implements the IRPCCoder interface with encode() and decode() methods.
  • Uses the aklomp/base64 library (Meson wrap subprojects/aklomp-base64.wrap).
  • encode(vector<char>) → string and decode(string) → vector<char>.
  • Includes overflow protection: throws std::length_error if input exceeds safe size limits.

Per API.md: only image pixel data (get-image-pair data fields) uses Base64. Calibration arrays (camera_matrix, dist_coeffs, rotation, translation) and legacy params are plain JSON doubles — never Base64. Unity encodes images before sending; the C++ client decodes them via Base64RPCCoder.

Client-side usage

include/cloud_point_rpc/rpc_client.hpp

RpcClient wraps jsonrpccxx::JsonRpcClient and provides typed access:

score::TCPConnector connector(ip, port);
score::RpcClient client(connector);

auto intrinsic = client.get_intrinsic_params();   // vector<double>
auto extrinsic = client.get_extrinsic_params();   // vector<double>
auto cloud     = client.get_cloud_point();        // vector<vector<double>>

The interactive CLI (src/cli.cpp) and minimal_client (src/minimal_client.cpp) demonstrate client usage.