// Copyright 2016 Open Source Robotics Foundation, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include "lifecycle_msgs/msg/state.h" #include "lifecycle_msgs/msg/transition.h" #include "rcl/error_handling.h" #include "rcl/rcl.h" #include "rcl_lifecycle/transition_map.h" #include "default_state_machine.h" // NOLINT #include "states.h" // NOLINT #ifdef __cplusplus extern "C" { #endif rcl_lifecycle_transition_key_t * empty_transition_key = NULL; rcl_lifecycle_transition_t * empty_transition = NULL; unsigned int empty_transition_size = 0; // Primary States rcl_lifecycle_state_t rcl_state_unknown = { "unknown", lifecycle_msgs__msg__State__PRIMARY_STATE_UNKNOWN, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_unconfigured = { "unconfigured", lifecycle_msgs__msg__State__PRIMARY_STATE_UNCONFIGURED, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_inactive = { "inactive", lifecycle_msgs__msg__State__PRIMARY_STATE_INACTIVE, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_active = { "active", lifecycle_msgs__msg__State__PRIMARY_STATE_ACTIVE, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_finalized = { "finalized", lifecycle_msgs__msg__State__PRIMARY_STATE_FINALIZED, NULL, NULL, 0 }; // Transition States rcl_lifecycle_state_t rcl_state_configuring = { "configuring", lifecycle_msgs__msg__State__TRANSITION_STATE_CONFIGURING, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_cleaningup = { "cleaningup", lifecycle_msgs__msg__State__TRANSITION_STATE_CLEANINGUP, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_shuttingdown = { "shuttingdown", lifecycle_msgs__msg__State__TRANSITION_STATE_SHUTTINGDOWN, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_activating = { "activating", lifecycle_msgs__msg__State__TRANSITION_STATE_ACTIVATING, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_deactivating = { "deactivating", lifecycle_msgs__msg__State__TRANSITION_STATE_DEACTIVATING, NULL, NULL, 0 }; rcl_lifecycle_state_t rcl_state_errorprocessing = { "errorprocessing", lifecycle_msgs__msg__State__TRANSITION_STATE_ERRORPROCESSING, NULL, NULL, 0 }; // Transitions const rcl_lifecycle_transition_t rcl_transition_configure = { "configure", lifecycle_msgs__msg__Transition__TRANSITION_CONFIGURE, &rcl_state_unconfigured, &rcl_state_configuring }; const rcl_lifecycle_transition_t rcl_transition_configure_success = { "configure_success", lifecycle_msgs__msg__Transition__TRANSITION_ON_CONFIGURE_SUCCESS, &rcl_state_configuring, &rcl_state_inactive }; const rcl_lifecycle_transition_t rcl_transition_configure_failure = { "configure_failure", lifecycle_msgs__msg__Transition__TRANSITION_ON_CONFIGURE_FAILURE, &rcl_state_configuring, &rcl_state_unconfigured }; const rcl_lifecycle_transition_t rcl_transition_configure_error = { "configure_error", lifecycle_msgs__msg__Transition__TRANSITION_ON_CONFIGURE_ERROR, &rcl_state_configuring, &rcl_state_errorprocessing }; const rcl_lifecycle_transition_t rcl_transition_cleanup = { "cleanup", lifecycle_msgs__msg__Transition__TRANSITION_CLEANUP, &rcl_state_inactive, &rcl_state_cleaningup }; const rcl_lifecycle_transition_t rcl_transition_cleanup_success = { "cleanup_success", lifecycle_msgs__msg__Transition__TRANSITION_ON_CLEANUP_SUCCESS, &rcl_state_cleaningup, &rcl_state_unconfigured }; const rcl_lifecycle_transition_t rcl_transition_cleanup_failure = { "cleanup_failure", lifecycle_msgs__msg__Transition__TRANSITION_ON_CLEANUP_FAILURE, &rcl_state_cleaningup, &rcl_state_inactive }; const rcl_lifecycle_transition_t rcl_transition_cleanup_error = { "cleanup_error", lifecycle_msgs__msg__Transition__TRANSITION_ON_CLEANUP_ERROR, &rcl_state_cleaningup, &rcl_state_errorprocessing }; const rcl_lifecycle_transition_t rcl_transition_activate = { "activate", lifecycle_msgs__msg__Transition__TRANSITION_ACTIVATE, &rcl_state_inactive, &rcl_state_activating }; const rcl_lifecycle_transition_t rcl_transition_activate_success = { "activate_success", lifecycle_msgs__msg__Transition__TRANSITION_ON_ACTIVATE_SUCCESS, &rcl_state_activating, &rcl_state_active }; const rcl_lifecycle_transition_t rcl_transition_activate_failure = { "activate_failure", lifecycle_msgs__msg__Transition__TRANSITION_ON_ACTIVATE_FAILURE, &rcl_state_activating, &rcl_state_inactive }; const rcl_lifecycle_transition_t rcl_transition_activate_error = { "activate_error", lifecycle_msgs__msg__Transition__TRANSITION_ON_ACTIVATE_ERROR, &rcl_state_activating, &rcl_state_errorprocessing }; const rcl_lifecycle_transition_t rcl_transition_deactivate = { "deactivate", lifecycle_msgs__msg__Transition__TRANSITION_DEACTIVATE, &rcl_state_active, &rcl_state_deactivating }; const rcl_lifecycle_transition_t rcl_transition_deactivate_success = { "deactivate_success", lifecycle_msgs__msg__Transition__TRANSITION_ON_DEACTIVATE_SUCCESS, &rcl_state_deactivating, &rcl_state_inactive }; const rcl_lifecycle_transition_t rcl_transition_deactivate_failure = { "deactivate_failure", lifecycle_msgs__msg__Transition__TRANSITION_ON_DEACTIVATE_FAILURE, &rcl_state_deactivating, &rcl_state_active }; const rcl_lifecycle_transition_t rcl_transition_deactivate_error = { "deactivate_error", lifecycle_msgs__msg__Transition__TRANSITION_ON_DEACTIVATE_ERROR, &rcl_state_deactivating, &rcl_state_errorprocessing }; const rcl_lifecycle_transition_t rcl_transition_unconfigured_shutdown = { "unconfigured_shutdown", lifecycle_msgs__msg__Transition__TRANSITION_UNCONFIGURED_SHUTDOWN, &rcl_state_unconfigured, &rcl_state_shuttingdown }; const rcl_lifecycle_transition_t rcl_transition_inactive_shutdown = { "inactive_shutdown", lifecycle_msgs__msg__Transition__TRANSITION_INACTIVE_SHUTDOWN, &rcl_state_inactive, &rcl_state_shuttingdown }; const rcl_lifecycle_transition_t rcl_transition_active_shutdown = { "active_shutdown", lifecycle_msgs__msg__Transition__TRANSITION_ACTIVE_SHUTDOWN, &rcl_state_active, &rcl_state_shuttingdown }; const rcl_lifecycle_transition_t rcl_transition_shutdown_success = { "shutdown_success", lifecycle_msgs__msg__Transition__TRANSITION_ON_SHUTDOWN_SUCCESS, &rcl_state_shuttingdown, &rcl_state_finalized }; const rcl_lifecycle_transition_t rcl_transition_shutdown_failure = { "shutdown_failure", lifecycle_msgs__msg__Transition__TRANSITION_ON_SHUTDOWN_FAILURE, &rcl_state_shuttingdown, &rcl_state_finalized }; const rcl_lifecycle_transition_t rcl_transition_shutdown_error = { "shutdown_error", lifecycle_msgs__msg__Transition__TRANSITION_ON_SHUTDOWN_ERROR, &rcl_state_shuttingdown, &rcl_state_errorprocessing }; const rcl_lifecycle_transition_t rcl_transition_error_success = { "errorprocessing_success", lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_SUCCESS, &rcl_state_errorprocessing, &rcl_state_unconfigured }; const rcl_lifecycle_transition_t rcl_transition_error_failure = { "errorprocessing_failure", lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_FAILURE, &rcl_state_errorprocessing, &rcl_state_finalized }; const rcl_lifecycle_transition_t rcl_transition_error_error = { "errorprocessing_error", lifecycle_msgs__msg__Transition__TRANSITION_ON_ERROR_ERROR, &rcl_state_errorprocessing, &rcl_state_finalized }; // default implementation as despicted on // design.ros2.org rcl_ret_t rcl_lifecycle_init_default_state_machine( rcl_lifecycle_state_machine_t * state_machine, const rcutils_allocator_t * allocator) { rcutils_ret_t ret; /* * we once register all primary states */ ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_unknown, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_unconfigured, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_inactive, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_active, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_finalized, allocator); if (ret != RCL_RET_OK) { goto fail; } /* * we once register all transition states */ ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_configuring, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_cleaningup, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_shuttingdown, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_activating, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_deactivating, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_state( &state_machine->transition_map, rcl_state_errorprocessing, allocator); if (ret != RCL_RET_OK) { goto fail; } /* * we register all transitions from each primary state * it registers the transition and the key on which to trigger */ // transition configure ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_configure, lifecycle_msgs__msg__Transition__TRANSITION_CONFIGURE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_configure_success, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_SUCCESS, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_configure_failure, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_FAILURE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_configure_error, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_ERROR, allocator); if (ret != RCL_RET_OK) { goto fail; } // transition cleanup ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_cleanup, lifecycle_msgs__msg__Transition__TRANSITION_CLEANUP, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_cleanup_success, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_SUCCESS, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_cleanup_failure, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_FAILURE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_cleanup_error, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_ERROR, allocator); if (ret != RCL_RET_OK) { goto fail; } // transition activate ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_activate, lifecycle_msgs__msg__Transition__TRANSITION_ACTIVATE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_activate_success, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_SUCCESS, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_activate_failure, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_FAILURE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_activate_error, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_ERROR, allocator); if (ret != RCL_RET_OK) { goto fail; } // transition deactivate ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_deactivate, lifecycle_msgs__msg__Transition__TRANSITION_DEACTIVATE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_deactivate_success, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_SUCCESS, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_deactivate_failure, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_FAILURE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_deactivate_error, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_ERROR, allocator); if (ret != RCL_RET_OK) { goto fail; } // transition shutdown ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_unconfigured_shutdown, lifecycle_msgs__msg__Transition__TRANSITION_SHUTDOWN, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_inactive_shutdown, lifecycle_msgs__msg__Transition__TRANSITION_SHUTDOWN, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_active_shutdown, lifecycle_msgs__msg__Transition__TRANSITION_SHUTDOWN, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_shutdown_success, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_SUCCESS, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_shutdown_failure, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_FAILURE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_shutdown_error, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_ERROR, allocator); if (ret != RCL_RET_OK) { goto fail; } // error state ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_error_success, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_SUCCESS, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_error_failure, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_FAILURE, allocator); if (ret != RCL_RET_OK) { goto fail; } ret = rcl_lifecycle_register_transition( &state_machine->transition_map, rcl_transition_error_error, lifecycle_msgs__msg__Transition__TRANSITION_CALLBACK_ERROR, allocator); if (ret != RCL_RET_OK) { goto fail; } state_machine->current_state = &rcl_state_unconfigured; return RCL_RET_OK; fail: if (rcl_lifecycle_transition_map_fini(&state_machine->transition_map, allocator) != RCL_RET_OK) { RCL_SET_ERROR_MSG("could not free lifecycle transition map. Leaking memory!\n", rcl_get_default_allocator()); } return RCL_RET_ERROR; } #ifdef __cplusplus } #endif // extern "C"