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(())
}

功能特点

  1. 高性能实时渲染:rerun_c针对实时可视化进行了优化
  2. 3D场景重建:支持点云、网格、相机视图等多种3D数据类型
  3. 时间序列支持:可以记录和回放随时间变化的数据
  4. 跨平台:支持多种操作系统和架构

请注意,当前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(())
}

性能优化技巧

  1. 批量发送数据:尽量一次性发送大量数据,而不是多次发送小批量数据
  2. 使用适当的数据类型:对于大型数据集,考虑使用更紧凑的数据表示
  3. 减少不必要的数据更新:只在数据变化时发送更新
  4. 利用时间戳:对于动态数据,使用时间戳来优化渲染

实际应用场景

  1. 机器人感知数据可视化
  2. 科学计算数据实时展示
  3. 3D扫描和重建
  4. 计算机视觉算法调试
  5. 传感器数据监控

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(())
}

这个完整示例展示了如何:

  1. 模拟生成机器人路径数据
  2. 可视化环境网格
  3. 绘制机器人运动路径
  4. 在关键帧显示机器人姿态
  5. 模拟并可视化传感器数据

通过这个示例,你可以看到rerun_c如何用于复杂的机器人应用场景,包括3D场景重建、路径规划和传感器数据可视化。

回到顶部