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 server implementation #323

Merged
merged 39 commits into from
Nov 20, 2018
Merged

Action server implementation #323

merged 39 commits into from
Nov 20, 2018

Conversation

jacobperron
Copy link
Member

@jacobperron jacobperron commented Nov 8, 2018

First iteration of implementation.

Connects to #306
Depends on ros2/rcl_interfaces#47
Depends on ros2/rosidl#310

@jacobperron jacobperron added the in progress Actively being worked on (Kanban column) label Nov 8, 2018
@jacobperron jacobperron self-assigned this Nov 8, 2018
@jacobperron jacobperron mentioned this pull request Nov 8, 2018
10 tasks
@jacobperron jacobperron force-pushed the jacob/action_server branch 3 times, most recently from c33d94b to 3406328 Compare November 9, 2018 02:42
@jacobperron
Copy link
Member Author

Intermediate CI to find any issues:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the calling library responsible for updating the goal handle (i.e. to transition to execute, to succeeded, etc.)?

rcl_action/src/rcl_action/action_server.c Outdated Show resolved Hide resolved
rcl_action/src/rcl_action/action_server.c Show resolved Hide resolved
rcl_action/src/rcl_action/action_server.c Show resolved Hide resolved
rcl_action/src/rcl_action/action_server.c Outdated Show resolved Hide resolved
rcl_action/src/rcl_action/action_server.c Outdated Show resolved Hide resolved
rcl_action/test/rcl_action/test_action_server.cpp Outdated Show resolved Hide resolved
rcl_action/test/rcl_action/test_action_server.cpp Outdated Show resolved Hide resolved
rcl_action/test/rcl_action/test_action_server.cpp Outdated Show resolved Hide resolved
rcl_action/include/rcl_action/types.h Show resolved Hide resolved
rcl_action/test/rcl_action/test_action_server.cpp Outdated Show resolved Hide resolved
@hidmic
Copy link
Contributor

hidmic commented Nov 12, 2018

Does this PR depend on #325 too?

@jacobperron
Copy link
Member Author

jacobperron commented Nov 12, 2018

@hidmic

Is the calling library responsible for updating the goal handle (i.e. to transition to execute, to succeeded, etc.)?

In the current implementation, yes. I was hoping to build on top of this (or refactor) after ros2/rosidl#314 in order to encapsulate more logic.

Does this PR depend on #325 too?

Yes, those commits are included in this PR for testing purposes, but I'll rebase after #325 is merged.

@jacobperron
Copy link
Member Author

Rebased on master. I think this is ready for review now. The only thing missing is the wait set related functions (which I plan to add in a follow-up PR).

CI:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

@jacobperron jacobperron added in review Waiting for review (Kanban column) and removed in progress Actively being worked on (Kanban column) labels Nov 13, 2018
@jacobperron
Copy link
Member Author

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but for a few small comments. Awesome work @jacobperron !

rcl_action/include/rcl_action/action_server.h Outdated Show resolved Hide resolved
rcl_action/test/rcl_action/test_action_server.cpp Outdated Show resolved Hide resolved
rcl_action/test/rcl_action/test_action_server.cpp Outdated Show resolved Hide resolved
// Try to initialize another action server with the same name
// FIXME(jacobperron): test failing
// rcl_action_server_t same_name_action_server = rcl_action_get_zero_initialized_server();
// ret = rcl_action_server_init(&same_name_action_server, &node, ts, action_name, &options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobperron I presume we're aiming to catch this by means of invalid service name checks, but it doesn't seem like that outcome means the service name is repeated (see here)?

Copy link
Member Author

@jacobperron jacobperron Nov 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's right, I realized later that it doesn't care if service names are repeated and meant to remove this commented test. But I can add a test for invalid names.


