Camera Sensor Model
\tableofcontents
In Chrono:Sensor:ChCameraSensor, the synthetic data is generated via GPU-based ray-tracing. By leveraging hardware accelerated support and the headless rendering capabilities provided by NVIDIA Optix Library.
Camera sensor Setup
chrono::ChFrame<double> offset_pose({10, 2, .5}, // Position
QuatFromAngleAxis(CH_PI, {0, 0, 1})); // Rotation
auto Camera = chrono_types::make_shared<ChCameraSensor>(
parent_body, // body camera is attached to
update_rate, // update rate in Hz
offset_pose, // offset pose
image_width, // image width
image_height, // image height
fov, // camera's horizontal field of view
alias_factor, // supersample factor for antialiasing
lens_model, // lens model for optional distortion
use_global_illumination, // optional for enabling global illumination on camera
gamma, // optionally set the gamma correction exponent (defaults to 2.2)
use_fog // optionally enable fog for this camera
);
Camera->SetName("Camera Sensor");
Camera->SetLag(lag);
Camera->SetCollectionWindow(exposure_time);
// Sensor data access filter
Camera->PushFilter(chrono_types::make_shared<ChFilterRGBA8Access>());
// Add sensor to manager
manager->AddSensor(Camera);
See [ChCameraSensor](@ref chrono::sensor::ChCameraSensor) for more details.
The camera setup process will automatically add the [Optix Render Filter](@ref chrono::sensor::ChFilterOptixRender) to the filter list
If the camera supersample_factor is greater than 1, the setup process will adjust the resolution and append the [Image Alias Filter](@ref chrono::sensor::ChFilterImgAlias) to the filter list.
Rendering steps
The Camera sensor in Chrono::sensor uses Optix as the render engine. For each pixel, the engine will shoot out a ray at that direction and find the first object intersects with the ray. By default, the engine uses the physically based BRDF shader for rendering objects. It will spawn additional rays for shadows, reflection, and refraction in a recursive fashion.
The camera update frequency is much slower than the physics. Therefore the [ChOptixEngine](@ref chrono::sensor::ChOptixEngine) spawns a thread to perform the rendering, and it will not block the main thread
Each Update (main thread)
Check if there is any camera need to be updated. If there is such camera
Update the scene information
Push it into render queue
Check if any camera should have the data ready to ship, or wait until they finish.
Continue to the next time step
Rendering thread
Wait until there is a camera in the render queue
Update those camera, clear the render queue, go back to step 1
Filter Graphs
Any number of filters can be append to the list and modify the final result. The filters are executed as the order in filter list. Here are some examples.
[Camera Noise](@ref chrono::sensor::ChFilterCameraNoiseConstNormal)
[Image Alias Filter](@ref chrono::sensor::ChFilterImgAlias)
[Transfer to Gray scale](@ref chrono::sensor::ChFilterGrayscale)
[Save Result](@ref chrono::sensor::ChFilterSave)
[Visualize Result](@ref chrono::sensor::ChFilterVisualize)
Camera animation
The position and rotation of the camera can be easily changed using SetOffsetPose
during simulation
Camera->SetOffsetPose(chrono::ChFrame<double>({8, 2, .5}, // Position
QuatFromAngleAxis(CH_PI, {0, 0, 1}))); // Rotation
Data access
Data will be ready after the lag time. To access
RGBA_ptr = Camera->GetMostRecentBuffer<UserRGBA8BufferPtr>();
if (RGBA_ptr->Buffer) {
unsigned int height = RGBA_ptr->Height;
unsigned int width = RGBA_ptr->Width;
PixelRGBA8 pixel_at_100_100 = RGBA_ptr->Buffer[100 * width + 100];
uint8_t red_channel_at_100_100 = unsigned(pixel_at_100_100.R);
}
Last updated