Skip to content

Commit fa16c2d

Browse files
committed
[#1490] update existing mujoco examples to use gravity factor class
1 parent 24958c9 commit fa16c2d

4 files changed

Lines changed: 37 additions & 85 deletions

File tree

examples/mujoco/scenarioAttitudeFeedbackRWMuJoCo.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@
5050
#. ``saturationSingleActuator`` optionally clamps each ``SingleActuatorMsg`` to
5151
emulate actuator torque limits (for example, reaction wheel ``uMax``).
5252
53+
Earth gravity is configured with :ref:`simIncludeGravBody`. Calling
54+
``gravFactory.addBodiesTo(scene)`` creates the intermediate
55+
:ref:`NBodyGravity<NBodyGravity>` model and automatically registers the bus and
56+
all three reaction wheels as gravity targets.
57+
5358
The simulation runs for 10 minutes. The attitude error, rate error, wheel
5459
motor torques, and wheel speeds are plotted at the end.
5560
@@ -72,10 +77,8 @@
7277

7378
from Basilisk.architecture import messaging
7479
from Basilisk.fswAlgorithms import attTrackingError, inertial3D, mrpFeedback, rwMotorTorque
75-
from Basilisk.simulation import NBodyGravity
7680
from Basilisk.simulation import arrayMotorTorqueToSingleActuators
7781
from Basilisk.simulation import mujoco
78-
from Basilisk.simulation import pointMassGravityModel
7982
from Basilisk.simulation import saturationSingleActuator
8083
from Basilisk.simulation import scalarJointStatesToRWSpeed
8184
from Basilisk.simulation import simpleNav
@@ -240,26 +243,16 @@ def run(showPlots: bool = False):
240243
rwActs = [scene.addJointSingleActuator(f"rw{i+1}Act", rwJoints[i]) for i in range(numRw)]
241244

242245
# -------------------------------------------------------------------------
243-
# 5) Add gravity to the special MuJoCo dynamics task (evaluated at integrator substeps)
246+
# 5) Add Earth gravity to every MuJoCo body through the gravity factory
244247
# -------------------------------------------------------------------------
245-
gravity = NBodyGravity.NBodyGravity()
246-
gravity.ModelTag = "gravity"
247-
scene.AddModelToDynamicsTask(gravity)
248-
249248
gravFactory = simIncludeGravBody.gravBodyFactory()
250249
earth = gravFactory.createEarth()
251250
earth.isCentralBody = True
252-
scene._vizGravBodies = gravFactory.gravBodies
253-
254251
muEarth = earth.mu # [m^3/s^2]
255-
earthPm = pointMassGravityModel.PointMassGravityModel()
256-
earthPm.muBody = muEarth
257-
gravity.addGravitySource("earth", earthPm, isCentralBody=True)
258252

259-
# Apply gravity to all bodies to allow consistent orbital motion.
260-
gravity.addGravityTarget("bus", busBody)
261-
for i in range(numRw):
262-
gravity.addGravityTarget(f"rw{i+1}", rwBodies[i])
253+
# This creates the NBodyGravity model, adds Earth as its central source, and
254+
# registers the bus and all three reaction wheels as gravity targets.
255+
gravFactory.addBodiesTo(scene)
263256

264257
# -------------------------------------------------------------------------
265258
# 6) Navigation: read the bus state from MJScene and publish standard nav outputs

examples/mujoco/scenarioFormationFlyingWithDrag.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
as a single point-mass body with three translational sliding joints (x, y, z).
2525
Their inertial properties are assigned directly in the XML.
2626
27-
Gravity is modeled using the :ref:`NBodyGravity` model, with a point-mass
28-
Earth defined by :ref:`pointMassGravityModel`. The exponential atmospheric model
27+
Gravity is configured with :ref:`simIncludeGravBody`. Its gravity factory
28+
creates a point-mass Earth and attaches it to the MuJoCo scene, automatically
29+
applying gravity to both spacecraft. The exponential atmospheric model
2930
(:ref:`exponentialAtmosphere`) is optionally added so that the chief and deputy
3031
can experience cannonball drag.
3132
@@ -52,7 +53,7 @@
5253
5354
* How to construct a multi-body MuJoCo scene with two independent spacecraft
5455
* How to configure translation-only scenarios
55-
* How to model gravity on multiple bodies using the :ref:`NBodyGravity` model
56+
* How to configure gravity on multiple MuJoCo bodies using the gravity factory
5657
* How to apply aerodynamic forces
5758
* How to configure and apply a classical-element feedback controller for formation control
5859
* How to record and visualize inertial trajectories, orbital-element histories,
@@ -91,8 +92,6 @@
9192
from Basilisk.architecture import messaging
9293
from Basilisk.simulation import mujoco
9394
from Basilisk.simulation import svIntegrators
94-
from Basilisk.simulation import pointMassGravityModel
95-
from Basilisk.simulation import NBodyGravity
9695
from Basilisk.simulation import cannonballDrag
9796
from Basilisk.simulation import MJLinearTimeInvariantSystem
9897
from Basilisk.simulation import exponentialAtmosphere
@@ -160,7 +159,6 @@ class SimulationModels:
160159
scene: mujoco.MJScene
161160
chiefBody: mujoco.MJBody
162161
deputyBody: mujoco.MJBody
163-
gravity: NBodyGravity.NBodyGravity
164162
atmo: exponentialAtmosphere.ExponentialAtmosphere
165163

166164
# Drag models
@@ -325,7 +323,6 @@ def createSimulationModels(
325323
# Create the MuJoCo scene and add it as a dynamic object
326324
scene = mujoco.MJScene(CHIEF_DEPUTY_SCENE_XML)
327325
scene.extraEoMCall = True
328-
scene._vizGravBodies = gravFactory.gravBodies
329326
scSim.AddModelToTask("test", scene, 1)
330327

331328
# Select integrator
@@ -338,16 +335,9 @@ def createSimulationModels(
338335
chiefBody: mujoco.MJBody = scene.getBody("chief")
339336
deputyBody: mujoco.MJBody = scene.getBody("deputy")
340337

341-
# Central body gravity
342-
gravity = NBodyGravity.NBodyGravity()
343-
gravity.ModelTag = "gravity"
344-
scene.AddModelToDynamicsTask(gravity)
345-
346-
gravityModel = pointMassGravityModel.PointMassGravityModel()
347-
gravityModel.muBody = planet.mu
348-
gravity.addGravitySource("earth", gravityModel, True)
349-
gravity.addGravityTarget("chief", chiefBody)
350-
gravity.addGravityTarget("deputy", deputyBody)
338+
# The factory creates the NBodyGravity model, adds Earth as its central
339+
# source, and registers both spacecraft as gravity targets.
340+
gravFactory.addBodiesTo(scene)
351341

352342
# Exponential atmosphere model
353343
atmo = exponentialAtmosphere.ExponentialAtmosphere()
@@ -364,7 +354,6 @@ def createSimulationModels(
364354
scene=scene,
365355
chiefBody=chiefBody,
366356
deputyBody=deputyBody,
367-
gravity=gravity,
368357
atmo=atmo,
369358
)
370359

examples/mujoco/scenarioMJSceneVizard.py

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@
5050
from Basilisk.architecture import messaging
5151
from Basilisk.simulation import coarseSunSensor
5252
from Basilisk.simulation import mujoco
53-
from Basilisk.simulation import NBodyGravity
54-
from Basilisk.simulation import pointMassGravityModel
5553
from Basilisk.simulation import spacecraft
5654
from Basilisk.simulation import StatefulSysModel
5755
from Basilisk.simulation import svIntegrators
@@ -197,29 +195,6 @@ def setStowed(scene, panelIds, bodyPrefix):
197195
).setPosition(JOINT_START_END[i - 1][0])
198196

199197

200-
def addOrbitalGravity(scene, mu, modelCache):
201-
"""Apply central-body point-mass gravity to every body in ``scene``.
202-
203-
Uses :ref:`NBodyGravity` with one gravity target per body (hub plus each
204-
deployable panel), so the field is evaluated and applied at each body's true
205-
center of mass. The whole structure is then in physical orbital freefall —
206-
the appendages are weightless — while the gravity gradient across it is
207-
captured.
208-
"""
209-
gravity = NBodyGravity.NBodyGravity()
210-
gravity.ModelTag = f"{scene.ModelTag}_gravity"
211-
scene.AddModelToDynamicsTask(gravity)
212-
213-
gravityModel = pointMassGravityModel.PointMassGravityModel()
214-
gravityModel.muBody = mu
215-
gravity.addGravitySource("earth", gravityModel, True)
216-
for name in scene.getBodyNames():
217-
gravity.addGravityTarget(name, scene.getBody(name))
218-
219-
modelCache.extend([gravity, gravityModel])
220-
return gravity
221-
222-
223198
# Main scenario
224199
def run(showPlots: bool = False):
225200
scSim = SimulationBaseClass.SimBaseClass()
@@ -264,11 +239,16 @@ def run(showPlots: bool = False):
264239
epochInMsg=True,
265240
)
266241
spiceObject.zeroBase = "Earth"
267-
scSim.AddModelToTask("simTask", spiceObject)
268242

269-
# vizSupport dedupes planets by name across scenes.
270-
primaryScene._vizGravBodies = gravFactory.gravBodies
271-
companionScene._vizGravBodies = gravFactory.gravBodies
243+
# MuJoCo gravity is evaluated at every integrator substep. Run SPICE after
244+
# the scene's high-priority forward kinematics and before gravity (default
245+
# priority -1), so every gravity evaluation reads current ephemerides.
246+
spiceDynamicsPriority = 75
247+
primaryScene.AddModelToDynamicsTask(spiceObject, spiceDynamicsPriority)
248+
companionScene.AddModelToDynamicsTask(spiceObject, spiceDynamicsPriority)
249+
250+
# The regular spacecraft below also needs SPICE at the top-level task rate.
251+
scSim.AddModelToTask("simTask", spiceObject)
272252

273253
# Trailer is a regular Basilisk Spacecraft, behind the primary along-track.
274254
# Uses ``gravFactory.addBodiesTo`` for the standard gravField wiring.
@@ -301,13 +281,13 @@ def run(showPlots: bool = False):
301281
addDeployment(companionScene, companionPanels, "companion_panel", models)
302282

303283
# Gravity setup. Each MJScene gets its own NBodyGravity model that applies
304-
# central-body gravity as a force at every body's center of mass (hub plus
305-
# each panel), preserving the gravity gradient across the structure.
284+
# the factory's Earth, Moon, and Sun gravity sources at every body's center
285+
# of mass, preserving the gravity gradient across each structure.
306286
hubBody = primaryScene.getBody("hub")
307287
companionBody = companionScene.getBody("companion_hub")
308288

309-
addOrbitalGravity(primaryScene, mu, models)
310-
addOrbitalGravity(companionScene, mu, models)
289+
gravFactory.addBodiesTo(primaryScene)
290+
gravFactory.addBodiesTo(companionScene)
311291

312292
# CSS sensors mounted on the primary hub. The MJScene body's origin state
313293
# message subscribes the same way a regular Spacecraft body state message

examples/mujoco/scenarioStochasticDrag.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
density model. The script illustrates how one defines and handles dynamic states
2626
that are driven by stochastic terms.
2727
28-
The spacecraft definition is given in ``CANNONBALL_SCENE_XML``; it contains a single
29-
body for which we set its mass directly. We use the :ref:`NBodyGravity` model to compute
30-
the gravity acting on this body due to a point-mass Earth.
28+
The spacecraft definition is given in ``CANNONBALL_SCENE_XML``; it contains a
29+
single body for which we set its mass directly. A
30+
:ref:`simIncludeGravBody` gravity factory creates the point-mass Earth and
31+
attaches it to the MuJoCo scene.
3132
3233
The drag force acting on the body is computed in the :ref:`CannonballDrag<CannonballDrag>`
3334
module. This takes as input the state of the spacecraft (so that
@@ -137,8 +138,6 @@
137138
from Basilisk.architecture import messaging
138139
from Basilisk.simulation import mujoco
139140
from Basilisk.simulation import svIntegrators
140-
from Basilisk.simulation import pointMassGravityModel
141-
from Basilisk.simulation import NBodyGravity
142141
from Basilisk.simulation import exponentialAtmosphere
143142
from Basilisk.simulation import cannonballDrag
144143
from Basilisk.simulation import MJStochasticAtmDensity
@@ -211,7 +210,6 @@ def run(showPlots: bool = False, useIgbm: bool = False):
211210
# Create the Mujoco scene (our MuJoCo DynamicObject)
212211
# Load the XML file that defines the system from a file
213212
scene = mujoco.MJScene(CANNONBALL_SCENE_XML)
214-
scene._vizGravBodies = gravFactory.gravBodies
215213
scSim.AddModelToTask("test", scene)
216214

217215
# Set a stochastic integrator on the DynamicObject, necessary since we have
@@ -231,18 +229,10 @@ def run(showPlots: bool = False, useIgbm: bool = False):
231229
body: mujoco.MJBody = scene.getBody("ball")
232230
dragPoint: mujoco.MJSite = body.getCenterOfMass()
233231

234-
### Create the NBodyGravity model
235-
# add model to the dynamics task of the scene
236-
gravity = NBodyGravity.NBodyGravity()
237-
scene.AddModelToDynamicsTask(gravity)
238-
239-
# Create a point-mass gravity source
240-
gravityModel = pointMassGravityModel.PointMassGravityModel()
241-
gravityModel.muBody = planet.mu
242-
gravity.addGravitySource("earth", gravityModel, True)
243-
244-
# Create a gravity target from the mujoco body
245-
gravity.addGravityTarget("ball", body)
232+
### Add Earth gravity to the MuJoCo scene
233+
# The factory creates the NBodyGravity model and registers the cannonball
234+
# body as a gravity target.
235+
gravFactory.addBodiesTo(scene)
246236

247237
### Create the density model
248238
atmo = exponentialAtmosphere.ExponentialAtmosphere()

0 commit comments

Comments
 (0)