Close

Redtree Hydra: Software Model

A project log for Redtree Hydra: A modular platform for robotics

The Redtree Hydra is the 1st computer for robotics designed to easily add components, communicate with groups of other robots and share data

redtree-roboticsRedtree Robotics 06/05/2015 at 10:590 Comments

In the Redtree Hydra system, everything is an m_module. This could be algorithms, entire robots, sensors, motors or anything else which might make up the "robot". This class defines what makes up the component (data types, other m_modules, m_devices etc).

A special type of m_module is an m_device. This is similar to an m_module except that it has defined behaviour states for handling failures. This is useful for things like motors or sensors. You might wish to attempt to land a flying device on a sensor failure to try to avoid a crash.

Repeating executable functions are given the type m_worker in the Redtree Hydra system. Functions which should run once are given the type m_job.

m_module

An m_module has several important functions which define the behaviour when the module loads.

configure()

The configure() function is called for every single tag, device, and module in reverse creation order.

The configure function lets the user set data dependicies for m_extern tags and low level settings like queue sizes based on low level settings. Which means this step is to setup the device/module/etc. into a state that it can then be initialized.

initialize()

The initialize function is used to apply the configuration that was created in the previous step. This steps are separated because parent modules and devices will likely change the configuration of child tags/devices, and modules. (i.e. A the CANOpen protocol module will change the baud rate tag of the CANBus Peripheral, or a Motor will configure the gains of its Control System Module)

setup()

The setup function is provides an intermediate step between initialize and the device/module/or tag starting its runtime behaviour. Sometimes this is necessary depending on the complexity of module/device or tag.

start()

Finally, the start method is called. The start function of any tag, module, or device must bring that component to its normal runtime state, and execute "Started = true;" once the unit is functional and runtime capable.

m_device

An m_device inherits all of the previous functions specified from the m_module above. In addition, there are some extra functions which are used to handle failure cases.

m_worker

In order for a module or device to run executable functions periodically or continually, the code must be wrapped as an m_worker. This allows the code to function with tags and take advantage of the real-time and seamless networking features of the Redtree Hydra system.

Here is an example of a globally available m_worker:

m_worker<void, void> my_task{"my_task",[&](){
	cout << "Executing my task function" << endl;
 
}};

And here is an example of an m_worker defined within a class:

class myclass : public m_device
{
	public:
		using m_device::m_device;
		void configure(void){}
		void initialize(void);
		void setup(void){}
		void start(void){Started = true;};
 
	private:
		int sockfd;
		struct addrinfo *servinfo;
		void send(void);
		m_worker<void, void> myclass{this, "myclass", std::bind(&myclass::my_task, this)};
};
myclass my_instance{"my_instance"};
 
void my_instance::my_task(void)
{
	cout << "Executing my task function within a class" << endl;
}

Periodic User Functions

User functions within an m_module or m_device can be run every x microseconds.

For instance, if you have an m_worker called my_task, you can run it every 500ms as follows:

my_task.run_every(500000)

Continual User Functions

You can also have a function run continually (it does not wake up on enforced time schedules - it is essentially a non-realtime task)

This is the type of function you would run a busy loop inside of if, for some reason you needed one. Note - in either of these cases - both of the functions never return - they will just be called over and over again.

my_task.run_when(Started);
Right now, it is only possible to run continual functions on a trigger (for example when the module has started) - but in the future we plan to allow functions to just "run" as soon as possible by removing the constraint. See triggered functions below.

Triggered User Functions

Continual or periodic functions can run on a trigger or for the case of a periodic function, just run every x microseconds. Here are a couple of examples of triggered functions:

my_task.run_when(Started); //continual, triggered
my_task2.run_every_when(250000, Started); //periodic, triggered
In both of these cases, the functions won't run unless Started == true.

This information can also be found on the Redtree Wiki

Discussions