Class Variable

Class Documentation

class Variable

The Variable interface definition.

A Variable defines some semantically meaningful group of one or more individual scale values. Each variable is treated as a block by the optimization engine, as the values of all of its dimensions are likely to be involved in the same constraints. Some common examples of variable groupings are a 2D point (x, y), 3D point (x, y, z), or camera calibration parameters (fx, fy, cx, cy).

To support the Ceres optimization engine, the Variable must hold the scalar values of each dimension in a contiguous memory space, and must provide access to that memory location via the Variable::data() methods.

Some Variables may require special update rules, either because they are over-parameterized, as is the case with 3D rotations represented as quaternions, or because the update of the individual dimensions exhibit some nonlinear properties, as is the case with rotations in general (e.g. 2D rotations have a discontinuity around ). To support these situations, Ceres uses an optional “local parameterization”. See the Ceres documentation for more details. http://ceres-solver.org/nnls_modeling.html#localparameterization

Public Functions

Variable() = default

Default constructor.

explicit Variable(const UUID &uuid)

Constructor.

The implemented UUID generation should be deterministic such that a variable with the same metadata will always return the same UUID. Identical UUIDs produced by sensors will be treated as the same variable by the optimizer, and different UUIDs will be treated as different variables. So, two derived variables representing robot poses with the same timestamp but different UUIDs will incorrectly be treated as different variables, and two robot poses with different timestamps but the same UUID will be incorrectly treated as the same variable.

One method of producing UUIDs that adhere to this requirement is to use the boost::uuid::name_generator() function. The type() string can be used to generate a UUID namespace for all variables of a given derived type, and the variable metadata of consequence can be converted into a carefully-formatted string or byte array and provided to the generator to create the UUID for a specific variable instance.

Parameters:

uuid[in] The unique ID number for this variable

virtual ~Variable() = default

Destructor.

inline const UUID &uuid() const

Returns a UUID for this variable.

virtual std::string type() const = 0

Returns a unique name for this variable type.

The variable type string must be unique for each class. As such, the fully-qualified class name is an excellent choice for the type string.

The suggested implementation for all derived classes is:

return return boost::typeindex::stl_type_index::type_id<Derived>().pretty_name();

To make this easy to implement in all derived classes, the FUSE_VARIABLE_TYPE_DEFINITION() and FUSE_VARIABLE_DEFINITIONS() macro functions have been provided.

virtual size_t size() const = 0

Returns the number of elements of this variable.

In most cases, this will be the number of degrees of freedom this variable represents. For example, a 2D pose has an x, y, and theta value, so the size will be 3. A notable exception is a 3D rotation represented as a quaternion. It only has 3 degrees of freedom, but it is represented as four elements, (w, x, y, z), so it’s size will be 4.

inline virtual size_t localSize() const

Returns the number of elements of the local parameterization space.

If you override the localParameterization() method, it is good practice to also override the localSize() method. By default, the size() method is used for localSize() as well.

virtual const double *data() const = 0

Read-only access to the variable data.

The data elements must be contiguous (such as a C-style array double[3] or std::vector<double>), and it must contain at least Variable::size() elements. Only Variable::size() elements will be accessed externally. This interface is provided for integration with Ceres, which uses raw pointers.

virtual double *data() = 0

Read-write access to the variable data.

The data elements must be contiguous (such as a C-style array double[3] or std::vector<double>), and it must contain at least Variable::size() elements. Only Variable::size() elements will be accessed externally. This interface is provided for integration with Ceres, which uses raw pointers.

virtual void print(std::ostream &stream = std::cout) const = 0

Print a human-readable description of the variable to the provided stream.

Parameters:

stream[out] The stream to write to. Defaults to stdout.

virtual Variable::UniquePtr clone() const = 0

Perform a deep copy of the Variable and return a unique pointer to the copy.

Unique pointers can be implicitly upgraded to shared pointers if needed.

This can/should be implemented as follows in all derived classes:

return Derived::make_unique(*this);

To make this easy to implement in all derived classes, the FUSE_VARIABLE_CLONE_DEFINITION() and FUSE_VARIABLE_DEFINITIONS() macros functions have been provided.

Returns:

A unique pointer to a new instance of the most-derived Variable

inline virtual fuse_core::LocalParameterization *localParameterization() const

Create a new Ceres local parameterization object to apply to updates of this variable.

If a local parameterization is not needed, a null pointer should be returned. If a local parameterization is needed, remember to also override the localSize() method to return the appropriate local parameterization size.

The Ceres interface requires a raw pointer. Ceres will take ownership of the pointer and promises to properly delete the local parameterization when it is done. Additionally, fuse promises that the Variable object will outlive any generated local parameterization (i.e. the Ceres objects will be destroyed before the Variable objects). This guarantee may allow optimizations for the creation of the local parameterization objects.

Returns:

A base pointer to an instance of a derived LocalParameterization

inline virtual double lowerBound(size_t) const

Specifies the lower bound value of each variable dimension.

Defaults to -max.

Parameters:

index[in] The variable dimension of interest (not used in base class)

Returns:

The lower bound for the requested variable dimension

inline virtual double upperBound(size_t) const

Specifies the upper bound value of each variable dimension.

Defaults to +max.

Parameters:

index[in] The variable dimension of interest (not used in base class)

Returns:

The upper bound for the requested variable dimension

inline virtual bool holdConstant() const

Specifies if the value of the variable should not be changed during optimization.

virtual void serialize(fuse_core::BinaryOutputArchive&) const = 0

Serialize this Variable into the provided binary archive.

This can/should be implemented as follows in all derived classes:

archive << *this;

Parameters:

archive[out] - The archive to serialize this variable into

virtual void serialize(fuse_core::TextOutputArchive&) const = 0

Serialize this Variable into the provided text archive.

This can/should be implemented as follows in all derived classes:

archive << *this;

Parameters:

archive[out] - The archive to serialize this variable into

virtual void deserialize(fuse_core::BinaryInputArchive&) = 0

Deserialize data from the provided binary archive into this Variable.

This can/should be implemented as follows in all derived classes:

archive >> *this;

Parameters:

archive[in] - The archive holding serialized Variable data

virtual void deserialize(fuse_core::TextInputArchive&) = 0

Deserialize data from the provided text archive into this Variable.

This can/should be implemented as follows in all derived classes:

archive >> *this;

Parameters:

archive[in] - The archive holding serialized Variable data

Friends

friend class boost::serialization::access