Junhyeok Lee

Applies to v0.1.0.

Network · Python API

Length-prefixed JSON over a plain TCP socket on port 7720. Native on macOS and Linux. No ROS, no Docker. This is how you drive the car, train a policy, or collect data.

SimServer does not start automatically. Press Start in the Network panel to open the listener on 7720. Launching the simulator alone is not enough.

Wire format

Every message, both directions, is a 4-byte little-endian length followed by UTF-8 JSON:

Request   {"id": N, "method": "<name>", "params_json": "<JSON string>"}
Response  {"id": N, "error": null|"<msg>", "result": "<JSON string>"}

params_json and result are double-encoded — JSON strings nested inside the outer JSON, not objects.

Methods

  • connect / disconnect — open and close the session.
  • describe — protocol, method list, and the vehicle limits block.
  • set_sync_mode {enabled} — deterministic stepping on or off.
  • reset — new episode; returns observation and info.
  • set_control {steering, throttle} — apply a control.
  • tick — step physics; returns observation, terminated, truncated, info.
  • get_observation / get_state — read without stepping.
  • get_frame_bin — binary unified sensor frame.
  • route_follow {action, steer_noise, throttle_noise} — the built-in expert autopilot.

A closed-loop episode is connectset_sync_modereset → loop(set_controltick) → disconnect. In sync mode tick advances physics; in free-run it just returns the current state.

Observation

{
  "ego_state": { "position":[x,y,z], "rotation":[x,y,z], "velocity":[x,y,z],
                 "speed":m_s, "steering":-1..1, "throttle":-1..1 },
  "lidar_ranges": [ ... ],                  // 2D scan, metres
  "imu":  { ... },                          // quat xyzw, gyro xyz, accel xyz
  "gnss": { ... },                          // sim-world metres
  "cameras": [ { "name":..., "width":..., "height":...,
                 "rgb":"<b64 jpeg>", "depth":"<b64 png>", "seg":"<b64 png>" } ],
  "route": { "cross_track_error":m, "heading_error_deg":deg,
             "distance_along":m, "distance_total":m, "advance":m,
             "segment":i, "segment_kind":"LaneFollow|Start|Branch|Reverse|Finish",
             "on_route":bool }
}

Example

The runnable examples live in the repository, not in the simulator download. drive_keyboard.py is a keyboard teleop, pure standard library, so any Python 3 runs it.

git clone https://github.com/Hyeokk/Nano-sim.git
cd Nano-sim/examples/python_api

python3 drive_keyboard.py

It asks the simulator for the car's limits rather than assuming them:

>> vehicle (describe): max_speed 0.500 m/s, lock 26.0 deg, wheelbase 0.1657 m

w/s speed, a/d steer, space stop, r reset, q quit. It needs a real terminal: POSIX only, and it exits immediately under a redirected stdin. See Environment for how the teleop scripts behave, and Vehicle control for what the values mean.

Remote simulator

--host defaults to 127.0.0.1. If the simulator runs elsewhere, point at it and open port 7720 on its firewall:

python3 drive_keyboard.py --host 192.168.0.42

Troubleshooting

  • ConnectionRefusedError — most often the simulator is running but SimServer was never started. Otherwise the host or port is wrong.
  • stdin is not a TTY — an IDE console or redirected input; use a real terminal.
  • Terminal left broken — killed with SIGKILL; run reset.