Bertrand's Design Study
Last year, I was involved in a project which consisted in building an autonomous robot to compete in the French Robotic Cup. My main task was to handle all the data transmissions in the robot. This mean I had to work a lot with networks, especially the CAN network (widely used in cars).
This one is not like TCP/IP, there is no sources nor destinations. All frames have IDs (11 or 29 bits), and each nodes connected to the network needs to determine if the frame is relevant or not by filtering IDs.
The main problem is for managing the whole network, which mean handling IDs:
- nodes are mostly µc like PIC, ARM, ... and are running homemade firmwares, without OS (written in C)
- the data part of a frame can be up to 8 bytes long, the format is determined by the developer
Managing the network "by hand" would be a really painful task: determining IDs, format, writing them in the code, ... can lead to an infinite amount of errors and wasted time. In order to do that, I developed a tool called CanXml in C++ which takes an XML-based configuration file describing the network (nodes, frames, format), and exporting it as a C header with all the networks IDs defined in here using #define with convenient names.
This tool was really helpful but when designing it, I was thinking in building a library that feature tools to manage the network, but also that can be used to debug the network.
This goal was not reached and the design I realized then is far from perfect, that's why I think it can be a great subject for my design study.
Requirements
The library must feature:
- network management abilities (IDs generation, XML import and C-header export)
- a way to process existing frames
- be memory efficient (in order to be used on Linux embedded devices)
And it also need to be clean, since I want to release it under an open source license.
Existing design critics
I made a few mistakes on my first attempt.
My naming convention appeared has a bad choice when I started implementing a way to process existing frames, there is a conflict between "abstract frames" (the "family") and "concrete frames" (transfered frames), which gets really confusing when processing the code.
The way it determines IDs is too static, the policy is static while it should be more ... well, dynamic. Network/Nodes/Frames is some kind of tree, and each frame generate his ID using a simple algorithm based on the node it belongs to, the priority, ...
There is another problem for XML import and C export which is closely related. The XML file is processed recursively by objects in order to build the tree. A similar pattern is used for C export.
The pattern I used for storing the format is too complex and inefficient. Since I was looking for a memory-efficient way to handle formats of different type, bit sizes, endianness while being able to process existing frames, I produced something that is heavy and not clean.
Refactoring
Work in progress :)