ADTF  3.18.2
Source Code for Demo Time Trigger Plugin
Location
./src/examples/src/adtf/filters/standard_filters/time_triggered_filter/
Namespace for entire ADTF SDK.
Build Environment
To see how to set up the build environment have a look at ADTF CMake Environment
this implementation shows:
Header
#pragma once
#include <random>
#include <functional>
using namespace adtf::util;
using namespace ddl;
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::filter;
enum class eSimpleEnum : tUInt8
{
eEnum_value_zero = 0,
eEnum_value_one = 1,
eEnum_value_two = 2,
eEnum_value_three = 3,
eEnum_value_four = 4,
eEnum_value_five = 5,
eEnum_value_six = 6,
eEnum_value_seven = 7,
eEnum_value_eight = 8,
eEnum_value_nine = 9
};
#pragma pack(push, 1)
struct tSimpleStruct
{
uint8_t ui8Val;
uint16_t ui16Val;
uint32_t ui32Val;
int32_t i32Val;
int64_t i64Val;
double f64Val;
float f32Val;
eSimpleEnum ei8EnumVal;
};
struct tHeaderStruct
{
uint32_t ui32HeaderVal;
double f64HeaderVal;
};
struct tNestedStruct
{
tHeaderStruct sHeaderStruct;
tSimpleStruct sSimpleStruct;
};
struct tNestedArrayStruct
{
tHeaderStruct sHeaderStructArray[100];
tSimpleStruct sSimpleStructArray[2000];
};
#pragma pack(pop)
class cSimpleDataGenerator : public cFilter
{
public:
ADTF_CLASS_ID_NAME(cSimpleDataGenerator,
"demo_time_trigger.filter.adtf.cid",
"Demo Time Trigger");
public:
cSimpleDataGenerator();
tResult Init(tInitStage eStage) override;
tResult Process(tNanoSeconds tmTimeOfTrigger,
IRunner* pRunner) override;
void GenerateSimpleData(tNanoSeconds tmTimeOfTrigger, double fOutValue);
void GenerateSimpleArrayData(tNanoSeconds tmTimeOfTrigger, double fOutValue);
void GenerateNestedData(tNanoSeconds tmTimeOfTrigger, double fOutValue);
void GenerateNestedArrayData(tNanoSeconds tmTimeOfTrigger, double fOutValue);
private:
// writer to an output pin for simple plain types
ISampleWriter* m_pWriterSimple = nullptr;
// writer to an output pin for simple plain array type
ISampleWriter* m_pWriterSimpleArray = nullptr;
// writer to an output pin structured types
ISampleWriter* m_pWriterNested = nullptr;
// writer to an output pin for structured array types
ISampleWriter* m_pWriterNestedArray = nullptr;
// a counter
uint64_t m_nCounter = 0;
// to generate random numbers
std::mt19937 m_oRandomGenerator;
std::uniform_real_distribution<double> m_oDistribution;
// the selected generator method
std::function<double()> m_fnGenerator;
enum tGeneratorType : uint32_t
{
eCounter = 0,
eRandom = 1
};
// this will reflect any property changes.
property_variable<tGeneratorType> m_eGeneratorType = eCounter;
};
uint8_t tUInt8
type definition for unsigned integer values (8bit) (platform and compiler independent type).
#define ADTF_CLASS_ID_NAME(_class, _strcid, _strclabel)
Common macro to enable correct treatment of class identifier AND Class Name by IClassInfo.
Definition: class_id.h:33
Copyright © Audi Electronics Venture GmbH.
Namespace for the ADTF Base SDK.
Namespace for the ADTF Filter SDK.
Namespace for the ADTF Media Description SDK.
Namespace for the ADTF Streaming SDK.
Namespace for the ADTF uCOM3 SDK.
alias namespace for the A_UTILS Library.
Implementation
#include "demo_timer_trigger_function.h"
#include <easy/profiler.h>
// this creates the plugin entry methods and class factories
ADTF_PLUGIN("Demo Time Trigger Plugin", cSimpleDataGenerator);
cSimpleDataGenerator::cSimpleDataGenerator():
m_oDistribution(0.0, 100.0)
{
// create the pin for plain types
m_pWriterSimple = CreateOutputPin("out", stream_type_plain<float>());
SetDescription("out", "Provides the generated data based on number_gen_type");
// create the pin for plain array types
m_pWriterSimpleArray = CreateOutputPin("out_array", stream_type_plain<std::array<int64_t, 10>>());
SetDescription("out_array", "Provides the generated data array based on number_gen_type");
auto oSimpleEnumDefinition = enumeration<eSimpleEnum>("eSimpleEnum")
.Add("eEnum_value_zero", eSimpleEnum::eEnum_value_zero)
.Add("eEnum_value_one", eSimpleEnum::eEnum_value_one)
.Add("eEnum_value_two", eSimpleEnum::eEnum_value_two)
.Add("eEnum_value_three", eSimpleEnum::eEnum_value_three)
.Add("eEnum_value_four", eSimpleEnum::eEnum_value_four)
.Add("eEnum_value_five", eSimpleEnum::eEnum_value_five)
.Add("eEnum_value_six", eSimpleEnum::eEnum_value_six)
.Add("eEnum_value_seven", eSimpleEnum::eEnum_value_seven)
.Add("eEnum_value_eight", eSimpleEnum::eEnum_value_eight)
.Add("eEnum_value_nine", eSimpleEnum::eEnum_value_nine);
// define our data type from an existing struct definition
auto oSimpleStructDefinition = structure<tSimpleStruct>("tSimpleStruct")
.Add("ui8Val", &tSimpleStruct::ui8Val)
.Add("ui16Val", &tSimpleStruct::ui16Val)
.Add("ui32Val", &tSimpleStruct::ui32Val)
.Add("i32Val", &tSimpleStruct::i32Val)
.Add("i64Val", &tSimpleStruct::i64Val)
.Add("f64Val", &tSimpleStruct::f64Val)
.Add("f32Val", &tSimpleStruct::f32Val)
.Add("ei8EnumVal", &tSimpleStruct::ei8EnumVal, oSimpleEnumDefinition);
auto oHeaderStructDefinition = structure<tHeaderStruct>("tHeaderStruct")
.Add("ui32HeaderVal", &tHeaderStruct::ui32HeaderVal)
.Add("f64HeaderVal", &tHeaderStruct::f64HeaderVal);
auto oNestedDefinition = structure<tNestedStruct>("tNestedStruct")
.Add("sHeaderStruct", &tNestedStruct::sHeaderStruct, oHeaderStructDefinition)
.Add("sSimpleStruct", &tNestedStruct::sSimpleStruct, oSimpleStructDefinition);
// we create an output pin with a writer that handles creating samples for tNestedStruct transparently.
m_pWriterNested = CreateOutputPin("nested_struct", oNestedDefinition);
SetDescription("nested_struct", "Provides the generated data based on number_gen_type");
auto oNestedArrayDefinition = structure<tNestedArrayStruct>("tNestedArrayStruct")
.Add("sHeaderStructArray", &tNestedArrayStruct::sHeaderStructArray, oHeaderStructDefinition)
.Add("sSimpleStructArray", &tNestedArrayStruct::sSimpleStructArray, oSimpleStructDefinition);
// we create an other output pin with a writer that handles creating samples for tNestedStruct in a huge array.
m_pWriterNestedArray = CreateOutputPin("nested_struct_array", oNestedArrayDefinition);
SetDescription("nested_struct_array", "Provides the generated data based on number_gen_type in a structure with arrays");
// create a trigger function that can be connected to an active runner.
CreateRunner("data_generator_function", cTimerTriggerHint(std::chrono::seconds{1}));
SetDescription("data_generator_function", "Runner to periodically trigger the function which generates the output data for all pins");
// setup and register our property variable which will reflect any property change.
// for compatibility with previous implementations we use the "data_generator_function" prefix.
m_eGeneratorType.SetValueList({{eCounter, "Counter"},
{eRandom, "Random"}});
m_eGeneratorType.SetDescription("Chooses the generator used for calculating output data.");
RegisterPropertyVariable("data_generator_function/number_gen_type", m_eGeneratorType);
// sets a short description for the component
SetDescription("Use this filter to generate data whenever a defined Timer Runner triggers.");
// set help link to jump to documentation from ADTF Configuration Editor
SetHelpLink("$(ADTF_DIR)/doc/adtf_html/page_demo_time_triggered_filter.html");
}
// in this method all property related and/or long running initialization can be done.
tResult cSimpleDataGenerator::Init(tInitStage eStage)
{
RETURN_IF_FAILED(cFilter::Init(eStage));
if (eStage == StageNormal)
{
switch (m_eGeneratorType)
{
case eCounter:
{
m_fnGenerator = [&]
{
return static_cast<double>(++m_nCounter);
};
LOG_INFO("Current generation type is Counter");
break;
}
case eRandom:
{
m_fnGenerator = [&]
{
return m_oDistribution(m_oRandomGenerator);
};
LOG_INFO("Current generation type is Random");
break;
}
default:
{
RETURN_ERROR_DESC(ERR_INVALID_ARG, "Invalid property value '%d' for 'number_gen_type', use Counter", *m_eGeneratorType);
}
}
}
}
//this function will be executed each time a trigger occured
tResult cSimpleDataGenerator::Process(tNanoSeconds tmTimeOfTrigger,
IRunner* /*pRunner*/)
{
double fOutValue = m_fnGenerator();
GenerateSimpleData(tmTimeOfTrigger, fOutValue);
GenerateSimpleArrayData(tmTimeOfTrigger, fOutValue);
GenerateNestedData(tmTimeOfTrigger, fOutValue);
GenerateNestedArrayData(tmTimeOfTrigger, fOutValue);
}
void cSimpleDataGenerator::GenerateSimpleData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<float> oOutputData(tmTimeOfTrigger);
oOutputData = static_cast<float>(fOutValue);
m_pWriterSimple->Write(oOutputData.Release());
}
void cSimpleDataGenerator::GenerateSimpleArrayData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<std::array<int64_t, 10>> oOutputData(tmTimeOfTrigger);
for (auto& oCurrentArrayValue : *oOutputData)
{
oCurrentArrayValue = static_cast<int64_t>(fOutValue);
}
m_pWriterSimpleArray->Write(oOutputData.Release());
}
void cSimpleDataGenerator::GenerateNestedData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<tNestedStruct> oOutputData(tmTimeOfTrigger);
uint8_t ui8Val = static_cast<uint8_t>(fOutValue);
oOutputData->sHeaderStruct.ui32HeaderVal = static_cast<uint32_t>(fOutValue);
oOutputData->sHeaderStruct.f64HeaderVal = fOutValue;
oOutputData->sSimpleStruct.ui8Val = ui8Val;
oOutputData->sSimpleStruct.ui16Val = static_cast<uint16_t>(fOutValue);
oOutputData->sSimpleStruct.ui32Val = static_cast<uint32_t>(fOutValue);
oOutputData->sSimpleStruct.i32Val = static_cast<int32_t>(fOutValue);
oOutputData->sSimpleStruct.i64Val = static_cast<int64_t>(fOutValue);
oOutputData->sSimpleStruct.f64Val = fOutValue;
oOutputData->sSimpleStruct.f32Val = static_cast<float>(fOutValue);
oOutputData->sSimpleStruct.ei8EnumVal = static_cast<eSimpleEnum>(ui8Val % 10);
m_pWriterNested->Write(oOutputData.Release());
}
void cSimpleDataGenerator::GenerateNestedArrayData(tNanoSeconds tmTimeOfTrigger, double fOutValue)
{
// we want to be able to profile this specific function
EASY_FUNCTION();
output_sample_data<tNestedArrayStruct> oOutputData(tmTimeOfTrigger);
for (size_t nCurrentPos = 0; nCurrentPos < 100; ++nCurrentPos)
{
oOutputData->sHeaderStructArray[nCurrentPos].ui32HeaderVal = static_cast<uint32_t>(fOutValue);
oOutputData->sHeaderStructArray[nCurrentPos].f64HeaderVal = fOutValue;
}
for (size_t nCurrentPos = 0; nCurrentPos < 2000; ++nCurrentPos)
{
uint8_t ui8Val = static_cast<uint8_t>(fOutValue);
oOutputData->sSimpleStructArray[nCurrentPos].ui8Val = ui8Val;
oOutputData->sSimpleStructArray[nCurrentPos].ui16Val = static_cast<uint16_t>(fOutValue);
oOutputData->sSimpleStructArray[nCurrentPos].ui32Val = static_cast<uint32_t>(fOutValue);
oOutputData->sSimpleStructArray[nCurrentPos].i32Val = static_cast<int32_t>(fOutValue);
oOutputData->sSimpleStructArray[nCurrentPos].i64Val = static_cast<int64_t>(fOutValue);
oOutputData->sSimpleStructArray[nCurrentPos].f64Val = fOutValue;
oOutputData->sSimpleStructArray[nCurrentPos].f32Val = static_cast<float>(fOutValue);
oOutputData->sSimpleStructArray[nCurrentPos].ei8EnumVal = static_cast<eSimpleEnum>(ui8Val % 10);
}
m_pWriterNestedArray->Write(oOutputData.Release());
}
#define ADTF_PLUGIN(__plugin_identifier,...)
The ADTF Plugin Macro will add the code of a adtf::ucom::ant::IPlugin implementation.
Definition: adtf_plugin.h:22
#define RETURN_ERROR_DESC(_code,...)
Same as RETURN_ERROR(_error) using a printf like parameter list for detailed error description.
#define RETURN_IF_FAILED(s)
Return if expression is failed, which requires the calling function's return type to be tResult.
#define RETURN_NOERROR
Return status ERR_NOERROR, which requires the calling function's return type to be tResult.