Go Down

Topic: Embedded Tool Kit (Read 3859 times) previous topic - next topic

Camel

Hi all,

I'd like to show off a project of mine, which I hope you will find useful.

https://github.com/supercamel/EmbeddedToolKit

It's a collection of lightweight and useful classes. It's got classes for string manipulation with atoi and atof implementations, an array wrapper that has a similar look and feel to std::vector, memory pools, basic math and a few algorithms such as swap and bubble_sort.

It also provides classes to handle vectors, matrices and quaternions. Great for orientation sensors, drones and other sensor fusion applications.

There are a bunch of navigation classes and heaps of other stuff too . . 

ETK contains no calls to malloc or new, it does not use exceptions and it uses no external libraries except for stdint.h and type_traits (for static assertions). There are unit tests, but they aren't 100% complete and there are a few known bugs. However, the intention is that ETK is more of less in accordance with high integrity coding standards such as MISRA.

Please let me know what you think.

Robin2

Where is the user manual?

IMHO that is almost more important than the code - especially if there is more than one function.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Camel

The user manual is very much a work in progress. I agree very much that it's super important and I'll be adding doxygen comments over the next few weeks.

In the mean time, there are a few blobs of documentation on my blog.

http://www.camelsoftware.com/blog/2015/12/11/ditching-c-libraries-concatenation-of-c-strings-without-stdio/

robtillaart

Code: [Select]
float Coordinate::cross_track_distance(Coordinate from, Coordinate to)
{
    float d13, brng13, brng12;
    d13 = from.distance_to(*this);
    brng13 = DEG_TO_RAD*(from.bearing_to(*this));
    brng12 = DEG_TO_RAD*(from.bearing_to(to));
    int R = 6371000.0f; //radius of the world in meters
    return asin(sin(d13/R)*sin(brng13-brng12)) * R;
}

should *this not be from?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#4
Dec 12, 2015, 10:50 am Last Edit: Dec 12, 2015, 10:52 am by robtillaart
Thanks for sharing BTW

The user manual is very much a work in progress. I agree very much that it's super important and I'll be adding doxygen comments over the next few weeks.

In the mean time, there are a few blobs of documentation on my blog.

http://www.camelsoftware.com/blog/2015/12/11/ditching-c-libraries-concatenation-of-c-strings-without-stdio/
better keep the doc in the GHrepo ?
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Camel

Code: [Select]
float Coordinate::cross_track_distance(Coordinate from, Coordinate to)
{
    float d13, brng13, brng12;
    d13 = from.distance_to(*this);
    brng13 = DEG_TO_RAD*(from.bearing_to(*this));
    brng12 = DEG_TO_RAD*(from.bearing_to(to));
    int R = 6371000.0f; //radius of the world in meters
    return asin(sin(d13/R)*sin(brng13-brng12)) * R;
}

should *this not be from?

Hmmm, I'm pretty sure that code is ok. The unit test for that function is actually commented out so it could well be broken. Thanks for the heads up.


robtillaart

A the picture is again worth a 1000 words ..
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Camel

Woot! I've been adding doxygen comments all day. I've also worked out how to use gh-pages so the documentation is now live on github.io

http://supercamel.github.io/EmbeddedToolKit/docs/html/index.html

Robin2

Thanks, that documentation is a big help.

I will bookmark this Thread for study when I get a bit of time.

Am I correct to assume your StaticStrings are just a version of standard C strings and do not suffer from the memory corruption problems that the String class can?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Camel

#9
Dec 13, 2015, 01:19 pm Last Edit: Dec 13, 2015, 01:24 pm by Camel
Thanks, that documentation is a big help.

I will bookmark this Thread for study when I get a bit of time.

Am I correct to assume your StaticStrings are just a version of standard C strings and do not suffer from the memory corruption problems that the String class can?

