Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Action goal state machine tests #311

Merged
merged 9 commits into from
Oct 30, 2018
101 changes: 42 additions & 59 deletions rcl_action/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ find_package(ament_cmake_ros REQUIRED)

find_package(action_msgs REQUIRED)
find_package(rcl REQUIRED)
find_package(rcutils REQUIRED)
# find_package(rmw REQUIRED)

include_directories(
include
${action_msgs_INCLUDE_DIRS}
${rcl_INCLUDE_DIRS}
${rcutils_INCLUDE_DIRS}
)

# Default to C11
Expand All @@ -34,77 +31,63 @@ add_executable(test_compile_headers
src/test_compile_headers.c
)

# set(rcl_action_sources
# src/action_server.c
# src/action_client.c
# src/action_goal.c
# src/transition_map.c
# )
# set_source_files_properties(
# ${rcl_action_sources}
# PROPERTIES language "C"
# )

### C-Library depending only on RCL
# add_library(
# ${PROJECT_NAME}
# ${rcl_action_sources}
# )
set(rcl_action_sources
src/${PROJECT_NAME}/goal_state_machine.c
)

# specific order: dependents before dependencies
# ament_target_dependencies(${PROJECT_NAME}
# "rcl"
# "action_msgs"
# "rosidl_generator_c"
# "rcutils"
# )
set_source_files_properties(
${rcl_action_sources}
PROPERTIES language "C"
)

add_library(
${PROJECT_NAME}
${rcl_action_sources}
)

ament_target_dependencies(${PROJECT_NAME}
"rcl"
"action_msgs"
)

# Causes the visibility macros to use dllexport rather than dllimport,
# which is appropriate when building the dll but not consuming it.
# target_compile_definitions(${PROJECT_NAME} PRIVATE "RCL_ACTION_BUILDING_DLL")
target_compile_definitions(${PROJECT_NAME} PRIVATE "RCL_ACTION_BUILDING_DLL")

# install(TARGETS ${PROJECT_NAME}
# ARCHIVE DESTINATION lib
# LIBRARY DESTINATION lib
# RUNTIME DESTINATION bin
# )
install(
DIRECTORY include/
DESTINATION include
)

install(TARGETS ${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)

if(BUILD_TESTING)
find_package(ament_cmake_gtest REQUIRED)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()

ament_find_gtest()
# Gtests
# ament_add_gtest(test_action_server
# test/test_action_server.cpp
# )
# if(TARGET test_action_server)
# target_include_directories(test_action_server PUBLIC
# ${rcl_INCLUDE_DIRS}
# )
# target_link_libraries(test_action_server ${PROJECT_NAME})
# endif()
# ament_add_gtest(test_action_client
# test/test_action_client.cpp
# )
# if(TARGET test_action_client)
# target_include_directories(test_action_client PUBLIC
# ${rcl_INCLUDE_DIRS}
# )
# target_link_libraries(test_action_client ${PROJECT_NAME})
# endif()
ament_add_gtest(test_goal_state_machine
test/rcl_action/test_goal_state_machine.cpp
)
if(TARGET test_goal_state_machine)
target_include_directories(test_goal_state_machine PUBLIC
${rcl_INCLUDE_DIRS}
)
target_link_libraries(test_goal_state_machine
${PROJECT_NAME}
)
endif()
endif()

# specific order: dependents before dependencies
ament_export_include_directories(include)
# ament_export_libraries(${PROJECT_NAME})
ament_export_libraries(${PROJECT_NAME})
ament_export_dependencies(ament_cmake)
ament_export_dependencies(rcl)
# ament_export_dependencies(action_msgs)
ament_export_dependencies(rcutils)
ament_export_dependencies(action_msgs)
ament_package()

install(
DIRECTORY include/
DESTINATION include
)
91 changes: 3 additions & 88 deletions rcl_action/include/rcl_action/goal_state_machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,106 +24,21 @@ extern "C"
#include "rcl_action/visibility_control.h"


typedef rcl_action_goal_state_t
(* rcl_action_goal_event_handler)(rcl_action_goal_state_t, rcl_action_goal_event_t);

// Transition event handlers
static inline rcl_action_goal_state_t
_execute_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if (GOAL_STATE_ACCEPTED != state || GOAL_EVENT_EXECUTE != event) {
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_EXECUTING;
}

static inline rcl_action_goal_state_t
_cancel_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if (GOAL_STATE_ACCEPTED != state ||
GOAL_STATE_EXECUTING != state ||
GOAL_EVENT_CANCEL != event)
{
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_CANCELING;
}

static inline rcl_action_goal_state_t
_set_succeeded_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if (GOAL_STATE_EXECUTING != state ||
GOAL_STATE_CANCELING != state ||
GOAL_EVENT_SET_SUCCEEDED != event)
{
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_SUCCEEDED;
}

static inline rcl_action_goal_state_t
_set_aborted_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if (GOAL_STATE_EXECUTING != state ||
GOAL_STATE_CANCELING != state ||
GOAL_EVENT_SET_ABORTED != event)
{
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_ABORTED;
}

static inline rcl_action_goal_state_t
_set_canceled_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if (GOAL_STATE_CANCELING != state || GOAL_EVENT_SET_CANCELED != event) {
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_CANCELED;
}

// Transition map
rcl_action_goal_event_handler
_goal_state_transition_map[GOAL_STATE_NUM_STATES][GOAL_EVENT_NUM_EVENTS] = {
[GOAL_STATE_ACCEPTED] = {
[GOAL_EVENT_EXECUTE] = _execute_event_handler,
[GOAL_EVENT_CANCEL] = _cancel_event_handler,
},
[GOAL_STATE_EXECUTING] = {
[GOAL_EVENT_CANCEL] = _cancel_event_handler,
[GOAL_EVENT_SET_SUCCEEDED] = _set_succeeded_event_handler,
[GOAL_EVENT_SET_ABORTED] = _set_aborted_event_handler,
},
[GOAL_STATE_CANCELING] = {
[GOAL_EVENT_SET_SUCCEEDED] = _set_succeeded_event_handler,
[GOAL_EVENT_SET_ABORTED] = _set_aborted_event_handler,
[GOAL_EVENT_SET_CANCELED] = _set_canceled_event_handler,
},
};

/// Transition a goal from one state to the next.
/**
* Given a goal state and a goal event, return the next state.
*
* \param[in] state the state to transition from
* \param[in] event the event triggering a transition
* \return the next goal state if the transition is valid, or
* \return `GOAl_STATE_UNKNOWN` if the transition is invalid or an error occured
* \return `GOAL_STATE_UNKNOWN` if the transition is invalid or an error occured
*/
RCL_ACTION_PUBLIC
RCL_WARN_UNUSED
inline rcl_action_goal_state_t
rcl_action_goal_state_t
rcl_action_transition_goal_state(
const rcl_action_goal_state_t state,
const rcl_action_goal_event_t event)
{
// rcl_action_goal_event_handler ** transition_map = get_state_transition_map();
rcl_action_goal_event_handler handler = _goal_state_transition_map[state][event];
if (NULL == handler) {
return GOAL_STATE_UNKNOWN;
}
return handler(state, event);
}
const rcl_action_goal_event_t event);

#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion rcl_action/include/rcl_action/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ typedef int8_t rcl_action_goal_state_t;
#define GOAL_STATE_SUCCEEDED action_msgs__msg__GoalStatus__STATUS_SUCCEEDED
#define GOAL_STATE_CANCELED action_msgs__msg__GoalStatus__STATUS_CANCELED
#define GOAL_STATE_ABORTED action_msgs__msg__GoalStatus__STATUS_ABORTED
#define GOAL_STATE_NUM_STATES 6 // not counting `UNKNOWN`
#define GOAL_STATE_NUM_STATES 7

/// Goal state transition events
typedef enum rcl_action_goal_event_t
Expand Down
6 changes: 0 additions & 6 deletions rcl_action/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,9 @@

<build_depend>action_msgs</build_depend>
<build_depend>rcl</build_depend>
<build_depend>rcutils</build_depend>
<build_depend>rmw_implementation</build_depend>
<build_depend>rosidl_generator_c</build_depend>

<exec_depend>action_msgs</exec_depend>
<exec_depend>rcl</exec_depend>
<exec_depend>rcutils</exec_depend>
<exec_depend>rmw_implementation</exec_depend>
<exec_depend>rosidl_generator_c</exec_depend>

<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_common</test_depend>
Expand Down
111 changes: 111 additions & 0 deletions rcl_action/src/rcl_action/goal_state_machine.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2018 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.

#ifdef __cplusplus
extern "C"
{
#endif

#include "rcl_action/goal_state_machine.h"


typedef rcl_action_goal_state_t
(* rcl_action_goal_event_handler)(rcl_action_goal_state_t, rcl_action_goal_event_t);

// Transition event handlers
rcl_action_goal_state_t
_execute_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if (GOAL_STATE_ACCEPTED != state || GOAL_EVENT_EXECUTE != event) {
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_EXECUTING;
}

rcl_action_goal_state_t
_cancel_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if ((GOAL_STATE_ACCEPTED != state && GOAL_STATE_EXECUTING != state) ||
GOAL_EVENT_CANCEL != event)
{
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_CANCELING;
}

rcl_action_goal_state_t
_set_succeeded_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if ((GOAL_STATE_EXECUTING != state && GOAL_STATE_CANCELING != state) ||
GOAL_EVENT_SET_SUCCEEDED != event)
{
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_SUCCEEDED;
}

rcl_action_goal_state_t
_set_aborted_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if ((GOAL_STATE_EXECUTING != state && GOAL_STATE_CANCELING != state) ||
GOAL_EVENT_SET_ABORTED != event)
{
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_ABORTED;
}

rcl_action_goal_state_t
_set_canceled_event_handler(rcl_action_goal_state_t state, rcl_action_goal_event_t event)
{
if (GOAL_STATE_CANCELING != state || GOAL_EVENT_SET_CANCELED != event) {
return GOAL_STATE_UNKNOWN;
}
return GOAL_STATE_CANCELED;
}

// Transition map
static rcl_action_goal_event_handler
_goal_state_transition_map[GOAL_STATE_NUM_STATES][GOAL_EVENT_NUM_EVENTS] = {
[GOAL_STATE_ACCEPTED] = {
[GOAL_EVENT_EXECUTE] = _execute_event_handler,
[GOAL_EVENT_CANCEL] = _cancel_event_handler,
},
[GOAL_STATE_EXECUTING] = {
[GOAL_EVENT_CANCEL] = _cancel_event_handler,
[GOAL_EVENT_SET_SUCCEEDED] = _set_succeeded_event_handler,
[GOAL_EVENT_SET_ABORTED] = _set_aborted_event_handler,
},
[GOAL_STATE_CANCELING] = {
[GOAL_EVENT_SET_SUCCEEDED] = _set_succeeded_event_handler,
[GOAL_EVENT_SET_ABORTED] = _set_aborted_event_handler,
[GOAL_EVENT_SET_CANCELED] = _set_canceled_event_handler,
},
};

rcl_action_goal_state_t
rcl_action_transition_goal_state(
const rcl_action_goal_state_t state,
const rcl_action_goal_event_t event)
{
rcl_action_goal_event_handler handler = _goal_state_transition_map[state][event];
if (NULL == handler) {
return GOAL_STATE_UNKNOWN;
}
return handler(state, event);
}

#ifdef __cplusplus
}
#endif
Loading