Skip to content

Commit 61f1a58

Browse files
Thibaud Teiltteil
Thibaud Teil
authored and
tteil
committed
add interface unit test
1 parent 06cac89 commit 61f1a58

File tree

1 file changed

+219
-0
lines changed

1 file changed

+219
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
# ISC License
2+
#
3+
# Copyright (c) 2024, 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+
import tempfile, sys
18+
from Basilisk import __path__
19+
bskPath = __path__[0]
20+
sys.path.append(bskPath + "/../../src/utilities/vizProtobuffer/")
21+
import cielimMessage_pb2
22+
import delimited_protobuf
23+
import numpy as np
24+
import pytest
25+
from Basilisk.architecture import messaging
26+
from Basilisk.utilities import SimulationBaseClass
27+
28+
importErr = False
29+
reasonErr = ""
30+
try:
31+
from Basilisk.simulation import cielimInterface
32+
except ImportError:
33+
importErr = True
34+
reasonErr = "\nCielim Interface not built ---check build option"
35+
36+
@pytest.mark.skipif(importErr, reason=reasonErr)
37+
def test_interface():
38+
read_write_test()
39+
40+
def read_write_test():
41+
tmpdir = tempfile.TemporaryDirectory()
42+
unit_task_name = "unitTask"
43+
unit_process_name = "TestProcess"
44+
unit_test_sim = SimulationBaseClass.SimBaseClass()
45+
46+
# Create test thread
47+
test_process_rate = int(1E9) # update process rate update time
48+
test_process = unit_test_sim.CreateNewProcess(unit_process_name)
49+
test_process.addTask(unit_test_sim.CreateNewTask(unit_task_name, test_process_rate))
50+
51+
module = cielimInterface.CielimInterface()
52+
module.ModelTag = "cielim_interface"
53+
module.setOpNavMode(cielimInterface.ClosedLoopMode_OPEN_LOOP)
54+
module.setSaveFile(tmpdir.name + "/test_proto")
55+
56+
unit_test_sim.AddModelToTask(unit_task_name, module)
57+
58+
# Create epoch message
59+
epoch_payload = messaging.EpochMsgPayload()
60+
epoch_payload.year = 2050
61+
epoch_payload.month = 2
62+
epoch_payload.day = 15
63+
epoch_payload.hours = 22
64+
epoch_payload.minutes = 8
65+
epoch_payload.seconds = 58
66+
epoch_message = messaging.EpochMsg().write(epoch_payload)
67+
module.epochMessage.subscribeTo(epoch_message)
68+
69+
# Create camera rendering message
70+
rendering_payload = messaging.CameraRenderingMsgPayload()
71+
rendering_payload.cameraId = 1
72+
rendering_payload.cosmicRayStdDeviation = 0.1
73+
rendering_payload.enableStrayLight = True
74+
rendering_payload.starField = True
75+
rendering_payload.rendering = "Lumen"
76+
rendering_payload.smear = True
77+
rendering_message = messaging.CameraRenderingMsg().write(rendering_payload)
78+
module.cameraRenderingMessage.subscribeTo(rendering_message)
79+
80+
# Create asteroid parameter message
81+
asteroid_parameter_payload = messaging.CelestialBodyParametersMsgPayload()
82+
asteroid_parameter_payload.bodyName = "asteroid_b612"
83+
asteroid_parameter_payload.shapeModel = "Ryugu"
84+
asteroid_parameter_payload.perlinNoise = 0.5
85+
asteroid_parameter_payload.proceduralRocks = 1.5
86+
asteroid_parameter_payload.brdf = "Lambertian"
87+
asteroid_parameter_payload.reflectanceParameters = [0.5]
88+
asteroid_parameter_payload.meanRadius = 50000
89+
asteroid_parameter_payload.principalAxisDistortion = [10, 5, 10]
90+
asteroid_parameter_message = messaging.CelestialBodyParametersMsg().write(asteroid_parameter_payload)
91+
module.celestialParametersMessage.subscribeTo(asteroid_parameter_message)
92+
93+
# Create camera message
94+
camera_payload = messaging.CameraModelMsgPayload()
95+
camera_payload.timeTag = int(0.5*1E9)
96+
camera_payload.cameraId = 1
97+
camera_payload.parentName = "cielim_sat"
98+
camera_payload.fieldOfView = [20*np.pi/180, 15*np.pi/180]
99+
camera_payload.bodyToCameraMrp = [1/3,-1/3,-1/3]
100+
camera_payload.cameraBodyFramePosition = [1,1,1]
101+
camera_payload.resolution = [4000, 3000]
102+
camera_payload.renderRate = 10000
103+
camera_payload.focalLength = 0.1
104+
camera_payload.readNoise = 1
105+
camera_payload.systemGain = 0.5
106+
camera_payload.gaussianPointSpreadFunction = 2
107+
camera_payload.exposureTime = 0.1
108+
camera_message = messaging.CameraModelMsg().write(camera_payload)
109+
module.cameraModelMessage.subscribeTo(camera_message)
110+
111+
# Create spacecraft message
112+
spacecraft_payload = messaging.SCStatesMsgPayload()
113+
spacecraft_payload.r_BN_N = [0,0,-3.83E5]
114+
spacecraft_payload.v_BN_N = [4, 5, 6]
115+
spacecraft_payload.sigma_BN = [np.sqrt(2)/2, 0, -np.sqrt(2)/2]
116+
spacecraft_message = messaging.SCStatesMsg().write(spacecraft_payload)
117+
module.spacecraftMessage.subscribeTo(spacecraft_message)
118+
119+
# Create spice body messages using a similar structure to the factory (for ease of implementation)
120+
class GravBodies:
121+
planetName = ""
122+
isCentralBody = False
123+
planetBodyInMsg = messaging.SpicePlanetStateMsg()
124+
125+
grav_bodies = []
126+
bodies_message_list = []
127+
sun = GravBodies()
128+
sun.planetName = "sun"
129+
sun_data = messaging.SpicePlanetStateMsgPayload()
130+
sun_data.PositionVector = [10E10,0,0]
131+
sun_data.VelocityVector = [4, 5, 6]
132+
sun_data.J20002Pfix = np.eye(3)
133+
sun.planetBodyInMsg = messaging.SpicePlanetStateMsg().write(sun_data)
134+
grav_bodies.append(sun)
135+
bodies_message_list.append(sun_data)
136+
137+
asteroid_b612 = GravBodies()
138+
asteroid_b612.planetName = "asteroid_b612"
139+
asteroid_b612.isCentralBody = True
140+
asteroid_data = messaging.SpicePlanetStateMsgPayload()
141+
asteroid_data.PositionVector = [0,0,0]
142+
asteroid_data.VelocityVector = [4, 5, 6]
143+
asteroid_data.J20002Pfix = -np.eye(3)
144+
asteroid_b612.planetBodyInMsg = messaging.SpicePlanetStateMsg().write(asteroid_data)
145+
grav_bodies.append(asteroid_b612)
146+
bodies_message_list.append(asteroid_data)
147+
148+
for gravBody in grav_bodies:
149+
body = cielimInterface.SpiceBody()
150+
body.name = gravBody.planetName
151+
body.isCentralBody = gravBody.isCentralBody
152+
body.spiceStateMessage.subscribeTo(gravBody.planetBodyInMsg)
153+
module.addCelestialBody(body)
154+
155+
# Run block
156+
unit_test_sim.InitializeSimulation()
157+
unit_test_sim.ConfigureStopTime(int(1e9))
158+
unit_test_sim.ExecuteSimulation()
159+
module.closeProtobufFile()
160+
161+
# Read the existing address book.
162+
file_handle = open(module.getSaveFilename(), "rb")
163+
cielim_message = delimited_protobuf.read(file_handle, cielimMessage_pb2.CielimMessage)
164+
165+
np.testing.assert_equal(cielim_message.currentTime.frameNumber, 0)
166+
np.testing.assert_equal(cielim_message.currentTime.simTimeElapsed, 0)
167+
168+
np.testing.assert_equal(cielim_message.epoch.year, epoch_payload.year)
169+
np.testing.assert_equal(cielim_message.epoch.month, epoch_payload.month)
170+
np.testing.assert_equal(cielim_message.epoch.day, epoch_payload.day)
171+
np.testing.assert_equal(cielim_message.epoch.hours, epoch_payload.hours)
172+
np.testing.assert_equal(cielim_message.epoch.minutes, epoch_payload.minutes)
173+
np.testing.assert_equal(cielim_message.epoch.seconds, epoch_payload.seconds)
174+
175+
np.testing.assert_equal(cielim_message.spacecraft.spacecraftName, "cielim_sat")
176+
np.testing.assert_equal(cielim_message.spacecraft.position, spacecraft_payload.r_BN_N)
177+
np.testing.assert_equal(cielim_message.spacecraft.velocity, spacecraft_payload.v_BN_N)
178+
np.testing.assert_equal(cielim_message.spacecraft.attitude, spacecraft_payload.sigma_BN)
179+
180+
np.testing.assert_equal(cielim_message.camera.cameraId, camera_payload.cameraId)
181+
np.testing.assert_equal(cielim_message.camera.parentName, "cielim_sat")
182+
np.testing.assert_equal(cielim_message.camera.fieldOfView,camera_payload.fieldOfView)
183+
np.testing.assert_equal(cielim_message.camera.resolution, camera_payload.resolution)
184+
np.testing.assert_equal(cielim_message.camera.cameraPositionInBody, camera_payload.cameraBodyFramePosition)
185+
np.testing.assert_equal(cielim_message.camera.bodyFrameToCameraMrp, camera_payload.bodyToCameraMrp)
186+
np.testing.assert_equal(cielim_message.camera.renderRate, camera_payload.renderRate)
187+
np.testing.assert_equal(cielim_message.camera.focalLength, camera_payload.focalLength)
188+
np.testing.assert_equal(cielim_message.camera.exposureTime, camera_payload.exposureTime)
189+
np.testing.assert_equal(cielim_message.camera.pointSpreadFunction, camera_payload.gaussianPointSpreadFunction)
190+
np.testing.assert_equal(cielim_message.camera.systemGain, camera_payload.systemGain)
191+
np.testing.assert_equal(cielim_message.camera.readNoise, camera_payload.readNoise)
192+
193+
np.testing.assert_equal(cielim_message.camera.renderParameters.cosmicRayStdDeviation, rendering_payload.cosmicRayStdDeviation)
194+
np.testing.assert_equal(cielim_message.camera.renderParameters.enableStrayLight, rendering_payload.enableStrayLight)
195+
np.testing.assert_equal(cielim_message.camera.renderParameters.starField, rendering_payload.starField)
196+
np.testing.assert_equal(cielim_message.camera.renderParameters.rendering, rendering_payload.rendering)
197+
np.testing.assert_equal(cielim_message.camera.renderParameters.enableSmear, rendering_payload.smear)
198+
199+
i = 0
200+
for message, body in zip(bodies_message_list, grav_bodies):
201+
name = body.planetName
202+
central = body.isCentralBody
203+
np.testing.assert_equal(cielim_message.celestialBodies[i].bodyName, name)
204+
np.testing.assert_equal(cielim_message.celestialBodies[i].position, message.PositionVector)
205+
np.testing.assert_equal(cielim_message.celestialBodies[i].velocity, message.VelocityVector)
206+
np.testing.assert_equal(cielim_message.celestialBodies[i].attitude, np.array(message.J20002Pfix).flatten())
207+
np.testing.assert_equal(cielim_message.celestialBodies[i].centralBody, central)
208+
if (name == asteroid_parameter_payload.bodyName):
209+
np.testing.assert_equal(cielim_message.celestialBodies[i].models.shapeModel, asteroid_parameter_payload.shapeModel)
210+
np.testing.assert_equal(cielim_message.celestialBodies[i].models.perlinNoiseStdDeviation, asteroid_parameter_payload.perlinNoise)
211+
np.testing.assert_equal(cielim_message.celestialBodies[i].models.proceduralRocks, asteroid_parameter_payload.proceduralRocks)
212+
np.testing.assert_equal(cielim_message.celestialBodies[i].models.brdfModel, asteroid_parameter_payload.brdf)
213+
np.testing.assert_equal(cielim_message.celestialBodies[i].models.reflectanceParameters, asteroid_parameter_payload.reflectanceParameters)
214+
np.testing.assert_equal(cielim_message.celestialBodies[i].models.meanRadius, asteroid_parameter_payload.meanRadius)
215+
np.testing.assert_equal(cielim_message.celestialBodies[i].models.principalAxisDistortion, asteroid_parameter_payload.principalAxisDistortion)
216+
i += 1
217+
218+
if __name__ == "__main__":
219+
test_interface()

0 commit comments

Comments
 (0)