-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
[binary filter] change boolean ros params #3796
base: main
Are you sure you want to change the base?
[binary filter] change boolean ros params #3796
Conversation
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.
I think also this entire thing could use a single https://docs.ros2.org/bouncy/api/rclcpp/classrclcpp_1_1_async_parameters_client.html, having the individual /set_parameter
clients seems not great
nav2_costmap_2d/include/nav2_costmap_2d/costmap_filters/binary_filter.hpp
Outdated
Show resolved
Hide resolved
param.param_name.c_str(), param.node_name.c_str()); | ||
|
||
auto change_parameters_client_ = node->create_client<rcl_interfaces::srv::SetParameters>( | ||
"/" + param.node_name + "/set_parameters"); |
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.
What if we have a namespace applied?
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.
I can removed the absolute slash ("/" +
) to make it automatically handle namespaces, but I guess then there would be an issue with /local_costmap
//global_costmap
sub-namespace of the costmap, which - I think - is the same reason why you use /scan
(instead of scan) in the obstacle layers (using a relative source, e.g. scan
creates a subscription to /global_costmap/scan
).
I mean, I kept it absolute to have more control. This way a user can add the namespace in the params file, while if the namespace would be handled automatically a user would need to do a remap.
What do you suggest?
I think something like this (from costmap_2d_ros would solve it:
"map_topic", rclcpp::ParameterValue(
(parent_namespace_ == "/" ? "/" : parent_namespace_ + "/") + std::string("map")));
But I don't have such information (parent_namespace_
) at costmap filter level
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.
To be honest I'm not sure about how I could solve this... As I said, the filter has not the access level to distinguish between the two namespaces, so only workarounds come to my mind (e.g. the only two sub_namespace I can image for these filter are global_costmap
and local_costmap
, so I could simply cut them from the service name), but I don't think that having earthbound reasoning is acceptable
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.
What will be happened, if you will just remain the
auto change_parameters_client_ = node->create_client<rcl_interfaces::srv::SetParameters>(
param.node_name + "/set_parameters");
without leading "/"?
- If
param.node_name
is specified in absolute path (e.g./some_node
) will be will applied as/some_node/set_parameters
service. - If
param.node_name
is specified in relative path (e.g.some_node
), won't service will be created relative to current BinaryFilter namespace:some_node/set_parameters
which will be treated as/my_namespace/some_node/set_parameters
when operating with it in the run-time?
auto change_parameters_client_ = node->create_client<rcl_interfaces::srv::SetParameters>( | ||
"/" + param.node_name + "/set_parameters"); | ||
change_parameters_clients_.push_back(change_parameters_client_); | ||
} |
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.
Perform wait for service here to make sure up before continuing
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.
void BinaryFilter::changeParameters(const bool state) | ||
{ | ||
for (size_t param_index = 0; param_index < binary_parameters_info_.size(); ++param_index) { | ||
if (!change_parameters_clients_.at(param_index)->wait_for_service( |
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.
Remove wait for service here
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 wait for service cycle seems to be moved to the end of BinaryFilter::initializeFilter()
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 related to previous comment:
Perform wait for service here to make sure up before continuing
Do you mean that if any service goes timeout at the beginning we should not add it or just give an error/warning? What if the server is temporary offline (e.g. from a plugin)?
Also, a node could go offline at a certain point and since the service is checked only at initialization time, there would not be information for the user to understand that parameters are not updated.
I understand that adding the wait_for_server
slows down the execution, but in my opinion it should be the user to keep attention to the selected parameters (e.g. too many "offline" servers).
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.
Once the BF is being configured, we need to check that services/nodes are available on that stage. Later on we are assuming that everything is OK, and we are working with bringed-up nodes. If something goes wrong (e.g. node became offline), service request should fail by timeout. For that, see Steve comment from above and please use spin_until_future_complete(future_result, change_parameter_timeout_)
API to not have infinite loops. Anyway, loosing the service with the node - is extraordinary situation, which could be handled by other than each time checking for service availability way (performance for usual serivce calls in this way will be faster, and we still could handle error situations).
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.
Hi there. I agree with using spin_until_future_complete(future_result, change_parameter_timeout_)
. However to me it's still not clear what should the filter do if a node is offline. I mean, service request fail by timeout and then? Should I throw an error? While log seems not much substantial, as I was saying this seems to be a little bit much. What if a node is not active yet or has just crashed and will be up again in a few seconds?
Anyway, it is only a matter of choices. If you want this to work only with nodes that are always up, it's ok!
By the way I could also add another parameter to somehow distinguish between "always-up" nodes and "discontinuous" ones (for instance plugin). Or adding a "global" timeout (not for the service request timeout but for the node in general, for instance 10 seconds timeout after the first service request timeout... this would implies some re-call logic, even when there's no binary state change). Or simply logging but also exposing error information for any third part diagnostic nodes... I really don't know, just shooting ideas
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.
There is no need to add global timeouts and try to re-send the service again. This should be a responsibility of DDS implementation, and if some node is not online for some reasons (e.g. bad network connection), DDS to re-try to deliver the request to the given node within a timeout. So, there is no need to do the same job twice.
Regarding throwing an exception, this is a good question. Changing the state of node - is a serious situation that might break full logic working mechanisms on the end-developer side. Imagine, if you have some handling "NodeA" that is having two sub-algorithms: robot local planning and hand manipulation. By moving into some marked area, the BinaryFilter decides to stop the robot and send a binary state to "NodeA" to switch algorithm from navigation -> to hand manipulation. If this signal won't be delivered to "NodeA", it will continue to working as previously, so the normal operation logic will break.
Additionally, this situation could be treated as ROS-parameter setting error, which is also always going with exceptions throwing.
So from this, I'd more inclined that we need to throw an error in service failure situation (and thus, stop normal BF execution).
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.
I mean, I agree a log is not enough, while an exception may be too much in some cases. What do you think of adding a parameter for letting the user decide this one?
Each parameter can have a parameter for this: something like a boolean critical
(default True
).
Any suggestion on the name is appreciated! It could be reverse also, like is_optional
(default False
).
Configuration would be:
ParamNamespace:
node_name: "node"
param_name: "param"
default_state: True
is_critical: False
Hence the code should look like this:
if (!change_parameters_client->wait_for_service(
std::chrono::milliseconds(change_parameter_timeout_)))
{
if (param.is_critical){
throw std::runtime_error("BinaryFilter: Service " +
std::string(change_parameters_client->get_service_name()) +
"not available!");
}
RCLCPP_ERROR(
logger_, "BinaryFilter: service %s not available. Skipping ...",
change_parameters_client->get_service_name());
} else {
RCLCPP_INFO(
logger_, "BinaryFilter: service %s available.",
change_parameters_client->get_service_name());
}
}
We could also think of having just one global parameter for the filter, without giving the chance to specify the behavior for each parameter, but I don't see great advantages a part from having less parameters.
What do you think?
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.
What is the example when we have the parameter of some node not changed, but we are still normally operating? Is this worth to skip this node in the config file at all, which is not reliable and not necessary for us?
I doubt about such situation: imagine - you have some node which might be offline or online. And you can not guarantee it's parameters consistency. Is it real worth to support? In this case, I believe it is better to throw to developer an exception causing an error, allowing the developer to remove this unreliable node from config at all. Since the node is unreliable, it's binary param won't be guaranteed to be consistent, and thus I do not think, this is normal situation.
In other words, not-changing / not-setting of ROS parameters - is already a critical situation which throws and error in ROS2 API. For these cases, we could compare setting the parameter through a service request and thus it could be treated with exception.
Adding additional parameter to choose throw exceptions or not for the unreliable nodes, in my opinion - over-complicating the structure, since we are still could not rely on this flaky node parameter, so why don't throw error instead in all times?
binary_parameters_info_.at(param_index).param_name.c_str(), | ||
bool_param.value.bool_value ? "true" : "false"); | ||
auto future_result = change_parameters_clients_.at(param_index)->async_send_request( | ||
request, response_received_callback); |
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.
Remove callback. Spin until future complete. Then check the value and throw something more substantial than a log if it failed. Just a log failure isn't good enough
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.
I guess it depends on what you think about this
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 main code has been checked. Please check the first Steve review and these items. After the code will be more-less stabilized, we could advance to next step with testcases and documentation verification.
nav2_costmap_2d/include/nav2_costmap_2d/costmap_filters/binary_filter.hpp
Outdated
Show resolved
Hide resolved
void BinaryFilter::changeParameters(const bool state) | ||
{ | ||
for (size_t param_index = 0; param_index < binary_parameters_info_.size(); ++param_index) { | ||
if (!change_parameters_clients_.at(param_index)->wait_for_service( |
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 wait for service cycle seems to be moved to the end of BinaryFilter::initializeFilter()
@enricosutera, this is kind ping, since there are no news more than one month. Are there any updates on this PR? |
@SteveMacenski |
@enricosutera good point, let me look at this again - but you have not yet responded to the bulk of the comments in my last review |
But generally looks good! Much better now |
@enricosutera, thank you for the update and taking care on this. Started the review, but I'm running out-of-time today. Will complete it at the beginning of next week. |
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.
Adding the review comments for the main code. There are some items remaining to fix from this and previous reviews.
void BinaryFilter::changeParameters(const bool state) | ||
{ | ||
for (size_t param_index = 0; param_index < binary_parameters_info_.size(); ++param_index) { | ||
if (!change_parameters_clients_.at(param_index)->wait_for_service( |
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.
Once the BF is being configured, we need to check that services/nodes are available on that stage. Later on we are assuming that everything is OK, and we are working with bringed-up nodes. If something goes wrong (e.g. node became offline), service request should fail by timeout. For that, see Steve comment from above and please use spin_until_future_complete(future_result, change_parameter_timeout_)
API to not have infinite loops. Anyway, loosing the service with the node - is extraordinary situation, which could be handled by other than each time checking for service availability way (performance for usual serivce calls in this way will be faster, and we still could handle error situations).
nav2_costmap_2d/include/nav2_costmap_2d/costmap_filters/binary_filter.hpp
Show resolved
Hide resolved
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.
There are a few items remained:
- Throw an exception if service was failed (discussable)
- Remove unnecessary calling of
wait_for_service
fromchangeParameters()
- Allow to use relative namespaces in ROS-parameters ([binary filter] change boolean ros params #3796 (comment))
- Switch to use non-default ROS-parameters instead of empty strings
- Future destroyed after end-of-loop question ([binary filter] change boolean ros params #3796 (comment))
- Other minor changes / nitpicks from the items below
Test code coverage is >95%
for binary_filter.cpp
which is OK (some exceptions were not covered):
@AlexeyMerzlyakov All the above points are satisfied a part from these two:
have you read my comment? Do you have any suggestion? |
@enricosutera, apologies for late respond: I was overkilled with other activities on prev. two weeks. Please refer to my comments on remaining two questions (exceptions and namespaces in service calls) from above |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #3796 +/- ##
==========================================
+ Coverage 89.75% 89.84% +0.09%
==========================================
Files 431 431
Lines 19571 19632 +61
==========================================
+ Hits 17566 17639 +73
+ Misses 2005 1993 -12 ☔ View full report in Codecov by Sentry. |
@enricosutera is it your intent to finish up this PR? I generally don't like to leave things hanging like this indefinitely |
Thank you for pinging. Yes I do. I will give a last shot asap |
…d acceleration limits (ros-navigation#3731) Signed-off-by: enricosutera <[email protected]>
* Fix GoalUpdater QoS * Fixes Signed-off-by: enricosutera <[email protected]>
…-navigation#3734) Signed-off-by: enricosutera <[email protected]>
…vigation#3733) * smach_planner_hybrid: add support visualization for hybrid Astar * smac_planner_hyrid: revert some * smach_planner_hybrid: improving code quality * utils: add some useful functions * utils: fix mistake * nav2_smac_planner: fix format problem * utils: fix format and revise functions * smach_planner_hybrid: delete _viz_expansion parameter * smac_planner_hybrid: fix format * README: update parameter * utils: corrct mistake return * utils: make timestamp a const reference * nav2_smac_planner: correct format problem * add unit test functions * further detection of element equality * test_utils: add non-trival translation and rotation * smac_planner_hybrid: pass value instead of references * completing hybrid A* visualization --------- Co-authored-by: xianglunkai <[email protected]> Signed-off-by: enricosutera <[email protected]>
* Update README.md * Update README.md Signed-off-by: enricosutera <[email protected]>
* adding uid to the logged message Signed-off-by: Christian Henkel <[email protected]> * less changes Signed-off-by: Christian Henkel <[email protected]> --------- Signed-off-by: Christian Henkel <[email protected]> Signed-off-by: enricosutera <[email protected]>
…ion#3751) * rviz view straight in default xy orientation Signed-off-by: Christian Henkel <[email protected]> * gazebo orientation to match rviz Signed-off-by: Christian Henkel <[email protected]> * rotating in direction of view --------- Signed-off-by: Christian Henkel <[email protected]> Signed-off-by: enricosutera <[email protected]>
1. Set forward_prune_distance to 1.0 to robot not getting lost 2. Correct map name for costmap filter tests Signed-off-by: enricosutera <[email protected]>
Signed-off-by: enricosutera <[email protected]>
Signed-off-by: enricosutera <[email protected]>
Signed-off-by: ymd-stella <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: enricosutera <[email protected]>
…ore launch navigation. (ros-navigation#3572) * Make it possible to launch namspaced robot which rewrites `<robot_namespace>` to namespace. - It allows to apply namespace automatically on specific target topic path in costmap plugins. Add new nav2 params file for multi-robot(rewriting `<robot_namespace>`) as an example. - nav2_multirobot_params_all.yaml Modify nav2_common.ReplaceString - add condition argument * Update nav2_bringup/launch/bringup_launch.py Co-authored-by: Steve Macenski <[email protected]> * Add new luanch script for multi-robot bringup Rename luanch script for multi-robot simulation bringup Add new nav2_common script - Parse argument - Parse multirobot pose Update README.md * Update README.md Apply suggestions from code review Fix pep257 erors Co-authored-by: Steve Macenski <[email protected]> --------- Co-authored-by: Steve Macenski <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: Tony Najjar <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: enricosutera <[email protected]>
* Rename PushRosNamespace to PushROSNamespace * Fix min_points checking * Add polygon source * Revert "Merge branch 'add-collision-points-debug' into add-polygon-source" This reverts commit 15c261c, reversing changes made to 5a63584. * . * fix * fix * fix lint * PR comments fixes * fixes * add test * fix space * use standard msg Polygonstamped * draft * . * fixes * fixes * fixes * fix * revert * fixes * add detector test * rebasing fixes * Adding polygon source * adjusting tests * linting --------- Co-authored-by: Tony Najjar <[email protected]> Co-authored-by: Tony Najjar <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: James Ward <[email protected]> Signed-off-by: enricosutera <[email protected]>
* provide validation_message.hpp Signed-off-by: goes <[email protected]> * fix typo Signed-off-by: goes <[email protected]> * add test_validation_messages.cpp Signed-off-by: goes <[email protected]> * change include-order Signed-off-by: goes <[email protected]> * reformat Signed-off-by: goes <[email protected]> * update test Signed-off-by: goes <[email protected]> --------- Signed-off-by: goes <[email protected]> Co-authored-by: goes <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: Silvio Traversaro <[email protected]> Signed-off-by: enricosutera <[email protected]>
) When the path is shorter than ´forward_sampling_distance´ the rotatitonShimController would directly give control to the primary controller to navigate to the goal. This would lead to the exact behavior that was tried to be fixed by the rotationShimController: "The result is an awkward, stuttering, or whipping around behavior" [1]. It often resulted in navigation failure. In this case, the controller should try to rotate towards the last point of the path, so that the primary controller can have a better starting orientation. [1] https://navigation.ros.org/tuning/index.html#rotate-in-place-behavior Signed-off-by: enricosutera <[email protected]>
…os-navigation#4293) % `ruff check` ``` Error: nav2_system_tests/src/system/test_wrong_init_pose_launch.py:117:21: F601 Dictionary key literal `'use_composition'` repeated ``` % ` ruff rule F601` # multi-value-repeated-key-literal (F601) Derived from the **Pyflakes** linter. Fix is sometimes available. ## What it does Checks for dictionary literals that associate multiple values with the same key. ## Why is this bad? Dictionary keys should be unique. If a key is associated with multiple values, the earlier values will be overwritten. Including multiple values for the same key in a dictionary literal is likely a mistake. ## Example ```python foo = { "bar": 1, "baz": 2, "baz": 3, } foo["baz"] # 3 ``` Use instead: ```python foo = { "bar": 1, "baz": 2, } foo["baz"] # 2 ``` ## References - [Python documentation: Dictionaries](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) Signed-off-by: Christian Clauss <[email protected]> Signed-off-by: enricosutera <[email protected]>
* Add footprint clearing for static layer Signed-off-by: Tony Najjar <[email protected]> * fix flckering --------- Signed-off-by: Tony Najjar <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: Steve Macenski <[email protected]> Signed-off-by: enricosutera <[email protected]>
…#4300) Signed-off-by: PRP <[email protected]> Signed-off-by: enricosutera <[email protected]>
* 64 bit for index Signed-off-by: Guillaume Doisy <[email protected]> * Graph storing in uint64 * Remove incorrect usage --------- Signed-off-by: Guillaume Doisy <[email protected]> Co-authored-by: Guillaume Doisy <[email protected]> Signed-off-by: enricosutera <[email protected]>
Update link to docs Signed-off-by: João Britto <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: Pradheep <[email protected]> Signed-off-by: enricosutera <[email protected]>
…n#4313) Signed-off-by: enricosutera <[email protected]>
When I build `nav2_amcl` with `-Wl,--no-undefined` I noticed `libpf_lib.so` has undefined symbols. This PR correctly links `libpf_lib.so` to `libm` so all symbols can be found. You can verify this by executing the following command: ``` ldd -r ./build/nav2_amcl/src/pf/libpf_lib.so linux-vdso.so.1 (0x00007ffd1f8c0000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000074e909a00000) /lib64/ld-linux-x86-64.so.2 (0x000074e909e60000) undefined symbol: ceil (./build/nav2_amcl/src/pf/libpf_lib.so) undefined symbol: atan2 (./build/nav2_amcl/src/pf/libpf_lib.so) undefined symbol: sin (./build/nav2_amcl/src/pf/libpf_lib.so) undefined symbol: hypot (./build/nav2_amcl/src/pf/libpf_lib.so) undefined symbol: cos (./build/nav2_amcl/src/pf/libpf_lib.so) undefined symbol: log (./build/nav2_amcl/src/pf/libpf_lib.so) undefined symbol: sqrt (./build/nav2_amcl/src/pf/libpf_lib.so) undefined symbol: floor (./build/nav2_amcl/src/pf/libpf_lib.so) ``` Signed-off-by: Ramon Wijnands <[email protected]> Signed-off-by: enricosutera <[email protected]>
…n#4301) * add validation check for PoseWithCovarianceStamped Signed-off-by: goes <[email protected]> * remove rebundant check before Signed-off-by: goes <[email protected]> * reformat Signed-off-by: goes <[email protected]> * typo fixed Signed-off-by: goes <[email protected]> * change the type-name Signed-off-by: goes <[email protected]> * update test Signed-off-by: goes <[email protected]> * reformat Signed-off-by: goes <[email protected]> * . Signed-off-by: goes <[email protected]> * add comment Signed-off-by: goes <[email protected]> * update comment Signed-off-by: goes <[email protected]> * change header Signed-off-by: goes <[email protected]> * update test Signed-off-by: goes <[email protected]> * typo fixed Signed-off-by: goes <[email protected]> --------- Signed-off-by: goes <[email protected]> Co-authored-by: goes <[email protected]> Signed-off-by: enricosutera <[email protected]>
…::getClosestAngularBin. (ros-navigation#4324) Signed-off-by: Krzysztof Pawełczyk <[email protected]> Co-authored-by: Krzysztof Pawełczyk <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: Steve Macenski <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: Steve Macenski <[email protected]> Signed-off-by: enricosutera <[email protected]>
Signed-off-by: Steve Macenski <[email protected]> Signed-off-by: enricosutera <[email protected]>
* add bond_heartbeat_period Signed-off-by: Guillaume Doisy <[email protected]> * lint Signed-off-by: Guillaume Doisy <[email protected]> --------- Signed-off-by: Guillaume Doisy <[email protected]> Co-authored-by: Guillaume Doisy <[email protected]> Signed-off-by: enricosutera <[email protected]>
Fix the bug that isPathUpdated function will return false for the reason that it compare the timestaped between new path and old path's last pose Signed-off-by: StetroF <[email protected]> Signed-off-by: enricosutera <[email protected]>
…os-navigation#4346) Signed-off-by: Guillaume Doisy <[email protected]> Co-authored-by: Guillaume Doisy <[email protected]> Signed-off-by: enricosutera <[email protected]>
* remove spin test that is failing reliably * cont. Signed-off-by: enricosutera <[email protected]>
Signed-off-by: enricosutera <[email protected]>
Signed-off-by: enricosutera <[email protected]>
2e0795f
to
e50c168
Compare
Signed-off-by: enricosutera <[email protected]>
Codecov ReportAttention: Patch coverage is
|
Basic Info
Description of contribution in a few bullet points
Description of documentation updates required from your changes
Future work that may be required in bullet points
double
parameters dynamically.For Maintainers: