Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0b4371d
fixes
SaltyJoss Feb 18, 2026
6d2b444
Merge pull request #68 from SaltyJoss/add/full_rigid-body_dynamics
SaltyJoss Feb 20, 2026
b1316c7
Merge pull request #69 from SaltyJoss/Main
SaltyJoss Feb 20, 2026
170e339
Revise Todo List format and item status
SaltyJoss Feb 20, 2026
36d193f
Merge pull request #70 from SaltyJoss/SaltyJoss-patch-1
SaltyJoss Feb 20, 2026
c2d9e8a
fixes
SaltyJoss Feb 20, 2026
29f18ab
fixes
SaltyJoss Feb 20, 2026
0cb1f90
Merge branch 'Dev' of https://github.com/SaltyJoss/RoboticArm_MathMod…
SaltyJoss Feb 20, 2026
7ff6919
Refactor of RobotSystem.cpp (#72)
SaltyJoss Feb 21, 2026
b5bb0ca
Refactor/code seperation (#73)
SaltyJoss Feb 21, 2026
2f83673
refactor: refactored robot joint state naming and add energy metrics
SaltyJoss Feb 21, 2026
60c7afc
update: going to add a basic double-buffer design to help testing runs
SaltyJoss Feb 21, 2026
2b0b7cc
WIP: adding double-buffered joint metric logging to RobotSystem
SaltyJoss Feb 21, 2026
3230a4c
WIP: added simulation run modes and refactor log buffer handling
SaltyJoss Feb 21, 2026
c303050
feat: added Headless core API, batch runner, and asset refactor
SaltyJoss Feb 21, 2026
19439af
WIP
SaltyJoss Feb 22, 2026
0a3601f
WIP: parallel batch runs & async integrator comparison in GUI
SaltyJoss Feb 22, 2026
4b4d119
Merge pull request #74 from SaltyJoss/add/implement_energy_metrics
SaltyJoss Feb 22, 2026
c893a88
WIP: batch study and background run support in GUI
SaltyJoss Feb 22, 2026
706c4ab
refactor: refactored SimulationCore to use unique_ptr for core systems
SaltyJoss Feb 22, 2026
444afac
refactor: removed singleton instance in DataManager to make logging p…
SaltyJoss Feb 22, 2026
ce795b0
fixes: improved data logging shutdown and HDF5 file handling
SaltyJoss Feb 22, 2026
0598549
refactor: added BatchArgs and flexible sweeps to batch mode
SaltyJoss Feb 22, 2026
b9e732c
fixes: support both owning and non-owning subsystems in SimulationCore
SaltyJoss Feb 22, 2026
4afe474
fixes: support both owning and non-owning subsystems in SimulationCore
SaltyJoss Feb 22, 2026
b9586ba
Merge branch 'add/implement_energy_metrics' of https://github.com/Sal…
SaltyJoss Feb 23, 2026
dd3b25a
Merge pull request #75 from SaltyJoss/add/implement_energy_metrics
SaltyJoss Feb 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 38 additions & 25 deletions MathLib/MathLib/include/core/Utils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#pragma once
#pragma warning(disable : 4251)

#include "MathLibAPI.h"
#include "core/Types.h"
Expand All @@ -11,21 +10,21 @@ using namespace constants;
namespace mathlib {
// Converts a non-eigen vector to Vec3 (if it has 3 elements)
template <typename T>
Vec3 toVec3(const T& vec) {
inline Vec3 toVec3(const T& vec) {
static_assert(std::tuple_size<T>::value == 3, "Input vector must have exactly 3 elements");
return Vec3(vec[0], vec[1], vec[2]);
}

// Converts a non-eigen vector to Vec4 (if it has 4 elements)
template <typename T>
Vec4 toVec4(const T& vec) {
inline Vec4 toVec4(const T& vec) {
static_assert(std::tuple_size<T>::value == 4, "Input vector must have exactly 4 elements");
return Vec4(vec[0], vec[1], vec[2], vec[3]);
}

// Converts a non-eigen 3x3 matrix to Mat3 (if it has 3 rows and 3 columns)
template <typename T>
Mat3 toMat3(const T& mat) {
inline Mat3 toMat3(const T& mat) {
static_assert(std::tuple_size<T>::value == 3 && std::tuple_size<typename T::value_type>::value == 3, "Input matrix must be 3x3");
return Mat3(mat[0][0], mat[0][1], mat[0][2],
mat[1][0], mat[1][1], mat[1][2],
Expand All @@ -35,7 +34,7 @@ namespace mathlib {

// Converts a non-eigen 4x4 matrix to Mat4 (if it has 4 rows and 4 columns)
template <typename T>
Mat4 toMat4(const T& mat) {
inline Mat4 toMat4(const T& mat) {
static_assert(std::tuple_size<T>::value == 4 && std::tuple_size<typename T::value_type>::value == 4, "Input matrix must be 4x4");
return Mat4(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
mat[1][0], mat[1][1], mat[1][2], mat[1][3],
Expand All @@ -45,48 +44,62 @@ namespace mathlib {
}

// Convert degrees to radians
double deg2rad(double degrees) { return degrees * (PI_d / 180.0); }
inline double deg2rad(double degrees) { return degrees * (PI_d / 180.0); }

// Convert radians to degrees
double rad2deg(double radians) { return radians * (180.0 / PI_d); }
inline double rad2deg(double radians) { return radians * (180.0 / PI_d); }

// Clamp a value between min and max
double clamp(double value, double minVal, double maxVal) {
inline double clamp(double value, double minVal, double maxVal) {
if (value < minVal) { return minVal; }
if (value > maxVal) { return maxVal; }
return value;
}

// Method to wrap an angle in radians to the range [-pi, pi]
inline double wrapToPi(double angleRad) {
angleRad = std::fmod(angleRad + PI_d, TWO_PI_d);
if (angleRad < 0.0f) { angleRad += TWO_PI_d; }
return angleRad - PI_d; // [rad]
}

// Method to wrap an angle in radians to the range [0, 2pi]
inline double wrapRad(double angleRad) {
angleRad = fmod(angleRad, TWO_PI_d);
if (angleRad < 0.0f) { angleRad += TWO_PI_d; }
return angleRad; // [rad]
}

// Linear interpolation between a and b by factor t (0 <= t <= 1)
double lerp(double a, double b, double t) { return a + t * (b - a); }
inline double lerp(double a, double b, double t) { return a + t * (b - a); }

// Check if two doubles are approximately equal within a tolerance
bool approximatelyEqual(double a, double b, double tolerance = 1e-9) { return std::fabs(a - b) <= tolerance; }
inline bool approximatelyEqual(double a, double b, double tolerance = 1e-9) { return std::fabs(a - b) <= tolerance; }

// Check if a value is within a specified range [minVal, maxVal]
bool isInRange(double value, double minVal, double maxVal) { return (value >= minVal) && (value <= maxVal); }
inline bool isInRange(double value, double minVal, double maxVal) { return (value >= minVal) && (value <= maxVal); }

// Sign function: returns -1 for negative, 1 for positive, and 0 for zero
double sgn(double val) { return (val > 0) - (val < 0); }
inline double sgn(double val) { return (val > 0) - (val < 0); }

// Returns a quadratic function f(x) = a*x^2 + b*x + c
std::function<double(double)> quadratic(double a, double b, double c) { return [a, b, c](double x) { return a * x * x + b * x + c; }; }
inline std::function<double(double)> quadratic(double a, double b, double c) { return [a, b, c](double x) { return a * x * x + b * x + c; }; }

// Returns a cubic function f(x) = a*x^3 + b*x^2 + c*x + d
std::function<double(double)> cubic(double a, double b, double c, double d) { return [a, b, c, d](double x) { return a * x * x * x + b * x * x + c * x + d; }; }
inline std::function<double(double)> cubic(double a, double b, double c, double d) { return [a, b, c, d](double x) { return a * x * x * x + b * x * x + c * x + d; }; }

// Dot product of two Vec3
double dot(const Vec3& v1, const Vec3& v2) { return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z(); }
inline double dot(const Vec3& v1, const Vec3& v2) { return v1.x() * v2.x() + v1.y() * v2.y() + v1.z() * v2.z(); }

// Natural frequency of a mass-spring system
double natural_freq(double k_p, double I) {
inline double natural_freq(double k_p, double I) {
if (!std::isfinite(k_p) || !std::isfinite(I)) return std::numeric_limits<double>::quiet_NaN();
if (k_p < 0.0 || I <= 0.0) return std::numeric_limits<double>::quiet_NaN();
return std::sqrt(k_p / I);
}

// Damping ratio of a mass-spring-damper system
double damping_ratio(double k_d, double I, double k_p) {
inline double damping_ratio(double k_d, double I, double k_p) {
if (!std::isfinite(k_p) || !std::isfinite(k_d) || !std::isfinite(I)) { return std::numeric_limits<double>::quiet_NaN(); }
if (k_p <= 0.0 || I <= 0.0) { return std::numeric_limits<double>::quiet_NaN(); }
double w_n = natural_freq(k_p, I);
Expand All @@ -95,48 +108,48 @@ namespace mathlib {

// Overloads for std::array and C arrays for Vec3 conversion
template <typename T, std::size_t N>
std::enable_if_t<N == 3, Vec3> toVec3(const std::array<T, N>& arr) {
inline std::enable_if_t<N == 3, Vec3> toVec3(const std::array<T, N>& arr) {
return Vec3(arr[0], arr[1], arr[2]);
}
template <typename T>
Vec3 toVec3(const T arr[3]) {
inline Vec3 toVec3(const T arr[3]) {
return Vec3(arr[0], arr[1], arr[2]);
}

// Overloads for std::array and C arrays for Vec4 conversion
template <typename T, std::size_t N>
std::enable_if_t<N == 4, Vec4> toVec4(const std::array<T, N>& arr) {
inline std::enable_if_t<N == 4, Vec4> toVec4(const std::array<T, N>& arr) {
return Vec4(arr[0], arr[1], arr[2], arr[3]);
}
template <typename T>
Vec4 toVec4(const T arr[4]) {
inline Vec4 toVec4(const T arr[4]) {
return Vec4(arr[0], arr[1], arr[2], arr[3]);
}

// Overloads for std::array and C arrays for Mat3 conversion
template <typename T, std::size_t N>
std::enable_if_t<N == 3, Mat3> toMat3(const std::array<std::array<T, N>, N>& mat) {
inline std::enable_if_t<N == 3, Mat3> toMat3(const std::array<std::array<T, N>, N>& mat) {
return Mat3(mat[0][0], mat[0][1], mat[0][2],
mat[1][0], mat[1][1], mat[1][2],
mat[2][0], mat[2][1], mat[2][2]);
}
template <typename T>
Mat3 toMat3(const T mat[3][3]) {
inline Mat3 toMat3(const T mat[3][3]) {
return Mat3(mat[0][0], mat[0][1], mat[0][2],
mat[1][0], mat[1][1], mat[1][2],
mat[2][0], mat[2][1], mat[2][2]);
}

// Overloads for std::array and C arrays for Mat4 conversion
template <typename T, std::size_t N>
std::enable_if_t<N == 4, Mat4> toMat4(const std::array<std::array<T, N>, N>& mat) {
inline std::enable_if_t<N == 4, Mat4> toMat4(const std::array<std::array<T, N>, N>& mat) {
return Mat4(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
mat[1][0], mat[1][1], mat[1][2], mat[1][3],
mat[2][0], mat[2][1], mat[2][2], mat[2][3],
mat[3][0], mat[3][1], mat[3][2], mat[3][3]);
}
template <typename T>
Mat4 toMat4(const T mat[4][4]) {
inline Mat4 toMat4(const T mat[4][4]) {
return Mat4(mat[0][0], mat[0][1], mat[0][2], mat[0][3],
mat[1][0], mat[1][1], mat[1][2], mat[1][3],
mat[2][0], mat[2][1], mat[2][2], mat[2][3],
Expand Down
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,21 +86,21 @@ Download the latest release of DSFE from `Release` in the `DSFE GitHub Repositor
> Therefore, I most likely will not make any updates until that period is over. <br />

### Todo List:
* Implement `collision meshes` with existin dynamics pipeline
* Improve UI, making it `Research-Oriented`
* Add workspace layouts
* Support multiple concurrent sessions
* Move simulation data output to a `dedicated Data-specific thread` **(IMPORTANT)**
* Replace the current diagonal Coriolis approximation to the `full Coriolis matrix formulation`
* Support `multiple articulated systems` within a single simulation instance
* Extend DSFE to support `other classes of dynamical systems` outside robotic manipulators
* Further `extend physcial modelling` for different robot models (humanoid, legged)
* Seperate physics/mathematics core from the GUI and visualisation layers
* Explore migration to a `CMake-only` build system
* Explore `DX11` and `Vulkan` alternatives
* Get DSFE to work on `Linux`
* Explore `non-x64 systesm` support
* Explore the adoption of `standardised URDF XML` in place of the current DSFE json format
* [ ] Implement `collision meshes` with existin dynamics pipeline
* [ ] Improve UI, making it `Research-Oriented`
* [ ] Add workspace layouts
* [ ] Support multiple concurrent sessions
* [ ] Move simulation data output to a `dedicated Data-specific thread` **(IMPORTANT)**
* [x] <s>Replace the current diagonal model with the standarised `full-matrix rigid-body model`</s>
* [ ] Support `multiple articulated systems` within a single simulation instance
* [ ] Extend DSFE to support `other classes of dynamical systems` outside robotic manipulators
* [ ] Further `extend physcial modelling` for different robot models (humanoid, legged)
* [ ] Seperate physics/mathematics core from the GUI and visualisation layers
* [ ] Explore migration to a `CMake-only` build system
* [ ] Explore `DX11` and `Vulkan` alternatives
* [ ] Get DSFE to work on `Linux`
* [ ] Explore `non-x64 systesm` support
* [ ] Explore the adoption of `standardised URDF XML` in place of the current DSFE json format

<br />

Expand Down
9 changes: 7 additions & 2 deletions Sim_Engine/Engine.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;$(SolutionDir)Engine\include;$(SolutionDir)External\Eigen;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
<ObjectFileName>$(IntDir)%(FileName).obj</ObjectFileName>
Expand Down Expand Up @@ -87,7 +87,7 @@ echo D | xcopy /E /Y /D "$(ProjectDir)Engine\configs\*" "$(TargetDir)configs\"
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)EngineLib;$(SolutionDir)EngineLib\include;$SolutionDir)External\GLFW;$(SolutionDir)External\GLAD;$(SolutionDir)External\GLM;$(SolutionDir)External\assimp;$(SolutionDir)External\MathLib\include;$(SolutionDir)Engine\include;$(SolutionDir)External\Eigen;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp20</LanguageStandard>
<PreprocessToFile>false</PreprocessToFile>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
Expand All @@ -111,6 +111,7 @@ echo D | xcopy /E /Y /D "$(ProjectDir)Engine\configs\*" "$(TargetDir)configs\"
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Engine\src\BatchMain.cpp" />
<ClCompile Include="Engine\src\Main.cpp" />
<ClCompile Include="External\stb\stb_image_write_impl.cpp" />
</ItemGroup>
Expand Down Expand Up @@ -138,6 +139,10 @@ echo D | xcopy /E /Y /D "$(ProjectDir)Engine\configs\*" "$(TargetDir)configs\"
<None Include="assets\shaders\world_grid.frag.glsl" />
<None Include="assets\shaders\world_grid.vert.glsl" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Engine\include\BatchArgs.h" />
<ClInclude Include="Engine\include\BatchEntry.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
Expand Down
14 changes: 14 additions & 0 deletions Sim_Engine/Engine.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
<ClCompile Include="External\stb\stb_image_write_impl.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="Engine\src\BatchMain.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="src">
Expand All @@ -15,6 +18,9 @@
<Filter Include="Shaders">
<UniqueIdentifier>{383daa6b-14af-40d3-b6df-31732d4d7a6a}</UniqueIdentifier>
</Filter>
<Filter Include="include">
<UniqueIdentifier>{146d8cfd-be4d-41a3-bc59-546deb084dc0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="assets\shaders\brdf_lut.frag.glsl">
Expand Down Expand Up @@ -84,4 +90,12 @@
<Filter>Shaders</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Engine\include\BatchEntry.h">
<Filter>include</Filter>
</ClInclude>
<ClInclude Include="Engine\include\BatchArgs.h">
<Filter>include</Filter>
</ClInclude>
</ItemGroup>
</Project>
19 changes: 19 additions & 0 deletions Sim_Engine/Engine/include/BatchArgs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include <string>
#include <vector>
#include <optional>

// Struct to hold command-line arguments for batch mode
struct BatchArgs {
std::string testPath;
// Base configuration for batch runs (if not provided, defaults will be used)
std::optional<std::string> baseDtRaw;
std::optional<double> baseDt;
std::optional<std::string> baseInt;
// Lists for sweep parameters (if not provided, defaults will be used)
std::vector<std::string> sweepDtRaw;
std::vector<double> sweepDt;
std::vector<std::string> sweepInt;
// Run name for output organisation
std::optional<std::string> runName;
};
3 changes: 3 additions & 0 deletions Sim_Engine/Engine/include/BatchEntry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once
struct BatchArgs;
int runBatchMode(const BatchArgs& args);
Loading
Loading