Ex: Synthetic Scene

Record a generated scene as a .vynt log with C++.

This example records a synthetic scene as a .vynt log: build each frame from generated points with VoyantFrame::synthetic(), declare the scan configuration with withSdl(), 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 into an analyzable Voyant log.

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 withSdl()
  • How to record the sequence into a normal .vynt recording

Prerequisites

  • Voyant SDK installed (see Installation)
  • No sensor needed — the scene is generated

Example Code

View the complete example on GitHub: synthetic_scene_example.cpp

Key Concepts

Generating Points

Frames are built from a std::vector<PointData>. 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 and keep the rest of the loop as is:

// Range drifts per frame so playback visibly moves
const float rangeM = 10.0f + 2.0f * std::sin(2.0f * kPi * frameNumber / 50.0f);

std::vector<PointData> points;
PointData point{};
point.range_m       = rangeM;
point.azimuth_rad   = azimuth;
point.elevation_rad = elevation;
point.azimuth_idx   = static_cast<uint16_t>(az);
point.elevation_idx = static_cast<uint16_t>(el);
point.drop_reason   = DROP_REASON_VALID;
points.push_back(point);

Building Synthetic Frames

VoyantFrame::synthetic() takes the points and a SyntheticFrameDesc carrying a software source identity and per-frame identity (timestamps and frame index). withSdl() 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:

SdlCommandParams sdl{};
sdl.req_state      = static_cast<uint8_t>(SdlState::PointCloud);
sdl.frame_rate_fps = 10.0f;
sdl.hfov_deg       = 90.0f;

VoyantFrame::SyntheticFrameDesc desc;
desc.source               = ProductId::SoftwareSimulator;
desc.timestampSeconds     = seconds;
desc.timestampNanoseconds = nanoseconds;
desc.frameIndex           = i;

std::optional<VoyantFrame> frame      = VoyantFrame::synthetic(generateWall(i), desc);
std::optional<VoyantFrame> configured = frame->withSdl(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:

VoyantRecorderConfig recConfig(outputPath);
recConfig.timestampFilename = false;
VoyantRecorder recorder(recConfig);

if (recorder.recordFrame(*configured) != RecordResult::Ok)
{
    std::cerr << "Failed to record frame " << i << std::endl;
    return 1;
}

recorder.finalize();

Building and Running

# Build the examples
mkdir build && cd build
cmake ..
make

# Record 100 frames to synthetic_scene.vynt (the defaults)
./bin/synthetic_scene_example

# Custom output path and frame count
./bin/synthetic_scene_example my_scene.vynt 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.