Done
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user