This series of articles focuses on creating a scalable object oriented modular software architecture based on services you can reuse in all your robots, without needing to start from scratch every time you create a new robot.
Maybe the most cost effective approach to start in robotics is with the Smart Robot Car you can buy on any e-commerce (aliexpress, banggood, etc). But of course buying it is the easiest part... You don't need to buy specifically that, and even with the description Smart Robot Car You'll find many different variants. I'll be creating "services" for all the most common modules you get with this kit, so you can choose which service you need, and use them together to create your own Smart robot, without the need to start from scratch on every robot you make.
IndexThis is the index of the series or articles Taibot Robot Services that I will be creating .
About the HardwareTo be able to follow this articles you'll probably need at least some idea of the Object Oriented Paradigm, if possible in C++. But I didn't know much C++, and still did this, so I think you'll be able to make it too.
I will be basing the services in cheap hardware you can get from any ecommerce. You'll see me mentioning the Arduino Smart Robot Car. Nevertheless, I don use that robot for my tests right now (I will probably in the future), but the RoboSoul TK-100, its a little more sturdy, but on the other hand, when it crashes into something, the result is more destructive.
This software is thought to be as scalable as possible, that is why, you should be able to use any hardware available. For some of them, you'll find here the services you can just reuse, and for others, you might need to implement the specific service for your specific hardware. It will be super easy, and if you decide to change your hardware after that, the changes you will need to do in the main code of your robot will be minimal.
About the ArchitectureI´ll try to keep this article updated with the latest class diagram, so it serves as reference of every service available in the code. You'll find it attached to this article.
Creating the Base ServiceAs the main idea is creating many services based on the same object oriented architecture, we first need to define what that architecture will be..
The "Service" base classFirst of all, we will keep in mind that we want to be able to just add a service for every hardware module you add to your project. So, what would be a good main class for a service? We want to be able to :
- Enable / Disable any service
- Make it verbose (to know whats happening within it for debugging)
- Allow the service to do some Setup
- Allow the service to run some Update code on every loop iteration
For now, that's it. More details will be added depending on what kind of service we are building. So the header file (Service.h) of the base service class will be like this:
#pragma once
#include "arduino.h"
namespace Taibot
{
class Service
{
public:
// isEnabled: Enables/Disables the Service
// isVerbose: Activates the logging output to Serial
Service(bool isEnabled, bool isVerbose);
// Use this method to know if the driver is enabled or not
bool IsEnabled();
// Use this method to know if the logging is is enabled or not before writing logs
bool IsVerbose();
// Enables/Disables the driver
void SetEnabled(bool isEnabled);
// Enables/Disables the logging
void SetVerbose(bool isVerbose);
// Needs to be implemented by every service, so we keep a convention
virtual void Setup() = 0;
// Needs to be implemented by every service, so we keep a convention
virtual void Update() = 0;
private:
// Enable/Disable the service
bool _isEnabled = false;
// Enable/Disable serial output for debugging
bool _isVerbose = false;
};
};
And its implementation (Service.cpp) like this:
#include "Service.h"
using namespace Taibot;
Service::Service(bool isEnabled, bool isVerbose)
{
_isEnabled = isEnabled;
_isVerbose = isVerbose;
}
bool Service::IsEnabled()
{
return _isEnabled;
}
bool Service::IsVerbose()
{
return _isVerbose;
}
void Service::SetEnabled(bool isEnabled)
{
_isEnabled = isEnabled;
}
void Service::SetVerbose(bool isVerbose)
{
_isVerbose = isVerbose;
}
The constructor of the base Service class forces us to set the enable and verbose configuration for the service: Service(bool isEnabled, bool isVerbose); Then you can see the methods that get or set this two properties.
The methods Setup() and Update() have no implementation here, since they need to be implemented by the services inheriting from this base class. In many cases, this methods might do nothing, but as the idea is to allow a service to work and update itself without any requirement from outside, we should allow every service to do what ever it requires from the mane sketch file.
This means that:
- On the sketch's setup() file, you will call all the Setup() methods from the services you are using.
- On the sketch's loop() file, you will call all the Update() methods from the services you are using.
I'll show an example on this as soon as we have our own real service implementation working.
Going back to the Service class is pretty simple. As you can see, we are using the Taibot namespace, just to avoid conflicts with other code you might have.
ConclusionRight now, this code looks super simple, and does not make much, but if you follow the rest of the articles, you will be able to get your robot working and with a nice, scalable and advance architecture that makes a lot more sense to me than having endless spaghetti code.
If you don't understand any part of this article, were unable to make this code work, found a bug, or have any suggestion, please let me know, I'm willing to improve this and make it a clean code base for anyone that wants to reuse it.
Comments