diff --git a/rcl_lifecycle/include/rcl_lifecycle/default_state_machine.h b/rcl_lifecycle/include/rcl_lifecycle/default_state_machine.h index d9802f2..1275ead 100644 --- a/rcl_lifecycle/include/rcl_lifecycle/default_state_machine.h +++ b/rcl_lifecycle/include/rcl_lifecycle/default_state_machine.h @@ -36,6 +36,54 @@ RCL_LIFECYCLE_PUBLIC extern const char * rcl_lifecycle_transition_success_label; RCL_LIFECYCLE_PUBLIC extern const char * rcl_lifecycle_transition_failure_label; RCL_LIFECYCLE_PUBLIC extern const char * rcl_lifecycle_transition_error_label; +/// Initialize a default state machine +/* + * This function initializes a default state machine. It registers all: primary states, + * transition states, transitions and the initial state. The primary state is unconfigured. + * + * States: unknown, unconfigured, inactive, active and finalized. + * Transition states: configuring, cleaningup, activating, deactivating, errorprocessing + * and shuttingdown. + * Transitions: + * - unconfigured to configuring + * - unconfigured to shuttingdown + * - configuring to inactive + * - configuring to unconfigured + * - configuring to errorprocessing + * - inactive to activating + * - inactive to cleaningup + * - inactive to shuttingdown + * - cleaningup to unconfigured + * - cleaningup to inactive + * - cleaniningup to errorprocessing + * - activating to active + * - activating to inactive + * - activating to errorprocessing + * - active to deactivating + * - active to shuttingdown + * - deactivating to inactive + * - deactivating to active + * - deactivating to errorprocessing + * - shutting down to finalized + * - shutting down to finalized + * - shutting down to errorprocessing + * - errorprocessing to uncofigured + * - errorprocessing to finalized + * - errorprocessing to finalized + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] state_machine struct to be initialized + * \param[in] allocator a valid allocator used to initialized the state machine + * \return `RCL_RET_OK` if the state machine was initialized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t diff --git a/rcl_lifecycle/include/rcl_lifecycle/rcl_lifecycle.h b/rcl_lifecycle/include/rcl_lifecycle/rcl_lifecycle.h index 8236f99..6d05e01 100644 --- a/rcl_lifecycle/include/rcl_lifecycle/rcl_lifecycle.h +++ b/rcl_lifecycle/include/rcl_lifecycle/rcl_lifecycle.h @@ -12,6 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. +/** \mainpage rcl: Common functionality ROS lifecycle + * + * `rcl_lifecycle` provides a pure C implementation of the ROS concept of lifecycle. + * It builds on top of the implementation of topics and services in `rcl`. + * + * `rcl_lifecycle` consists of functions and structs for the following ROS lifecycle entities: + * + * - Lifecycle states + * - Lifecycle transitions + * - Lifecycle state machine + * - Lifecycle triggers + * + * Some useful abstractions: + * + * - Return codes and other types + * - rcl_lifecycle/data_types.h + */ + #ifndef RCL_LIFECYCLE__RCL_LIFECYCLE_H_ #define RCL_LIFECYCLE__RCL_LIFECYCLE_H_ @@ -26,10 +44,41 @@ extern "C" #include "rcl_lifecycle/default_state_machine.h" #include "rcl_lifecycle/visibility_control.h" +/// Return a rcl_lifecycle_state_t struct with members set to `NULL` or 0. +/** + * Should be called to get a null rcl_lifecycle_state_t before passing to + * rcl_lifecycle_state_init(). + * + * \return rcl_lifecycle_state_t a initilized struct + */ RCL_LIFECYCLE_PUBLIC rcl_lifecycle_state_t rcl_lifecycle_get_zero_initialized_state(); +/// Initialize a rcl_lifecycle_state_init. +/** + * This function initializes a state based on an `id` and a `label`. + * + * The given `rcl_lifecycle_state_t` must be zero initialized with the function + * `rcl_lifecycle_get_zero_initialized_state()` and must not be already initialized + * by this function. + * The allocator will be used to allocate the label string. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] state pointer to the state struct to be initialized + * \param[in] id identifier of the state + * \param[in] label label of the state + * \param[in] allocator a valid allocator used to initialized the lifecycle state + * \return `RCL_RET_OK` if state was initialized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -39,6 +88,26 @@ rcl_lifecycle_state_init( const char * label, const rcl_allocator_t * allocator); +/// Finalize a rcl_lifecycle_state_t. +/** + * + * Calling this will set the rcl_lifecycle_state_t struct into the an unitialized state that is + * functionally the same as before rcl_lifecycle_state_init was called. This function make the + * rcl_lifecycle_state_t invalid. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] state struct to be finalized + * \param[in] allocator a valid allocator used to finalize the lifecycle state + * \return `RCL_RET_OK` if the state was finalized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -46,16 +115,44 @@ rcl_lifecycle_state_fini( rcl_lifecycle_state_t * state, const rcl_allocator_t * allocator); +/// Return a rcl_lifecycle_transition_t struct with members set to `NULL` or 0. +/** + * Should be called to get a null rcl_lifecycle_transition_t before passing to + * rcl_lifecycle_transition_init(). + */ RCL_LIFECYCLE_PUBLIC rcl_lifecycle_transition_t rcl_lifecycle_get_zero_initialized_transition(); -/// Initialize transition with existing states +/// Initialize a transition from a start state to the goal state. /** + * The given `rcl_lifecycle_transition_t` must be zero initialized with the function + * `rcl_lifecycle_get_zero_initialized_transition()` and must not be already initialized + * by this function. + * The allocator will be used to allocate the label string and the rcl_lifecycle_state_t structs. + * * Note: the transition pointer will take ownership * of the start and goal state. When calling * rcl_lifecycle_transition_fini(), the two states * will be freed. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] transition to a preallocated, zero-initialized transition structure + * to be initialized. + * \param[in] id identifier of the transition + * \param[in] label label of the transition + * \param[in] start the value where the transition is initialized + * \param[in] goal the objetive of the transition + * \param[in] allocator a valid allocator used to finalize the lifecycle state + * \return `RCL_RET_OK` if the transition is initialized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED @@ -68,6 +165,25 @@ rcl_lifecycle_transition_init( rcl_lifecycle_state_t * goal, const rcl_allocator_t * allocator); +/// Finalize a rcl_lifecycle_transition_t. +/** + * Calling this will set the rcl_lifecycle_transition_t struct into the an unitialized state that is + * functionally the same as before rcl_lifecycle_transition_init was called. This function make the + * rcl_lifecycle_transition_t invalid. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] transition struct to be finalized + * \param[in] allocator a valid allocator used to finalize the transition + * \return `RCL_RET_OK` if the state was finalized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -75,10 +191,46 @@ rcl_lifecycle_transition_fini( rcl_lifecycle_transition_t * transition, const rcl_allocator_t * allocator); +/// Return a rcl_lifecycle_state_machine_t struct with members set to `NULL` or 0. +/** + * Should be called to get a null rcl_lifecycle_state_machine_t before passing to + * rcl_lifecycle_state_machine_init(). + */ RCL_LIFECYCLE_PUBLIC rcl_lifecycle_state_machine_t rcl_lifecycle_get_zero_initialized_state_machine(); +/// Initialize state machine +/** + * This function initialize the state machine: one publisher to publish transitions messages + * and a set of services to get information about states and transitions. + * If `default_state` is `true` then a new default state machine is initialized. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] state_machine struct to be initialized + * \param[in] node_handle a valid (not finalized) handle to the node used to create the publisher + * and the services + * \param[in] ts_pub_notify pointer to transition publisher, it used to publish the transitions + * \param[in] ts_srv_change_state pointer to the service that allows to trigger changes on the state + * \param[in] ts_srv_get_state pointer to the service that allows to get the current state + * \param[in] ts_srv_get_available_states pointer to the service that allows to get the available states + * \param[in] ts_srv_get_available_transitions pointer to the service that allows to get the + * available transitions + * \param[in] ts_srv_get_transition_graph pointer to the service that allows to get transitions from + * the graph + * \param[in] default_states if `true` a new default state machine is initialized, otherwise + * the state_machine pointer is only used to initialize the interfaces + * \param[in] allocator a valid allocator used to initialized the state machine + * \return `RCL_RET_OK` if the state machine was initialized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -94,6 +246,26 @@ rcl_lifecycle_state_machine_init( bool default_states, const rcl_allocator_t * allocator); +/// Finalize a rcl_lifecycle_state_machine_t. +/** + * Calling this will set the rcl_lifecycle_state_machine_t struct into the an unitialized state that is + * functionally the same as before rcl_lifecycle_state_machine_init was called. This function make the + * rcl_lifecycle_state_machine_t invalid. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] state_machine struct to be finalized + * \param[in] node_handle valid (not finalized) handle to the node + * \param[in] allocator a valid allocator used to finalize the state machine + * \return `RCL_RET_OK` if the state was finalized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -102,12 +274,47 @@ rcl_lifecycle_state_machine_fini( rcl_node_t * node_handle, const rcl_allocator_t * allocator); +/// Check if a state machine is active. +/** + * If the state is initialized then returns `RCL_RET_OK`, otherwise returns `RCL_RET_ERROR` + * In the case where `RCL_RET_ERROR` is to be returned, an error message is set. + * This function cannot fail. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] state_machine pointer to the state machine struct + * \return `RCL_RET_OK` if the state is initialized, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_lifecycle_state_machine_is_initialized( const rcl_lifecycle_state_machine_t * state_machine); +/// Get a state by id. +/** + * A pointer to the internally transition struct is returned + * based on the `id`. If the `id` is not set in the state then returns NULL. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] state pointer to the state struct + * \param[in] id identifier to be find in the valid transitions + * \return a pointer to the lifecycle transition if the `id` exists or otherwise it return NULL + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED const rcl_lifecycle_transition_t * @@ -115,6 +322,23 @@ rcl_lifecycle_get_transition_by_id( const rcl_lifecycle_state_t * state, uint8_t id); +/// Get a state by id. +/** + * A pointer to the internally transition struct is returned + * based on the `label`. If the `label` is not set in the state then returns NULL. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] state pointer to the state struct + * \param[in] label label to be find in the valid transitions + * \return a pointer to the lifecycle transition if the label exists or otherwise it return NULL + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED const rcl_lifecycle_transition_t * @@ -122,6 +346,27 @@ rcl_lifecycle_get_transition_by_label( const rcl_lifecycle_state_t * state, const char * label); +/// Trigger a state by id. +/** + * This function will trigger a transition based on the `id`. If the argument + * `publish_notification` is `true` then a message will be published in the + * ROS 2 network notifying the transition, if `false` no message will be published. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] state_machine pointer to the state machine struct + * \param[in] id identifier of the transition to be triggered + * \param[in] publish_notification if the value is `true` a message will be published + * notifying the transition, otherwise no message will be published + * \return `RCL_RET_OK` if the transition was triggered successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -130,6 +375,27 @@ rcl_lifecycle_trigger_transition_by_id( uint8_t id, bool publish_notification); +/// Trigger a state by label. +/** + * This function will trigger a transition base on the `label`. If the argument + * `publish_notification` is `true` then a message will be published in the + * ROS 2 network notifying the transition, if `false` no message will be published. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] state_machine pointer to the state machine struct + * \param[in] label of the transition to be triggered + * \param[in] publish_notification if the value is `true` a message will be published + * notifying the transition, otherwise no message will be published + * \return `RCL_RET_OK` if the transition was triggered successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -138,6 +404,21 @@ rcl_lifecycle_trigger_transition_by_label( const char * label, bool publish_notification); +/// Print the state machine data +/** + * This function will print in the standard output the data in the + * rcl_lifecycle_state_machine_t struct. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] state_machine pointer to the state machine struct to print + */ RCL_LIFECYCLE_PUBLIC void rcl_print_state_machine(const rcl_lifecycle_state_machine_t * state_machine); diff --git a/rcl_lifecycle/include/rcl_lifecycle/transition_map.h b/rcl_lifecycle/include/rcl_lifecycle/transition_map.h index fa8bde9..24af35b 100644 --- a/rcl_lifecycle/include/rcl_lifecycle/transition_map.h +++ b/rcl_lifecycle/include/rcl_lifecycle/transition_map.h @@ -25,17 +25,61 @@ extern "C" { #endif +/// Initialize a rcl_lifecycle_state_init. +/* + * Should be called to get a null rcl_lifecycle_transition_map_t before passing to + * rcl_lifecycle_register_state() or rcl_lifecycle_register_transition(). + * + * \return rcl_lifecycle_transition_map_t a initilized struct + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_lifecycle_transition_map_t rcl_lifecycle_get_zero_initialized_transition_map(); +/// Check if a transition map is active using a rcl_lifecycle_state_machine_t. +/* + * The function checks if the transition map is initialized. It returns `RCL_RET_OK` + * if the transition map is initialized successfully or `RCL_RET_ERROR` if the transition + * map is not initialized. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] transition_map pointer to the transition map struct to check + * \return `RCL_RET_OK` if the transition map is initialized successfully, or + * \return `RCL_RET_ERROR` if the transition map is not initialized. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_lifecycle_transition_map_is_initialized( const rcl_lifecycle_transition_map_t * transition_map); +/// Finalize a rcl_lifecycle_transition_map_t. +/* + * Calling this will set the rcl_lifecycle_transition_map_t struct into the an unitialized state that is + * functionally the same as before rcl_lifecycle_register_state or + * rcl_lifecycle_register_transition was called. This function make the rcl_lifecycle_transition_map_t invalid. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[inout] transition_map struct to be deinitialized + * \param[in] allocator a valid allocator used to deinitialized the state machine + * \return `RCL_RET_OK` if the state was deinitialized successfully, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -43,6 +87,25 @@ rcl_lifecycle_transition_map_fini( rcl_lifecycle_transition_map_t * transition_map, const rcl_allocator_t * allocator); +/// Register a state +/* + * This function registers a new state in the transition map. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] map to be modified + * \param[in] state the state to register + * \param[in] allocator a valid allocator used to register the state machine + * \return `RCL_RET_OK` if the state was registered successfully, or + * \return `RCL_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -51,6 +114,25 @@ rcl_lifecycle_register_state( rcl_lifecycle_state_t state, const rcl_allocator_t * allocator); +/// Register a transition +/* + * This function registers a new transition in the transition map. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Yes + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] transition_map to be modified + * \param[in] transition the transition to register + * \param[in] allocator a valid allocator used to register the state machine + * \return `RCL_RET_OK` if the state was deinitialized successfully, or + * \return `RCL_RET_BAD_ALLOC` if allocating memory failed, or + * \return `RCL_RET_ERROR` if an unspecified error occurs. + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_ret_t @@ -59,6 +141,22 @@ rcl_lifecycle_register_transition( rcl_lifecycle_transition_t transition, const rcl_allocator_t * allocator); +/// Get the state from a transition map based on the state id +/* + * A pointer to the internally lifecycle state struct is returned based on the `id`. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] transition_map + * \param[in] state_id + * \return pointer to a rcl_lifecycle_state_t or NULL if the state id doesn't exist + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_lifecycle_state_t * @@ -66,6 +164,22 @@ rcl_lifecycle_get_state( rcl_lifecycle_transition_map_t * transition_map, unsigned int state_id); +/// Get the state from a transition map based on the state id +/* + * A pointer to the internally lifecycle transition struct is returned based on the `label`. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | No + * Thread-Safe | No + * Uses Atomics | No + * Lock-Free | Yes + * + * \param[in] transition_map to be modified + * \param[in] state_id used to get the label to search + * \return pointer to a rcl_lifecycle_state_t or NULL if the state id doesn't exist + */ RCL_LIFECYCLE_PUBLIC RCL_WARN_UNUSED rcl_lifecycle_transition_t *