DCCL v4
|
DCCL uses the Google Protocol Buffers (Protobuf) language to define messages. The DCCL IDL is defined as extensions to the Protobuf language message and field options to allow more compact encoding than is possible with the default Protobuf meta-data. You should familiarize yourself with basic Protobuf usage before reading the rest of this document: see http://code.google.com/apis/protocolbuffers/docs/overview.html.
An example DCCL message is as follows:
In the above message, the snippet
represents the message options extensions since they affect the design of the entire DCCL message (in this case "NavigationReport"). The field options affect a given field, e.g.
The full Protobuf definition of the DCCL extensions is given in option_extensions.proto (as messages DCCLFieldOptions and DCCLMessageOptions).
The core set of DCCL options is given in the following table:
The DCCL ID is used to uniquely identify a given message name without having to encode the name in the message (encoding a number is much cheaper than a string). To interoperate with other groups, please see http://gobysoft.org/wiki/DcclIdTable. For private work, please use IDs 124-127 (one-byte) and 128-255 (two-byte).
This value is the maximum message size before you get an error from DCCL. This is a design tool to help ensure messages do not exceed a desired value, typically the path maximum transmission unit (MTU). Messages that do not take the actual max_bytes size are encoded only as the size they take up (i.e. they are not padded to max_bytes).
This option sets the default codec version (which is not wire-compatibility between Goby/DCCL 2, DCCL 3, and DCCL 4). This should always be set to "4" when you are able to use DCCL v4 for all nodes that deploy this message, or an earlier version if required (e.g., if one of the nodes has access only to DCCL3, use "3").
Since the DCCL field bounds (min, max, and precision) are often based off the physical origins of the data, it is important to define the units of measure of those fields. The DCCL IDL has support for defining the units of a numeric field's quantity. When using the DCCL C++ library, this support is directly connected to the Boost Units C++ library: http://www.boost.org/doc/html/boost_units.html. The units of a given field are given by two parameters: the physical dimension (e.g. length, force, mass, etc.), and the unit system which defaults to the International System of Units (SI). The units of the field can also be specified directly, outside of a canonical system (e.g. nautical mile, fathom, yard, knot, etc.).
The fields defined with units generate additional C++ methods using the DCCL plugin (protoc-gen-dccl) to the GPB compiler (protoc). The Debian package for the plugin is
These additional methods provide accessors and mutators for the dimensioned Boost Units quantities, with full static "unit safety", and correct conversions between different units of the same dimensions (e.g. feet to meters). Unit safety is defined as static (compiler-checked) dimensional analysis. The term is a blending of the (computer science) notion of type safety with (physical) dimensional analysis. For example, in a unit-safe system, the compiler will not allow the user to set a field with dimensions of length to a quantity of hours.
The Units field extension has the following options:
base_dimensions
(string): Specifies the dimensions of the field as a combination of powers of the base dimensions given in Table 3. For example, acceleration would be defined as "LT^-2"
. derived_dimensions
(string): As a convenience alternative to the base_dimensions
specification, any of the Boost Units "derived dimensions" can be used. For example instead of base_dimensions:
"L^-1 M T^-2"
for pressure, one can use derived_dimensions: "pressure"
. Multiplication and division of derived dimensions is also supported using the "*" and "/" operators. The available derived dimensions are those listed here: http://www.boost.org/doc/html/boost_units/Reference.html#dimensions_reference. The string to use here is the name of the dimension as given in Boost Units, minus the "_dimension". For example to use boost::units::acceleration_dimension, specify "acceleration" in this field. system
(string, defaults to "si"): A boost::units or user-defined system of units to use for this field. Defaults to the SI system with base units of kelvin (temperature), second (time), meter (length), kilogram (mass), candela (luminous intensity), mole (amount of substance) and ampere (electric current). The available Boost Units systems include: relative_temperature
(bool, defaults to false): A special extension only used for temperature fields. Setting this to true means that the temperature is relative (i.e. a difference of absolute temperatures) instead of an absolute temperature. This matters to support correct unit conversions between different temperature systems. For example, relative degrees Kelvin are the same as relative degrees Celsius, but the absolute scales differ by 273.15 degrees. unit
(string): As an alternative to the dimensions
and system
specification, the field can be set to use particular (typically non-SI) units. A few examples of such units that are still often encountered in the marine domain are unit:
"metric::nautical_mile"
, unit:
"metric::bar"
, and unit:
"us::yard"
. Here you can use any of the Boost Units Base Unit types, given here: http://www.boost.org/doc/html/boost_units/Reference.html#boost_units.Reference.base_units_by_category. The string to specify here is the Base Unit to use, minus the "boost::units::" prefix and the "_base_unit" suffix. For example, boost::units::metric::nautical_mile_base_unit
should be specified as "metric::nautical_mile" in this field. The DCCL Units C++ generated accessors and mutators mirror those provided by the standard Google Protocol Buffers compiler for numeric fields, with the method name appended by the string "_with_units". For the standard Protobuf generated code see https://developers.google.com/protocol-buffers/docs/reference/cpp-generated. DCCL Units are only valid on numeric fields (either singular or repeated). Two accessors are provided for convenience: a non-template accessor that returns the value as the Quantity (i.e. boost::units::quantity) defined in the DCCL field, and a template accessor that can take any valid Boost Units Quantity (i.e. a type with the same dimensions as the DCCL field) and return the value in that type, accounting for all conversion factors.
For a singular (optional or required) field "foo" with the following parameters:
the following additional methods are defined for unit safe access to the DCCL message:
For a repeated field "foo" with the following parameters:
the following additional methods are defined for unit safe access to the DCCL message:
Here are a few example DCCL messages which include unit specification:
For example, to set an AUVStatus message's x
and y
fields to meters (the default for the base dimension of length, since the default system is SI), and then later access them as nautical miles, one can use this C++ example:
The value of x_nm
is 0.54 nautical miles and y_nm
is 0.27 nautical miles.
Dynamic Conditions is a new feature in DCCL4 that allows for conditional encoding of the fields based on runtime conditions (values of other parts of the message). This feature allows you to omit a field, mark a field "required", or change the values of the min/max bounds based on the value of one or more fields in the message.
Each dynamic condition is a string that contains a script written in Lua (https://www.lua.org/) that is evaluated each time the message is encoded or decoded.
The available dynamic_conditions are:
Within the Lua script you are given access to some special variables set by DCCL:
For example, given the following message:
"this" and "root" refer to the contents of TestMsg.
However, given a different message:
Now within the context of field "i", "this" refers to Child, and "root" refers to TestMsg.
Since this is a common idiom and to reduce extra code, you can omit "return" if it is the first part of the Lua script. That is, these are identical:
If your script doesn't begin with "return" you must put it in explicitly:
The Lua Protobuf functionality uses this wonderful Github project: https://github.com/starwing/lua-protobuf. Please reference the documentation in the event you need more details about the "this" or "root" tables, which are built using this library.
For more details, and an example usage, see the dccl_dynamic_conditions unit test.