Skip to content

Commit 7f6cfff

Browse files
Merge pull request #1117 from AVSLab/feature/expose-individual-bodies-n-dof-effector
Expose individual bodies NDOF effector
2 parents 53ff167 + 41f378d commit 7f6cfff

18 files changed

+558
-333
lines changed

docs/source/Support/bskReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ Version |release|
4141
- Add a desired relative attitude between spacecraft in :ref:`constraintDynamicEffector`.
4242
- Added a new stepper motor simulation module :ref:`stepperMotor`. This kinematic profiler module is useful to
4343
simulate the actuation of motor-driven prescribed spacecraft components.
44+
- Made individual structures for each degree of freedom in :ref:`spinningBodyNDOFStateEffector` and
45+
:ref:`linearTranslationNDOFStateEffector`.
46+
- Capitalized all structures in :ref:`linearTranslationOneDOFStateEffector` and :ref:`linearTranslationNDOFStateEffector`.
4447

4548

4649
Version 2.8.0 (August 30, 2025)

examples/scenarioExtendingBoom.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ def run(show_plots):
131131
scObject.hub.sigma_BNInit = [[0.0], [0.0], [0.0]]
132132
scObject.hub.omega_BN_BInit = [[0.1], [0.1], [0.1]]
133133

134-
translatingBodyEffector = linearTranslationNDOFStateEffector.linearTranslationNDOFStateEffector()
134+
translatingBodyEffector = linearTranslationNDOFStateEffector.LinearTranslationNDOFStateEffector()
135135
translatingBodyEffector.ModelTag = "translatingBodyEffector"
136136
scObject.addStateEffector(translatingBodyEffector)
137137
scSim.AddModelToTask(dynTaskName, translatingBodyEffector)
138138

139-
translatingBody1 = linearTranslationNDOFStateEffector.translatingBody()
139+
translatingBody1 = linearTranslationNDOFStateEffector.TranslatingBody()
140140
translatingBody1.setMass(100)
141141
translatingBody1.setIPntFc_F([[translatingBody1.getMass() / 12 * (3 * (scGeometry.diameterArm / 2) ** 2 + scGeometry.heightArm ** 2), 0.0, 0.0],
142142
[0.0, translatingBody1.getMass() / 12 * (scGeometry.diameterArm / 2) ** 2, 0.0],
@@ -151,7 +151,7 @@ def run(show_plots):
151151
translatingBody1.setK(100.0)
152152
translatingBodyEffector.addTranslatingBody(translatingBody1)
153153

154-
translatingBody2 = linearTranslationNDOFStateEffector.translatingBody()
154+
translatingBody2 = linearTranslationNDOFStateEffector.TranslatingBody()
155155
translatingBody2.setMass(100)
156156
translatingBody2.setIPntFc_F([[translatingBody2.getMass() / 12 * (3 * (scGeometry.diameterArm / 2) ** 2 + scGeometry.heightArm ** 2), 0.0, 0.0],
157157
[0.0, translatingBody2.getMass() / 12 * (scGeometry.diameterArm / 2) ** 2, 0.0],
@@ -182,7 +182,7 @@ def run(show_plots):
182182
translatingRigidBodyMsg2 = messaging.LinearTranslationRigidBodyMsg().write(translatingRigidBodyMsgData)
183183
profiler2.linearTranslationRigidBodyInMsg.subscribeTo(translatingRigidBodyMsg2)
184184

185-
translatingBody3 = linearTranslationNDOFStateEffector.translatingBody()
185+
translatingBody3 = linearTranslationNDOFStateEffector.TranslatingBody()
186186
translatingBody3.setMass(100)
187187
translatingBody3.setIPntFc_F([[translatingBody3.getMass() / 12 * (
188188
3 * (scGeometry.diameterArm / 2) ** 2 + scGeometry.heightArm ** 2), 0.0, 0.0],
@@ -214,7 +214,7 @@ def run(show_plots):
214214
translatingRigidBodyMsg3 = messaging.LinearTranslationRigidBodyMsg().write(translatingRigidBodyMsgData)
215215
profiler3.linearTranslationRigidBodyInMsg.subscribeTo(translatingRigidBodyMsg3)
216216

217-
translatingBody4 = linearTranslationNDOFStateEffector.translatingBody()
217+
translatingBody4 = linearTranslationNDOFStateEffector.TranslatingBody()
218218
translatingBody4.setMass(100)
219219
translatingBody4.setIPntFc_F([[translatingBody4.getMass() / 12 * (
220220
3 * (scGeometry.diameterArm / 2) ** 2 + scGeometry.heightArm ** 2), 0.0, 0.0],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# ISC License
2+
#
3+
# Copyright (c) 2025, Autonomous Vehicle Systems Lab, University of Colorado at Boulder
4+
#
5+
# Permission to use, copy, modify, and/or distribute this software for any
6+
# purpose with or without fee is hereby granted, provided that the above
7+
# copyright notice and this permission notice appear in all copies.
8+
#
9+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16+
17+
18+
#
19+
# Unit Test Script
20+
# Module Name: linearTranslatingBodiesNDOF
21+
# Author: João Vaz Carneiro
22+
# Creation Date: October 10, 2025
23+
#
24+
25+
import numpy as np
26+
from Basilisk.simulation import linearTranslationNDOFStateEffector
27+
28+
29+
def test_changeParametersTranslatingBody(show_plots):
30+
r"""
31+
**Validation Test Description**
32+
33+
This unit test checks that we can retrieve a body of the N-DOF module, change its parameters and retrieve them while
34+
keeping all data in memory.
35+
36+
**Description of Variables Being Tested**
37+
38+
All setter and getter methods are exercised and compared to the truth values.
39+
"""
40+
changeParameters()
41+
42+
43+
def changeParameters():
44+
mass = 20
45+
IPntFc_F = [[767, 0.0, 0.0],
46+
[0.0, 912, 0.0],
47+
[0.0, 0.0, 360]]
48+
dcm_FP = [[-1.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, 1.0]]
49+
r_FcF_F = [[0.412],
50+
[0.623],
51+
[0.456]]
52+
r_F0P_P = [[0.199],
53+
[0.624],
54+
[0.771]]
55+
fHat_P = [[1], [0], [0]]
56+
k = 152
57+
c = 432
58+
59+
translatingBodyEffector = linearTranslationNDOFStateEffector.LinearTranslationNDOFStateEffector()
60+
translatingBodyEffector.addTranslatingBody(linearTranslationNDOFStateEffector.TranslatingBody())
61+
62+
translatingBody = translatingBodyEffector.getTranslatingBody(0)
63+
translatingBody.setMass(mass)
64+
translatingBody.setIPntFc_F(IPntFc_F)
65+
translatingBody.setDCM_FP(dcm_FP)
66+
translatingBody.setR_FcF_F(r_FcF_F)
67+
translatingBody.setR_F0P_P(r_F0P_P)
68+
translatingBody.setFHat_P(fHat_P)
69+
translatingBody.setK(k)
70+
translatingBody.setC(c)
71+
72+
translatingBodyTest = translatingBodyEffector.getTranslatingBody(0)
73+
np.testing.assert_equal(translatingBodyTest.getMass(), mass)
74+
np.testing.assert_equal(translatingBodyTest.getIPntFc_F(), IPntFc_F)
75+
np.testing.assert_equal(translatingBodyTest.getDCM_FP(), dcm_FP)
76+
np.testing.assert_equal(translatingBodyTest.getR_FcF_F(), r_FcF_F)
77+
np.testing.assert_equal(translatingBodyTest.getR_F0P_P(), r_F0P_P)
78+
np.testing.assert_equal(translatingBodyTest.getFHat_P(), fHat_P)
79+
np.testing.assert_equal(translatingBodyTest.getK(), k)
80+
np.testing.assert_equal(translatingBodyTest.getC(), c)
81+
82+
83+
if __name__ == "__main__":
84+
changeParameters()

src/simulation/dynamics/linearTranslationalBodies/linearTranslationBodiesNDOF/_UnitTest/test_linearTranslationNDOFStateEffector.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ def translatingBodyNoInput(show_plots):
9797
testProc.addTask(unitTestSim.CreateNewTask(unitTaskName, testProcessRate))
9898

9999
# Create four translating rigid bodies
100-
translatingBodyEffector = linearTranslationNDOFStateEffector.linearTranslationNDOFStateEffector()
100+
translatingBodyEffector = linearTranslationNDOFStateEffector.LinearTranslationNDOFStateEffector()
101101
translatingBodyEffector.ModelTag = "translatingBodyEffector"
102102

103103
# define properties
104-
translatingBody1 = linearTranslationNDOFStateEffector.translatingBody()
104+
translatingBody1 = linearTranslationNDOFStateEffector.TranslatingBody()
105105
translatingBody1.setMass(np.random.uniform(5.0, 50.0))
106106
translatingBody1.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
107107
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -119,7 +119,7 @@ def translatingBodyNoInput(show_plots):
119119
translatingBody1.setK(np.random.random())
120120
translatingBodyEffector.addTranslatingBody(translatingBody1)
121121

122-
translatingBody2 = linearTranslationNDOFStateEffector.translatingBody()
122+
translatingBody2 = linearTranslationNDOFStateEffector.TranslatingBody()
123123
translatingBody2.setMass(np.random.uniform(5.0, 50.0))
124124
translatingBody2.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
125125
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -137,7 +137,7 @@ def translatingBodyNoInput(show_plots):
137137
translatingBody2.setK(np.random.random())
138138
translatingBodyEffector.addTranslatingBody(translatingBody2)
139139

140-
translatingBody3 = linearTranslationNDOFStateEffector.translatingBody()
140+
translatingBody3 = linearTranslationNDOFStateEffector.TranslatingBody()
141141
translatingBody3.setMass(np.random.uniform(5.0, 50.0))
142142
translatingBody3.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
143143
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -155,7 +155,7 @@ def translatingBodyNoInput(show_plots):
155155
translatingBody3.setK(np.random.random())
156156
translatingBodyEffector.addTranslatingBody(translatingBody3)
157157

158-
translatingBody4 = linearTranslationNDOFStateEffector.translatingBody()
158+
translatingBody4 = linearTranslationNDOFStateEffector.TranslatingBody()
159159
translatingBody4.setMass(np.random.uniform(5.0, 50.0))
160160
translatingBody4.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
161161
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -308,7 +308,7 @@ def translatingBodyNoInput(show_plots):
308308
plt.close("all")
309309

310310
# Testing setup
311-
accuracy = 1e-12
311+
accuracy = 1e-13
312312

313313
np.testing.assert_allclose(finalOrbEnergy, initialOrbEnergy, rtol=accuracy, err_msg="Orbital energy is not constant.")
314314
np.testing.assert_allclose(finalRotEnergy, initialRotEnergy, rtol=accuracy,
@@ -339,11 +339,11 @@ def translatingBodyLockAxis(show_plots):
339339
testProc.addTask(unitTestSim.CreateNewTask(unitTaskName, testProcessRate))
340340

341341
# Create four translating rigid bodies
342-
translatingBodyEffector = linearTranslationNDOFStateEffector.linearTranslationNDOFStateEffector()
342+
translatingBodyEffector = linearTranslationNDOFStateEffector.LinearTranslationNDOFStateEffector()
343343
translatingBodyEffector.ModelTag = "translatingBodyEffector"
344344

345345
# define properties
346-
translatingBody1 = linearTranslationNDOFStateEffector.translatingBody()
346+
translatingBody1 = linearTranslationNDOFStateEffector.TranslatingBody()
347347
translatingBody1.setMass(np.random.uniform(5.0, 50.0))
348348
translatingBody1.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
349349
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -361,7 +361,7 @@ def translatingBodyLockAxis(show_plots):
361361
translatingBody1.setK(np.random.random())
362362
translatingBodyEffector.addTranslatingBody(translatingBody1)
363363

364-
translatingBody2 = linearTranslationNDOFStateEffector.translatingBody()
364+
translatingBody2 = linearTranslationNDOFStateEffector.TranslatingBody()
365365
translatingBody2.setMass(np.random.uniform(5.0, 50.0))
366366
translatingBody2.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
367367
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -379,7 +379,7 @@ def translatingBodyLockAxis(show_plots):
379379
translatingBody2.setK(np.random.random())
380380
translatingBodyEffector.addTranslatingBody(translatingBody2)
381381

382-
translatingBody3 = linearTranslationNDOFStateEffector.translatingBody()
382+
translatingBody3 = linearTranslationNDOFStateEffector.TranslatingBody()
383383
translatingBody3.setMass(np.random.uniform(5.0, 50.0))
384384
translatingBody3.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
385385
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -397,7 +397,7 @@ def translatingBodyLockAxis(show_plots):
397397
translatingBody3.setK(np.random.random())
398398
translatingBodyEffector.addTranslatingBody(translatingBody3)
399399

400-
translatingBody4 = linearTranslationNDOFStateEffector.translatingBody()
400+
translatingBody4 = linearTranslationNDOFStateEffector.TranslatingBody()
401401
translatingBody4.setMass(np.random.uniform(5.0, 50.0))
402402
translatingBody4.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
403403
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -556,7 +556,7 @@ def translatingBodyLockAxis(show_plots):
556556
plt.close("all")
557557

558558
# Testing setup
559-
accuracy = 1e-12
559+
accuracy = 1e-13
560560

561561
np.testing.assert_allclose(finalOrbEnergy, initialOrbEnergy, rtol=accuracy,
562562
err_msg="Orbital energy is not constant.")
@@ -588,11 +588,11 @@ def translatingBodyCommandedForce(show_plots):
588588
testProc.addTask(unitTestSim.CreateNewTask(unitTaskName, testProcessRate))
589589

590590
# Create four translating rigid bodies
591-
translatingBodyEffector = linearTranslationNDOFStateEffector.linearTranslationNDOFStateEffector()
591+
translatingBodyEffector = linearTranslationNDOFStateEffector.LinearTranslationNDOFStateEffector()
592592
translatingBodyEffector.ModelTag = "translatingBodyEffector"
593593

594594
# define properties
595-
translatingBody1 = linearTranslationNDOFStateEffector.translatingBody()
595+
translatingBody1 = linearTranslationNDOFStateEffector.TranslatingBody()
596596
translatingBody1.setMass(np.random.uniform(5.0, 50.0))
597597
translatingBody1.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
598598
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -610,7 +610,7 @@ def translatingBodyCommandedForce(show_plots):
610610
translatingBody1.setK(np.random.random())
611611
translatingBodyEffector.addTranslatingBody(translatingBody1)
612612

613-
translatingBody2 = linearTranslationNDOFStateEffector.translatingBody()
613+
translatingBody2 = linearTranslationNDOFStateEffector.TranslatingBody()
614614
translatingBody2.setMass(np.random.uniform(5.0, 50.0))
615615
translatingBody2.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
616616
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -628,7 +628,7 @@ def translatingBodyCommandedForce(show_plots):
628628
translatingBody2.setK(np.random.random())
629629
translatingBodyEffector.addTranslatingBody(translatingBody2)
630630

631-
translatingBody3 = linearTranslationNDOFStateEffector.translatingBody()
631+
translatingBody3 = linearTranslationNDOFStateEffector.TranslatingBody()
632632
translatingBody3.setMass(np.random.uniform(5.0, 50.0))
633633
translatingBody3.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
634634
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -646,7 +646,7 @@ def translatingBodyCommandedForce(show_plots):
646646
translatingBody3.setK(np.random.random())
647647
translatingBodyEffector.addTranslatingBody(translatingBody3)
648648

649-
translatingBody4 = linearTranslationNDOFStateEffector.translatingBody()
649+
translatingBody4 = linearTranslationNDOFStateEffector.TranslatingBody()
650650
translatingBody4.setMass(np.random.uniform(5.0, 50.0))
651651
translatingBody4.setIPntFc_F([[np.random.uniform(5.0, 100.0), 0.0, 0.0],
652652
[0.0, np.random.uniform(5.0, 100.0), 0.0],
@@ -797,7 +797,7 @@ def translatingBodyCommandedForce(show_plots):
797797
plt.close("all")
798798

799799
# Testing setup
800-
accuracy = 1e-12
800+
accuracy = 1e-13
801801

802802
np.testing.assert_allclose(finalOrbEnergy, initialOrbEnergy, rtol=accuracy,
803803
err_msg="Orbital energy is not constant.")

0 commit comments

Comments
 (0)