wiki:WikiStart/Standards/RG3

NOTE The base methods base::nan<>() and base::infinity<>() will be added to base/types if this proposal gets accepted

This details the acceptable semantics of NaN and Infinity as special values in oroGen interfaces and/or C++ libraries

Floating-point values (float and double in C++) have two "special" values: Not A Number (NaN) and Infinity. This page details the accepted semantic, in Rock, of these special values across component boundaries.

Unset parameters

NaN can be used in configuration data structures to represent that a special parameter has not been set. In C++ for a float parameter, this is done with

#include <base/float.h>
config.value = base::unset<float>();

If you do not want to add a dependency to base/types, use the standard C++ method (rock uses quiet_nan())

#include <limits>
config.value = std::numeric_limits<float>::quiet_nan();

A not-set value can be interpreted in two ways:

  • as an error (if the caller should set this particular value)
  • as a way to disable some part of the functionality.

It can be tested with

#include <float.h>
if (base::isUnset(config.value))
  // generate an error

Note that one CANNOT use if (config.value == base::unset()) as, in IEEE 754, NaN != NaN

It must NOT be interpreted as a "use default value" indicator. If a sane default value exists, it should be used instead of NaN.

Unknown values

On data structures that do not represent uncertainty, NaN can be used to represent unknown values. For instance, a 3-vector of

base::Vector3d v(0, 0, base::unknown<double>())

can be used to represent a position that is known in X, Y but completely unknown in Z. It can then be tested with

if (base::isUnknown(v.x()))
  // generate an error

On data structures that represent uncertainty, the unknown is not represented can be set in two ways:

  • in e.g. in information filters, the value of zero is used to represent no information
  • in e.g. covariance matrix representations, no information is represented as infinity
#include <base/float.hpp>
covariance(3, 2) = base::infinity<double>();

If you do not want to add a dependency to base/types, use the standard C++ method:

#include <limits>
covariance(3, 2) = std::numeric_limits<double>::infinity();

Even though one can test against infinity, for consistency reasons, testing should be done using base::isInfinity(v)

It is encouraged for such types to have some invalidation / validity test methods. For instance, RigidBodyState offers the invalidate(), invalidatePosition(), invalidateOrientation() methods to resp. set all covariance values to infinity, the position covariance to infinity and/or the orientation covariance to infinity. The corresponding test methods hasValidPosition() and hasValidOrientation() allows then to test if some information is present in these fields.

In Ruby

In the Typelib/Ruby bindings, i.e. when interacting with log data and/or live orocos components, one can set floating-point values to Infinity and NaN in the following way:

config.value = Infinity
covariance.data[5] = NaN

I.e. infinity is mapped to the Infinity toplevel constant, while NaN is mapped to the NaN constant.

For consistency reasons, the base/types_ruby package also defines the following:

require 'base/float'
Base::infinity()
Base::infinity?(v)
Base::unset()
Base::unset?(v)
Base::unknown()
Base::unknown?(v)
Last modified 8 years ago Last modified on 08/05/11 14:57:49