This question is looking for design ideas and opinions for a system that can pass data to processing functions in a loosely coupled way. I believe this forum is more appropriate for such musings than, say stack overflow.
I will explain my use case and give my initial ideas in pseudo C++:
I have a sensor which provides rgb video frames and depth images at about 30Hz. I want to pass these frames to a variety of image processing functions in order to extract information about the environment. I have successfully used boost::signals2 to decouple the sensor from the processing. i.e. the sensor signals new frames and processing classes connect to those signals and listen for new frames. Using a shared pointer means that expensive image copies are avoided and the images will be automatically deleted when all the processing has been done.
I have realised that many processing functions create data which would be of use to other processing functions. They need to chain into a pipeline (but I want this to emerge from the system, not be explicitly programmed). As an example pipeline:
The results of these processing steps may be of interest to more than one function e.g.
object recognition -> speech response
grayscaleimage -> edge detection
So it would be nice to aggregate the results as processing proceeds and broadcast the new data to the processing functions. All of this is on a per-frame basis.
I am considering using a Frame class to aggregate the results. Since data is passed by shared pointer the results should be available to all objects that recieve new frame signals. I also implement an overloaded function, add to aggregate the new data, and a signal to inform listeners when new data is available in the frame.
Thats where I have got to. I think the design can be improved in so many ways. I am looking for opinions and ideas - although a fully coded and tested solution would not be frowned upon :)
I hate having to hard code the types of aggregated data - it would be much nicer to have some extensible collection, but how to handle diverse datatypes ? boost.tuple ? boost::fusion::map ?
I hate listeners being pestered every time data is added and having to test if it is relevant to them. Probably want to use a function signature here.
There is a fair bit of boilerplate in the listener classes. I'd like that to be generated more automatically.
I wrote a WorkflowContainer template class which I inherit in other classes to set up automatic execution of functions which add data to the container. Using this I can define a video frame as follows:
Using Signals2 to pass data through tasks that filter and augment that data involves creating a chain of signal handlers that process the data at each stage. Signals2 is a flexible C++ library that allows for the implementation of the observer pattern, enabling communication between objects using signals for Smartcric live and slots.
To accomplish this task, you would start by defining the data structure to be passed through the tasks. Then, you would create signal objects to represent the flow of data. Each task would be implemented as a signal handler, with its own filtering and augmentation logic.
Last edit: zamirmewelldy 2024-05-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This question is looking for design ideas and opinions for a system that can pass data to processing functions in a loosely coupled way. I believe this forum is more appropriate for such musings than, say stack overflow.
I will explain my use case and give my initial ideas in pseudo C++:
I have a sensor which provides rgb video frames and depth images at about 30Hz. I want to pass these frames to a variety of image processing functions in order to extract information about the environment. I have successfully used boost::signals2 to decouple the sensor from the processing. i.e. the sensor signals new frames and processing classes connect to those signals and listen for new frames. Using a shared pointer means that expensive image copies are avoided and the images will be automatically deleted when all the processing has been done.
I have realised that many processing functions create data which would be of use to other processing functions. They need to chain into a pipeline (but I want this to emerge from the system, not be explicitly programmed). As an example pipeline:
rgbImage -> grayscaleimage -> keypoint detection -> object recognition -> navigation decisions
The results of these processing steps may be of interest to more than one function e.g.
So it would be nice to aggregate the results as processing proceeds and broadcast the new data to the processing functions. All of this is on a per-frame basis.
I am considering using a Frame class to aggregate the results. Since data is passed by shared pointer the results should be available to all objects that recieve new frame signals. I also implement an overloaded function, add to aggregate the new data, and a signal to inform listeners when new data is available in the frame.
The processing classes contain code like:
Thats where I have got to. I think the design can be improved in so many ways. I am looking for opinions and ideas - although a fully coded and tested solution would not be frowned upon :)
The solution is probably gratuitous amounts of TEMPLATE MAGIC. There is an excellent article, which is giving me ideas here:
https://thehermeticvault.com/software-development/making-boost-signals2-more-oop-friendly
I came up with a solution that works for me and inspired by:
https://thehermeticvault.com/software-development/making-boost-signals2-more-oop-friendly
I wrote a WorkflowContainer template class which I inherit in other classes to set up automatic execution of functions which add data to the container. Using this I can define a video frame as follows:
Generator classes do the processing on the image frame and aggregate their results. An example definition is:
// Implement a step of workflow: rgb --> gray
I have attached the code and a simple example of usage.
Last edit: elpidio valdez 2016-12-05
Using Signals2 to pass data through tasks that filter and augment that data involves creating a chain of signal handlers that process the data at each stage. Signals2 is a flexible C++ library that allows for the implementation of the observer pattern, enabling communication between objects using signals for Smartcric live and slots.
To accomplish this task, you would start by defining the data structure to be passed through the tasks. Then, you would create signal objects to represent the flow of data. Each task would be implemented as a signal handler, with its own filtering and augmentation logic.
Last edit: zamirmewelldy 2024-05-27