RoFI Configuration
Configuration is a way of representing any collection of RoFI Modules in an universal manner. It contains all building blocks of the RoFI platform such as various modules and joints.
Using these blocks, you can specify every RoFI world – a set of rofibots (connected set of RoFI modules fixed in space) – and work with it. Configuration computes positions of every component and provides useful functions for manipulation with the whole world, including some validity checks (e.g. collision checks).
Usage
The main class is RofiWorld
for which you create an instance
and add all the modules you want to have in the world.
You have to connect these modules together appropriately
to form individual rofibots.
If you want to use absolute positions, you have to fix
one of the components of each rofibot in space,
otherwise, the configuration cannot figure out its coordinates.
Example
Let us create a world with a single bot consisted of two universal modules.
#include <configuration/rofiworld.hpp>
// ...
RofiWorld world;
// add universal module with id 42 in the default state
auto& m1 = world.insert( UniversalModule( 42, 0_deg, 0_deg, 0_deg ) );
// add universal module with id 42 with beta set to 45 degrees and gamma to 90 degrees
auto& m2 = world.insert( UniversalModule( 66, 0_deg, 45_deg, 90_deg ) );
// connect A+X of the universal module with id = 42 to A-X of UM with id = 66
connect( m1.connectors()[ 2 ], m2.connectors()[ 0 ], Orientation::North );
// fix the position of the `shoe A` in { 0, 0, 0 }
connect< RigidJoint >( m1.bodies()[ 0 ], { 0, 0, 0 }, identity );
With the world in hand, you can then prepare it (i.e. compute positions of each part – rofibot – of the world) and check for its validity.
if ( auto prepared = world.prepare(); !prepared )
std::cerr << "Could not prepare configuration: " << prepared.assume_error() << "\n";
if ( auto valid = world.isValid( SimpleCollision() ); !valid )
std::cerr << "Invalid configuration: " << valid.assume_error() << "\n";
// or you can shorten the above to
auto ok = world.validate( SimpleCollision() );
// also, the SimpleCollision model is the default one, so you can ommit it too and get
auto ok = world.validate();
Types and Constants
-
using rofi::configuration::ModuleId = int
ModuleId.
-
enum class rofi::configuration::ComponentType
Values:
-
enumerator Roficom
-
enumerator UmBody
-
enumerator UmShoe
-
enumerator CubeBody
-
enumerator Roficom
Classes
-
class RofiWorld
RoFI world.
The RofiWorld is composed out of modules.
Public Types
-
using RoficomJointHandle = atoms::HandleSet<RoficomJoint>::handle_type
-
using SpaceJointHandle = atoms::HandleSet<SpaceJoint>::handle_type
Public Functions
-
RofiWorld() = default
-
inline Module &insert(const Module &m)
Insert a module from the RofiWorld
The module position is not specified. You should connect the module to other modules via connect(). The module is assigned a unique id within the world.
- Throws
std::logic_error – if module with the same ID is already present
- Returns
reference to the newly created module.
-
template<std::derived_from<Module> ModuleT>
inline ModuleT &insert(const ModuleT &m) Insert a module from the RofiWorld
The module position is not specified. You should connect the module to other modules via connect(). The module is assigned a unique id within the world.
- Returns
reference to the newly created module.
-
inline Module *getModule(ModuleId id) const
Get pointer to module with given id within the RofiWorld.
-
inline Module *getModule(ModuleInfoHandle h) const
Get pointer to module with given id within the RofiWorld.
-
inline auto modules() const -> std::ranges::range auto
Get a range of modules.
-
inline auto modules() -> std::ranges::range auto
Get a range of modules.
-
inline auto modulesWithAbsPos() const -> std::ranges::range auto
Get a range of modules with their absolute positions.
this
has to be prepared.
-
inline const auto &roficomConnections() const
Get a container of RoficomJoint.
-
inline const auto &referencePoints() const
-
inline bool isPrepared() const
Return true if the configuration is prepared.
Configuration can be prepared with
prepare
.
-
inline atoms::Result<std::monostate> isValid(const Collision &collisionModel = SimpleCollision()) const
Decide whether the configuration is valid given the collision model.
- Returns
result - the error gives textual description of the reason for invalidity
-
inline atoms::Result<std::monostate> validate(const Collision &collisionModel = SimpleCollision())
Prepare configuration if needed and decide whether it is valid with given collision model.
- Returns
result - the error gives textual description of the reason for invalidity
-
atoms::Result<std::monostate> prepare()
Precompute position of all the modules in the configuration.
- Returns
result error if the configuration is inconsistent
-
void setSpaceJointPositions(SpaceJointHandle jointId, std::span<const float> p)
Set position of a space joints specified by its id.
-
inline Matrix getModulePosition(ModuleId id)
Get position of a module specified by its id.
- Throws
std::logic_error – if configuration is inconsistent or module with given ID doesn’t exist
-
void disconnect(RoficomJointHandle h)
-
void disconnect(SpaceJointHandle h)
-
using RoficomJointHandle = atoms::HandleSet<RoficomJoint>::handle_type
-
class Module
RoFI module.
The module is composed out of components.
Subclassed by rofi::configuration::Cube, rofi::configuration::Pad, rofi::configuration::UniversalModule, rofi::configuration::UnknownModule
Public Functions
-
inline Module(ModuleType type, std::vector<Component> components, int connectorCount, std::vector<ComponentJoint> joints, ModuleId id, std::optional<int> rootComponent = std::nullopt)
Construct module.
Note that components contain all module components out of which first
connectorCount
are module connectors.The user can optionally specify a root component (e.g, in case of cyclic joints). If no root component is specified, component with no ingoing joints is selected.
-
virtual ~Module() = default
-
bool setId(ModuleId newId)
Set ID of the module to the new value.
Checks if the new value is not used within its world, in which case the ID is changed to the new value. Otherwise the ID is left the same.
- Returns
whether the value was changed
-
void setJointPositions(int idx, std::span<const float> p)
-
atoms::Result<std::monostate> changeJointPositionsBy(int idx, std::span<float> diff)
Changes parameters of joint positions by values in <diff>.
Assumes <idx> is at most index of last joint in joint container. Assumes <diff> contains as many values as joint has parameters. If values from <diff> added to values of current parameters are not bounded by pairs of values in joint limits, function does not change the positions and does not clear component positions (configuration is still prepared).
- Parameters
idx – Joint index
diff – Span of values to be added to current parameters (can be negative).
- Returns
result_error if any of the resulting parameters does not respect corresponding joint limit.
-
inline Matrix getComponentRelativePosition(int idx)
Get a component position relative to module origin.
- Throws
std::logic_error – if the components are inconsistent
-
inline Matrix getComponentRelativePosition(int idx) const
Get a component position relative to module origin.
- Throws
std::logic_error – if the components are not prepared
-
void clearComponentPositions()
-
inline std::vector<Matrix> getOccupiedRelativePositions() const
Get a vector of occupied positions relative to module origin.
- Throws
std::logic_error – if the components are not prepared
-
inline atoms::Result<std::monostate> prepare()
Precompute component relative positions.
- Returns
result error if the components are inconsistent
-
inline auto configurableJoints()
-
inline auto configurableJoints() const
-
inline std::span<const ComponentJoint> joints() const
-
inline Module(ModuleType type, std::vector<Component> components, int connectorCount, std::vector<ComponentJoint> joints, ModuleId id, std::optional<int> rootComponent = std::nullopt)
-
struct Component
Single body of a module.
Public Types
-
using JointId = int
Public Functions
-
inline Component(ComponentType type, std::vector<JointId> inJoints, std::vector<JointId> outJoints, Module *parent = nullptr)
-
inline explicit Component(ComponentType type)
-
int getIndexInParent() const
Get the index of component in parent.
-
Matrix getPosition() const
Get the absolute component position.
- Throws
std::logic_error – if the world is not prepared
-
std::optional<std::pair<const Component&, roficom::Orientation>> getNearConnector() const
Find a connector of another module in the same RofiWorld.
that can be connected to
- Throws
std::logic_error – if the world is not prepared
- Returns
the connector and orientation
- Returns
nullopt
if no such connector exists
-
using JointId = int
-
struct Joint : public atoms::VisitableBase<Joint, JointVisitor>
Joint between two coordinate systems.
Joints represents a parametric description of positional relationship between two coordinate systems (e.g., component origins). This class in abstract. See below for concrete instances.
Each joint has Joint::paramCount() parameters (real value), which are stored in Joint::position. These params are, e.g., angle for rotation joint.
Subclassed by rofi::configuration::RoficomJoint
Public Functions
-
inline explicit Joint(std::vector<std::pair<float, float>> jointLimits)
-
virtual ~Joint() = default
-
inline std::span<const std::pair<float, float>> jointLimits() const
-
inline std::span<const float> positions() const
-
inline virtual void setPositions(std::span<const float> pos)
Sets joint settings to corresponding values given by <pos>.
Assumes there are exactly as many values as there are joint settings.
- Throws
std::logic_error – if the given settings do not respect joint limits.
-
inline virtual atoms::Result<std::monostate> changePositionsBy(std::span<const float> diff)
Changes each joint setting by the corresponding value in <diff>.
Assumes there are exactly as many values given as there are joint settings.
- Returns
result error if the resulting values do not respect joint limits.
-
virtual Matrix sourceToDest() const = 0
-
inline virtual Matrix destToSource() const
-
inline explicit Joint(std::vector<std::pair<float, float>> jointLimits)
-
struct RigidJoint : public atoms::Visitable<Joint, RigidJoint>
Public Functions
-
inline RigidJoint(const Matrix &sToDest)
Construct a rigid joint based on transformation between source and dest.
Example usage:
RigidJoint( rotate( M_PI/2, { 1, 0, 0, 1 } ) * translate( { 20, 0, 0 } ) )
-
inline Matrix sourceToDest() const override
-
inline Matrix destToSource() const override
-
ATOMS_CLONEABLE(RigidJoint)
-
inline RigidJoint(const Matrix &sToDest)
-
struct RotationJoint : public atoms::Visitable<Joint, RotationJoint>
Public Functions
-
inline RotationJoint(Vector sourceOrigin, Vector sourceAxis, Vector destOrigin, Vector desAxis, Angle min, Angle max)
Construct rotation joint by specifing the same axis and origin point in source coordinate system and destination coordinate system.
-
inline RotationJoint(Matrix pre, Vector axis, Matrix post, Angle min, Angle max)
Construct rotation joint by specifying transformation before rotation, followed by rotation axis with origin in (0, 0, 0), followed by another transformation.
-
inline Matrix sourceToDest() const override
-
inline Matrix destToSource() const override
-
inline Angle position() const
-
inline void setPosition(Angle pos)
-
inline std::pair<Angle, Angle> jointLimit() const
-
inline const Matrix pre() const
-
inline const Matrix post() const
-
inline const Vector axis() const
-
ATOMS_CLONEABLE(RotationJoint)
-
inline RotationJoint(Vector sourceOrigin, Vector sourceAxis, Vector destOrigin, Vector desAxis, Angle min, Angle max)
-
struct RoficomJoint : public rofi::configuration::Joint
Joint between two modules.
The joint is created between two components of two modules specified by module ids and corresponding component index.
Public Functions
-
inline RoficomJoint(roficom::Orientation o, RofiWorld::ModuleInfoHandle sourceModule, RofiWorld::ModuleInfoHandle destModule, int sourceConnector, int destConnector)
-
inline virtual Matrix sourceToDest() const override
-
ATOMS_CLONEABLE(RoficomJoint)
Public Members
-
roficom::Orientation orientation
-
RofiWorld::ModuleInfoHandle sourceModule
-
RofiWorld::ModuleInfoHandle destModule
-
int sourceConnector
-
int destConnector
-
inline RoficomJoint(roficom::Orientation o, RofiWorld::ModuleInfoHandle sourceModule, RofiWorld::ModuleInfoHandle destModule, int sourceConnector, int destConnector)
-
struct ComponentJoint
Joint between two components of the same module.
Public Functions
-
ComponentJoint(ComponentJoint&&) = default
-
ComponentJoint &operator=(ComponentJoint&&) = default
-
inline ComponentJoint(const ComponentJoint &o)
-
inline ComponentJoint &operator=(const ComponentJoint &o)
-
ComponentJoint(ComponentJoint&&) = default
-
struct SpaceJoint
Joint between a fixed point in space and a module.
Public Functions
-
inline SpaceJoint(atoms::ValuePtr<Joint> joint, Vector refPoint, RofiWorld::ModuleInfoHandle destModule, int destComponent)
-
SpaceJoint(SpaceJoint&&) = default
-
SpaceJoint &operator=(SpaceJoint&&) = default
-
inline SpaceJoint(const SpaceJoint &o)
-
inline SpaceJoint &operator=(const SpaceJoint &o)
-
inline SpaceJoint(atoms::ValuePtr<Joint> joint, Vector refPoint, RofiWorld::ModuleInfoHandle destModule, int destComponent)
-
class NoCollision : public rofi::configuration::Collision
Completely ignores any collisions.
-
class SimpleCollision : public rofi::configuration::Collision
Each module component takes up a unit sphere of space.
Module Classes
-
class UniversalModule : public rofi::configuration::Module
Public Functions
-
ATOMS_CLONEABLE(UniversalModule)
-
inline explicit UniversalModule(int id)
-
inline UniversalModule(int id, Angle a, Angle b, Angle g)
-
inline Angle getAlpha() const
-
inline Angle getBeta() const
-
inline Angle getGamma() const
-
inline void setAlpha(Angle a)
-
inline void setBeta(Angle a)
-
inline void setGamma(Angle a)
-
inline const auto &getConnector(std::string_view cStr) const
-
ATOMS_CLONEABLE(UniversalModule)
-
class UnknownModule : public rofi::configuration::Module
Public Functions
-
inline UnknownModule(std::vector<Component> components, int connectorCount, std::vector<ComponentJoint> joints, ModuleId id, std::optional<int> rootComponent = std::nullopt)
-
ATOMS_CLONEABLE(UnknownModule)
-
inline UnknownModule(std::vector<Component> components, int connectorCount, std::vector<ComponentJoint> joints, ModuleId id, std::optional<int> rootComponent = std::nullopt)
Functions
-
RofiWorld::RoficomJointHandle rofi::configuration::connect(const Component &c1, const Component &c2, roficom::Orientation o)
Connect two modules via connector.
- Throws
std::logic_error – if components don’t belong to the same configuration
- Returns
handle to the connection joint
-
template<typename JointT, typename ...Args>
RofiWorld::SpaceJointHandle rofi::configuration::connect(const Component &c, Vector refpoint, Args&&... args) Connect a module’s component to a point in space via given joint type.
- Template Parameters
JointT – connection joint type
- Parameters
c – component to connect
refpoint – reference point in space
args – arguments to forward to
JointT
creation
- Returns
handle to the connection joint
-
template<typename JointT, typename ...Args>
ComponentJoint rofi::configuration::makeComponentJoint(int source, int dest, Args&&... args)