...R
When you say standard C strings, I think of character arrays and functions such as strcpy and sprintf. On the inside StaticStrings use an etk::List which is essentially a char array, but they don't depend on any C libraries. They're so encapsulated that I don't think you could call StaticStrings a version of standard C strings. It's probably a bit closer to std::string, except StaticStrings obviously can run out of space whereas std::string continues to allocate memory as required. Normal use of StaticStrings won't corrupt memory like the standard C string functions could as buffer overruns are protected against.

Robin2

When you say standard C strings, I think of character arrays and functions such as strcpy and sprintf.
Yes, that is what I meant.

Quote
It's probably a bit closer to std::string, except StaticStrings obviously can run out of space whereas std::string continues to allocate memory as required.
But this confuses me. A char array does not "continue to allocate memory" AFAIK whereas the String class does. And the String class causes problems in the limited amount of memory on an Arduino.

Does your string or rope class grab extra SRAM that the user would not be aware of? If it does it seems to me it could easily consume all the available memory and cause a crash.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Camel

Yes, that is what I meant.
But this confuses me. A char array does not "continue to allocate memory" AFAIK whereas the String class does. And the String class causes problems in the limited amount of memory on an Arduino.

Does your string or rope class grab extra SRAM that the user would not be aware of? If it does it seems to me it could easily consume all the available memory and cause a crash.

...R
Ah, ok. No, StaticString and Rope do not grab extra memory. They both use fixed sized arrays. StaticString contains it's own memory. Rope requires a pointer to an external buffer. The maximum length of a StaticString is specified by the template parameter. StaticString<5> ss; for example will creating a string with a maximum length of 5 character. If you write ss = "Hello world"; ss will contain "Hello". Attempting to write past the end of the string like this ss[8] = 'c' will also silently fail.

Robin2

Thanks, that is very clear and sounds like a good concept. There are quite a few problems among the Forum questions in which the cause is writing beyond the bounds of an array.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Camel

I've added some more interesting stuff, notably the EvoPID class.
https://github.com/supercamel/EmbeddedToolKit/blob/master/inc/etk/evopid.h

EvoPID is a self-tuning PID controller that uses an EA (evolutionary algorithm) to search for optimal PID gains. I've used the EvoPID concept (not this exact code, but similar) in a UAV flight control system before, and it could finely auto-tune a drone within 10mins of operation.

EAs are great because they can solve complex problems fairly quickly. They do this by having a 'population of genomes'. This is EA lingo for 'a bunch of random PID settings'. Each genome / PID setting is given a go at controlling the system and is given a fitness rating. Once all 8 PID gains have been rated, survival of the fittest takes place. The best ranked PID gain is randomly mixed with one of the next best PID gains to generate another whole new population. Sometimes there is a genetic mutation (ie. a PID gain is varied randomly). This is necessary to keep the search from settling on local optimas. The cycle repeats . . . favouring the best PID gains each time. Eventually the entire population of PID gains will be pretty close to the optimal settings.

The most critical part of EAs is how they are rated. If the rating algorithm is giving good scores to bad genomes, then the EA will not work very well. This is especially possible when a system with bad gains has reached a stable point and is not being perturbed. I've provided a basic PID rater with ETK which should be suitable for most control systems, but it's relatively straightforward to implement your own PID rater with ETK.

Due to the random nature of genetic mutations in EAs, it's probable that it will at some point select PID gains that are really bad. This could shake a system to pieces and be disastrous. The basic PID rater can detect and abort fatal mutations. This means that bad performers will be stopped quickly and removed from the gene pool, thereby preventing a potential accident.

All of this bla bla means great control systems without wasting time fiddling with settings.

Example code and documentation coming soon . . .

Robin2

#14
Dec 18, 2015, 10:49 am Last Edit: Dec 18, 2015, 10:52 am by Robin2
EAs are great because they can solve complex problems fairly quickly. They do this by having a 'population of genomes'.
Interesting idea.

I wonder if the likelihood of of your code being used would be increased by putting like-minded code into separate Toolkits rather than having a large mixed bag.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up