I also found a bug where empty action names are acceptable because we are appending the additional service/topic strings to it (e.g. "/_action/send_goal").

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that's a bug in rcl_action/names.cc.

}
RCL_CHECK_ARGUMENT_FOR_NULL(goal_handles, RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_ARGUMENT_FOR_NULL(num_goals, RCL_RET_INVALID_ARGUMENT);
*goal_handles = action_server->impl->goal_handles;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobperron should we check for NULL == *goal_handles?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. We can set *goal_handles to a valid pointer, regardless of it's initial value.

Copy link
Contributor

@sloretz sloretz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review, I'll continue reviewing but wanted to give some feedback first.

@@ -18,6 +18,7 @@
<test_depend>ament_cmake_gtest</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>test_msgs</test_depend>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also add <build_depend> + <build_export_depend> for rosidl_generator_c, and <build_depend> for rmw + rcutils.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 00ecdf0

// Initialize clock
rcl_ret_t ret = rcl_clock_init(options->clock_type, &action_server->impl->clock, &allocator);
if (RCL_RET_OK != ret) {
return RCL_RET_ERROR;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to deallocate action_server->impl before returning

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

action_server->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);

// Initialize clock
rcl_ret_t ret = rcl_clock_init(options->clock_type, &action_server->impl->clock, &allocator);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend allowing clock to be passed in to this function. A ROS clock created here won't receive sim time updates. The time source API's in the client libraries currently need the higher level clock type to do that.

https://github.com/ros2/rclcpp/blob/33a755c535d654c97401eb6d199580368c19eb40/rclcpp/include/rclcpp/time_source.hpp#L63

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. Then I suppose it will not be the action servers responsibility to finalize the clock and we hope that it stays valid as long as the action server is valid. Does this sound right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this sound right?

I think so

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 4eb7fdb

default_options.status_topic_qos = rcl_action_qos_profile_status_default;
default_options.allocator = rcl_get_default_allocator();
default_options.clock_type = RCL_ROS_TIME;
default_options.result_timeout.nanoseconds = (rcl_duration_value_t)9e11; // 15 minutes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recommend RCUTILS_S_TO_NS(15 * 60) for readability and to avoid the cast from a floating point literal.

https://github.com/ros2/rcutils/blob/3c982d048914e1c30002d8ea69d86ac1cc6976fd/include/rcutils/time.h#L30

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

_goal_info_stamp_to_nanosec(const rcl_action_goal_info_t * goal_info)
{
assert(goal_info);
return (int64_t)(goal_info->stamp.sec * 1e9) + (int64_t)goal_info->stamp.nanosec;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RCUTILS_S_TO_NS(goal_info->stamp.sec) + ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

{
assert(nanosec);
assert(goal_info);
goal_info->stamp.sec = (int32_t) (*nanosec / (int64_t)1e9);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

assert(nanosec);
assert(goal_info);
goal_info->stamp.sec = (int32_t) (*nanosec / (int64_t)1e9);
goal_info->stamp.nanosec = (uint32_t)(*nanosec - (int64_t)(goal_info->stamp.sec * 1e9));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nanosec % RCUTILS_S_TO_NS(1)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

goal_handles = (rcl_action_goal_handle_t **)tmp_ptr;

// Allocate space for a new goal handle
tmp_ptr = allocator.allocate(sizeof(rcl_action_goal_handle_t), allocator.state);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this allocation could be removed by changing action_server->impl->goal_handles could be changed to an array of goal_handles instead of an array of pointers to goal handles.

Copy link
Member Author

@jacobperron jacobperron Nov 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, the main reason I went with an array of pointers was that is made it easier for removing expired goals from the middle of the list:

// Fill in any gaps left in the array with pointers from the end
action_server->impl->goal_handles[i] = action_server->impl->goal_handles[num_goal_handles];
action_server->impl->goal_handles[num_goal_handles--] = NULL;

But I guess it wouldn't be too much overhead to copy the entire goal handle in this case (instead of just the pointer).

ret = rcl_action_goal_handle_get_info(
action_server->impl->goal_handles[i], &status_message->msg.status_list.data[i].goal_info);
if (RCL_RET_OK != ret) {
return RCL_RET_ERROR;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to .._fini() status_message before returning

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

ret = rcl_action_goal_handle_get_status(
action_server->impl->goal_handles[i], &status_message->msg.status_list.data[i].status);
if (RCL_RET_OK != ret) {
return RCL_RET_ERROR;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about deallocating status_message

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

rcl_ret_t
rcl_action_clear_expired_goals(
const rcl_action_server_t * action_server,
size_t * num_expired)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is a C++ wrapper for a goal handle then it might be helpful for the C++ API to separate this API into two: one that says which goals are expired, and another that expires a goal.

This function will fini() goal handles, but a user may have kept a reference to a language specific wrapper rclcpp_action::GoalHandle. It would be nice if the rcl_action goal handle was deallcated when the rclcpp_action::GoalHandle is destructed. Currently this deallocation could happen sooner and calls to the higher level wrapper might use a free'd object.

Copy link
Member Author

@jacobperron jacobperron Nov 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My original thinking was that since the action server is the entity creating the goal handles, it should be the one responsible for destroying them.

If a rcl goal handle is finalized, then the goal handle becomes invalid (ie. rcl_action_goal_handle_is_valid() returns false) and so, I'm pretty sure, any rcl operations involving the goal handle should fail with an error code. So at least the C++ wrapper of a goal handle wouldn't be using a free'd goal handle without getting an explicit error.

Is it enough for the client libraries to check their goal handles with rcl_action_goal_handle_is_valid() and/or get a fresh list of goal handles with rcl_action_server_get_goal_handles() ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it enough for the client libraries to check their goal handles with rcl_action_goal_handle_is_valid()

I guess the question is what does a C++ goal handle wrapper have a reference to? If it has an rcl_action_goal_handle_t * rcl_handle_; pointing to storage owned by rcl_action_server_impl_t, then rcl_action_goal_handle_is_valid(rcl_handle_) isn't safe because the memory it's pointing to could change any time impl->goal_handles is resized. It seems like it needs to be the other way around where the C++ goal handle wrapper has an rcl_action_goal_handle_t and rcl_action_server_t is the one with a pointer to it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see; makes sense now.

Copy link
Contributor

@hidmic hidmic Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so just to be clear, rcl* will handle all incoming result requests by first checking for goal handle validity, rejecting the request once the goal handle is no longer valid and only then deallocating it, right? I'd be somewhat more comfortable with just marking the goal handle as expired to keep finalization and deallocation close together, but this will do to. Only downside is that an error in that case isn't really an error, but the normal logic flow, so we have to be careful not to throw/assert/abort.

Copy link
Contributor

@hidmic hidmic Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, then how does the calling library know when a goal handle has expired?

Copy link
Member Author

@jacobperron jacobperron Nov 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, then how does the calling library know when a goal handle has expired?

What about if we return a list of expired goal handles as part of the expire function?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like an option. Though judging by @sloretz rclcpp API skeleton, I'd imagine that having the client library wrappers checking if the goal handle they own has expired or not may be simpler. But we can somehow reverse the mapping to know which wrappers have to go away when goal handles expire.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The client library can call rcl_action_server_goal_exists() to check if a previously accepted goal has expired.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed finalize of expired goal handles in 1140112.
It is expected that the client library will finalize goal handles either after they expire (which can be checked with rcl_action_server_goal_exists()) or after the action server is finalized.

Note, the rcl goal handles are still initialized in rcl_action_accept_new_goal(). I was going to update the API to take an already initialized goal handle as an argument, but then we lose the time stamp created when the goal was accepted:

// Re-stamp goal info with current time
rcl_action_goal_info_t goal_info_stamp_now = rcl_action_get_zero_initialized_goal_info();
goal_info_stamp_now = *goal_info;
rcl_time_point_value_t now_time_point;
rcl_ret_t ret = rcl_clock_get_now(&action_server->impl->clock, &now_time_point);
if (RCL_RET_OK != ret) {
return NULL; // Error already set
}
_nanosec_to_goal_info_stamp(&now_time_point, &goal_info_stamp_now);

If we want the client library to pass the goal handle to rcl, then we can

  1. Create a setter function for the goal handle's info and override the info in rcl_action_accept_goal_info, or
  2. Leave the responsibility to the client library to use the same clock and stamp the goal handles properly.

}

// Shrink goal handle array if some goals expired
if (*num_expired > 0u) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should deallocate if the new size is zero because allocator.reallocate() is supposed to behave like realloc() which has undefined behavior when the new size is zero.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in c6b436e

for (size_t i = 0; i < total_num_goals; ++i) {
goal_handle = action_server->impl->goal_handles[i];
rcl_ret_t ret = rcl_action_goal_handle_get_info(goal_handle, &goal_info);
assert(RCL_RET_OK == ret);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC assert is compiled out in release builds. Is this an assert() because its calling out an assumption that the above call will always succeed? Is it possible the above call could fail in normal use?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it should always succeed, but after thinking about it some more, this can fail if the goal handle is finalized outside of the action server's control.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 8f9041e


if (uuidcmp(request_uuid, goal_info.uuid)) {
if (rcl_action_goal_handle_is_cancelable(goal_handle)) {
goal_handles_to_cancel[num_goals_to_cancel++] = goal_handle;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional postfix increment? I think the style guide says to always use prefix increment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this is intentional. Assigning the goal handle to index num_goals_to_cancel and then increment.

for (size_t i = 0; i < total_num_goals; ++i) {
goal_handle = action_server->impl->goal_handles[i];
rcl_ret_t ret = rcl_action_goal_handle_get_info(goal_handle, &goal_info);
assert(RCL_RET_OK == ret);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment about assert

if (rcl_action_goal_handle_is_cancelable(goal_handle) &&
((goal_nanosec <= request_nanosec) || uuidcmp(request_uuid, goal_info.uuid)))
{
goal_handles_to_cancel[num_goals_to_cancel++] = goal_handle;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment++

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

rcl_action/src/rcl_action/action_server.c Show resolved Hide resolved
@hidmic
Copy link
Contributor

hidmic commented Nov 15, 2018

Looks like this PR needs a rebase.

@jacobperron
Copy link
Member Author

Rebased.

Copy link
Contributor

@hidmic hidmic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comments, awesome work Jacob!

allocator.deallocate(action_server->impl->goal_handles, allocator.state);
} else {
void * tmp_ptr = allocator.reallocate(
action_server->impl->goal_handles, num_goal_handles, allocator.state);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobperron num_goal_handles --> num_goal_handles * sizeof(rcl_action_goal_handle_t *) ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good catch.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 7aadb55

rcl_action_cancel_request_t cancel_request = rcl_action_get_zero_initialized_cancel_request();
for (int i = 0; i < UUID_SIZE; ++i) {
cancel_request.goal_info.uuid[i] = static_cast<uint8_t>(i + 2);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobperron just curious, why not reusing one of the init_test_uuid*() functions?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can reuse init_test_uui0(), but the init_test_uuid1() wouldn't do because the ID doesn't exist in this test case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 7aadb55

rcl_action_goal_info_t * goal_info = &cancel_response.msg.goals_canceling.data[0];
for (int i = 0; i < UUID_SIZE; ++i) {
EXPECT_EQ(goal_info->uuid[i], static_cast<uint8_t>(i + 2));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobperron could be EXPECT_TRUE(uuidcmp(goal_info->uuid, cancel_request.goal_info.uuid)); as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 7aadb55

goal_info_out = &cancel_response.msg.goals_canceling.data[i];
for (size_t j = 0; j < UUID_SIZE; ++j) {
EXPECT_EQ(goal_info_out->uuid[j], static_cast<uint8_t>(i + j));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobperron same as above but using goals_info_out instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, we would need to reconstruct the uuid in a similar loop before comparing anyways.

goal_info_out = &cancel_response.msg.goals_canceling.data[num_goals_canceling - 1];
for (int i = 0; i < UUID_SIZE; ++i) {
EXPECT_EQ(goal_info_out->uuid[i], static_cast<uint8_t>(i + goal_index));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jacobperron same as above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 7aadb55

* Move communcation tests to separate file
* Define UUID_SIZE
* Remove const for action server in rcl_action_accept_new_goal()
* Make private function static
* Add missing override specifiers
Introduce rcl_clock_t to action server implementation.
* Change internal goal handle array to be an array of pointers.
* Add check for invalid action names
Rather than initializing internally.
The test is not checking expected behavior
Instead, leave it up to the caller to finalize goal handles.
Renamed the function to rcl_action_expire_goals.
Bugfix: Ensure options (containing allocator) are copied before a finalize occurs (e.g. goto fail).
@hidmic
Copy link
Contributor

hidmic commented Nov 20, 2018

@jacobperron One more CI run and I think this one is ready to go.

@jacobperron
Copy link
Member Author

Up to rcl_action:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

Copy link
Contributor

@sloretz sloretz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just tiny changes that can be done later.

@@ -49,8 +53,11 @@ add_library(${PROJECT_NAME}
)

ament_target_dependencies(${PROJECT_NAME}
"rcl"
"rosidl_generator_c"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, alphabetical order

target_include_directories(test_action_communication PUBLIC
include
${rcl_INCLUDE_DIRS}
${test_msgs_INCLUDE_DIRS}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, This is taken care of by ament_target_dependencies() below

target_include_directories(test_action_server PUBLIC
include
${rcl_INCLUDE_DIRS}
${test_msgs_INCLUDE_DIRS}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, This is taken care of by ament_target_dependencies() below

@jacobperron
Copy link
Member Author

@sloretz Thanks, I'll take note and include fixes for the small things in the next PR.

@jacobperron jacobperron merged commit acc974e into master Nov 20, 2018
@jacobperron jacobperron deleted the jacob/action_server branch November 20, 2018 20:04
@jacobperron jacobperron removed the in review Waiting for review (Kanban column) label Nov 20, 2018
nburek pushed a commit to nburek/rcl that referenced this pull request Nov 26, 2018
* Implement action server init, fini, and is_valid functions

* Add macros for initializing services and publishers

* Implement rcl_action_server_get_default_options()

* Implement rcl_action_accept_new_goal()

* Add function, rcl_action_server_goal_exists(), for checking if goal is already being tracked by an action server

* Add unit tests

* Implement rcl_action_server_get_goal_handles()

* Implement rcl_action_server_get_options()

* Implement rcl_action_server_get_action_name()

* Implement rcl_action_get_goal_status_array()

* Bugfix: reset pointers and size in type finalize functions
Also let finalize functions be called on already finalized objects

* Implement send/take functions for action server services

* Implement action server publishers for feedback and status

* Implement rcl_action_process_cancel_request()

* Add partial communication tests

* Define UUID_SIZE

* Use type-erased pointer for rcl_action_publish_status()

* Implement rcl_action_clear_expired_goals()
Introduce rcl_clock_t to action server implementation.

* Change internal goal handle array to be an array of pointers.

* Add check for invalid action names

* Do heap allocation of temporary array to satisfy MSVC compiler

* Bugfix: finalize node in test tear downs and reset expected errors

* Update documentation

* Update package.xml

* Pass in rcl_clock_t to action server
Rather than initializing internally.

* Do not finalize goal handles in expire function
Instead, leave it up to the caller to finalize goal handles.
Renamed the function to rcl_action_expire_goals.
nburek added a commit to nburek/rcl that referenced this pull request Nov 26, 2018
nburek added a commit to nburek/rcl that referenced this pull request Nov 26, 2018
@@ -86,6 +94,34 @@ if(BUILD_TESTING)
)
ament_target_dependencies(test_action_client "rcl" "test_msgs")
endif()
ament_add_gtest(test_action_communication
test/rcl_action/test_action_communication.cpp
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test (as well as the one below) is only covering the default rmw impl. It would be good if they test would be invoked for every rmw impl.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants