|
Three components are required for implementing a custom unit in ArmarX:
The only capability of the demo unit that is developed in this howto is to periodically publish a certain value. The value is internally stored as a Variant and can be changed using the unit's interface. Every unit needs to define two interfaces:
The ExampleUnit defines the two interfaces ExampleUnitInterface and ExampleUnitListener. The difference between these two interfaces is the component that is intended to implement it. The first interface, ExampleUnitInterface, will be implemented by the unit itself and can therefore define functions that manipulate the unit's behavior. In this case, we add a function that changes the value published by the unit. The other interface is to be implemented by any component that aims at receiving the unit's published values. This is primarily the matching observer. Therefore the functions defined in the listener-interface can be seen as callbacks for the observer, called whenever new values got published.
To satisfy the linker, the interface library of the unit-interface need to be linked. To do so, add the library name (here ExampleUnitInterfaces) to the COMPONENT_LIBS
list in your CMakeLists.txt
of your component.
A unit is essentially a component that implements the respective unit interface:
The unit implementation ExampleUnit derives from the base class Component and from the interface ExampleUnitInterface. Both base classes define virtual methods that need to be implemented. In case of a Component, these methods are getDefaultName, onInitComponent, onConnectComponent and onExitComponent. The ExampleUnitInterface solely defines the method setPeriodicValue that is used by other components to configure ExampleUnit. Apart from that and some internal members for handling the emittance period and the value to publish, the unit needs a proxy to the ExampleUnitListener-interface. The type of this proxy is ExampleUnitListenerPrx.
As any other component, units may have properties, in this case the reporting period in milliseconds:
The implementation of the ExampleUnit class looks as follows:
By calling offeringTopic, the unit declares the name under which it is going to publish values. An observer can subscribe to this topic and will then receive the emitted values. The unit needs to fetch a proxy to the ExampleUnitListener-interface, as it is not implementing this interface itself, but using it to publish the periodic value. Therefore it needs to call getTopic to obtain the respective proxy object.
The last part necessary for building a custom unit is the application that makes the unit actually executable. Like for other executable ArmarX Components, we need a ExampleUnitApp class and a respective main-function that instantiates this class. Both parts should be located in the applications folder of an ArmarX project.