Ex: Synthetic Scene

Record a generated scene as a .vynt log with Python.

This example records a synthetic scene as a .vynt log: build each frame from a generated point matrix with VoyantFrame.synthetic(), declare the scan configuration with with_sdl(), and record the sequence. The output opens in the visualizer and replays like any sensor recording, identified by its SIM-SW device id — useful for turning simulator output (e.g. a Python-wrapped simulation scene) into an analyzable Voyant log.

Requires pip install voyant-api.

What You’ll Learn

  • How to build frames from generated points with VoyantFrame.synthetic()
  • How to declare the scan configuration a synthetic scene claims with with_sdl()
  • How to record the sequence into a normal .vynt recording

Prerequisites

  • Python 3.9 or later
  • voyant-api installed:
    pip install voyant-api
    
  • No sensor needed — the scene is generated

Example Code

View the complete example on GitHub: synthetic_scene_example.py

Key Concepts

Generating Points

Frames are built from a matrix in the points() column layout — VoyantFrame.points_columns() gives the column order. The example generates a wall of points on an equally spaced azimuth/elevation grid whose range drifts over time; swap the generator for your own (e.g. points sampled from a simulator scene) and keep the rest of the loop as is:

import math
import numpy as np
from voyant_api import ProductId, RecordStatus, SdlCommand, SdlState, VoyantFrame, VoyantRecorder, init_voyant_logging

init_voyant_logging()

COLS = VoyantFrame.points_columns()

# Range drifts per frame so playback visibly moves
range_m = 10.0 + 2.0 * math.sin(2.0 * math.pi * frame_number / 50.0)

matrix = np.zeros((n_points, len(COLS)))
matrix[:, COLS.index("range_m")] = range_m
matrix[:, COLS.index("azimuth_rad")] = azimuths
matrix[:, COLS.index("elevation_rad")] = elevations
matrix[:, COLS.index("drop_reason")] = 1  # valid

Building Synthetic Frames

VoyantFrame.synthetic() takes the point matrix, a software source identity, and per-frame identity (timestamps and frame index). with_sdl() then declares the configuration the scene claims to have been generated under — it replays as applied sensor configuration, visible in the visualizer’s state panels:

sdl = SdlCommand()
sdl.req_state = SdlState.PointCloud
sdl.frame_rate_fps = 10.0
sdl.hfov_deg = 90.0

frame = VoyantFrame.synthetic(
    matrix,
    source=ProductId.SoftwareSimulator,
    timestamp_seconds=seconds,
    timestamp_nanoseconds=nanoseconds,
    frame_index=i,
).with_sdl(sdl)

A synthetic frame always carries a software device identity — synthetic() rejects a real sensor’s id, so generated data cannot pass as a sensor’s. Points that did come from a real sensor but without its heartbeat (a ROS cloud, a CSV) belong in a stateless() frame, which may name it.

Recording the Sequence

Synthetic frames record like any other:

with VoyantRecorder("synthetic_scene.vynt", timestamp_filename=False) as recorder:
    for i in range(n_frames):
        frame = build_frame(i)
        if recorder.record_frame(frame) != RecordStatus.OK:
            raise SystemExit(f"Failed to record frame {i}")

Command Line Options

python synthetic_scene_example.py

# Custom output path and frame count
python synthetic_scene_example.py --output my_scene.vynt --frames 250

Expected Output

Recorded 100 synthetic frames to synthetic_scene.vynt
View it by running: voyant_visualizer --input synthetic_scene.vynt

Open the result in the visualizer — with --input as printed, or from its Open File… dialog — it plays back like a sensor recording.

Next Steps


Copyright © Voyant Photonics, Inc.

This site uses Just the Docs, a documentation theme for Jekyll.