This guide covers creating a simple ADTF Filter that generates data samples and forwards them to a data sink. After reading this guide, you will know how to:
In the Data Filter Processor Tutorial we created a Filter that:
Now we need to create a Filter that:
First, create a new Filter project for the data generator Filter using CMake.
cmake_minimum_required(VERSION 3.18 FATAL_ERROR)
project (DataGenerator)
set (DATA_GENERATOR_FILTER tutorial_filter_data_generator)
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tutorial_filter_data_generator.h)
file(WRITE tutorial_filter_data_generator.h)
endif()
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tutorial_filter_data_generator.cpp)
file(WRITE tutorial_filter_data_generator.cpp)
endif()
find_package(ADTF COMPONENTS filtersdk)
# Adds the data_generator_filter project to the Visual Studio solution, which when build
# creates a shared object called data_generator_filter.adtfplugin
adtf_add_filter(${DATA_GENERATOR_FILTER} tutorial_filter_data_generator.h tutorial_filter_data_generator.cpp)
# Adds the INSTALL project to the Visual Studio solution, which when build
# copies our Filter to the subdirectory given as the second argument into ${CMAKE_INSTALL_PREFIX}
adtf_install_filter(${DATA_GENERATOR_FILTER} src/examples/bin)
# Generate a plugindescription for our Filter
adtf_create_plugindescription(
TARGET ${DATA_GENERATOR_FILTER}
PLUGIN_SUBDIR "src/examples/bin"
VERSION "0.8.15"
LICENSE "ADTF"
SUPPORT_MAIL "support@mycompany.org"
HOMEPAGE_URL "www.mycompany.org"
)
# Generate a documentation for our Filter
adtf_convert_plugindescription_to_dox(
TARGET ${DATA_GENERATOR_FILTER}
DIRECTORY ${CMAKE_BINARY_DIR}/src/doxygen/generated
)
Now use the CMake-GUI to fill in all the information required by CMake to create the Visual Studio solution.
If you need help have a look at the CMake-GUI.
Then open thedata_generator_filter
project in the solution explorer.
Open the tutorial_filter_data_generator header and source files in Visual Studio.
Just like before we continue by creating our tutorial_filter_data_generator.h header file.
/**
*
* ADTF Tutorial filter for data processing
*
*/
#pragma once
// Include all necessary headers from the ADTF SDK
#include <adtffiltersdk/adtf_filtersdk.h>
// For simplicity use the necessary namespaces
using namespace adtf::util;
using namespace adtf::ucom;
using namespace adtf::base;
using namespace adtf::streaming;
using namespace adtf::mediadescription;
using namespace adtf::filter;
// Now we declare a new class cTutorialFilterDataGenerator that
// inherits from cFilter. This will be our Tutorial Filter.
class cTutorialFilterDataGenerator: public cFilter
{
public:
// Inside the class declaration we use an ADTF macro to enable correct treatment
// of class identifier and class name by IClassInfo and the class factories.
ADTF_CLASS_ID_NAME(cTutorialFilterDataGenerator,
"tutorial_data_generator.filter.adtf_guides.cid",
"Tutorial Data Generator");
public:
// We implement the constructor where we create our Pins and Runners.
cTutorialFilterDataGenerator();
// We override the Process method in order to handle triggers from the
// connected Active Runner.
tResult Process(tNanoSeconds tmTrigger, IRunner* pRunner) override;
private:
// Some helper methods.
float CalculateVelocityValue();
float CalculateYawRateValue();
// Our writers for our output data.
ISampleWriter* m_pVelocityWriter;
ISampleWriter* m_pYawRateWriter;
// Defines property variables, this properties will occur within your property set
// You still need to register with name in the constructor.
// Defines the change rates for the velocity/yaw rate values.
property_variable<float> m_fVelocityChangeRate = 5.0;
property_variable<float> m_fYawRateChangeRate = 1.0;
// Defines the max values for velocity and yaw rate.
property_variable<float> m_fVelocityMax = 100.0;
property_variable<float> m_fYawRateMax = 10.0;
// Store the current values.
float m_fCurrentVelocity = 50.0;
float m_fCurrentYawRate = 10.0;
};
Now we need to write the tutorial_filter_data_generator.cpp source file.
/**
*
* ADTF Tutorial Filter for data processing
*
*/
#include "tutorial_filter_data_generator.h"
#include <cmath>
// The code behind the macro creates a plugin and the main entries to the plugin DLL or shared object.
// The cTutorialFilterDataGenerator will be available through the plugins class factory.
ADTF_PLUGIN("ADTF Tutorial Filter Data Generator Plugin", cTutorialFilterDataGenerator);
cTutorialFilterDataGenerator::cTutorialFilterDataGenerator()
{
// Create our output pins with a simple plain stream type.
m_pVelocityWriter = CreateOutputPin("velocity", stream_type_plain<float>());
SetDescription("velocity", "Provides the generated velocity data samples");
m_pYawRateWriter = CreateOutputPin("yawrate", stream_type_plain<float>());
SetDescription("yawrate", "Provides the generated yawrate data samples");
// Now create our Runner and give the ADTF Configuration Editor a hint on which
// Active Runner to connect to it. In this case a Timer Runner.
CreateRunner("generate_data", cTimerTriggerHint(std::chrono::seconds(1)));
SetDescription("generate_data", "Runner to periodically trigger the function which executes the calculation");
// And register your Property Variables to make them accessible via the
// configuration.
m_fVelocityChangeRate.SetDescription("Value for velocity.");
RegisterPropertyVariable("velocity_change_rate", m_fVelocityChangeRate);
m_fYawRateChangeRate.SetDescription("Value for yawrate.");
RegisterPropertyVariable("yaw_rate_change_rate", m_fYawRateChangeRate);
m_fVelocityMax.SetDescription("Maximum for velocity.");
RegisterPropertyVariable("velocity_max_value", m_fVelocityMax);
m_fYawRateMax.SetDescription("Maximum for yawrate.");
RegisterPropertyVariable("yaw_rate_max_value", m_fYawRateMax);
// set basic information about the component itself and purpose
SetDescription("This filter shows how to generate data specified by property calibration values.");
}
// This function will be executed each time a trigger for the "generate_data" Runner occurs
tResult cTutorialFilterDataGenerator::Process(tNanoSeconds tmTrigger, IRunner* /*pRunner*/)
{
// To create output data use the output_sample_data template
// This will handle sample allocation for you and you can use it just
// like its template parameter type.
output_sample_data<float> fVelocity(tmTrigger, CalculateVelocityValue());
// Write it to the connected sample stream.
// Do not call any methods of output_sample_data after you have called Release() which
// hands over the sample instance.
m_pVelocityWriter->Write(fVelocity.Release());
// we do the same for the yaw rate
output_sample_data<float> fYawRate(tmTrigger, CalculateYawRateValue());
m_pYawRateWriter->Write(fYawRate.Release());
RETURN_NOERROR;
}
float cTutorialFilterDataGenerator::CalculateVelocityValue()
{
// negate the velocity change rate if the max/min values are reached
if ((m_fCurrentVelocity - std::abs(m_fVelocityChangeRate)) <= 0 ||
m_fCurrentVelocity > m_fVelocityMax)
{
m_fVelocityChangeRate = -m_fVelocityChangeRate;
}
m_fCurrentVelocity += m_fVelocityChangeRate;
LOG_INFO("Data Generator: Velocity: %f", m_fCurrentVelocity);
return m_fCurrentVelocity;
}
float cTutorialFilterDataGenerator::CalculateYawRateValue()
{
// negate the yaw rate change rate if the max/min values are reached
if ((m_fCurrentYawRate - std::abs(m_fYawRateChangeRate)) <= 0 ||
m_fCurrentYawRate > m_fYawRateMax)
{
m_fYawRateChangeRate = -m_fYawRateChangeRate;
}
m_fCurrentYawRate += m_fYawRateChangeRate;
LOG_INFO("Data Generator: Yaw Rate: %f", m_fCurrentYawRate);
return m_fCurrentYawRate;
}
Finally we need to build the Project.
Now we want to integrate and test our Filters in an ADTF Project
.
We can accomplish this using the Configuration Editor.
Have a look at the ADTF Project Tutorial.