1
0
Fork 0

AP: fix erroneous warning with Monostable FlipFlip

Add a unit-test written by Huntely, and extend the AP configure code, so the
'time' config of monostables doesn't trigger an incorrect warning in the
console / logs.

Thanks to Huntley Palmer for pointing this out.

SF-ID: https://sourceforge.net/p/flightgear/codetickets/2812/
This commit is contained in:
James Turner 2023-07-25 10:50:27 +01:00
parent 87029295c1
commit c54fba1095
7 changed files with 184 additions and 7 deletions

View file

@ -52,12 +52,12 @@ bool Component::configure( SGPropertyNode& prop_root,
if( !configure(*child, cname, prop_root)
&& cname != "params" ) // 'params' is usually used to specify parameters
// in PropertList files.
SG_LOG
(
SG_AUTOPILOT,
SG_INFO,
"Component::configure: unknown node: " << cname
);
// consider using the error reporting mechanism here, at level warning
SG_LOG(
SG_AUTOPILOT,
SG_DEV_WARN,
"Component::configure: unknown node: " << cname);
}
return true;

View file

@ -269,6 +269,12 @@ protected:
SGPropertyNode& prop_root );
InputValueList _time;
double _t;
bool isConfigProperty(const std::string& cfg_name) const override
{
return cfg_name == "time";
}
public:
/**
* @brief constructor for a MonoFlopImplementation
@ -457,6 +463,12 @@ bool FlipFlop::configure( SGPropertyNode& cfg_node,
return true;
}
if (_implementation && _implementation->isConfigProperty(cfg_name)) {
// componentForge CreateAndConfigureFunctor<> already called configure with all the nodes
// on our implementation, but we need to ensure we don't return false here for such nodes
return true;
}
return false;
}

View file

@ -58,6 +58,8 @@ public:
*/
bool configure( SGPropertyNode& prop_root,
SGPropertyNode& cfg );
virtual bool isConfigProperty(const std::string& cfg_name) const { return false; }
};
/**

View file

@ -5,6 +5,7 @@ set(TESTSUITE_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/testPidController.cxx
${CMAKE_CURRENT_SOURCE_DIR}/testPidControllerData.cxx
${CMAKE_CURRENT_SOURCE_DIR}/testInputValue.cxx
${CMAKE_CURRENT_SOURCE_DIR}/testMonostable.cxx
PARENT_SCOPE
)
@ -14,5 +15,6 @@ set(TESTSUITE_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/testPidController.hxx
${CMAKE_CURRENT_SOURCE_DIR}/testPidControllerData.hxx
${CMAKE_CURRENT_SOURCE_DIR}/testInputValue.hxx
${CMAKE_CURRENT_SOURCE_DIR}/testMonostable.hxx
PARENT_SCOPE
)

View file

@ -18,10 +18,12 @@
*/
#include "testDigitalFilter.hxx"
#include "testPidController.hxx"
#include "testInputValue.hxx"
#include "testMonostable.hxx"
#include "testPidController.hxx"
// Set up the unit tests.
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(MonostableTests, "Unit tests");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(DigitalFilterTests, "Unit tests");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(PidControllerTests, "Unit tests");
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(InputValueTests, "Unit tests");

View file

@ -0,0 +1,122 @@
/*
* SPDX-FileName: testMonostable.cxx
* SPDX-FileComment: Unit tests for monostable autopilot element
* SPDX-FileCopyrightText: Copyright (C) 2023 Huntley Palmer
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "testMonostable.hxx"
#include <strstream>
#include "test_suite/FGTestApi/testGlobals.hxx"
#include <Autopilot/autopilot.hxx>
#include <Autopilot/digitalfilter.hxx>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <simgear/math/sg_random.hxx>
#include <simgear/props/props_io.hxx>
// Set up function for each test.
void MonostableTests::setUp()
{
FGTestApi::setUp::initTestGlobals("ap-monostable");
}
// Clean up after each test.
void MonostableTests::tearDown()
{
FGTestApi::tearDown::shutdownTestGlobals();
}
SGPropertyNode_ptr MonostableTests::configFromString(const std::string& s)
{
SGPropertyNode_ptr config = new SGPropertyNode;
std::istringstream iss(s);
readProperties(iss, config);
return config;
}
void MonostableTests::testMonostable()
{
sg_srandom(999);
//
// Simple monostable from wiki:
// monostable stable state is false, true when Set, until timeout
// ( S == False, test/S == 0 ) : O/P = 0
// ( S == True , test/S == 1 ) : O/P = 1
// ( S == False, test/S == 0 ) : Timer running, O/P = 1
// ( S == False, test/S == 0 ) : Timed out , O/P = 0
//
//
auto config = configFromString(R"(<?xml version="1.0" encoding="UTF-8"?>
<PropertyList>
<flipflop>
<type>monostable</type>
<S>
<property>/test/S</property>
</S>
<time>
<value>0.50</value>
</time>
<output>/test/Q</output>
</flipflop>
</PropertyList>
)");
auto ap = new FGXMLAutopilot::Autopilot(globals->get_props(), config);
globals->get_subsystem_mgr()->add("ap", ap);
ap->bind();
ap->init();
// Initially test/S is 0 O/P s.b stable state == 0
fgSetBool("/test/S", false);
ap->update(0.01);
CPPUNIT_ASSERT_EQUAL(false, fgGetBool("/test/Q"));
// steady input test/S = 0 s.b. no change
ap->update(0.24);
CPPUNIT_ASSERT_EQUAL(false, fgGetBool("/test/Q"));
// steady test/S = 0 s.b. no change during timer
ap->update(0.25);
CPPUNIT_ASSERT_EQUAL(false, fgGetBool("/test/Q"));
// steady test/S = 0 s.b. no change after timeout
ap->update(0.25);
CPPUNIT_ASSERT_EQUAL(false, fgGetBool("/test/Q"));
// Set S input true == 1 O/P should immediately = 1, true
fgSetBool("/test/S", true);
ap->update(0.01);
CPPUNIT_ASSERT_EQUAL(true, fgGetBool("/test/Q"));
// steady test/S = 1 s.b. no change during timer
ap->update(0.24);
CPPUNIT_ASSERT_EQUAL(true, fgGetBool("/test/Q"));
// steady test/S = 1 s.b. no change after timeout
ap->update(0.25);
CPPUNIT_ASSERT_EQUAL(true, fgGetBool("/test/Q"));
// Reset Input test/S = 0 s.b. no change
fgSetBool("/test/S", false);
ap->update(0.01);
CPPUNIT_ASSERT_EQUAL(true, fgGetBool("/test/Q"));
// steady test/S = 0 s.b. no change during timer
ap->update(0.24);
CPPUNIT_ASSERT_EQUAL(true, fgGetBool("/test/Q"));
// steady test/S = 0 O/P resets = 0 after timeout
ap->update(0.25);
CPPUNIT_ASSERT_EQUAL(false, fgGetBool("/test/Q"));
}

View file

@ -0,0 +1,37 @@
/*
* SPDX-FileName: testMonostable.hxx
* SPDX-FileComment: Unit tests for monostable autopilot element
* SPDX-FileCopyrightText: Copyright (C) 2023 Huntley Palmer
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <simgear/props/props.hxx>
// The system tests.
class MonostableTests : public CppUnit::TestFixture
{
// Set up the test suite.
CPPUNIT_TEST_SUITE(MonostableTests);
CPPUNIT_TEST(testMonostable);
CPPUNIT_TEST_SUITE_END();
SGPropertyNode_ptr configFromString(const std::string& s);
public:
// Set up function for each test.
void setUp();
// Clean up after each test.
void tearDown();
// The tests.
void testMonostable();
};