Skip to content

Commit bc90b56

Browse files
Kinin-Code-OfficalKinin-Code-Offical
andauthored
feat: unify RobotStudio package, diagnostics visuals, and perf fixes (#198)
Co-authored-by: Kinin-Code-Offical <yamacgursel@gmail.com>
1 parent ddfd870 commit bc90b56

81 files changed

Lines changed: 14612 additions & 222 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CoreSim/src/RobotTwin.CoreSim/Host/RealtimeHardening.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,23 @@ private static void TrySetAffinity(long affinityMask)
6666
try
6767
{
6868
using var process = Process.GetCurrentProcess();
69-
process.ProcessorAffinity = (IntPtr)affinityMask;
69+
IntPtr affinityMask1 = (IntPtr)affinityMask;
70+
71+
#if NET5_0_OR_GREATER
72+
if (OperatingSystem.IsWindows())
73+
{
74+
typeof(Process).GetProperty("ProcessorAffinity")?.SetValue(process, affinityMask1);
75+
}
76+
else if (OperatingSystem.IsLinux())
77+
{
78+
typeof(Process).GetProperty("ProcessorAffinity")?.SetValue(process, affinityMask1);
79+
}
80+
#else
81+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
82+
{
83+
typeof(Process).GetProperty("ProcessorAffinity")?.SetValue(process, affinityMask1);
84+
}
85+
#endif
7086
}
7187
catch
7288
{
@@ -82,17 +98,21 @@ private sealed class RealtimeHardeningScope : IDisposable
8298
public void TryBeginTimerResolution(uint periodMs)
8399
{
84100
if (_timerActive) return;
101+
#pragma warning disable CA1416 // Guarded by OS checks; best-effort hardening only.
85102
if (timeBeginPeriod(periodMs) == 0)
86103
{
87104
_timerActive = true;
88105
_timerPeriod = periodMs;
89106
}
107+
#pragma warning restore CA1416
90108
}
91109

92110
public void Dispose()
93111
{
94112
if (!_timerActive) return;
113+
#pragma warning disable CA1416 // Guarded by OS checks; best-effort hardening only.
95114
timeEndPeriod(_timerPeriod);
115+
#pragma warning restore CA1416
96116
_timerActive = false;
97117
}
98118
}

CoreSim/src/RobotTwin.CoreSim/Serialization/SimulationSerializer.cs

Lines changed: 198 additions & 16 deletions
Large diffs are not rendered by default.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System.Collections.Generic;
2+
3+
namespace RobotTwin.CoreSim.Specs
4+
{
5+
public class AssemblySpec
6+
{
7+
public List<AssemblyPartSpec> Parts { get; set; } = new List<AssemblyPartSpec>();
8+
public List<AssemblyWireSpec> Wires { get; set; } = new List<AssemblyWireSpec>();
9+
}
10+
11+
public class AssemblyPartSpec
12+
{
13+
public string InstanceId { get; set; } = string.Empty;
14+
public string ComponentType { get; set; } = string.Empty;
15+
public string CatalogId { get; set; } = string.Empty;
16+
public Vec3 Position { get; set; } = new Vec3();
17+
public Vec3 Rotation { get; set; } = new Vec3();
18+
public Vec3 Scale { get; set; } = new Vec3 { X = 1, Y = 1, Z = 1 };
19+
public bool Pinned { get; set; }
20+
public double DensityKgPerM3 { get; set; } = 1200.0;
21+
public double MassKg { get; set; }
22+
public double Friction { get; set; } = 0.6;
23+
}
24+
25+
public class AssemblyWireSpec
26+
{
27+
public string Id { get; set; } = string.Empty;
28+
public string From { get; set; } = string.Empty;
29+
public string To { get; set; } = string.Empty;
30+
public double LengthMeters { get; set; }
31+
public double YoungModulus { get; set; } = 2.0e9;
32+
public double MaxStress { get; set; } = 2.0e8;
33+
public double Damping { get; set; } = 0.2;
34+
}
35+
36+
public struct Vec3
37+
{
38+
public double X { get; set; }
39+
public double Y { get; set; }
40+
public double Z { get; set; }
41+
}
42+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace RobotTwin.CoreSim.Specs
2+
{
3+
public class EnvironmentSpec
4+
{
5+
public string Name { get; set; } = "DefaultEnvironment";
6+
public double TemperatureC { get; set; } = 22.0;
7+
public double VibrationAmplitude { get; set; } = 0.0;
8+
public double VibrationFrequencyHz { get; set; } = 0.0;
9+
public double Gravity { get; set; } = 9.81;
10+
public double AirDensity { get; set; } = 1.225;
11+
public double SurfaceFriction { get; set; } = 0.6;
12+
}
13+
}

CoreSim/src/RobotTwin.CoreSim/Specs/ProjectManifest.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ public class ProjectManifest
1717
public required RobotSpec Robot { get; set; }
1818
public required WorldSpec World { get; set; }
1919

20+
/// <summary>
21+
/// Optional assembly layout for RobotStudio / Full Mode preparation.
22+
/// Stored as assembly.json in binary packages.
23+
/// </summary>
24+
public AssemblySpec? Assembly { get; set; }
25+
26+
/// <summary>
27+
/// Optional environment factors (temperature, vibration, etc.).
28+
/// Stored as environment.json in binary packages.
29+
/// </summary>
30+
public EnvironmentSpec? Environment { get; set; }
31+
2032
public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
2133
}
2234
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.Collections.Generic;
2+
3+
namespace RobotTwin.CoreSim.Specs
4+
{
5+
public class RobotStudioPackage
6+
{
7+
public RobotSpec Robot { get; set; } = new RobotSpec { Name = "Robot" };
8+
public CircuitSpec Circuit { get; set; } = new CircuitSpec();
9+
public AssemblySpec Assembly { get; set; } = new AssemblySpec();
10+
public EnvironmentSpec Environment { get; set; } = new EnvironmentSpec();
11+
public Dictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
12+
public ProjectManifest? Project { get; set; }
13+
}
14+
}

CoreSim/tests/RobotTwin.CoreSim.Tests/RtwinRoundTripTests.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,93 @@ public void RtwinExtractWritesWorkspaceSnapshotFiles()
124124
}
125125
}
126126

127+
[Fact]
128+
public void RtrobotSaveLoadExtractRoundTripPreservesAssemblyAndEnvironment()
129+
{
130+
var tempRoot = Path.Combine(Path.GetTempPath(), "RobotTwin.CoreSim.Tests", Guid.NewGuid().ToString("N"));
131+
Directory.CreateDirectory(tempRoot);
132+
133+
try
134+
{
135+
var filePath = Path.Combine(tempRoot, "robotstudio_fixture.rtrobot");
136+
var workspaceRoot = Path.Combine(tempRoot, "robotstudio_fixture");
137+
138+
var package = new RobotStudioPackage
139+
{
140+
Robot = new RobotSpec { Name = "Robot-1" },
141+
Circuit = new CircuitSpec { Id = "circuit-rs-1", Mode = SimulationMode.Fast },
142+
Assembly = new AssemblySpec
143+
{
144+
Parts = new List<AssemblyPartSpec>
145+
{
146+
new AssemblyPartSpec
147+
{
148+
InstanceId = "part-1",
149+
ComponentType = "servo",
150+
CatalogId = "catalog/servo/sg90",
151+
Position = new Vec3 { X = 1, Y = 2, Z = 3 },
152+
Rotation = new Vec3 { X = 0, Y = 90, Z = 0 },
153+
Scale = new Vec3 { X = 1, Y = 1, Z = 1 },
154+
Pinned = true,
155+
DensityKgPerM3 = 1200,
156+
MassKg = 0.055,
157+
Friction = 0.8
158+
}
159+
},
160+
Wires = new List<AssemblyWireSpec>
161+
{
162+
new AssemblyWireSpec
163+
{
164+
Id = "wire-1",
165+
From = "part-1:signal",
166+
To = "mcu:pwm0",
167+
LengthMeters = 0.15,
168+
YoungModulus = 1e9,
169+
MaxStress = 4e7,
170+
Damping = 0.05
171+
}
172+
}
173+
},
174+
Environment = new EnvironmentSpec
175+
{
176+
Name = "Lab",
177+
TemperatureC = 22,
178+
VibrationAmplitude = 0.01,
179+
VibrationFrequencyHz = 60,
180+
Gravity = 9.81,
181+
AirDensity = 1.225,
182+
SurfaceFriction = 0.6
183+
},
184+
Metadata = new Dictionary<string, object> { { "author", "fixture" } }
185+
};
186+
187+
SimulationSerializer.SaveRobotPackage(package, filePath);
188+
Assert.True(File.Exists(filePath), $"Expected .rtrobot to exist: {filePath}");
189+
190+
var loadedNoExtract = SimulationSerializer.LoadRobotPackage(filePath, extractWorkspace: false);
191+
Assert.NotNull(loadedNoExtract);
192+
Assert.NotNull(loadedNoExtract!.Assembly);
193+
Assert.NotNull(loadedNoExtract.Environment);
194+
Assert.Single(loadedNoExtract.Assembly.Parts);
195+
Assert.Single(loadedNoExtract.Assembly.Wires);
196+
Assert.Equal("Lab", loadedNoExtract.Environment.Name);
197+
Assert.Equal(9.81, loadedNoExtract.Environment.Gravity, 3);
198+
199+
var loadedWithExtract = SimulationSerializer.LoadRobotPackage(filePath, extractWorkspace: true);
200+
Assert.NotNull(loadedWithExtract);
201+
202+
Assert.True(File.Exists(Path.Combine(workspaceRoot, "assembly.json")));
203+
Assert.True(File.Exists(Path.Combine(workspaceRoot, "environment.json")));
204+
Assert.True(File.Exists(Path.Combine(workspaceRoot, "robot.json")));
205+
Assert.True(File.Exists(Path.Combine(workspaceRoot, "circuit.json")));
206+
Assert.True(File.Exists(Path.Combine(workspaceRoot, "metadata.json")));
207+
}
208+
finally
209+
{
210+
TryDeleteDirectory(tempRoot);
211+
}
212+
}
213+
127214
private static byte[] LoadFixtureBytes(string fileName)
128215
{
129216
var fixturePath = Path.Combine(AppContext.BaseDirectory, "Fixtures", fileName);
9 KB
Binary file not shown.
0 Bytes
Binary file not shown.

RobotWin/Assets/Resources/Prefabs/Circuit3D/4xAA BATTERY HOLDER 1_5V.glb.meta

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)