Coding Conventions

First of all: the documentation as well as class and variable names are written in English.

The rule set for the coding conventions is based on the BSD/Allman style. Here is an example:

/**
* A sample source file for the code formatter preview
*/
#include <memory>
#include <cmath>
namespace Foo
{
class Point
{
public:
Point(double xc, double yc) :
x(xc),
y(yc),
MATH_PI(3.14)
{
}
double distance(const Point& other) const;
bool isZero() const;
static double Distance(const Point& a, const Point& b);
private:
double x;
double y;
};
using PointPtr = std::shared_ptr<Point>;
enum EnumType
{
eFirstEntry,
eSecondEntry,
eThirdEntry
};
const float MATH_PI;
}
using namespace Foo;
double Point::distance(const Point& other) const
{
double dx = x - other.x;
double dy = y - other.y;
return sqrt(dx * dx + dy * dy);
}
bool Point::isZero() const
{
bool isZero = false;
if ((0 == x) && (0 == y))
{
isZero = true;
}
return isZero;
}
double Point::Distance(const Point& a, const Point& b)
{
return a.distance(b);
}

Classes

  • Classnames all start with an uppercase letter.
  • Classnames do not start with a C prefix(applies primarily to new classes).
  • Classnames are written in CamelCase.
  • Classes are stored in files named exactly like the class.

Classmembers

  • Static member methods start with an Uppercase letter.
  • Non-Static member methods start with a lowercase letter.
  • All member methods are written in camelCase.
  • Constants are written all UPPER_CASE and single words are separated by underscores.
  • Members are NEVER aligned in the sourcecode. There is only one Space between the classname and the variablename. (Maintaining this order is too much work if members get added or removed).

Enums

  • Try to avoid Enums if possible
  • If you really think you have to use Enums use the following style: Name the Enum type like a classname in CamelCase and don't put a preceeding 'E' at the beginning; start the entries in the Enum type with a lowercase 'e' and proceed with CamelCase naming.

C++ Pointer

  • Always use smart-/shared pointer whenever possible.
  • For classes inheriting from Ice use IceUtil::Handle.
  • For classes inheriting from Qt classes use QPointer if the object has a parent and QSharedPointer if no parent is set.
  • For every other kind of classes use std::shared_ptr<ClassName> (requires #include <memory>).
  • Always provide a "ClassNamePtr" typedef for the appropriate smartpointer type in the header file (note the Ptr suffix).

Naming Conventions

  • include guards (those after #ifdef ... #define ... in headers): ARMARX<ComponentType>_<ArmarXPackageName>_<ComponentName>_h (you can also take a look at the skeleton files in 'ArmarXCore/etc/scripts/armarx-package/skeleton/package/source')
  • Topic names
  • Library/Component names

Indentation

  • NO TABS
  • Standard Indentation value is 4 Spaces
  • No trailing whitespaces at the end of line (most editors can handle that automatically)
  • All opening/closing brackets start on a seperate line aligned with the enclosing code block they belong to.
  • No space between method name and parenthesis.
  • One space between all control structures and the beginning parenthesis of their corresponding condition (if, while, for, else if, switch).
  • One space after each comma or semicolon in the middle of a statement.
  • One space before and after a comparison or assignment operator (=, ==, !=, >, <, >=, <=, ...).
  • public:/protected:/private: align with the class definition.
  • The : of the initialisation list is placed after the closing bracket of the constructor.
  • The inialisation list itself is placed on a new line and indented by the standard indentation value.
  • Everything inside namespaces is indented by the standard indentation value.
  • If a 'normal' pointer is needed it is written the following way: <Classname>* <variableName> (one space before the variable name, no space after the class-/typename)
  • one space between leading 'const' and a class-/typename
  • class-/typename followed by a space followed by 'const' followed by another space followed by the variablename

Files

  • All files must be named like the classes they contain with exactly the same upper-/lowercase spelling.
  • No comments AFTER endif directives in header files.
  • C++ files end with .cpp (no .cxx, .cc or anything else).
  • Source files are located in source/PackageName/
  • Slice files end with .ice
  • Slice files are located in source/PackageName/interface/

General

  • Never place a 'using namspace XYZ;' directive in header files (Reason: this results in namespace pollution and might override method definitions in namespace XYZ).
  • Remove all #include directives in header files which are not required for error free compilation (see next item).
  • Use forward class declarations in header files for each class (Reason: this results in a cleaner and faster build).
  • NEVER put forward class declarations inside #ifdefs (Reason: these declarations tells the compiler to expect a pointer to a class so that it does not need the class declaration. Therefore it doesn't make any sense to put those declarations inside #ifdefs because no other information is associated with it than 'use each pointer declaration as a pointer to a class').
  • Use cmath instead of math.h and cstdio instead of stdio.h in C++ code (applies to most of the standard C header files). This is the official C++ way of including C headers (Reason: using the .h versions can result in namespace issues. The method in the 'c' prefixed files are all defined in the std namespace). See here for a list of available headers: http://www.cplusplus.com/reference/clibrary/. Only use the C versions if method definitions should be missing in the C++ headers.

Slice Definitions

  • Interface-, Class-, Struct-, and Exception-names are written CamelCase.
  • Interface definitions always end with "Interface".
  • Implementations of an interface definition omit the "Interface" suffix.
  • Class names in Slice files end with "IceBase".
  • Subclasses of classes defined in Slice files omit the "IceBase" suffix.
  • No comments after endif.
  • For Enums apply the same rules as mentioned in Enums
  • Naming of report functions?
  • Slice Documentation?
  • #ifdef convention?

CMake

  • functions and macros are spelled lowercase
  • all header and source files are listed explicitly (not by using GLOB or GLOB_RECURSE)
  • NEVER use find_package(Xyz REQUIRED); instead use a combination of find_package(Xyz QUIET) + armarx_build_if(Xyz_FOUND "Xyz Library is missing")
  • every generated file must be generated inside CMAKE_BINARY_DIR

Units

  • Angle: radian
  • Angular velocity: radian / second
  • Length/Position: millimeters
  • Velocity: millimeter / second?
  • Time: seconds / milliseconds?
  • Coordinate Systems: right/left handed?
  • Current: ?
  • Force: ?
  • Torque: ?

Xenomai

  • All Xenomai binaries must have a ".xeno" suffix.

Scenarios

  • Scenarios are located in the "scenarios" directory of each ArmarX Package
  • Each scenario is placed inside its own direktory under "scenarios"
  • Configuration files must follow the format: "config/${COMPONENT_NAME}[.optionalString].cfg"

Documentation

  • Documentation is done using Doxygen.
  • Slice files are documented using slice2html.
  • All classes, methods, members, etc. are documented in the header files NOT in the cpp files (Rational: Template methods can only be implemented and thus documented in header files).
  • Section identifiers on pages are prefixed with the pagename to prevent duplicate identfiers which lead to inconsistent cross-linking.
  • It does not matter if you use \param or @param but be consistent within your project. Also keep the current documentation style of other projects you are working on.
  • ${ArmarXPackage_DIR}/etc/doxygen/images contains images which are included in the documentation with the following doxygen command:
    \image html Image.svg "Text Description of image" width=300px
  • ${ArmarXPackage_DIR}/etc/doxygen/snippets contains sourcecode stored in .dox files. These are later added with the following command:
    \include MyCodeExample.dox
  • Additional documentation resides in ${ArmarXPackage_DIR}/etc/doxygen/pages and is put into .dox files.
  • API documentation is divided into groups defined by @defgroup which is usually defined in the header file of the baseclass
  • Any class belonging to that group must use the following doc header
    @class ClassName
    @brief Description of the class in one line
    @ingroup GroupOfClass (defined by a @defgroup command)
    Here comes the rest of the documentation
  • Tables:

How To #include

Include files in the following order:

  • "": Include files belonging to the same project and going into the same library with "".
  • <>: Include all system headers and all headers from other libraries with <>.

Automatic code formatting with AStyle

Astyle is a tool for automatic code formatting and can be found at http://astyle.sourceforge.net/.

ArmarX Packages have convenience make target to perform the formatting automatically:

make astyle

The rules applied by astyle can be found in ${ArmarXCore_DIR}/etc/templates/armarx.astylerc.

GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:662
armarx::ctrlutil::a
double a(double t, double a0, double j)
Definition: CtrlUtil.h:45
Point
Definition: PointCloud.h:21
visionx::Point
Eigen::Vector3f Point
Definition: ObjectShapeClassification.h:69
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:88