#pragma once #include #include namespace fluidsim::port { // Rotational quantities use SI: rad, rad/s, N m, kg m2, J and W. enum class DriveMode {Torque,Speed}; struct ShaftParameters { double inertia{.15},initial_speed{},initial_angle{}; double friction_constant{},friction_viscous{},friction_quadratic{}; bool forward_only{}; }; struct DriveParameters {DriveMode mode{DriveMode::Torque};double command{};bool enabled{true};}; struct BrakeParameters {double constant{},viscous{},quadratic{};bool enabled{true};}; struct ShaftState { std::uint32_t id{}; double angle{},previous_angle{},speed{},inertia{},kinetic_energy{}; double net_torque{},source_torque{},external_torque{},friction_torque{},brake_torque{},constraint_torque{}; double external_work{},drive_work{},friction_loss{},brake_loss{},initial_energy{}; // initial_energy + external_work + drive_work = kinetic_energy + losses. }; struct DriveState { std::uint32_t id{},shaft{}; double torque{},power{},work{}; }; struct BrakeState { std::uint32_t id{},shaft{}; double torque{},power{},loss{}; // Torque on shaft signed; absorbed power >= 0. }; // Independent rigid shaft nodes. Gears and clutches will couple these nodes; // direct attachment adds torque or inertia to one named node exactly once. class MechanicalSystem { public: MechanicalSystem(); ~MechanicalSystem(); MechanicalSystem(const MechanicalSystem&)=delete; MechanicalSystem& operator=(const MechanicalSystem&)=delete; void add_shaft(std::uint32_t,const ShaftParameters&); void add_flywheel(std::uint32_t id,std::uint32_t shaft,double inertia); void add_drive(std::uint32_t id,std::uint32_t shaft,const DriveParameters&); void add_brake(std::uint32_t id,std::uint32_t shaft,const BrakeParameters&); void set_drive(std::uint32_t,const DriveParameters&); void set_brake(std::uint32_t,const BrakeParameters&); void set_friction(std::uint32_t shaft,double constant,double viscous,double quadratic); void add_torque(std::uint32_t shaft,double torque); void step(double dt); const ShaftState& shaft(std::uint32_t)const; const DriveState& drive(std::uint32_t)const; const BrakeState& brake(std::uint32_t)const; private: struct Impl; std::unique_ptr impl_; }; }