Skip to content

Commit 5b19949

Browse files
committed
[#156] Separate atmospheric dynamics models
1 parent 7638a11 commit 5b19949

File tree

3 files changed

+99
-58
lines changed

3 files changed

+99
-58
lines changed

src/bsk_rl/sim/dyn/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
3939
from deprecated import deprecated
4040

4141
from bsk_rl.sim.dyn.base import (
42+
AtmosphericDragDynModel,
4243
BaseDynamicsModel,
4344
BasicDynamicsModel,
45+
DisturbanceTorqueDynModel,
4446
DynamicsModel,
4547
EclipseDynModel,
4648
)
@@ -74,6 +76,8 @@ def __init__(self, *args, **kwargs) -> None:
7476
"BaseDynamicsModel",
7577
"BasicDynamicsModel",
7678
"EclipseDynModel",
79+
"DisturbanceTorqueDynModel",
80+
"AtmosphericDragDynModel",
7781
"LOSCommDynModel",
7882
"ImagingDynModel",
7983
"ContinuousImagingDynModel",

src/bsk_rl/sim/dyn/base.py

Lines changed: 92 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -395,67 +395,16 @@ def setup_eclipse_object(self) -> None:
395395
self.eclipse_index = len(self.world.eclipseObject.eclipseOutMsgs) - 1
396396

397397

398-
class BasicDynamicsModel(EclipseDynModel, BaseDynamicsModel):
399-
"""Basic Dynamics model with minimum necessary Basilisk components."""
398+
class DisturbanceTorqueDynModel(BaseDynamicsModel):
399+
"""Dynamics model with constant disturbance torque."""
400400

401401
def __init__(self, *args, **kwargs) -> None:
402-
"""A dynamics model with a basic feature set.
403-
404-
Includes the following:
405-
406-
* Spacecraft hub physical properties
407-
* Gravity
408-
* Constant disturbance torque (defaults to none)
409-
* Aerodynamic drag
410-
* Eclipse checking for power generation
411-
* Reaction wheels
412-
* Momentum desaturation thrusters
413-
* Solar panels, battery, and power system
414-
415-
Args:
416-
*args: Passed to superclass
417-
**kwargs: Passed to superclass
418-
"""
402+
"""Dynamics model with constant disturbance torque."""
419403
super().__init__(*args, **kwargs)
420404

421-
@classmethod
422-
def _requires_world(cls) -> list[type["WorldModel"]]:
423-
return [
424-
world.AtmosphereWorldModel,
425-
] + super()._requires_world()
426-
427-
@property
428-
def battery_charge(self):
429-
"""Battery charge [W*s]."""
430-
return self.powerMonitor.batPowerOutMsg.read().storageLevel
431-
432-
@property
433-
def battery_charge_fraction(self):
434-
"""Battery charge as a fraction of capacity."""
435-
return self.battery_charge / self.powerMonitor.storageCapacity
436-
437-
@property
438-
def wheel_speeds(self):
439-
"""Wheel speeds [rad/s]."""
440-
return np.array(self.rwStateEffector.rwSpeedOutMsg.read().wheelSpeeds)[0:3]
441-
442-
@property
443-
def wheel_speeds_fraction(self):
444-
"""Wheel speeds normalized by maximum allowable speed."""
445-
return self.wheel_speeds / (self.maxWheelSpeed * macros.rpm2radsec)
446-
447405
def _setup_dynamics_objects(self, **kwargs) -> None:
448406
super()._setup_dynamics_objects(**kwargs)
449407
self.setup_disturbance_torque(**kwargs)
450-
self.setup_density_model()
451-
self.setup_drag_effector(**kwargs)
452-
self.setup_reaction_wheel_dyn_effector(**kwargs)
453-
self.setup_thruster_dyn_effector()
454-
self.setup_solar_panel(**kwargs)
455-
self.setup_battery(**kwargs)
456-
self.setup_power_sink(**kwargs)
457-
self.setup_reaction_wheel_power(**kwargs)
458-
self.setup_thruster_power(**kwargs)
459408

460409
@default_args(disturbance_vector=None)
461410
def setup_disturbance_torque(
@@ -474,11 +423,33 @@ def setup_disturbance_torque(
474423
self.extForceTorqueObject.extTorquePntB_B = disturbance_vector
475424
self.scObject.addDynamicEffector(self.extForceTorqueObject)
476425

426+
427+
class AtmosphericDragDynModel(BaseDynamicsModel):
428+
"""Dynamics model with atmospheric drag."""
429+
430+
def __init__(self, *args, **kwargs) -> None:
431+
"""Dynamics model with atmospheric drag."""
432+
super().__init__(*args, **kwargs)
433+
434+
@classmethod
435+
def _requires_world(cls) -> list[type["WorldModel"]]:
436+
return [
437+
world.AtmosphereWorldModel,
438+
] + super()._requires_world()
439+
440+
def _setup_dynamics_objects(self, **kwargs) -> None:
441+
super()._setup_dynamics_objects(**kwargs)
442+
self.setup_density_model()
443+
self.setup_drag_effector(**kwargs)
444+
477445
def setup_density_model(self) -> None:
478446
"""Set up the atmospheric density model effector."""
479447
self.world.densityModel.addSpacecraftToModel(self.scObject.scStateOutMsg)
480448

481-
@default_args(dragCoeff=2.2)
449+
@default_args(
450+
dragCoeff=2.2,
451+
panelArea=2 * 1.0 * 0.5,
452+
)
482453
def setup_drag_effector(
483454
self,
484455
width: float,
@@ -547,6 +518,69 @@ def setup_drag_effector(
547518
self.task_name, self.dragEffector, ModelPriority=priority
548519
)
549520

521+
522+
class BasicDynamicsModel(
523+
EclipseDynModel,
524+
DisturbanceTorqueDynModel,
525+
AtmosphericDragDynModel,
526+
BaseDynamicsModel,
527+
):
528+
"""Basic Dynamics model with minimum necessary Basilisk components."""
529+
530+
def __init__(self, *args, **kwargs) -> None:
531+
"""A dynamics model with a basic feature set.
532+
533+
Includes the following:
534+
535+
* Spacecraft hub physical properties
536+
* Gravity
537+
* Constant disturbance torque (defaults to none)
538+
* Aerodynamic drag
539+
* Eclipse checking for power generation
540+
* Reaction wheels
541+
* Momentum desaturation thrusters
542+
* Solar panels, battery, and power system
543+
544+
Args:
545+
*args: Passed to superclass
546+
**kwargs: Passed to superclass
547+
"""
548+
super().__init__(*args, **kwargs)
549+
550+
@classmethod
551+
def _requires_world(cls) -> list[type["WorldModel"]]:
552+
return super()._requires_world()
553+
554+
@property
555+
def battery_charge(self):
556+
"""Battery charge [W*s]."""
557+
return self.powerMonitor.batPowerOutMsg.read().storageLevel
558+
559+
@property
560+
def battery_charge_fraction(self):
561+
"""Battery charge as a fraction of capacity."""
562+
return self.battery_charge / self.powerMonitor.storageCapacity
563+
564+
@property
565+
def wheel_speeds(self):
566+
"""Wheel speeds [rad/s]."""
567+
return np.array(self.rwStateEffector.rwSpeedOutMsg.read().wheelSpeeds)[0:3]
568+
569+
@property
570+
def wheel_speeds_fraction(self):
571+
"""Wheel speeds normalized by maximum allowable speed."""
572+
return self.wheel_speeds / (self.maxWheelSpeed * macros.rpm2radsec)
573+
574+
def _setup_dynamics_objects(self, **kwargs) -> None:
575+
super()._setup_dynamics_objects(**kwargs)
576+
self.setup_reaction_wheel_dyn_effector(**kwargs)
577+
self.setup_thruster_dyn_effector()
578+
self.setup_solar_panel(**kwargs)
579+
self.setup_battery(**kwargs)
580+
self.setup_power_sink(**kwargs)
581+
self.setup_reaction_wheel_power(**kwargs)
582+
self.setup_thruster_power(**kwargs)
583+
550584
@default_args(
551585
wheelSpeeds=lambda: np.random.uniform(-1500, 1500, 3),
552586
maxWheelSpeed=np.inf,
@@ -779,4 +813,7 @@ def setup_reaction_wheel_power(
779813
"DynamicsModel",
780814
"BaseDynamicsModel",
781815
"BasicDynamicsModel",
816+
"EclipseDynModel",
817+
"DisturbanceTorqueDynModel",
818+
"AtmosphericDragDynModel",
782819
]

tests/unittest/sim/test_dynamics.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ def test_is_alive(self):
3838

3939
@patch(basicdyn + "_requires_world", MagicMock(return_value=[]))
4040
@patch(basicdyn + "setup_spacecraft_hub")
41-
@patch(basicdyn + "setup_drag_effector")
4241
@patch(basicdyn + "setup_reaction_wheel_dyn_effector")
4342
@patch(basicdyn + "setup_thruster_dyn_effector")
4443
@patch(basicdyn + "setup_simple_nav_object")
@@ -48,8 +47,9 @@ def test_is_alive(self):
4847
@patch(basicdyn + "setup_power_sink")
4948
@patch(basicdyn + "setup_reaction_wheel_power")
5049
@patch(basicdyn + "setup_thruster_power")
51-
@patch(basicdyn + "setup_disturbance_torque")
52-
@patch(basicdyn + "setup_density_model")
50+
@patch(module + "DisturbanceTorqueDynModel." + "setup_disturbance_torque")
51+
@patch(module + "AtmosphericDragDynModel." + "setup_density_model")
52+
@patch(module + "AtmosphericDragDynModel." + "setup_drag_effector")
5353
def test_basic_setup_objects(self, *args):
5454
BasicDynamicsModel(MagicMock(simulator=MagicMock()), 1.0)
5555
for setter in args:

0 commit comments

Comments
 (0)