Skip to content

C parameters#54

Closed
jacquelinekay wants to merge 1 commit intomasterfrom
c_parameters
Closed

C parameters#54
jacquelinekay wants to merge 1 commit intomasterfrom
c_parameters

Conversation

@jacquelinekay
Copy link
Copy Markdown
Contributor

@jacquelinekay jacquelinekay commented Apr 28, 2016

This is currently an API stub, NOT a fully functional implementation.

I'm submitting this PR to get initial feedback on the approach before I fully implement the API. I'm making an effort to make sure this branch builds and links so that I can also prototype how it will be used in rclcpp.

I suggest starting with test_parameters.cpp, which lays out how the API calls will be used.

Here are the remaining items to address before I will consider this ready for merging:

  • Prototype usage in rclcpp and refine API as needed
  • Add array assign, array copy, and array resize functions in rosidl_generator_c
  • Change rcl_interfaces::msg::ParameterValue to allow arrays of primitives (bool, int, float). (optional, but I think this would be useful!)
  • Finish implementation in this PR
    • Error checking!
    • Sanitize ParameterValue messages by setting unset fields to "NOT_SET"
    • Finish convert_changes_to_event convenience function
    • Add better test coverage (e.g. unsetting parameters)

Some questions that came up while prototyping this:

  • In the current rclcpp implementation, the parameter events topic is global. That is, all nodes publish parameter event changes to the topic "parameter_events". Should the topic instead be node local (e.g."node_name__parameter_events")? Should this be a configuration option?
  • Should ParameterEvent messages be timestamped?
  • Should the floating point type, which has an underlying storage type of "double", be called "float" or "double"?
  • Should set_parameters_atomically be a special case of set_parameters or should they use separate services and clients as they do in this current prototype?
  • Should there be utilities in rcl for managing parameter namespacing? In this implementation, rcl currently has no conception of parameter namespaces, it simply passes a "prefixes" option to list_parameters.
  • Am I abusing macros too much in the .c files? Or am I not using them enough (i.e. should I use them in the header files too)?

Connects to #28

@jacquelinekay jacquelinekay added the in progress Actively being worked on (Kanban column) label Apr 28, 2016
delete this->wait_set;

ret = rcl_parameter_service_fini(this->parameter_service);
delete this->parameter_service;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You should probably delete these in reverse order, i.e. you should probably fini and delete the parameter service before the node.

@wjwwood
Copy link
Copy Markdown
Member

wjwwood commented Apr 29, 2016

For the functions in parameter.h, I think you should consider type erasing the set and get functions. For example:

rcl_ret_t
rcl_parameter_set_integer(
  void * parameter,
  rcl_parameter_type_support_t * ts,
  const char * parameter_name,
  int value);

Where the rcl_parameter_type_support_t struct would look like this:

typedef struct rcl_parameter_type_support_t
{
  rcl_ret_t (*set_integer) (void * parameter, const char * name, int value);
  rcl_ret_t (*set_double) (void * parameter, const char * name, double value);
  // And so on...
} rcl_parameter_type_support_t;

There would be a version of this structure for each language supported and could live in a static (not generated) header in the rcl_interfaces package.

What this lets you do is use either C or C++ versions of the Parameter messages, for example C++:

#include <rcl_interfaces/msg/Parameter.hpp>
#include <rcl_interfaces/cpp/type_support.hpp>

rcl_interfaces::msg::Parameter param;
rcl_parameter_set_integer(
  &param,
  rcl_interfaces::get_cpp_parameter_type_support(),
  "foo", 42);

And the same for C using the same rcl_parameter* functions:

#include <rcl_interfaces/msg/Parameter.hpp>
#include <rcl_interfaces/c/type_support.h>

rcl_interfaces__msg__Parameter param;
rcl_parameter_set_integer(
  &param,
  rcl_interfaces_get_c_parameter_type_support(),
  "foo", 42);

And in the rcl_parameter_set_integer function you'd do something like this:

rcl_ret_t
rcl_parameter_set_integer(
  void * param,
  rcl_parameter_type_support_t * ts,
  const char * name,
  int value)
{
  return ts->set_integer(param, name, value);
}

This is all sort of roundabout, but allows you to add new language types (maybe PyObj * for Python or Local<Object> for NodeJS) without modifying rcl's API. The alternative is to unroll this and have get_int/set_int for functions in rcl for each supported language. In this pr only C is support, but you'd at least need to expand that to include C++ I think.

I suppose it's also worth taking a step back to consider if it is necessary to support more than just C messages in this parameter API. I don't have a high enough level view yet to say one way or the other.

@wjwwood
Copy link
Copy Markdown
Member

wjwwood commented Apr 29, 2016

For the functions in parameter.h and my last comment those could almost just go into rcl_interfaces completely, since they are just operations on the data structures themselves.

However, I think my above argument about using type erasure and type support structures to delegate work for different types applies more to functions like this:

RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_parameter_client_take_set_response(
  const rcl_parameter_client_t * parameter_client,
  rmw_request_id_t * request_header,
  rcl_interfaces__msg__SetParametersResult__Array * set_parameters_result);

