Im working on a real time machine control system, which performs a series of tasks, and should react to a large number of inputs. I've decided to implement this system using a state machine.
Ive used simple switch/case based state machines in the past and would like to transition to a more maintainable solution. At the moment I'm a little confused as to how to handle input and transitions.
For example I have an AnalogInput class which provides me with measurement values which i should monitor. Say I have a state WaitForThreshold, which should read a AnalogInput and then transition if the threshold is reached.
Do I
a) a pass a reference of the AnalogInput class to the WaitForThreshold class and allow it to monitor the input itself, signaling to the StateMachine class that it wishes to transition.
b) create dedicated events, LaserMeasurementAtThreshold and a state transition map: StateMachine.addTransition(State A, Event e, State B)
c)create more generic events AnalogInputChanged and implement event handlers for each of the events, which again signal to the StateMachine that a transition is desired
option a is essentially the larger version of a simple switch/case state machine, which could get messy with time, but offers great flexibility and b/c seems more structured and clean but seems like i may have to jump through alot of hoops to implement relatively simple tasks because the number of events can be very large.
Can someone offer some insight on the design of state machines where a large number of inputs sources and types must be monitored, and events are largely state-specific(Most event pertain only to a single state)?
Are there possibly other alternatives to state machine design to control a system where a sequence of steps must be implemented (non linear, looping and branchig must be possible)
Language: C++
Thanks
I believe this would be clearer to implement as a table of transitions:
typedef (void)((*Pointer_To_Transition_Function)());
struct Table_Entry
{
Input_Type input_value;
Pointer_To_Transisiton_Function p_trans_function;
};
static const Table_Entry Transition_Table[] =
{
{4, Read_Sensor},
};
static const size_t transition_quantity =
sizeof(Transition_Table) / sizeof(Transition_Table[0]);
//...
for (size_t index = 0; index < transition_quantity; ++index)
{
if (input_value = Transition_Table[index].input_value)
{
Pointer_To_Transition_Function p_function = Transition_Table[index].p_trans_function;
// Call the function:
p_function();
break;
}
}
You could use std::map, but the std::map has to be initialized during run-time. The table (array) is static and constant, thus it can be placed into a read-only memory segment (convenient for embedded systems); and doesn't use dynamic memory allocation.
Edit 1: ASCII drawing of the table
+-------------+--------------------------------+
| Input value | Pointer to transition function |
+-------------+--------------------------------+
| 4 | Read sensor |
+-------------+--------------------------------+
| 2 | Start motor |
+-------------+--------------------------------+
Related
I'm trying to create a performance monitor of sorts to run on a Particle board (STM32 based). I'm used to programming in c so the OOP approach is a bit new but I think it would fit well here.
For the purpose of this question let's assume I have two types of monitors:
Frequency. The application can call a "tick" method of the monitor to calculate the time since it last ran and store it.
Period- call a "start" and "stop" method of the monitor to calculate how long a process takes to run and store it.
What I would like to do is to create instances of these monitors throughout my application and be able to report on the stats of all monitors of all types from the main module.
I've read about the singleton design pattern which seems like it might be what I need but I'm not sure and I'm also concerned about thread safety with that.
I'm thinking I will create a "StatMonitor" class and a derived class "FrequencyMonitor" and "PeriodMonitor". Monitor would be a singleton and everywhere I wanted to create a new monitor I would request an instance of "Monitor" and use that like so:
freqMonitor * task1FreqMonitor = StatMonitor::GetInstance()->Add_Freq_Monitor("Task1");
The StatMonitor would track all monitors I've added and when I wanted to print the stats I could just call the printAll method which would iterate it's array of monitors and request their results like so:
StatMonitor::GetInstance()->PrintAllStats();
Am I going down the right path?
Your path sounds good, except that FrequencyMonitor and PeriodMonitor should not derive from the class that "manages" all these monitors (let's call it MonitorPrinter).
MonitorPrinter should be a singleton and could look like this:
class MonitorPrinter
{
public:
static MonitorPrinter& getInstance()
{
static MonitorPrinter monitorPrinter;
return monitorPrinter;
}
void printAllStats()
{
for (const auto& [_, frequencyMonitor] : _frequencyMonitors)
frequencyMonitor.print();
for (const auto& [_, periodMonitor] : _periodMonitors)
periodMonitor.print();
}
FrequencyMonitor& getFrequencyMonitor(std::string name)
{ return _frequencyMonitors[name]; }
PeriodMonitor& getPeriodMonitor(std::string name)
{ return _periodMonitors[name]; }
private:
MonitorPrinter() = default;
std::map<std::string, FrequencyMonitor> _frequencyMonitors;
std::map<std::string, PeriodMonitor> _periodMonitors;
};
Demo
(The const auto& [_, frequencyMonitor] is a structured binding).
FrequencyMonitor and PeriodMonitor should not have anything to do with singletons, and from your description, they need not be part of a class hierarchy either (as they have different interfaces). If you want, you can prevent users (other than the MonitorPrinter) from instantiating these classes using other techniques, but I won't elaborate on that here.
In short, there is no need to use OOP here. Use a singleton to provide (and keep track of) the monitors, and implement the monitors to your liking. Be wary of thread safety if this is relevant (the above is not thread-safe!).
I have a class (lets call it checker) and diffrent kind of classes that execute tasks (lets call them tasks). each tasks belongs to several categories
each task runs and at some point asks checker if they are allowed to do something. checker answers according to system state and according to their category. a task can be in multiple categories
how would you implement that? (cpp but I don't really think its language specific).
I was thinking adding a list of categories in each task and have a function that gets a category and answers if the task belongs to it.
class checker {
bool is_allowed(Task * task);
}
class Task
{
bool is_belongging_to_category(Category cat);
void some_task_to_do()
{
...
if (checker::is_allowed(this)) { ....}
else {....}
}
}
Is there a better way to solve this? Maybe some known design pattern...
This looks like questionable design. You're making tasks the objects.
Let's say your tasks are: Eat, Drink, and Be_Merry
If you make each of those tasks objects, they'll have to maintain a reference to the actual individual that they operate on, then when the condition is met they'll need to modify state on the given individual.
This is a violation of Object Oriented Design which defines an object as:
A tight coupling or association of data structures with the methods or functions that act on the data
Notice that you have split the "methods or functions that act on the data" from the object. Instead you should have modeled the objects Jack and Jill which had methods: Eat, Drink, and BeMerry
As far as checker, whether it's parceled out will depend upon whether you're using a push or a pull coding. If you're doing push coding, then checker is simply a holding area for the behavioral properties of Jack and Jill, in such a case the properties should be pushed to Jack and Jill rather than held in checker. If they are properties for all Jack or Jill objects, use a static property. If however you are using pull coding then the information is unavailable until you attempt to execute the task. In this case the checker should probably be a singleton that Jack and Jill access in the process of performing their tasks.
EDIT:
Your comment reveals further tragedy in the design. It seems as though you've kicked off a bunch of threads which are doing busy waiting on checker. This indicates that you need to be using a pull coding. You're Jack and Jill objects need to maintain booleans for which tasks they are actively involved in, for example m_is_going_to_school, then when checker gets the condition that would stop your busy waiting in your design, instead kick off the goToSchool method.
You could make a vector to store all the possible allowed options. You can make a bool function (like you have) called IsAllowed with argument string and that will check if the option its going to do is allowed. If not, return false. That's just my idea though. Of course there's a zillion different ways to implement this. If you want multiple choices. Then you can make a 2d vector, and see if the corresponding row has any of the options. Good luck!
If you know the maximum number of categories in advance, I'd recommend using Bit Flags to do this.
enum Category {
CATEGORY_A = 1,
CATEGORY_B = 1 << 1,
CATEGORY_C = 1 << 2,
CATEGORY_D = 1 << 3,
};
class Task {
int32_t categories_;
public:
Task() : categories_(0) {}
void add_category(Category cat) {
categories_ |= cat;
}
void run() {
checker::can_run(categories_);
}
}
This allows to test for multiple categories all at once:
namespace checker {
bool can_run(int32_t categories) {
int32_t cannot_run_right_now = CATEGORY_A | CATEGORY_C;
if(categories & cannot_run_right_now != 0) {
return false;
}
...
}
}
Well, it depends. If you are 100% sure that you know how many categories there are to be and that is not some gigantic number then you might store this information as an integer. If n-th bit is 1 then task belongs to n-th category. Then depends on the state of system you might create some another integer that would serve as a mask. In the end you would just do some bit-AND ( mask & categories != 0 ) operation to determine if task and mask share common bit.
On the other hand if there will be unknown number of categories you might just make a list of categories it belongs to. Make a dictionary of [SYSTEM_STATE] => [CATEGORIES_AVAILABLE] and check
bool is_allowed(Task * task){
foreach (Category sysC in stateCategories[sys.GetState()])
{
foreach (Category taskC in task.GetCategories())
{
if(sysC == taskC) return true;
}
}
return false;
}
That would of course be slow for a big number of categories.
You could improve this method by making this list of categories some another data structure, in which searching is not O(n) such that the code would look like this :
bool is_allowed(Task * task){
foreach (Category sysC in stateCategories[sys.GetState()])
{
if task.GetCategories().Contains(sysC) {
return true;
}
}
It depends
I am trying to perform some numerical computation on a large distributed data set. The algorithms fit the MapReduce model well with the additional property that output from the map step is small in size compared to the input data. Data can be considered read-only and is statically distributed over the nodes (except for re-balancing on fail-over). Note that this is somewhat contrary to the standard word-count examples where the input data is sent to the nodes performing the map step.
This implies that the map step shall be executed in parallel on all nodes, processing each node's local data, while it is acceptable that the output from the map step is sent to one node for the reduce step.
What is the best way to implement this with GridGain?
It seems there has been a reduce(..) method on GridCache/GridCacheProjection interfaces in earlier versions of GridGain, but this is not present any longer. Is there any replacement? I am thinking of a mechanism that takes a map closure and executes it distributed on each datum exactly once while avoiding to copy any input data across the network.
The (somewhat manual) approach I have come up with so far is the following:
public class GridBroadcastCountDemo {
public static void main(String[] args) throws GridException {
try (Grid grid = GridGain.start(CONFIG_FILE)) {
GridFuture<Collection<Integer>> future = grid.forRemotes().compute().broadcast(new GridCallable<Integer>() {
#Override
public Integer call() throws Exception {
GridCache<Integer, float[]> cache = grid.cache(CACHE_NAME);
int count = 0;
for (float[] array : cache.primaryValues()) {
count += array.length;
}
return count;
}
});
int totalCount = 0;
for (int count : future.get()) {
totalCount += count;
}
// expect size of input data
System.out.println(totalCount);
}
}
}
There is however no guarantee that each datum is processed exactly once with this approach. E.g. when re-balancing takes place while the GridCallables are executed, part of the data could be processed zero or multiple times.
GridGain Open Source (which is now Apache Ignite) has ComputeTask API which has both, map() and reduce() methods. If you are looking for a reduce() method, then ComputeTask is definitely the right API for you.
For now your implementation is OK. Apache Ignite is adding a feature where a node will not be considered primary until the migration is fully finished. It should be coming soon.
I'm designing a new power-up system for a game I'm creating. It's a side scroller, the power ups appear as circular objects and the player has to touch / move through them to pick up their power. The power up then becomes activated, and deactivates itself a few seconds later. Each power-up has its own duration defined. For simplicity's sake the power ups are spawned (placed on the screen) every X seconds.
I created a PowerUpManager, a singleton whose job is to decide when to create new power ups and then where to place them.
I then created the Powerup base class, and a class that inherits from that base class for every new Powerup. Every Power-up can be in one of three states: Disabled, placed on the screen, and picked up by the player. If the player did not pick up the power up but moved on, the power up will exit the screen and should go back from the placed state to the disabled state, so it can be placed again.
One of the requirements (that I) put in place is that there should be minimal code changes when I code up a new Power up class. The best I could do was one piece of code: The PowerUpManager's constructor, where you must add the new power-up to the to the container that holds all power-ups:
PowerupManager::PowerupManager()
{
available = {
new PowerupSpeed(),
new PowerupAltWeapon(),
...
};
}
The PowerUpManager, in more details (Question is coming up!):
Holds a vector of pointers to PowerUp (The base class) called available. This is the initial container that holds one copy of each power up in the game.
To handle the different states, it has a couple of lists: One that holds pointers to currently placed power ups, and another list that holds pointers to currently active power ups.
It also has a method that gets called every game tick that decides if and where to place a new power up and clean up power ups that weren't picked up. Finally it has a method that gets called when the player runs into a power up, that activates the power up (Moves it from the placed to the active list, and calls the power up's activate method).
Finally, once you understand the full picture, the question:
I needed a way for client code to ask if a particular power-up is currently active. For example: The player has a weapon, but there is a power up that replaces that weapon temporarily. Where I poll for input and recognize that the player wants to fire his weapon, I need to call the correct fire method - The alternative weapon power up fire method, and not the regular weapon fire method.
I thought of this particular demand for a while and came up with this:
template <typename T>
T* isActivated() // Returns a pointer to the derived Powerup if it exists in the activated list, or nullptr if it doesn't
{
for(Powerup *i : active) // Active is a list of currently active power ups
{
T *result = dynamic_cast<T*>(i);
if(result)
return result;
}
return nullptr;
}
So client code looks like this:
PowerUpAltWeapon *weapon = powerUpManager->isActivated<PowerUpAltWeapon>();
if(weapon)
...
I thought the solution is elegant and kind of neat, but essentially what it is is trying to convert a base type to a derived type. If that doesn't work, you try the next derived type... A long chain of if / else if, it's just disguised in a loop. Does this violate the guideline that I just described? Not casting a base type to all of its derived types in a long chain of if / else if until you get a hit? Is there another solution?
A secondary question is: Is there a way to get rid of the need to construct all the different power ups in the PowerupManager constructor? That is currently the only place you need to make a change if you want to introduce a new power up. If I can get rid of that, that'd be interesting...
This is based on your design, but if it was me I choose an ID for each PowerUp and a set of IDs in the client, and each time a user posses a PowerUp that ID will be added to its set and ... you know the rest. Using this technique I can do fast look up for every PowerUp and avoid dynamic_cast:
std::set<PowerUp::ID> my_powerUps;
template< class T > bool isActivated() {
return my_powerUps.find( T::id() ) != my_powerUps.end();
}
And about your second question, I have a similar program that load some plugins instead of PowerUp, I have a pure virtual base class that contain all methods that required by that plugin and implement it in shared modules and then at startup I load them from an specific folder. For example each shared module contain a create_object that return a plugin* (in your case PowerUp* of course) and then I iterate the folder, load modules and call create_object to create my plugins from them and register them in my plugin_manager
The diagram http://www.freeimagehosting.net/uploads/2fd3f4161c.png
Here's the Minimalist-UML diagram of an app I've been working on. It's supposed to simulate the management of a bunch of sensors relating to different measurements.
Please ignore the House class, the diagram is outdated...
However, I have trouble. Each sensor (sound, contact, heat, pressure, gas - All of these inherit from sensor) has an unique ID, starting at 0 for the first one and ending at the total number of sensors - 1.
For good practices' sake, where shall I store the total number of sensors, so the classes I'm using for input/output of files (saving and loading) and insertion of new sensors can access and increment that counter?
Thank you for your time!
One option would be to create a static function in your Sensor class that increments and returns a static counter variable. The constructor for Sensor could call this function to get an ID.
// header file
class Sensor
{
...
protected:
static int getId() { return id++; }
private:
static int id;
int myId;
};
// .cpp file
int Sensor::id = 0;
Sensor::Sensor(...)
: myId(getId())
...
{}
I'm ignoring threading and persistence issues here. But hopefully this gives you a better idea.
Whatever object creates the sensors should assign the identifiers to the sensors.
If multiple objects create sensors, then they should be assigned a pointer or reference to a provider of identifiers when they are created and they should query that provider for a new unique identifier as they create new sensor objects.
Your unique ID, like a database table ID will likely have some issues.
You will probably find, eventually, that your ID needs to persist across sessions--that your window's ID is used in some other relationship.
You may, some day, also find that it needs to be unique across multiple server/client sets.
I'm just suggesting that you should consider these issues off the bat.
As for where the ID should be generated, since all your "Sensor" classes inherit from one base class, I think I'd generate it via a threadsafe method in that base class--and I'd store it there as well.
what's the problem? do you use a Vector to store your sensors? define a Vector of holding sensor-objects in the house.
can access and increment that counter
you don't have to do this, the Vector does it for you
Have a look at the Singleton pattern assuming you don't want to do it with a database of some sort.