EnerOS v0.37.0
Release Date: 2026-05-23 Codename: TwinX Git Tag: v0.37.0 Support Status: Stable Total Crates: 90 (6 new) Test Cases: 11400+ (700 new)
Overview
EnerOS v0.37.0 “TwinX” is a digital twin enhancement-focused release, upgrading EnerOS’s digital twin capabilities from “2D data mapping” to a complete digital twin system of “3D visualization + physics simulation + immersive interaction.” This release enables EnerOS to build a 3D digital twin that corresponds 1:1 with the physical grid, supporting scenarios such as operations inspection, training drills, and plan rehearsals.
The core design philosophy of the TwinX release is “virtual-real synchronization + physical consistency” — the digital twin is not only visually consistent with physical equipment, but also follows physical laws in behavior. The twin’s state changes are driven by real-time data, and the twin’s operation rehearsals are guaranteed by physics simulation, ensuring “what you see in digital space is what happens in physical space, and the rehearsal results of operations in digital space are the results of operations in physical space.”
This release introduces five core capabilities: 3D Visualization Engine, Physics Simulation Integration, AR/VR Interface, Real-time Synchronization Framework, and Twin Scenario Orchestration. All capabilities are implemented through five new crates: eneros-twinx, eneros-twinx-3d, eneros-twinx-physics, eneros-twinx-arvr, and eneros-twinx-sync.
Key Metrics
| Metric | Value | Description |
|---|---|---|
| 3D scene loading | 1.2s | 1000 devices |
| Real-time sync latency | 50ms | State refresh |
| Physics simulation FPS | 60 FPS | Real-time rendering |
| AR end-to-end latency | 35ms | Includes rendering |
| New Crates | 6 | Twin-related |
| New tests | 700+ | Includes 80 end-to-end |
New Features
1. 3D Visualization Engine
Adds the eneros-twinx-3d crate, providing a WebGPU-based 3D rendering engine, supporting fine-grained 3D modeling and real-time rendering of substations, lines, and equipment.
3D Scene Construction
use eneros_twinx_3d::{Scene3D, SceneBuilder, Camera, Lighting};
let mut scene = SceneBuilder::new()
.background(Environment::Sky)
.lighting(Lighting::sun_position(now()))
.camera(Camera::orbit().target(0.0, 10.0, 0.0).distance(50.0))
.build().await?;
// Auto-generate 3D scene from topology
scene.load_from_topology(&network).await?;
// Load equipment 3D models
scene.load_model("transformer-110kv", "/models/transformer.glb").await?;
scene.load_model("breaker-vacuum", "/models/breaker.glb").await?;
// Bind equipment instances to 3D objects
for equipment in &network.equipments {
scene.bind_instance(equipment.id, &equipment.model_3d, equipment.position)?;
}
scene.start_render().await?;
3D Object Properties
| Property | Type | Description |
|---|---|---|
| geometry | Mesh | 3D geometry |
| material | PBR | Physical material |
| transform | Matrix4x4 | Position/rotation/scale |
| animation | Skeleton | Skeletal animation |
| interaction | Collider | Collision detection |
| metadata | JSON | Device info |
State-driven Visualization
// Device state drives 3D appearance in real-time
scene.on_state_change(|device_id, state| {
let obj = scene.get_object(device_id)?;
match state {
DeviceState::Energized => obj.set_material(Material::emissive(Color::green())),
DeviceState::Deenergized => obj.set_material(Material::standard(Color::gray())),
DeviceState::Fault => {
obj.set_material(Material::emissive(Color::red()));
obj.start_animation("alarm_blink")?;
}
DeviceState::Maintenance => obj.set_material(Material::emissive(Color::yellow())),
}
}).await?;
// Real-time data drives dynamic effects
scene.bind_data("transformer-001", "temperature", |obj, temp| {
// Higher temperature, stronger winding glow
let intensity = (temp - 40.0) / 60.0;
obj.set_emissive_intensity(intensity.max(0.0));
}).await?;
2. Physics Simulation Integration
Adds the eneros-twinx-physics crate, integrating a physics simulation engine into the digital twin, making equipment behavior in the 3D scene conform to physical laws.
Simulation Capabilities
| Simulation Type | Engine | Application Scenario | Accuracy |
|---|---|---|---|
| Rigid body dynamics | rapier | Equipment motion, collision | High |
| Fluid dynamics | In-house | Oil flow, airflow | Medium |
| Electromagnetic field | FEM | Electromagnetic field distribution | High |
| Thermodynamics | FDM | Temperature field distribution | Medium |
| Acoustics | ray-tracing | Noise propagation | Medium |
Physics Simulation Example
use eneros_twinx_physics::{PhysicsWorld, RigidBody, Collider};
let mut physics = PhysicsWorld::new();
physics.gravity(Vec3::new(0.0, -9.81, 0.0));
// Simulate kinematics of switch operation
let breaker = RigidBody::dynamic()
.mass(5.0)
.collider(Collider::box_(0.2, 0.5, 0.2))
.build();
physics.add_body(breaker);
// Simulate switch opening process
physics.apply_force("breaker-arm", Vec3::new(0.0, 500.0, 0.0));
let trajectory = physics.simulate(Duration::milliseconds(100)).await?;
// For operations training: observe mechanical stress during opening
for step in &trajectory {
println!("t={:.3}s position={:?} stress={:.1} N",
step.time, step.position, step.stress);
}
3. AR/VR Interface
Adds the eneros-twinx-arvr crate, providing Augmented Reality (AR) and Virtual Reality (VR) interfaces, supporting operators to interact with the digital twin through immersive devices.
AR Inspection
use eneros_twinx_arvr::{ArSession, ArConfig, Overlay};
let ar = ArSession::new(ArConfig {
device: ArDevice::Hololens3,
anchor_strategy: AnchorStrategy::SpatialMapping,
hand_tracking: true,
voice_commands: true,
}).await?;
// Start AR inspection
ar.start_inspection(StationId::from("SS-110-01")).await?;
// Device information overlay
ar.on_gaze(|device_id| {
let info = phm.get_profile(device_id).await?;
ar.show_overlay(Overlay::info_panel()
.title(&info.name)
.field("Health score", format!("{:.1}", info.health_score.value))
.field("Temperature", format!("{:.1} C", info.current_temp))
.field("Load rate", format!("{:.1}%", info.load_rate))
.anchor(device_id))?;
}).await?;
// Voice commands
ar.on_voice("Show internal structure", |_| {
ar.set_xray_mode(true); // See through internal structure
}).await?;
ar.on_voice("Replay last fault", |_| {
ar.replay_event("fault-2026-05-20-001");
}).await?;
VR Training
use eneros_twinx_arvr::{VrSession, VrScenario};
let vr = VrSession::new(VrConfig {
device: VrDevice::Quest3,
teleport: true,
physics_interaction: true,
}).await?;
// Load training scenario
vr.load_scenario(VrScenario::switch_operation_training()).await?;
// Trainee action evaluation
vr.on_action(|action| {
match action {
Action::ApproachDevice(id) => log::info!("Approaching device {}", id),
Action::OpenSwitch(id) => {
// Validate operation sequence
if !procedure.check_step("verify_deenergized")? {
vr.show_warning("Please verify de-energized first!");
return;
}
vr.execute_switch_operation(id).await?;
}
Action::Complete => {
let score = procedure.evaluate();
vr.show_result(score);
}
}
}).await?;
AR/VR Capability Comparison
| Capability | AR | VR | Description |
|---|---|---|---|
| Reality overlay | Supported | Not supported | AR core capability |
| Immersive scene | Partial | Complete | VR core capability |
| Gesture interaction | Supported | Supported | Both support |
| Voice control | Supported | Supported | Both support |
| Multi-user collaboration | Supported | Supported | Shared space |
4. Real-time Synchronization Framework
Adds the eneros-twinx-sync crate, ensuring real-time synchronization between the digital twin and the physical grid, supporting sub-second state refresh.
Synchronization Architecture
use eneros_twinx_sync::{SyncEngine, SyncConfig, SyncSource};
let sync = SyncEngine::new(&ctx)
.config(SyncConfig {
refresh_rate: 20, // 20 FPS
max_latency: Duration::milliseconds(100),
interpolation: true, // Inter-frame interpolation
extrapolation: false, // No extrapolation
priority: PriorityBy::Criticality,
})
.source(SyncSource::PmuStream { resolution: Duration::milliseconds(20) })
.source(SyncSource::ScadaPolling { interval: Duration::seconds(2) })
.source(SyncSource::TopologyEvents { realtime: true })
.build().await?;
// Start real-time sync
sync.start().await?;
// Sync status monitoring
sync.on_metrics(|m| {
println!("Sync latency: {:.0}ms, dropped frames: {}, FPS: {:.1}",
m.latency_p99, m.dropped_frames, m.actual_fps);
}).await?;
Synchronization Priority
| Data Type | Priority | Refresh Frequency | Description |
|---|---|---|---|
| Protection action | Highest | Real-time | Immediate sync |
| Switch status | High | 100ms | Topology change |
| Voltage/current | Medium | 20ms | PMU data |
| Equipment temperature | Low | 5s | Slowly changing data |
| Environmental data | Lowest | 60s | Meteorological data |
5. Twin Scenario Orchestration
Adds the eneros-twinx crate (twin core), providing scenario orchestration capabilities, supporting advanced scenarios such as rehearsal, playback, and comparison.
Operation Rehearsal
use eneros_twinx::{ScenarioEngine, Scenario, ScenarioResult};
let engine = ScenarioEngine::new(&ctx);
// Build operation rehearsal scenario
let scenario = Scenario::new("switch-maintenance-001")
.description("110kV Bus 5 maintenance transfer operation")
.step(Step::verify_deenergized(BusId::from(5)))
.step(Step::ground(BusId::from(5)))
.step(Step::maintenance_window(Duration::hours(4)))
.step(Step::remove_ground(BusId::from(5)))
.step(Step::energize(BusId::from(5)));
// Dry run in twin
let result: ScenarioResult = engine.dry_run(&scenario).await?;
println!("Rehearsal result:");
println!(" Estimated duration: {:?}", result.estimated_duration);
println!(" Impact scope: {} devices", result.affected_devices);
println!(" Risk assessment: {:?}", result.risk_level);
println!(" Constraint check: {}", if result.constraints_ok { "Passed" } else { "Violation" });
if result.has_warnings() {
for w in &result.warnings {
println!(" Warning: {}", w);
}
}
Historical Playback
// Replay a fault event
let replay = engine.replay_event("fault-2026-05-20-001")
.speed(0.5) // 0.5x speed
.show_data_overlay(true)
.highlight_cascade(true) // Highlight cascading fault path
.start().await?;
Scenario Comparison
// Compare execution effects of two dispatching plans
let comparison = engine.compare(
Scenario::from_schedule(schedule_a),
Scenario::from_schedule(schedule_b),
).await?;
println!("Plan comparison:");
println!("{:<15} {:<15} {:<15}", "Metric", "Plan A", "Plan B");
println!("{:<15} {:<15.0} {:<15.0}", "Cost(CNY)", a.cost, b.cost);
println!("{:<15} {:<15.1}% {:<15.1}%", "Utilization", a.renewable, b.renewable);
println!("{:<15} {:<15.2} {:<15.2}", "Loss(MW)", a.loss, b.loss);
Improvements
- Topology Engine: Supports 3D coordinate properties, automatic equipment positioning
- Timeseries Engine: Dedicated twin sync channel, latency reduced by 60%
- Equipment Model: Added 3D model templates for 150+ devices
- Security Gateway: Strict isolation between twin operation rehearsal and actual control
- Observability: Twin state integrated into Grafana 3D dashboards
Bug Fixes
- Fixed
eneros-twinx-3dframe rate drops in large-scale scenes (#3703) - Fixed
eneros-twinx-physicsrigid body simulation penetration during high-speed collisions (#3710) - Fixed
eneros-twinx-arvrAR anchor loss in low-light environments (#3716) - Fixed
eneros-twinx-syncinter-frame interpolation anomalies during network jitter (#3722) - Fixed
eneros-twinxscenario playback timeline errors across time zones (#3728)
Breaking Changes
Scene3D::load_from_topology: Parameter addscoordinate_systemoptionPhysicsWorld::simulate: Return type changed fromTrajectorytoResult<Trajectory>ArSession::start_inspection: Parameter changed from&strtoStationId
Upgrade Guide
- Update the
enerosdependency inCargo.tomlto0.37.0 - Install 3D model resource pack:
eneros twinx install-models - Configure AR/VR device connections in
eneros.toml - Run
eneros twinx build-sceneto build 3D scene
Acknowledgments
Thanks to the 36 contributors who submitted 550+ commits, and to the 3D modeling team for device model resources.