This function only supports the C type, and as you mentioned offline, it would be nice to use this interface in rclcpp with the C++ version of the parameter messages. You could imagine something more like this:

RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_parameter_client_take_set_response(
  const rcl_parameter_client_t * parameter_client,
  rmw_request_id_t * request_header,
  void * set_parameters_result,
  rcl_message_type_support_t * set_parameters_result_ts);

Not sure about the types and stuff, but you get the idea. In this way these functions would emulate the underlying functions like publish, take, send_request, take_response, and so on.

{
// the parameter client provides storage and utility functions for parameter event subscription
// Should instead have a create_parameter_event_subscription function for this parameter client?
// rcl_subscription_t * parameter_event_subscription;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Naively, I'd say that the fact that a subscription is involved is an implementation detail of parameters. A related question is whether or not the user can get a handle on the subscription object that the client uses or change the QoS options of that subscription.

If we don't expose these "details" of how parameters work, then I think it's clear that the subscription should be created and destroyed within rcl without extra action from the client library.

I think you've already done the other necessary bits to "abstract" the implementation of the parameter client and server from the user of rcl with rcl_wait_set_add_parameter_client and the matching take functions.

More to your question, can you describe in more detail what create_parameter_event_subscription would do and what the alternative default behavior is?

@wjwwood
Copy link
Copy Markdown
Member

wjwwood commented Apr 29, 2016

Ok, I've finished my first review. I tried to give some useful feedback on any questions I saw and raise questions where I didn't understand, but now I'm just hoping it was more help than hindrance 😄.

@jacquelinekay jacquelinekay self-assigned this May 3, 2016
@jacquelinekay jacquelinekay force-pushed the c_parameters branch 2 times, most recently from 0d8b0c4 to 8a703b0 Compare May 5, 2016 00:36
rcl_interfaces__msg__Parameter * prior_entry = &prior_state->data[prior_idx];
for (new_idx = 0; new_idx < new_state->size; ++new_idx) {
rcl_interfaces__msg__Parameter * new_entry = &new_state->data[new_idx];
// If the parameter has the same name but a different type or value, count it as changed.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Here we assume uniqueness of parameter name in parameter arrays. Is there a place where we prevent user to have duplicated parameter names in a given Parameter__Array ?
For example if one append a new parameter with the same name at the end of the array but different type or value, this parameter won't appear in the parameter event message (given that it wont be catched neither as a changed one nor a new one)
I agree that parameter names should be unique for a given node, I just can't find a place where it's enforced.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Where would you suggest adding the check for uniqueness of parameter keys?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure what the right place would be. I have trouble to figure the scope of this feature. If it's going to be only used for parameters and nowhere else I would put it in the send request client macro so that the client ensure the integrity of the data before interacting with the server and the server never has to deal with duplicates

@jacquelinekay
Copy link
Copy Markdown
Contributor Author

bf05549 will ignore the parameters test for Connext Dynamic. With the fix_cpp_convert branches the test should pass for other middlewares.

@jacquelinekay jacquelinekay added in review Waiting for review (Kanban column) and removed in progress Actively being worked on (Kanban column) labels Jun 1, 2016
@tfoote tfoote added in progress Actively being worked on (Kanban column) and removed in review Waiting for review (Kanban column) labels Jun 14, 2016

#include "rcl_interfaces/srv/set_parameters.h"
#include "rcl_interfaces/msg/set_parameters_result.h"
#include "rcl_interfaces/msg/parameter.h"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think these are used.

@codebot codebot assigned wjwwood and unassigned jacquelinekay Oct 25, 2016
@codebot codebot removed the in progress Actively being worked on (Kanban column) label Oct 25, 2016
@codebot codebot added the ready Work is about to start (Kanban column) label Oct 25, 2016
@wjwwood wjwwood mentioned this pull request Nov 17, 2016
@mikaelarguedas mikaelarguedas self-assigned this Apr 5, 2017
@clalancette clalancette mentioned this pull request Aug 4, 2017
clalancette referenced this pull request in ros2/rmw_connext Aug 15, 2017
mikaelarguedas added a commit that referenced this pull request Nov 22, 2017
mikaelarguedas added a commit that referenced this pull request Nov 28, 2017
emersonknapp pushed a commit to aws-ros-dev/rcl that referenced this pull request Jun 3, 2019
update style to match latest uncrustify
ivanpauno pushed a commit that referenced this pull request Jan 2, 2020
julionce pushed a commit to micro-ROS/rcl that referenced this pull request Jan 15, 2020
julionce pushed a commit to micro-ROS/rcl that referenced this pull request Jan 20, 2020
@ivanpauno
Copy link
Copy Markdown
Member

Closing, as it's a bit outdated (same as ros2/rclcpp#276 (comment)).

@ivanpauno ivanpauno closed this Apr 29, 2020
@wjwwood wjwwood deleted the c_parameters branch April 22, 2021 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready Work is about to start (Kanban column)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants