This commit is contained in:
2026-02-24 13:19:03 +01:00
parent 5fb3c3bf90
commit 1cadd242e7
16 changed files with 274 additions and 43 deletions

View File

@@ -19,6 +19,7 @@
#include <opendaq/function_block_impl.h>
#include <opendaq/opendaq.h>
#include <opendaq/stream_reader_ptr.h>
#include <iir/Butterworth.h>
BEGIN_NAMESPACE_EXAMPLE_MODULE
@@ -50,8 +51,7 @@ private:
std::vector<uint64_t> inputDomainData;
bool configValid = false;
Float scale;
Float offset;
Float cutoffFrequency;
Float outputHighValue;
Float outputLowValue;
Bool useCustomOutputRange;
@@ -62,7 +62,7 @@ private:
void createSignals();
void calculate();
void processData(SizeT readAmount, SizeT packetOffset) const;
void processData(SizeT readAmount, SizeT packetOffset);
void processEventPacket(const EventPacketPtr& packet);
void processSignalDescriptorChanged(const DataDescriptorPtr& dataDescriptor,
@@ -72,6 +72,8 @@ private:
void initProperties();
void propertyChanged(bool configure);
void readProperties();
Iir::Butterworth::LowPass<4> filter;
};
END_NAMESPACE_EXAMPLE_MODULE

View File

