From e28dcd80a152a2d70d5d661bac74258a7f78f920 Mon Sep 17 00:00:00 2001 From: Hanspeter Schaub Date: Thu, 29 Dec 2022 15:40:59 -0700 Subject: [PATCH 1/7] document message `read()` method Add documentation on how to read the current message values from python. --- docs/source/Learn/bskPrinciples/bskPrinciples-4.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/source/Learn/bskPrinciples/bskPrinciples-4.rst b/docs/source/Learn/bskPrinciples/bskPrinciples-4.rst index b04a7e5286..b9ccc66088 100644 --- a/docs/source/Learn/bskPrinciples/bskPrinciples-4.rst +++ b/docs/source/Learn/bskPrinciples/bskPrinciples-4.rst @@ -64,9 +64,15 @@ After the simulation completes, the recorded data is stored inside the ``msgRec` Clearing the Message Recorder Data Log -------------------------------------- -Note that the messager recorder will continuously add message data to its internal data vectors. If you start and stop the simulation, pull the data, resume the simulation and so on, this message data recording process is cumulative. If you stop the simulation and want to clear the message recorder data log so that only new data is recorded, you can clear the message recorder module data buffer using the ``.clear()`` method. For example, assume a message recorder ``scRec`` has been setup and needs to be cleared, this is done with:: +Note that the message recorder will continuously add message data to its internal data vectors. If you start and stop the simulation, pull the data, resume the simulation and so on, this message data recording process is cumulative. If you stop the simulation and want to clear the message recorder data log so that only new data is recorded, you can clear the message recorder module data buffer using the ``.clear()`` method. For example, assume a message recorder ``scRec`` has been setup and needs to be cleared, this is done with:: scRec.clear() +Reading the Current Value of a Message +-------------------------------------- +If you have a message `msg` and want to pull a current copy of the message data or payload, you can use +this method on both C and C++ wrapped message objects:: + + msgCopy = msg.read() From 3a796c4701801b6ae796dbe3ea71a33ac1b46732 Mon Sep 17 00:00:00 2001 From: Hanspeter Schaub Date: Thu, 29 Dec 2022 15:43:06 -0700 Subject: [PATCH 2/7] highlight Recording a Redirected C-wrapped Message Highlight in the documentation that recording a C-wrapped message will record the message payload, not where the `payloadPointer` goes. Thus, if an message is redirected to write to second message, the recorder needs to be setup on the 2nd message, not the original message. --- docs/source/Learn/bskPrinciples/bskPrinciples-7.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/source/Learn/bskPrinciples/bskPrinciples-7.rst b/docs/source/Learn/bskPrinciples/bskPrinciples-7.rst index 7d27fd7660..f5d88428c2 100644 --- a/docs/source/Learn/bskPrinciples/bskPrinciples-7.rst +++ b/docs/source/Learn/bskPrinciples/bskPrinciples-7.rst @@ -52,7 +52,12 @@ To redirect the output of a C++ module ``someCppModule`` to this stand-alone mes someCppModule.dataOutMsg = cppStandAloneMsg -If you want to record the output of ``someCModule`` be sure to record ``cStandAloneMsg`` instead of ``someCModule.dataOutMsg``. The later is no longer being written to. In C++ we are setting ``cppStandAloneMsg`` equal to ``someCppModule.dataOutMsg``. Here recording either will give the same result. +.. note:: + + If you want to record the output of ``someCModule`` be sure to record ``cStandAloneMsg`` + instead of ``someCModule.dataOutMsg``. The later is no longer being written to. In C++ + we are setting ``cppStandAloneMsg`` equal to ``someCppModule.dataOutMsg``. Here recording either + will give the same result. To see the message states of both the module internal message objects and the stand-alone messages, the sample script shows how to use ``.read()`` to read the current state of the message object. This will return a copy of the message payload structure. The same method can be used to access both C and C++ wrapped messages. After executing the script you should see the following terminal output: From aff337af5b6a299da7cf0284d1b47cd3c4b4b2d2 Mon Sep 17 00:00:00 2001 From: Hanspeter Schaub Date: Thu, 29 Dec 2022 15:51:02 -0700 Subject: [PATCH 3/7] added release notes --- docs/source/Support/bskReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/Support/bskReleaseNotes.rst b/docs/source/Support/bskReleaseNotes.rst index 99951a3e6d..cc3a5dce64 100644 --- a/docs/source/Support/bskReleaseNotes.rst +++ b/docs/source/Support/bskReleaseNotes.rst @@ -35,6 +35,8 @@ Version |release| - Refactored :ref:`keplerianOrbit` to not depend on the ``gravityEffector`` class - Updated Basilisk install documentation to discuss accessing source code from GitHub.com - Fixed an issue where attaching a thruster to a body different than the hub when using ``zeroBase`` would yield very large offsets. +- Added documentation in :ref:`bskPrinciples-4` on how to read the current message values +- Highlighted the challege of setting up a ``recorder`` on a re-directed message in :ref:`bskPrinciples-7` Version 2.1.5 (Dec. 13, 2022) From bea43aacc910da7f3aea0ca026a1048555fa98d4 Mon Sep 17 00:00:00 2001 From: Hanspeter Schaub Date: Mon, 2 Jan 2023 08:48:11 -0700 Subject: [PATCH 4/7] Implement recording of C-wrapped input message --- src/architecture/messaging/msgAutoSource/msg_C.cpp.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/architecture/messaging/msgAutoSource/msg_C.cpp.in b/src/architecture/messaging/msgAutoSource/msg_C.cpp.in index 5d0108043f..2aef627ac1 100644 --- a/src/architecture/messaging/msgAutoSource/msg_C.cpp.in +++ b/src/architecture/messaging/msgAutoSource/msg_C.cpp.in @@ -54,6 +54,10 @@ void {type}_C_write({type}Payload *data, {type}_C *destination, int64_t moduleID if (!source->header.isLinked) {{ BSK_PRINT(MSG_ERROR,"In C input msg, you are trying to read an un-connected message of type {type}."); }} + //! ensure the current message container has a copy of a subscribed message. + //! Does nothing if the message is writing to itself + source->payload = *source->payloadPointer; + return *source->payloadPointer; }}; From ad858728f378ac9a53fb57b53d085caa6539c56f Mon Sep 17 00:00:00 2001 From: Hanspeter Schaub Date: Fri, 6 Jan 2023 10:53:04 -0700 Subject: [PATCH 5/7] create unit test for recording C-wrapped input message --- .../_UnitTest/test_RecordInputMessages.py | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/architecture/messaging/_UnitTest/test_RecordInputMessages.py diff --git a/src/architecture/messaging/_UnitTest/test_RecordInputMessages.py b/src/architecture/messaging/_UnitTest/test_RecordInputMessages.py new file mode 100644 index 0000000000..aa1544436a --- /dev/null +++ b/src/architecture/messaging/_UnitTest/test_RecordInputMessages.py @@ -0,0 +1,88 @@ +# +# Copyright (c) 2023, Autonomous Vehicle Systems Lab, University of Colorado at Boulder +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +# +# Purpose: Test if a C-wrapped input message can be logged with a recorder module +# Author: Hanspeter Schaub +# Creation Date: Jan. 3, 2023 +# + + +from Basilisk.utilities import SimulationBaseClass +from Basilisk.utilities import macros +from Basilisk.moduleTemplates import cModuleTemplate +from Basilisk.architecture import messaging +from Basilisk.utilities import unitTestSupport as uts +from Basilisk.architecture import bskLogging + + +def test_RecordingInputMessages(): + """ + testing recording a C-wrapped input message with the recorder module + """ + + bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING) + testFailCount = 0 # zero unit test result counter + testMessages = [] # create empty array to store test log messages + + # Create a sim module as an empty container + scSim = SimulationBaseClass.SimBaseClass() + + # create the simulation process + dynProcess = scSim.CreateNewProcess("dynamicsProcess") + + # create the dynamics task and specify the integration update time + dynProcess.addTask(scSim.CreateNewTask("dynamicsTask", macros.sec2nano(1.))) + + # create modules + mod1 = cModuleTemplate.cModuleTemplateConfig() + mod1Wrap = scSim.setModelDataWrap(mod1) + mod1Wrap.ModelTag = "cModule1" + scSim.AddModelToTask("dynamicsTask", mod1Wrap, mod1) + + # Write input data + inputData = messaging.CModuleTemplateMsgPayload() + inputData.dataVector = [1, 2, 3] + inputDataMsg = messaging.CModuleTemplateMsg().write(inputData) + + # Subscribe input message to stand alone message + mod1.dataInMsg.subscribeTo(inputDataMsg) + + # Create recorders tied to IO messages + dataInRec = mod1.dataInMsg.recorder() + scSim.AddModelToTask("dynamicsTask", dataInRec) + + # initialize Simulation: + scSim.InitializeSimulation() + + # configure a simulation stop time and execute the simulation run + scSim.ConfigureStopTime(macros.sec2nano(1.0)) + scSim.ExecuteSimulation() + + testFailCount, testMessages = uts.compareArray([inputData.dataVector]*2 + , dataInRec.dataVector + , 0.01 + , "recorded input message was not correct." + , testFailCount + , testMessages) + + # each test method requires a single assert method to be called + # this check below just makes sure no sub-test failures were found + assert testFailCount < 1, testMessages + + +if __name__ == "__main__": + test_RecordingInputMessages() From d9123dfe6a1beec7c24596b086fb05e0be93adbd Mon Sep 17 00:00:00 2001 From: Hanspeter Schaub Date: Mon, 2 Jan 2023 08:49:00 -0700 Subject: [PATCH 6/7] fixed minor typos, no functional change --- src/utilities/unitTestSupport.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utilities/unitTestSupport.py b/src/utilities/unitTestSupport.py index 41f22700ab..3403a47b53 100755 --- a/src/utilities/unitTestSupport.py +++ b/src/utilities/unitTestSupport.py @@ -101,7 +101,7 @@ def isArrayEqual(result, truth, dim, accuracy): def isArrayEqualRelative(result, truth, dim, accuracy): - """Compare relative accuracy of two arracy""" + """Compare relative accuracy of two arrays""" # the result array is of dimension dim, no time stamp # the truth array is of dimesion dim, no time stamp if dim < 1: @@ -164,10 +164,10 @@ def compareVector(trueStates, dataStates, accuracy, msg, testFailCount, testMess def compareArray(trueStates, dataStates, accuracy, msg, testFailCount, testMessages): """Compare two arrays size and values and check absolute accuracy""" - if (len(trueStates) != len(dataStates)): + if len(trueStates) != len(dataStates): testFailCount += 1 testMessages.append("FAILED: " + msg + r" unequal data array sizes\n") - elif (len(trueStates) == 0 or len(dataStates) == 0): + elif len(trueStates) == 0 or len(dataStates) == 0: testFailCount += 1 testMessages.append("FAILED: " + msg + r" data had empty arrays\n") else: From 534bcf2ef0bfe382900f47308f64d319dab7547a Mon Sep 17 00:00:00 2001 From: Hanspeter Schaub Date: Mon, 2 Jan 2023 08:53:18 -0700 Subject: [PATCH 7/7] updated release notes --- docs/source/Support/bskReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/Support/bskReleaseNotes.rst b/docs/source/Support/bskReleaseNotes.rst index cc3a5dce64..2fe08917e8 100644 --- a/docs/source/Support/bskReleaseNotes.rst +++ b/docs/source/Support/bskReleaseNotes.rst @@ -37,6 +37,7 @@ Version |release| - Fixed an issue where attaching a thruster to a body different than the hub when using ``zeroBase`` would yield very large offsets. - Added documentation in :ref:`bskPrinciples-4` on how to read the current message values - Highlighted the challege of setting up a ``recorder`` on a re-directed message in :ref:`bskPrinciples-7` +- added the ability to add a ``recorder()`` to a C-wrapped module input message Version 2.1.5 (Dec. 13, 2022)