From 417f9fde3e67332811a8021e82b5d5ce144385a1 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 28 Jan 2019 07:53:02 -0800 Subject: [PATCH] [RST-1476] Added API docs for the Variable class (#36) * Added API docs for the Variable class --- README.md | 18 +- doc/Variables.md | 373 +++++++++++++++++++++++++ doc/variables-common_property.png | Bin 0 -> 9263 bytes doc/variables-multiple_occurrences.png | Bin 0 -> 10480 bytes doc/variables-time_series.png | Bin 0 -> 24228 bytes 5 files changed, 388 insertions(+), 3 deletions(-) create mode 100644 doc/Variables.md create mode 100644 doc/variables-common_property.png create mode 100644 doc/variables-multiple_occurrences.png create mode 100644 doc/variables-time_series.png diff --git a/README.md b/README.md index 07dca0d10..735004fab 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,13 @@ # fuse + The fuse stack provides a general architecture for performing sensor fusion live on a robot. Some possible applications include state estimation, localization, mapping, and calibration. ## Overview + fuse is a ROS framework for performing sensor fusion using nonlinear least squares optimization techniques. In particular, fuse provides: + * a plugin-based system for modeling sensor measurements * a similar plugin-based system for motion models * a plugin-based system for publishing optimized state values @@ -14,8 +17,8 @@ particular, fuse provides: (unpresented) ROSCon 2018 Lightning Talk [slides](doc/fuse_lightning_talk.pdf) - Data flows through the system approximately like this: + * A sensor model receives raw sensor data. The sensor model generates a constraint and sends it to the optimizer. * The optimizer receives the new sensor constraint. A request is sent to each configured motion model to generate a constraint between the previous state and the new state involved in the sensor constraint. @@ -36,6 +39,7 @@ publishing of data to the ROS topic. ![fuse sequence diagram](doc/fuse_sequence_diagram.png) ## Example + Let's consider a simple robotics example to illustrate this. Assume we have a typical indoor differential-drive robot. This robot has wheel encoders and a horizontal laser. @@ -145,17 +149,25 @@ plot how the wheel diameter changes over the length of the race. Now our system estimates the wheel diameters at each time step as well as the robot's pose. ## The Math + Internally `fuse` uses Google's [Ceres Solver](http://ceres-solver.org) to perform the nonlinear least squares optimization, which produces the optimal state variable values. I direct any interested parties to the Ceres Solver ["Non-linear Least Squares"](http://ceres-solver.org/nnls_tutorial.html) tutorial for an excellent primer on the core concepts and involved math. ## Summary + The purpose of `fuse` is to provide a framework for performing sensor fusion tasks, allowing common components to be reused between systems, while also allowing components to be customized for different use cases. The goal is to allow end users to concentrate on modelling the robot, sensor, system, etc. and spend less time wiring the different sensor models together into runable code. And since all of the models are implemented as plugins, separate plugin libraries can be shared or kept private at the discretion of their authors. -## API -Class API details coming soon... +## API Concepts + +* [Variables](doc/Variables.md) +* Constraints -- coming soon +* Sensor Models -- coming soon +* Motion Models -- coming soon +* Publishers -- coming soon +* Optimizers -- coming soon diff --git a/doc/Variables.md b/doc/Variables.md new file mode 100644 index 000000000..4d533365d --- /dev/null +++ b/doc/Variables.md @@ -0,0 +1,373 @@ +# Variables + +In the fuse stack, a Variable does two things: + +## Variable Value + +First, a Variable has a _value_. A Variable holds one or more dimensions of floating point data that represents some +physical or logical property. For example, a two dimensional pose consists of `x`, `y`, and `yaw` floating point +values. A single Variable class could be implemented to hold all three pose dimensions. The exact value of each +dimension will be unknown and uncertain. It is the job of an Optimizer to find the most likely value of each dimension +held by each Variable instance in the system. + +## Variable Identity + +Second, a Variable must have an _identity_, some way of distinguishing one occurrence of a Variable from another within +the system. There are several reasons multiple identities of a Variable will be contained within a single system: + +* The Variable may represent a property common to multiple entity types. Both a robot and a visual landmark have a + position in space. Different identities of the same Variable may be used to describe these different entities. + ![common property](variables-common_property.png) +* Similarly, there may be multiple occurrences of the same entity type within the system. A multi-robot configuration + will want to track the pose of each robot, and thus different identities of a Variable will be used for each robot + in the system. + ![multiple occurrences](variables-multiple_occurrences.png) +* Most commonly, a Variable will represent a time-varying process. A different identity will be required for each + time instant for which the process value is to be estimated. For example, the pose of the robot will change over + time, so we need a unique identity representing the robot pose at time `t1` **and** another unique identity + representing the robot pose at time `t2`. Any time-varying process must be discretized within the fuse stack. + ![time series](variables-time_series.png) + +The identity takes the form of a UUID or hash, and is generally derived from a set of additional properties that +describe what makes each occurrence unique from other occurrences. In the case of a time-varying process, this will +likely involve the timestamp. In the case of a Variable that can describe multiple robots, this might involve the +serial number of the robot. + +An important aspect of the identity is that the same UUID must be generated when the same identity is referenced +from different places in the distributed fuse stack. For example, a robot may estimate its pose at a specific time +using wheel odometry measurements, and it may estimate its pose at the same time instant using some laserscan +matching algorithm. Both measurements involve the same identity: the pose of robot `R` measured at time `t`, and +thus both sensors must generate a Variable instance with the same identity. + +## Design Principles + +The most important consideration when creating a new Variable is deciding what data dimensions should be +included. Including too many physical properties in a Variable will be inefficient and cumbersome when used in +places where most of the dimensions are unused. However, including too few physical properties in a Variable +also leads to inefficient and cumbersome usage when even the simplest of observation models involve many variables. +This is one of those "Goldilocks principle" situations. + +![Goldilocks principle](http://home.netcom.com/~swansont_2/goldilocks.jpg) + +Understanding how Variable interact with the rest of the system will help in the design of "good" Variable. + +* The fuse stack is designed to combine observations _of the same variable identity_ from multiple sources. As + described above, if a robot measures its current pose using wheel odometry as well as with a laserscan, then we have + two different measurements of the same pose. In order for these two measurements to be combined together in fuse, + **they must use the same Variable class**. In a way, the Variables are analogous to message definitions in ROS. + Much of the power of ROS comes from the use of common message types across the ROS ecosystem. While it is possible + for someone to define a custom laserscan message that matches their use-case exactly, no other existing code would + be compatible with that custom laserscan message. You would be unable to use the laser filters package, or visualize + the laser data in RViz. Whenever possible, it is preferred to reused existing messages, even if they are not a + perfect fit. Similarly, because the fuse Variable class must match exactly to be combined together, it is always + better to reuse existing Variables. +* A measurement can involve multiple Variable instances and multiple Variable classes. For example, a measurement could + involve both a 2D pose **and** a 2D velocity. This allows a system with a large number of measured dimensions to be + broken up into smaller, more reusable Variables. It may be tempting to break down the state in single-dimension + quantities; e.g. `x` is one Variable, `y` is a second Variable, etc. This would allow the most possible + Variable reuse, after all. However, it also means that certain kinds of measurements will involve an annoyingly + large number of inputs. For example, a 3D inertial strapdown sensor estimates the change in the 3D pose, + 3D velocity, and 3D linear acceleration. This involves a total of 15 dimensions of data measured at two different + timestamps. If every dimension is its Variable, such a measurement would require 30 inputs, making + it very awkward to write. +* Conversely, a Variable could be defined that contains all the measured dimensions of your system. In the 3D inertial + strapdown case, this would a 15-dimensional vector representing the 3D pose, 3D velocity, and 3D linear acceleration + at a specific timestamp. However, this means that every sensor must consume all 15 dimensions and define the error + function in terms of all 15 dimensions, even if the sensor only measures a small subset of those dimensions. At best, + this is inconvenient. It will also limit your ability to reuse sensor models from external sources, unless the + external source happened to use that exact same 15-dimensional Variable. +* For the purposes of efficient sparse matrix operations, all of the dimensions of a variable are treated as a group. + If there are too many dimensions in a Variable, resulting in measurements errors with large numbers of zeros, + then that sparsity information is lost. This can lead to performing dense matrix operations on larger-than-needed + blocks, and to suboptimal solving orders. If there are too few dimensions in a Variable, then computation will + be wasted computing the solving order over each dimension instead of each block. + +For the most part, reasonable Variables will be fairly obvious: 2D position, 2D velocity, 2D acceleration, etc. +The biggest debate is generally whether to include the linear and angular information into a single Variable (e.g. +a 2D pose consists of a 2D position and 2D orientation), or the if they should be separate. For fuse, it was decided +to keep the linear and angular components separate. The [`fuse_variables`](fuse_variables) package provides a set +of common, reusable 2D and 3D Variables. And submissions of new Variables are always welcome. + +## Variable API + +Like basically everything in fuse, the Variable system is designed to be extensible. The +[`fuse_core::Variable`](fuse_core/include/fuse_core/variable.h) base class defines the minimum interface required +for all derived Variables. + +* `Derived::type() -> std::string` + + All derived Variables must implement a `type()` method that returns the fully-qualified class name. This is of the + form `namespace::ClassName`. Under most circumstances, the base class implementation will return the correct class + name. However, templated Variables may need to override the `type()` method to return the desired name. + +* `Derived::size() -> size_t` + + The derived Variable must return the number of dimensions of its value. This will likely just return a fixed + constant. + +* `Derived::data() -> double*` + + The value portion of the derived Variable must be accessible from a contiguous memory location of size + `derived.size() * sizeof(double)`. + +* `Derived::uuid() -> fuse_core::UUID` + + Each derived class is required to return a unique ID to act as the identity of the Variable. Some functions for + generating UUIDs are provided [here](fuse_core/include/fuse_core/uuid.h). + +* `Derived::print(std::ostream& stream)` + + It's nice to be able to print important information during debugging. Each derived Variable is required to + implement a `print()` method, but the details of exactly what to print are left to the derived Variable class + designer. At a minimum, the Variable `type()` and `uuid()` is suggested. + +* `Derived::clone() -> fuse_core::Variable::UniquePtr` + + All derived Variables are required to implement a `clone()` method. This should be implemented as + `return Derived::make_unique(*this)`. Because this definition requires the use of the derived type, a common + implementation could not be provided in the base class. + +* `Derived::localParameterization() -> ceres::LocalParameterization*` + + This is a complex topic on its own. See the + [Ceres documentation](http://ceres-solver.org/nnls_modeling.html#localparameterization) for an in-depth discussion + of "local parameterizations" and their uses. If the derived Variable requires a local parameterization, this + method may be overridden to provide it. + +* `SMART_PTR_DEFINITIONS(Derived);` + + It is highly recommended that all derived Variables include `SMART_PTR_DEFINITIONS(Derived);` in the public + interface. This defines some common smart pointer aliases, such as `Derived::SharedPtr` and `Derived::UniquePtr`. + +Additional member properties and member functions may be added to the derived Variable. These can only be used +when an object is created with a known type. Despite this limitation, providing some syntax sugar is encouraged, as +it can make working with the derived Variable objects more satisfying. For example, `fuse_variables` classes provide +named accessors for the individual dimension values. This allows use of `var.y()` in lieu of `var.data()[1]`. + +## Example + +As a concrete example, we will review the details of `Position2dStamped` Variable class provided in the +[`fuse_variables`](fuse_variables) package. For illustrative purposes, some class hierarchies present in the actual +code have been collapsed in the code sample below. + +```C++ +class Position2DStamped : public fuse_core::Variable +{ +protected: + std::array data_; + fuse_core::UUID device_id_; + ros::Time stamp_; + fuse_core::UUID uuid_; + +public: + SMART_PTR_DEFINITIONS(Position2DStamped); + + explicit Position2DStamped(const ros::Time& stamp, const fuse_core::UUID& device_id) : + data{}, + device_id_(device_id), + stamp_(stamp), + uuid_(fuse_core::uuid::generate(type(), stamp, device_id)) + {} + + size_t size() const override { return data_.size(); } + + const double* data() const override { return data_.data(); } + double* data() override { return data_.data(); } + + fuse_core::UUID uuid() const override { return uuid_; } + + void print(std::ostream& stream = std::cout) const override + { + stream << type() << ":\n" + << " uuid: " << uuid() << "\n" + << " stamp: " << stamp() << "\n" + << " device_id: " << deviceId() << "\n" + << " size: " << size() << "\n" + << " data:\n" + << " - x: " << data_[0] << "\n" + << " - y: " << data_[1] << "\n"; + } + + fuse_core::Variable::UniquePtr clone() const override + { + return Position2DStamped::make_unique(*this); + } + + const ros::Time& deviceId() const { return device_id_; } + const ros::Time& stamp() const { return stamp_; } + + double& x() { return data_[0]; } + const double& x() const { return data_[0]; } + double& y() { return data_[1]; } + const double& y() const { return data_[1]; } +}; +``` + +Now let's examine the class details step by step. + +All new Variables must derive from the fuse_core::Variable base class. + +```C++ +class Position2DStamped : public fuse_core::Variable +``` + +We need to define to define a contiguous memory location to hold the Variable's value. This is a 2D position +variable, so there are two data dimensions: `x` and `y`. There are several obvious options: a simple C-style array +`double[2]`, a variable-sized `std::vector` that we resize appropriately, or a C++-style fixed-size array +`std::array`. Here we choose the C++-style array so we look "modern". + +```C++ +protected: + std::array data_; +``` + +Our Variable also needs to hold the identity information. For this Variable we want to support both multi-robot +scenarios as well as time-varying processes, so we need some sort of "robot id" and a timestamp. Since this is a +ROS library, we will use a `ros::Time` to hold the timestamp. And we will choose a `fuse_core::UUID` to act as a +generic "robot id". fuse ships with several functions for converting strings and other types into a UUID +([UUID functions](fuse_core/include/fuse_core/uuid.h)), so this choice should support most use-cases. + +```C++ +protected: + fuse_core::UUID device_id_; + ros::Time stamp_; +``` + +fuse expects the identity portion of the Variable to be distilled into a `fuse_core::UUID` value. We choose to make +the Variable identity immutable so that the UUID may be computed once on construction. This allows us to cache the +UUID as a class member variable. + +```C++ +protected: + fuse_core::UUID uuid_; +``` + +As a consequence, when we construct a Position2DStamped instance, we must specify the `stamp` and `device_id`. After +construction, these values cannot be changed. + +```C++ +public: + explicit Position2DStamped(const ros::Time& stamp, const fuse_core::UUID& device_id) : + data{}, + device_id_(device_id), + stamp_(stamp), + uuid_(fuse_core::uuid::generate(type(), stamp, device_id)) + {} +``` + +Specifically note the function call: + +```C++ +fuse_core::uuid::generate(type(), stamp, device_id) +``` + +Here we are constructing the identity UUID from the type name itself, the value of `stamp` and the value of +`device_id`. Every Position2DStamped constructed with the same `stamp` and `device_id` value will generate the same +identity UUID. + +And now for some less interesting things: + +```C++ +size_t size() const override { return data_.size(); } +``` + +The `fuse_core::Variable` interface requires read-only access to the number of dimensions of this Variable. Here, the +container's `size()` method is used. We could have also just `return 2;`. + +```C++ +const double* data() const override { return data_.data(); } +double* data() override { return data_.data(); } +``` + +The `fuse_core::Variable` interface requires read-write access to the data array via a C-style pointer, an artifact of +using Google Ceres under the hood for optimization. Again, we can use the built-in methods of our data container to +implement this requirement. And we provide both read-only and read-write versions to support proper const-correctness +in the surrounding code. + +```C++ +fuse_core::UUID uuid() const override { return uuid_; } +``` + +The `fuse_core::Variable` interface requires read-only access to the identity UUID value. Since we computed the UUID +during construction, we can just return our cached copy. + +```C++ +void print(std::ostream& stream = std::cout) const override +{ + stream << type() << ":\n" + << " uuid: " << uuid_ << "\n" + << " stamp: " << stamp_ << "\n" + << " device_id: " << device_id_ << "\n" + << " size: " << data_.size() << "\n" + << " data:\n" + << " - x: " << data_[0] << "\n" + << " - y: " << data_[1] << "\n"; +} +``` + +We are required to implement a `print()` function as well. Here we print all the relevant properties to the provided +stream. The base class implements the C++ stream operator in terms of the polymorphic `print()` function, so variables +can be streamed to `std::cout` as well. + +```C++ +fuse_core::Variable::UniquePtr clone() const override +{ + return Position2DStamped::make_unique(*this); +} +``` + +And finally a `clone()` method is required. Here we implement `clone()` exactly as suggested in the +`fuse_core::Variable` documentation. + +There are two method implementations inherited from the `fuse_core::Variable` base class. + +```C++ +std::string type() const { return boost::core::demangle(typeid(*this).name()); } +``` + +The base class implementation is smart enough to return the correct `fuse_variables::Position2dStamped` type string +here, so we don't need to reimplement the `type()` method. + +And our "position" type behaves linearly, so there is no need to use a "local parameterization" inside the optimizer. + +```C++ +virtual ceres::LocalParameterization* localParameterization() const +{ + return nullptr; +} +``` + +Local parameterizations allow updating the dimensions of a Variable in a nonlinear way, in case the Variable describes +some sort of nonlinear manifold. It also allows a Variable to represent a lower degree-of-freedom property to be +embedded in a higher dimensional space. The classic example is a 3D rotation; a change in one of the rotation +dimensions can affect the values of all three rotation dimensions (i.e. it has a nonlinear update), and its 3 dof are +represented as a 4-dof quaternion. See the +[Ceres documentation](http://ceres-solver.org/nnls_modeling.html#localparameterization) for more information. + +And finally we reach the recommended but optional implementation details. + +```C++ +public: + SMART_PTR_DEFINITIONS(Position2DStamped); +``` + +Calling the `SMART_PTR_DEFINITIONS` macro inside the `public` region of the derived Variable is not strictly required, +but it is very strongly recommended. This creates some standard aliases for variable smart pointer types, e.g. +`Position2dStamped::SharedPtr` and `Position2dStamped::UniquePtr` as well as a some smart pointer creation functions, +e.g.`Position2dStamped::make_shared()` and `Position2dStamped::make_unique()`. + +```C++ +const ros::Time& deviceId() const { return device_id_; } +const ros::Time& stamp() const { return stamp_; } +``` + +Providing accessor functions for the identity information, not just the identity UUID, is also recommended. + +```C++ +double& x() { return data_[0]; } +const double& x() const { return data_[0]; } +double& y() { return data_[1]; } +const double& y() const { return data_[1]; } +``` + +And providing named accessors to the different dimensions is some nice syntax sugar. diff --git a/doc/variables-common_property.png b/doc/variables-common_property.png new file mode 100644 index 0000000000000000000000000000000000000000..3c743703134d1796e7b28fef5ce9d71ae9db6005 GIT binary patch literal 9263 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 NqO7t^k(6=Z{{Xau@ACiv literal 0 HcmV?d00001 diff --git a/doc/variables-time_series.png b/doc/variables-time_series.png new file mode 100644 index 0000000000000000000000000000000000000000..6af6d6c1853f6d30ff36ce56f3b9b68641a0793b GIT binary patch literal 24228 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