@@ -33,8 +33,8 @@ if (MSVC)
target_compile_options(${LIB_NAME} PRIVATE /bigobj)
endif()
target_link_libraries(${LIB_NAME} PUBLIC daq::opendaq
)
find_package(iir)
target_link_libraries(${LIB_NAME} PUBLIC daq::opendaq iir::iir_static)
target_include_directories(${LIB_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>

View File

@@ -4,7 +4,7 @@
BEGIN_NAMESPACE_EXAMPLE_MODULE
ExampleFBImpl::ExampleFBImpl(const ContextPtr& ctx, const ComponentPtr& parent, const StringPtr& localId)
: FunctionBlock(CreateType(), ctx, parent, localId)
: FunctionBlock(CreateType(), ctx, parent, localId)
{
initComponentStatus();
createInputPorts();
@@ -14,14 +14,9 @@ BEGIN_NAMESPACE_EXAMPLE_MODULE
void ExampleFBImpl::initProperties()
{
const auto scaleProp = FloatProperty("Scale", 1.0);
const auto scaleProp = FloatProperty("CutoffFrequency", 1.0);
objPtr.addProperty(scaleProp);
objPtr.getOnPropertyValueWrite("Scale") +=
[this](PropertyObjectPtr& obj, PropertyValueEventArgsPtr& args) { propertyChanged(true); };
const auto offsetProp = FloatProperty("Offset", 0.0);
objPtr.addProperty(offsetProp);
objPtr.getOnPropertyValueWrite("Offset") +=
objPtr.getOnPropertyValueWrite("CutoffFrequency") +=
[this](PropertyObjectPtr& obj, PropertyValueEventArgsPtr& args) { propertyChanged(true); };
const auto useCustomOutputRangeProp = BoolProperty("UseCustomOutputRange", False);
@@ -61,8 +56,7 @@ void ExampleFBImpl::propertyChanged(bool configure)
void ExampleFBImpl::readProperties()
{
scale = objPtr.getPropertyValue("Scale");
offset = objPtr.getPropertyValue("Offset");
cutoffFrequency = objPtr.getPropertyValue("CutoffFrequency");
useCustomOutputRange = objPtr.getPropertyValue("UseCustomOutputRange");
outputHighValue = objPtr.getPropertyValue("OutputHighValue");
outputLowValue = objPtr.getPropertyValue("OutputLowValue");
@@ -72,7 +66,7 @@ void ExampleFBImpl::readProperties()
FunctionBlockTypePtr ExampleFBImpl::CreateType()
{
return FunctionBlockType("ExampleScalingModule", "Scaling", "Signal scaling");
return FunctionBlockType("ExampleIIRFilter", "Scaling", "Signal scaling");
}
void ExampleFBImpl::processSignalDescriptorChanged(const DataDescriptorPtr& dataDescriptor,
@@ -145,15 +139,15 @@ void ExampleFBImpl::configure()
}
else
{
auto outputHigh = scale * static_cast<Float>(inputDataDescriptor.getValueRange().getLowValue()) + offset;
auto outputLow = scale * static_cast<Float>(inputDataDescriptor.getValueRange().getHighValue()) + offset;
auto outputHigh = static_cast<Float>(inputDataDescriptor.getValueRange().getLowValue());
auto outputLow = static_cast<Float>(inputDataDescriptor.getValueRange().getHighValue());
if (outputLow > outputHigh)
std::swap(outputLow, outputHigh);
outputRange = Range(outputLow, outputHigh);
}
auto name = outputName.empty() ? inputPort.getSignal().getName().toStdString() + "/Scaled" : outputName;
auto name = outputName.empty() ? inputPort.getSignal().getName().toStdString() + "/Filtered" : outputName;
auto unit = outputUnit.empty() ? inputDataDescriptor.getUnit() : Unit(outputUnit);
outputDataDescriptor = DataDescriptorBuilder()
@@ -172,6 +166,9 @@ void ExampleFBImpl::configure()
inputData.resize(sampleRate);
inputDomainData.resize(sampleRate);
filter.setup(sampleRate, cutoffFrequency);
setComponentStatus(ComponentStatus::Ok);
}
catch (const std::exception& e)
@@ -208,17 +205,20 @@ void ExampleFBImpl::calculate()
}
}
void ExampleFBImpl::processData(SizeT readAmount, SizeT packetOffset) const
void ExampleFBImpl::processData(SizeT readAmount, SizeT packetOffset)
{
if (readAmount == 0)
return;
const auto outputDomainPacket = DataPacket(outputDomainDataDescriptor, readAmount, packetOffset);
const auto outputPacket = DataPacketWithDomain(outputDomainPacket, outputDataDescriptor, readAmount);
auto outputData = static_cast<Float*>(outputPacket.getRawData());
const DataPacketPtr outputDomainPacket = DataPacket(outputDomainDataDescriptor, readAmount, packetOffset);
const DataPacketPtr outputPacket = DataPacketWithDomain(outputDomainPacket, outputDataDescriptor, readAmount);
Float* outputData = static_cast<Float*>(outputPacket.getRawData());
for (size_t i = 0; i < readAmount; i++)
*outputData++ = scale * static_cast<Float>(inputData[i]) + offset;
{
// *outputData++ = static_cast<Float>(inputData[i]);
*outputData++ = filter.filter(inputData[i]);
}
outputSignal.sendPacket(outputPacket);
outputDomainSignal.sendPacket(outputDomainPacket);
@@ -243,8 +243,8 @@ void ExampleFBImpl::createInputPorts()
void ExampleFBImpl::createSignals()
{
outputSignal = createAndAddSignal("Scaled");
outputDomainSignal = createAndAddSignal("ScaledTime", nullptr, false);
outputSignal = createAndAddSignal("Filtered");
outputDomainSignal = createAndAddSignal("FilteredTime", nullptr, false);
outputSignal.setDomainSignal(outputDomainSignal);
}

View File

@@ -10,20 +10,20 @@ using ExampleModuleTest = testing::Test;
TEST_F(ExampleModuleTest, TestAdd)
{
const auto instance = Instance();
ASSERT_TRUE(instance.addFunctionBlock("ExampleScalingModule").assigned());
ASSERT_TRUE(instance.addFunctionBlock("ExampleIIRFilter").assigned());
}
TEST_F(ExampleModuleTest, TestPropCount)
{
const auto instance = Instance();
auto fb = instance.addFunctionBlock("ExampleScalingModule");
ASSERT_EQ(fb.getAllProperties().getCount(), 7);
auto fb = instance.addFunctionBlock("ExampleIIRFilter");
ASSERT_EQ(fb.getAllProperties().getCount(), 6);
}
TEST_F(ExampleModuleTest, TestDataScaling)
{
const auto instance = Instance();
auto fb = instance.addFunctionBlock("ExampleScalingModule");
auto fb = instance.addFunctionBlock("ExampleIIRFilter");
fb.setPropertyValue("Scale", 2);
auto dataDescriptor = DataDescriptorBuilder().setSampleType(SampleType::Float32).setValueRange(Range(-10, 10)).build();