-
Notifications
You must be signed in to change notification settings - Fork 418
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
Get single parameter #245
Get single parameter #245
Conversation
Should this function have an optional "default value" parameter? Or should we have a separate function that provides that syntax sugar? |
Sorry, looks like merging the other pr makes this one conflict. You'll need to rebase it. |
@wjwwood Rebased Do you think the default value should be on all three versions of the function, or just on the one that returns a parameter? |
Adding more functions (in this case three different signatures) might be helpful for the user but imo it increases the long term maintenance burden since actual functionality and syntactic sugar is mixed (as I mentioned in #233 (comment)). From my point of view we should have one component with a minimal interface providing and implementing all the core functionality (call it a "micro kernel"). Any additional API for syntactic sugar should be separated. |
I thought that the minimal interface as supposed to be provided by rcl, and that rclcpp is the more user-friendly frontend. If we want to keep the node class minimal, we could move all parameter functionality to the That way any node that doesn't pull in the The downside to this approach would be that in order to pass a handle around for creating publishers/subscribers and getting/setting parameters, you would need a pointer to both the |
Would you say that maintainability would be increased if instead of the 3 signatures being completely independent/freestanding, they were composed on top of each-other? |
Sorry, I hit the close and comment instead of the comment button |
@rohbotics I have a different opinion from @dirk-thomas: this is the highest level interface and the appropriate place to have convenience functions. We can choose to back these functions with a minimal interface in the future if we choose. I do agree that you should try to have the functions call each other where possible. It looks like at least two of them are basically duplicates. |
How should I handle the locking between functions if they call each other? |
The higher level one does not need to lock if it's just calling the other one that locks. |
I made all the functions lock, then call a common non-locking private function. |
|
||
rclcpp::parameter::ParameterVariant parameter_variant(parameter); | ||
bool result = get_parameter_(name, parameter_variant); | ||
parameter = parameter_variant.get_value<ParameterT>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If result
is false
will this not raise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not throw if result == false
That enables use like this
double foo = 0.1;
if (!get_parameter("foo", foo) {
set_parameter("foo", foo);
}
We do throw if get_value
fails because of differing types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if result
is false
, then the ParameterVariant
will be "not set" right? So get_value
will raise I think (that was what I was referring to before).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After talking with @rohbotics I think I might be wrong about get_value
throwing because the ParameterVariant
is seeded with the given parameter
value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The seeding doesn't compile with anything other than a string, so looks like I need to rethink this a little bit.
Also, I'd like to clarify that I agree with @dirk-thomas in that we need to restructure the Node class and make a separation between high level interfaces and the foundation of those interfaces. However, I see it as a larger task that goes beyond these couple of new functions, and that it shouldn't be a pre-requisite for opportunistically taking some contributions like this one. |
@wjwwood I cleaned up a little, and we don't need the non-locking private function I added tests here ros2/system_tests#158 as we discussed |
if (get_parameter(name, parameter)) { | ||
return parameter; | ||
} else { | ||
throw std::out_of_range("Parameter: " + name + " does not exist in map"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: would you change this to "Parameter '" + name + "' not set"
? We usually wrap variables output into string inside of quotes in case name
is an empty string, for example. Also, the fact that a map is used is an implementation detail.
Other than my comment, this lgtm. I still need to review the tests you added (thanks for those btw), and then run CI. |
I fixed the exception message |
if (get_parameter(name, parameter)) { | ||
return parameter; | ||
} else { | ||
throw std::out_of_range("Parameter '" + name + "' not set"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, out_of_range
may not be appropriate here. Instead maybe a custom exception should be used... I think if this were a method on a "ParameterSet" or "ParameterMap" object it might make sense because out_of_range
is the functional reason the parameter cannot be returned (the given key resulted in a "key error"), but it's not really the non-functional reason. In the context of a user asking for a parameter, it might make sense to throw a more domain specific exception type.
I've not convinced myself enough to suggest that you should change it right now, but maybe others can give their opinions.
@rohbotics looks like your new tests have some compiler warnings: http://ci.ros2.org/job/ci_linux/1678/warnings20Result/new/ |
One new warning on Windows: http://ci.ros2.org/job/ci_windows/1609/warnings39Result/new/ |
Fixed warning and test on Windows @wjwwood, looks like on windows you have to use C++11's instead of C99's <stdint.h>, or you need a specific include order |
@rohbotics Yeah, makes sense. CI looks good, thanks for following up on this. |
* added function to get parameter by exact name * added ros1 style get_parameter for parameter variant * added ros1 style get_param for non-variant types * Make the get_parameter functions call a private base function * Parameter Variant requires name in constructor * Cleaned up to no longer need private function * Made exception message more clear
…os2#245) * Follow style conventions better and throw eagerly * Use constant naming convention in ZstdCompressor Signed-off-by: Zachary Michaels <zmichaels11@gmail.com>
Added an API for getting a single parameter.
Note: this PR is based on master, and might conflict with my other PR