Skip to content

Reference counting issue with SpiceInterface REQUIRED_KERNELS #1010

@Mark2000

Description

@Mark2000

Describe the bug
A SPICE(NOLEAPSECONDS) error is being thrown under certain conditions:

Toolkit version: N0067
 
SPICE(NOLEAPSECONDS) --
 
The variable that points to the leapseconds (DELTET/DELTA_AT) could not be
located in the kernel pool. It is likely that the leapseconds kernel has not
been loaded.
 
A traceback follows.  The name of the highest level module is first.
et2utc_c --> ET2UTC --> TTRANS
 
Oh, by the way:  The SPICELIB error handling actions are USER-TAILORABLE.  You
can choose whether the Toolkit aborts or continues when errors occur, which
error messages to output, and where to send the output.  Please read the ERROR
"Required Reading" file, or see the routines ERRACT, ERRDEV, and ERRPRT.

To reproduce

from Basilisk import __path__
from Basilisk.utilities import SimulationBaseClass, macros, simIncludeGravBody

bskPath = __path__[0]

class TrajectorySimulator(SimulationBaseClass.SimBaseClass):

    def __init__(
        self,
        utc_init: str,
        dt: float = 30.0,
    ) -> None:
        super().__init__()
        self.utc_init = utc_init
        self.dt = dt
        self._init_simulator()

    def _init_simulator(self) -> None:
        print("init sim, id:", id(self))
        simTaskName = "simTask"
        simProcessName = "simProcess"
        dynProcess = self.CreateNewProcess(simProcessName)
        simulationTimeStep = macros.sec2nano(self.dt)
        dynProcess.addTask(self.CreateNewTask(simTaskName, simulationTimeStep))

        self.gravFactory = simIncludeGravBody.gravBodyFactory()
        self.gravFactory.createSpiceInterface(
            bskPath + "/supportData/EphemerisData/", self.utc_init
        )
        self.AddModelToTask(simTaskName, self.gravFactory.spiceObject)

        self.InitializeSimulation()
        print("init sim complete, id:", id(self))

    def extend_to(self, t: float) -> None:
        print("running sim, id:", id(self))
        self.ConfigureStopTime(macros.sec2nano(t))
        self.ExecuteSimulation()
        print("running complete, id:", id(self))

    def __del__(self) -> None:
        print("deleting sim, id:", id(self))
        self.gravFactory.unloadSpiceKernels()
        print("deleting complete, id:", id(self))

if __name__ == "__main__":
    epoch = "2005 JUL 24 20:50:33.771 (UTC)"

    print("SIM 1")
    ts = TrajectorySimulator(epoch)
    ts.extend_to(100.0)
    print("SIM 2")
    ts = TrajectorySimulator(epoch)
    print("SIM 3")
    ts = TrajectorySimulator(epoch)
    ts.extend_to(100.0)

returns output

SIM 1
init sim, id: 4373724656
init sim complete, id: 4373724656
running sim, id: 4373724656
running complete, id: 4373724656
SIM 2
init sim, id: 13163280224
init sim complete, id: 13163280224
deleting sim, id: 4373724656
deleting complete, id: 4373724656
SIM 3
init sim, id: 13163278976
init sim complete, id: 13163278976
deleting sim, id: 13163280224
deleting complete, id: 13163280224
running sim, id: 13163278976 
================================================================================
 
Toolkit version: N0067
 
SPICE(NOLEAPSECONDS) --
 
The variable that points to the leapseconds (DELTET/DELTA_AT) could not be
located in the kernel pool. It is likely that the leapseconds kernel has not
been loaded.
 
A traceback follows.  The name of the highest level module is first.
et2utc_c --> ET2UTC --> TTRANS
 
Oh, by the way:  The SPICELIB error handling actions are USER-TAILORABLE.  You
can choose whether the Toolkit aborts or continues when errors occur, which
error messages to output, and where to send the output.  Please read the ERROR
"Required Reading" file, or see the routines ERRACT, ERRDEV, and ERRPRT.
 
================================================================================

Strangely, the call to self.ExecuteSimulation() results in the error only if gravFactory.unloadSpiceKernels has been called in a different sim instance. Commenting out self.gravFactory.unloadSpiceKernels() causes the script to run successfully.

Expected behavior
You should be able to call gravFactory.unloadSpiceKernels() on one sim without breaking ExecuteSimulation() on a different sim.

Desktop (please complete the following information):

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

Status

✅ Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions