The Basics

Be Consistent

The important reason for having a style guide is to be consistent. This style guide can't cover every possible thing you may need to write a wiki page about, so just remember to be consistent in your own documentation.

If you invent a new style, remember that it has to be applied everywhere

There will be times where of a new way of formatting something that improves its readability, or you have to come up with some standard way of presenting something new. Remember though: if you come up with a new way of formatting a particular item, that formatting has to be applied to all occurrences of that item throughout the wiki (and documented here).

Common Names

Capitalization: the following are capitalized

The following are not capitalized:

Heading Levels

Pages: Start with heading-level 2 (i.e. ==). Heading 1 is reserved for the actual page title, which is automatically used

Heading level 5: Any heading level beyond level 4 gets more difficult to interpret. Consider other ways of formatting content. For an example of this, see Sample 1 and Sample 2 below.


Sample 1

BLTs

BLTs consist of three ingredients, which are discussed below.

Bacon

Bacon is delicious.

Lettuce

Lettuce is to make it healthy.

Tomato

Tomatoes bring out the red in the bacon.

Grilled Cheese

Now I will talk about my other favorite sandwich, the Grilled Cheese.


Sample 2

BLTs

BLTs consist of three ingredients, which are discussed below.

Bacon

  • Bacon is delicious.

Lettuce

  • Lettuce is to make it healthy.

Tomato

  • Tomatoes bring out the red in the bacon.

Grilled Cheese

Now I will talk about my other favorite sandwich, the Grilled Cheese.


Code

Code Style Guides

There are existing code style guides for ROS packages:

Code API

Code API is generally done in Doxygen, Epydoc, or Sphinx. This documentation is automatically linked from the Wiki page for a ROS Package. While your wiki documentation can refer to the Code API, the comprehensive documentation should be done by the automatic generation capabilities of the language you are using. See rosdoc for more information.

Code (e.g. C++ classes, Python methods, etc...)

Example: Remember to invoke rospy.is_shutdown() regularly...

All code should be written in monospace using the backtick operator, e.g. `ros::Publisher`.

All methods should be clarified as method_calls() -- the parens operators make it very clear what you are referring to.

C++ class::Names

When referring to a C++ class, make it clear by including the namespace, e.g. my_package::Class, not Class.

You should only use C++ class names in your documentation when the documentation specifically applies to C++ classes. In other words, in general, do not use C++-style syntax when referring to:

  • Message types (e.g. sensor_msgs::LaserScan vs. sensor_msgs/LaserScan)

  • ROS concepts (e.g. ros::Publisher vs. publisher)

Python class names

The same rules apply as with C++ class names: include the module name when referring to a class, e.g. rospy.Publisher, so that it is clear that you are referring to the Python entity.

ROS

ROS Names

Example: Node foo publishes messages to the bar topic.

ROS names are monospace. This includes tf frames, parameter names, service names, topic names, etc...

ROS Message Types and Service Types

Example: The node receives sensor_msgs/LaserScan messages...

NOTE: be careful to distinguish between ROS Messages, i.e. the data, vs. ROS Message types, the format of the data.

When referring to message types, you should always use the MsgLink macro, e.g.

<<MsgLink(sensor_msgs/LaserScan)>>

produces the link, sensor_msgs/LaserScan.

Similarly, use the SrvLink macro for services, e.g.:

<<SrvLink(nav_msgs/GetMap)>>

Look here for macros: WikiMacros

ROS Concepts

Example: When working with ROS topics....

When referring to ROS concepts like topics, services, and Packages, it is generally good form to indicate to the reader that you are talking about the ROS-meaning of these terms. When you introduce these concepts in your text, use a "ROS" prefix . After you have introduced the concept, you can use it without the prefix (unless you need to disambiguate).

The reason we do this is that concepts like "package" have meaning in ROS, Java, Debian, Python, and many other places. This immediately clarifies to a reader who may have entered at your page.

ROS API

Each ROS node in your documentation needs to have ROS API documentation. To help make this consistent and allow us to make some stylistic changes in the future, we do this using the CS/NodeAPI clearsilver template.

Clearsilver uses a hierarchical data format called HDF.

Your node API ends up being specified in a consistent HDF representation inside a code block. The code block will always start with:

{{{
#!clearsilver CS/NodeAPI

In the event of a single node, you should specify HDF strings for the name and description of the node.

Additionally, the following sections can optionally be specified

  • sub - topics the node subscribes to

    • Expects sub-fields: name, type, desc

  • pub - topics the node publishes

    • Expects sub-fields: name, type, desc

  • srv - services the node provides

    • Expects sub-fields: name, type, desc

  • srv_called - services the node calls

    • Expects sub-fields: name, type, desc

  • param - parameters the node checks

    • Expects sub-fields: name, type, desc, default

  • param_set - parameters the node sets

    • Expects sub-fields: name, type, desc, default

  • req_tf - tf frames the node expects

    • Expects sub-fields: from, to, desc

  • prov_tf - tf frames the node provides

    • Expects sub-fields: from, to, desc

  • goal - action goal the node provides

    • Expects sub-fields: name, type, desc

  • feedback - action feedback the node provides

    • Expects sub-fields: name, type, desc

  • result - action result the node provides

    • Expects sub-fields: name, type, desc

  • act_called - actions the node calls

    • Expects sub-fields: name, type, desc

As a minimal example, the code:

{{{
#!clearsilver CS/NodeAPI
name = my_node
desc = does something interesting
sub {
  0.name = topic_name1
  0.type = std_msgs/String
  0.desc = it publishes this topic
  1.name = topic_name2
  1.type = std_msgs/String
  1.desc = it also publishes to this topic
}
}}}

will produce the following:


my_node

does something interesting

Subscribed Topics

topic_name1 (std_msgs/String)
  • it publishes this topic
topic_name2 (std_msgs/String)
  • it also publishes to this topic


A full specification of all the possible sub-sections would look like:

{{{
#!clearsilver CS/NodeAPI
name = node_name
desc = does...
sub {
  0.name = foo/topic_name1
  0.type = std_msgs/String
  0.desc = topic_desciption 1
}
pub {
  0.name = foo/topic_name
  0.type = std_msgs/String
  0.desc = topic description, including any important rate information
}
srv {
  0.name = foo/service_name
  0.type = nav_msgs/GetMap
  0.desc = service description
}
srv_called {
  0.name = foo/service_name
  0.type = nav_msgs/GetMap
  0.desc = service description
}
param {
  0.name = ~parameter_name
  0.type = type
  0.desc = parameter description
  0.default = value
}
param_set {
  0.name = ~parameter_name
  0.type = type
  0.desc = parameter description
  0.default = value
}
req_tf {
  0.from = foo
  0.to   = bar
  0.desc = description of transform
}
prov_tf {
  0.from = baz
  0.to   = mumble
  0.desc = description of transform
}
}}}

And produce:


node_name

does...

Subscribed Topics

foo/topic_name1 (std_msgs/String)
  • topic_desciption 1

Published Topics

foo/topic_name (std_msgs/String)
  • topic description, including any important rate information

Services

foo/service_name (nav_msgs/GetMap)
  • service description

Services Called

foo/service_name (nav_msgs/GetMap)
  • service description

Parameters

~parameter_name (type, default: value)
  • parameter description

Parameters Set

~parameter_name (type, default: value)
  • parameter description

Required tf Transforms

foobar
  • description of transform

Provided tf Transforms

bazmumble
  • description of transform


Additionally, these variables can be pushed down into a variable called node, or, in the event of multiple nodes, an array, specified in HDF by node.0, node.1, etc.

== Nodes ==
{{{
#!clearsilver CS/NodeAPI
node.0 {
  name = One node
  desc = ...
}
node.1 {
  name = Another Node
  desc = ...
}
}}}

Which produces:


Nodes

One node

...

Another Node

...


Occasionally, it may be necessary to specify a list of one of the sub-sections without a node:

{{{
#!clearsilver CS/NodeAPI
pub {
  0.name = foo/topic_name1
  0.type = std_msgs/String
  0.desc = topic_desciption 1
  }
}}}

Or, to break up a sub-section into multiple groupings:

{{{
#!clearsilver CS/NodeAPI
param {
  group.0 {
    0.name = ~parameter_name
    0.type = type
    0.desc = parameter description
    0.default = value
  }
  group.1 {
    name = DEPRECATED
    desc = description of parameters which should no longer be used.
    0.name = ~old_parameter_name
    0.type = type
    0.desc = old parameter description
    0.default = value
  }
}}}

Which ends up looking like:

Parameters

~parameter_name (type, default: value)
  • parameter description
DEPRECATED
description of parameters which should no longer be used.
~old_parameter_name (type, default: value)
  • old parameter description

If you have a description that is long or requires multi-line formatting, HDF's heredoc syntax is useful:

{{{
#!clearsilver CS/NodeAPI
#!clearsilver CS/NodeAPI
param {
  0.name = charles
  0.type = string
  0.default = dickens
  0.desc << EOM
It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to heaven, we were all going direct the other way - in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.
EOM
}
}}}

Which looks like:

Parameters

charles (string, default: dickens)
  • It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to heaven, we were all going direct the other way - in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.

The heading for a sub-section can be suppressed by no_header=True. One common use case: when maintaining a node's documentation over multiple ROS distros with the Version macro, some parameters (topics, etc) may only exist in certain distros. You could separate them as follows:

<<Version()>>

{{{
#!clearsilver CS/NodeAPI
param {
  0.name = common_parameter
  0.type = string
  0.default = foo
  0.desc = This parameter present in all versions.
}}}
{{{{#!wiki version indigo jade
{{{
#!clearsilver CS/NodeAPI
param {
  no_header=True
  1.name = new_parameter
  1.type = string
  1.default = bar
  1.desc = This parameter added in ROS Jade.
}}}
}}}}

Which looks like:

  Show EOL distros: 

Parameters

common_parameter (string, default: foo)
  • This parameter present in all versions.

new_parameter (string, default: bar)

  • This parameter added in ROS Indigo.

For other examples of this, see the gmapping and image_transport packages.

Package/Stack Documentation

Linking to Trac Tickets

The TracLink macro lets you link into Trac tickets so that visitors can easily file tickets, e.g.:

<<TracLink(ros-pkg geometry)>> 

Expands to: <<TracLink(ros-pkg geometry)>>

Thirdparty Packages

Thirdparty ROS Packages need documentation too. It is customary to include a "External Documentation" section, like the one below, so that users can quickly see that they should go elsewhere for proper documentation.

=== External Documentation ===
This is a third party package with [[http://www.continuousphysics.com/Bullet/BulletFull/index.html|external documentation]].

Files

Filenames

Filenames are monospace. In general, it's a good idea to specify filenames relative to the package they are in, e.g. roslaunch/example.launch.

Using external editors

If you do any significant amount of wiki editing, you will grow to hate the in-browser text box. Do yourself a favor and use your favorite text editor instead.

The simplest approach is to copy the text box content to your editor, make your changes, and copy back. Depending on your preferred browser, you may be able to streamline this:

Emacs

Follow the instructions at http://moinmo.in/EmacsForMoinMoin to install the handy MoinMoin editing mode. Make sure to install both moinmoin-mode.el and screen-lines.el.

If using It's All Text!, add .wiki in the “File Extensions” list in the preferences setting dialog. Then you can right-click the edit button and choose “Edit as '.wiki'”.

Vim

See http://moinmo.in/VimHighlighting.

Wiki: StyleGuide (last edited 2015-05-02 18:54:26 by DirkThomas)