Rust数据可视化插件库rerun_c的使用:高性能实时渲染与3D场景重建工具
Rust数据可视化插件库rerun_c的使用:高性能实时渲染与3D场景重建工具
rerun_c介绍
rerun_c是rerun系列crate的一部分,提供了Rerun的C语言绑定。目前版本为0.24.0,采用MIT或Apache-2.0双协议授权。
安装方式
在项目目录中运行以下Cargo命令:
cargo add rerun_c
或者在Cargo.toml中添加:
rerun_c = "0.24.0"
示例代码
以下是一个使用rerun_c进行3D场景重建的基本示例:
use rerun_c as rr;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化Rerun记录器
let rec = rr::RecordingStreamBuilder::new("scene_reconstruction").spawn()?;
// 创建3D点云数据
let points = vec![
rr::components::Point3D::new(0.0, 0.0, 0.0),
rr::components::Point3D::new(1.0, 0.0, 0.0),
rr::components::Point3D::new(0.0, 1.0, 0.0),
rr::components::Point3D::new(0.0, 0.0, 1.0),
];
// 记录点云数据
rec.log(
"points",
&rr::archetypes::Points3D::new(points)
.with_colors([255, 0, 0, 255]) // 红色
.with_radii([0.05]),
)?;
// 添加相机视图
rec.log(
"world/camera",
&rr::archetypes::Pinhole::from_focal_length_and_resolution(
[500.极, 500.0], // 焦距
[640, 480], // 分辨率
)
.with_camera_xyz(rr::components::ViewCoordinates::RDF), // 右-下-前坐标系
)?;
Ok(())
}
完整示例:实时3D可视化
以下是更完整的示例,展示如何实时更新3D场景:
use rerun_c as rr;
use std::f32::consts::TAU;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let rec = rr::RecordingStreamBuilder::new("3d_visualization").spawn()?;
// 设置坐标系
rec.log_timeless("world", &rr::archetypes::Axes3D::default())?;
// 动画循环
for i in 0..100 {
let time = i as f32 * 0.1;
// 创建螺旋形点云
let points: Vec<_> = (0..100)
.map(|j| {
let angle = j as f32 * 0.1;
rr::components::Point3D::new(
angle.cos() * 2.0,
angle.sin() * 2.0,
time * 0.5,
)
})
.collect();
// 记录当前帧的点云
rec.set_time_seconds("sim_time", time.into());
rec.log(
"world/spiral",
&rr::archetypes::Points3D::new(points)
.with_colors([0, (time * 50.0) as u8, 255, 255])
.with_radii([0.03]),
)?;
// 添加文字说明
rec.log(
"world/text",
&rr::archetypes::TextDocument::new(format!("Frame: {}, Time: {:.1}s", i, time)),
)?;
std::thread::sleep(std::time::Duration::from_millis(100));
}
Ok(())
}
功能特点
- 高性能实时渲染:rerun_c针对实时可视化进行了优化
- 3D场景重建:支持点云、网格、相机视图等多种3D数据类型
- 时间序列支持:可以记录和回放随时间变化的数据
- 跨平台:支持多种操作系统和架构
请注意,当前rerun_c仍处于开发阶段,API可能会有变动。建议定期检查更新日志以获取最新功能和改进。
1 回复
Rust数据可视化插件库rerun_c的使用:高性能实时渲染与3D场景重建工具
介绍
rerun_c是一个用于Rust的高性能数据可视化库,专注于实时渲染和3D场景重建。它特别适合需要可视化复杂科学数据、3D点云、机器人感知数据或任何需要实时可视化的应用场景。
主要特点:
- 实时数据流可视化
- 支持2D和3D渲染
- 高性能渲染引擎
- 跨平台支持
- 易于集成到现有Rust项目中
安装方法
在Cargo.toml中添加依赖:
[dependencies]
rerun_c = "0.8" # 请使用最新版本
基本使用方法
1. 简单2D点集可视化
use rerun_c::{
components::{ColorRGBA, Point2D},
MsgSender, RecordingStreamBuilder,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (rec_stream, _server_handle) = RecordingStreamBuilder::new("my_app").connect()?;
let points = vec![
Point2D::new(0.0, 0.0),
Point2D::new(1.0, 1.0),
Point2D::new(2.0, 0.5),
Point2D::new(3.0, 1.5),
];
let colors = vec![
ColorRGBA::from_rgb(255, 0, 0),
ColorRGBA::from_rgb(0, 255, 0),
ColorRGBA::from_rgb(0, 0, 255),
ColorRGBA::from_rgb(255, 255, 0),
];
MsgSender::new("points")
.with_component(&points)?
.with_component(&colors)?
.send(&rec_stream)?;
Ok(())
}
2. 3D点云可视化
use rerun_c::{
components::{ColorRGBA, Point3D, Radius},
MsgSender, RecordingStreamBuilder,
};
use rand::Rng;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (rec_stream, _server_handle) = RecordingStreamBuilder::new("point_cloud_demo").connect()?;
let mut rng = rand::thread_rng();
let mut points = Vec::new();
let mut colors = Vec::new();
for _ in 0..1000 {
points.push(Point3D::new(
rng.gen_range(-5.0..5.0),
rng.极客时间rng.gen_range(-5.0..5.0),
rng.gen_range(-5.0..5.0),
));
colors.push(ColorRGBA::from_rgb(
rng.gen_range(0..255),
rng.gen_range(0..255),
rng.gen_range(0..255),
));
}
MsgSender::new("random_points")
.with_component(&points)?
.with_component(&colors)?
.with_component(&vec![Radius(0.05); points.len()])?
.send(&rec_stream)?;
Ok(())
}
3. 时间序列数据可视化
use rerun_c::{
components::{Scalar, TimePoint},
MsgSender, RecordingStreamBuilder,
};
use std::f32::consts::PI;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (rec_stream, _server_handle) = RecordingStreamBuilder::new("sine_wave").connect()?;
for step in 0..100 {
let time = step as f32 * 0.1;
let value = (time * 2.0 * PI).sin();
let time_point = TimePoint::from_seconds_since_epoch(time as f64);
MsgSender::极客时间("sine_wave")
.with_time(time_point)
.with_component(&[Scalar::from(value)])?
.send(&rec_stream)?;
}
Ok(())
}
高级功能
1. 3D场景重建
use rerun_c::{
archetypes::Points3D,
components::{ColorRGBA, Point3D, Radius},
MsgSender, RecordingStreamBuilder,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (rec_stream, _server_handle) = RecordingStreamBuilder::new("scene_reconstruction").connect()?;
// 模拟从深度相机获取的点云数据
let width = 100;
let height = 100;
let mut points = Vec::new();
for y in 0..height {
for x in 0..width {
let xf = (x as f32 - width as f32 / 2.0) * 0.1;
let yf = (y as f32 - height as f32 / 2.0) * 0.1;
let zf = (xf * xf + yf * yf).sqrt().sin() * 2.0;
points.push(Point3D::new(xf, yf, zf));
}
}
MsgSender::from_archetype("scene/points", &Points3D::new(points)
.with_colors(vec![ColorRGBA::from_rgb(255, 255, 255); points.len()])
.with_radii(vec![Radius(0.02); points.len()]))?
.send(&rec_stream)?;
Ok(())
}
2. 自定义着色器和渲染设置
use rerun_c::{
archetypes::Points3D,
components::{ColorRGBA, Point3D},
external::glam::Vec3,
MsgSender, RecordingStreamBuilder,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let (rec_stream, _server_handle) = RecordingStreamBuilder::new("custom_rendering").connect()?;
// 创建自定义着色器数据
let points = vec![
Point3D::new(0.0, 0.0, 0.0),
Point3D::new(1.0, 1.0, 1.0),
Point3D::new(2.0, 0.0, 0.5),
];
let normals = vec![
Vec3::new(1.0, 0.0, 0.0),
Vec3::new(0.0, 1.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
];
MsgSender::from_archetype("custom/render", &Points3D::new(points)
.with_colors(vec![
ColorRGBA::from_rgb(255, 0, 0),
ColorRGBA::from_rgb(0, 255, 0),
ColorRGBA::from_rgb(0, 0, 255),
]))?
.send(&rec_stream)?;
// 可以添加自定义着色器代码...
Ok(())
}
性能优化技巧
- 批量发送数据:尽量一次性发送大量数据,而不是多次发送小批量数据
- 使用适当的数据类型:对于大型数据集,考虑使用更紧凑的数据表示
- 减少不必要的数据更新:只在数据变化时发送更新
- 利用时间戳:对于动态数据,使用时间戳来优化渲染
实际应用场景
- 机器人感知数据可视化
- 科学计算数据实时展示
- 3D扫描和重建
- 计算机视觉算法调试
- 传感器数据监控
rerun_c库提供了丰富的API和灵活的配置选项,可以满足从简单到复杂的各种数据可视化需求。通过合理使用其功能,可以构建出高性能的实时可视化应用。
完整示例Demo
基于上述内容,这里提供一个完整的机器人路径规划可视化示例:
use rerun_c::{
archetypes::{Points3D, Transform3D},
components::{ColorRGBA, Point3D, Radius, Vec3D},
datatypes::{Quaternion, Rotation3D, Scale3D, TranslationAndMat3x3, TranslationRotationScale3D},
MsgSender, RecordingStreamBuilder,
};
use std::f32::consts::PI;
// 机器人路径点结构体
struct RobotWaypoint {
position: [f32; 3],
orientation: [f32; 4], // 四元数表示
timestamp: f64,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化rerun连接
let (rec_stream, _server_handle) = RecordingStreamBuilder::new("robot_path_visualization").connect()?;
// 模拟生成机器人路径
let waypoints = generate_robot_path(50);
// 可视化环境网格
visualize_environment(&rec_stream)?;
// 可视化机器人路径
visualize_robot_path(&rec_stream, &waypoints)?;
// 可视化传感器数据
visualize_sensor_data(&rec_stream, &waypoints)?;
Ok(())
}
/// 生成模拟机器人路径
fn generate_robot_path(num_points: usize) -> Vec<RobotWaypoint> {
let mut waypoints = Vec::with_capacity(num_points);
for i in 0..num_points {
let t = i as f32 * 0.1;
waypoints.push(RobotWaypoint {
position: [
t.cos() * 2.0,
t.sin() * 2.0,
t * 0.1,
],
orientation: [
0.0,
(t * 0.5).sin(),
0.0,
(t * 0.5).cos(),
],
timestamp: t as f64,
});
}
waypoints
}
/// 可视化环境网格
fn visualize_environment(rec_stream: &rerun_c::RecordingStream) -> Result<(), Box<dyn std::error::Error>> {
// 创建网格点
let mut points = Vec::new();
for x in -5..5 {
for z in -5..5 {
points.push(Point3D::new(x as f32, -1.0, z as f32));
}
}
// 发送网格数据
MsgSender::from_archetype("environment/ground", &Points3D::new(points)
.with_colors(vec![ColorRGBA::from_rgb(100, 100, 100); points.len()])
.with_radii(vec![Radius(0.02); points.len()]))?
.send(rec_stream)?;
Ok(())
}
/// 可视化机器人路径
fn visualize_robot_path(
rec_stream: &rerun_c::RecordingStream,
waypoints: &[RobotWaypoint],
) -> Result<(), Box<dyn std::error::Error>> {
// 提取路径点位置
let positions: Vec<Point3D> = waypoints
.iter()
.map(|wp| Point3D::new(wp.position[0], wp.position[1], wp.position[2]))
.collect();
// 发送路径线
MsgSender::from_archetype("robot/path", &Points3D::new(positions.clone())
.with_colors(vec![ColorRGBA::from_rgb(0, 255, 255); positions.len()])
.with_radii(vec![Radius(0.05); positions.len()]))?
.send(rec_stream)?;
// 可视化关键帧
for (i, wp) in waypoints.iter().enumerate().step_by(5) {
let time_point = rerun_c::components::TimePoint::from_seconds_since_epoch(wp.timestamp);
// 创建坐标系变换
let transform = TranslationRotationScale3D {
translation: Some(Vec3D::new(wp.position[0], wp.position[1], wp.position[2])),
rotation: Some(Rotation3D::Quaternion(Quaternion {
x: wp.orientation[0],
y: wp.orientation[1],
z: wp.orientation[2],
w: wp.orientation[3],
})),
scale: Some(Scale3D::Uniform(0.5)),
..Default::default()
};
// 发送机器人姿态
MsgSender::new(format!("robot/frame_{}", i))
.with_time(time_point)
.from_archetype("robot/transform", &Transform3D::new(transform))?
.send(rec_stream)?;
}
Ok(())
}
/// 可视化传感器数据
fn visualize_sensor_data(
rec_stream: &rerun_c::RecordingStream,
waypoints: &[RobotWaypoint],
) -> Result<(), Box<dyn std::error::Error>> {
// 模拟传感器数据 (点云)
for (i, wp) in waypoints.iter().enumerate().step_by(10) {
let time_point = rerun_c::components::TimePoint::from_seconds_since_epoch(wp.timestamp);
let mut points = Vec::new();
let mut colors = Vec::new();
// 生成模拟点云数据 (锥形传感器视野)
for j in 0..100 {
let angle = j as f32 * 2.0 * PI / 100.0;
let dist = 0.5 + (j as f32 / 100.0) * 3.0;
points.push(Point3D::new(
wp.position[0] + angle.cos() * dist,
wp.position[1] + angle.sin() * dist,
wp.position[2] + dist * 0.5,
));
// 根据距离设置颜色 (越远颜色越红)
let intensity = (255.0 * (1.0 - (dist / 3.5).min(1.0))) as u8;
colors.push(ColorRGBA::from_rgb(255, intensity, intensity));
}
// 发送传感器数据
MsgSender::new(format!("sensor/scan_{}", i))
.with_time(time_point)
.from_archetype("sensor/points", &Points3D::new(points)
.with_colors(colors)
.with_radii(vec![Radius(0.03); points.len()]))?
.send(rec_stream)?;
}
Ok(())
}
这个完整示例展示了如何:
- 模拟生成机器人路径数据
- 可视化环境网格
- 绘制机器人运动路径
- 在关键帧显示机器人姿态
- 模拟并可视化传感器数据
通过这个示例,你可以看到rerun_c如何用于复杂的机器人应用场景,包括3D场景重建、路径规划和传感器数据可视化。