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
.vyntrecording
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
- Synthetic Scene (Python) — the same flow with
VoyantFrame.synthetic() - Playback — read back the recorded scene
- API Documentation — full
VoyantFramereference