-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable generate_parameter_module through ament_cmake_python (#161)
- Loading branch information
Showing
11 changed files
with
761 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
Changelog for package cmake_generate_parameter_module_example | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
cmake_minimum_required(VERSION 3.16) | ||
project(cmake_generate_parameter_module_example) | ||
|
||
find_package(ament_cmake REQUIRED) | ||
find_package(ament_cmake_python REQUIRED) | ||
find_package(generate_parameter_library REQUIRED) | ||
|
||
generate_parameter_module(admittance_parameters | ||
cmake_generate_parameter_module_example/parameters.yaml | ||
cmake_generate_parameter_module_example.custom_validation | ||
) | ||
|
||
ament_python_install_package(${PROJECT_NAME}) | ||
|
||
ament_package() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
# Example: | ||
|
||
## Build the node | ||
|
||
``` | ||
mkdir -p colcon_ws/src | ||
cd colcon_ws/src | ||
git clone https://github.com/picknikrobotics/generate_parameter_library.git | ||
cd .. | ||
colcon build | ||
``` | ||
|
||
## Run the Python node | ||
|
||
``` | ||
source install/setup.bash | ||
python3 src/generate_parameter_library/example_cmake_python/cmake_generate_parameter_module_example/minimal_publisher.py --ros-args --params-file src/generate_parameter_library/example_python/config/implementation.yaml | ||
``` | ||
|
||
You should see an output like this: | ||
`[INFO] [1656018676.015816509] [admittance_controller]: Initial control frame parameter is: 'ee_link'` | ||
|
||
|
||
## ROS 2 CLI | ||
|
||
Run the following: | ||
|
||
`ros2 param list` | ||
|
||
You should see: | ||
|
||
``` | ||
/admittance_controller: | ||
admittance.damping_ratio | ||
admittance.mass | ||
admittance.selected_axes | ||
admittance.stiffness | ||
chainable_command_interfaces | ||
command_interfaces | ||
control.frame.external | ||
control.frame.id | ||
enable_parameter_update_without_reactivation | ||
fixed_array | ||
fixed_string | ||
fixed_string_no_default | ||
fixed_world_frame.frame.external | ||
fixed_world_frame.frame.id | ||
ft_sensor.filter_coefficient | ||
ft_sensor.frame.external | ||
ft_sensor.frame.id | ||
ft_sensor.name | ||
gravity_compensation.CoG.force | ||
gravity_compensation.CoG.pos | ||
gravity_compensation.frame.external | ||
gravity_compensation.frame.id | ||
interpolation_mode | ||
joints | ||
kinematics.alpha | ||
kinematics.base | ||
kinematics.group_name | ||
kinematics.plugin_name | ||
kinematics.plugin_package | ||
kinematics.tip | ||
one_number | ||
pid.elbow_joint.d | ||
pid.elbow_joint.i | ||
pid.elbow_joint.p | ||
pid.rate | ||
pid.shoulder_lift_joint.d | ||
pid.shoulder_lift_joint.i | ||
pid.shoulder_lift_joint.p | ||
pid.shoulder_pan_joint.d | ||
pid.shoulder_pan_joint.i | ||
pid.shoulder_pan_joint.p | ||
pid.wrist_1_joint.d | ||
pid.wrist_1_joint.i | ||
pid.wrist_1_joint.p | ||
pid.wrist_2_joint.d | ||
pid.wrist_2_joint.i | ||
pid.wrist_2_joint.p | ||
pid.wrist_3_joint.d | ||
pid.wrist_3_joint.i | ||
pid.wrist_3_joint.p | ||
qos_overrides./parameter_events.publisher.depth | ||
qos_overrides./parameter_events.publisher.durability | ||
qos_overrides./parameter_events.publisher.history | ||
qos_overrides./parameter_events.publisher.reliability | ||
scientific_notation_num | ||
state_interfaces | ||
three_numbers | ||
three_numbers_of_five | ||
use_feedforward_commanded_input | ||
use_sim_time | ||
``` | ||
|
||
All parameter are automatically declared and callbacks are setup by default. You can set a parameter by typing: | ||
|
||
`ros2 param set /admittance_controller control.frame.id new_frame` | ||
|
||
You should see: | ||
|
||
`[INFO] [1656019001.515820371] [admittance_controller]: New control frame parameter is: 'new_frame'` | ||
|
||
Congratulations, you updated the parameter! | ||
|
||
If you try to set a parameter that is read only, you will get an error. Running the following | ||
|
||
`ros2 param set /admittance_controller command_interfaces ["velocity"]` | ||
|
||
will result in the error | ||
|
||
`Setting parameter failed: Trying to set a read-only parameter: command_interfaces.` | ||
|
||
Running the following | ||
|
||
`ros2 param describe /admittance_controller admittance.damping_ratio` | ||
|
||
will show a parameter's description | ||
|
||
``` | ||
Parameter name: admittance.damping_ratio | ||
Type: double array | ||
Description: specifies damping ratio values for x, y, z, rx, ry, and rz used in the admittance calculation. The values are calculated as damping can be used instead: zeta = D / (2 * sqrt( M * S )) | ||
Constraints: | ||
Min value: 0.1 | ||
Max value: 10.0 | ||
``` | ||
|
||
If you try to set a value out of the specified bounds, | ||
|
||
`ros2 param set /admittance_controller admittance.damping_ratio [-10.0,-10.0,-10.0,-10.0,-10.0,-10.0]` | ||
|
||
you will get the error | ||
|
||
`Setting parameter failed: Value array('d', [-10.0, -10.0, -10.0, -10.0, -10.0, -10.0]) in parameter 'admittance.damping_ratio' must be within bounds [0.1, 10.0]` | ||
|
||
If you try to set a vector parameter with the wrong length, | ||
|
||
`ros2 param set /admittance_controller admittance.damping_ratio [1.0,1.0,1.0]` | ||
|
||
you will get the error | ||
|
||
`Setting parameter failed: Length of parameter 'admittance.damping_ratio' is '3' but must be equal to 6` | ||
|
||
If you try to load a yaml file with missing required parameters | ||
|
||
`python3 src/generate_parameter_library/example_cmake_python/cmake_generate_parameter_module_example/minimal_publisher.py --ros-args --params-file src/generate_parameter_library/example_python/config/missing_required.yaml` | ||
|
||
you will get the error | ||
|
||
``` | ||
Traceback (most recent call last): | ||
[...] | ||
rclpy.exceptions.ParameterUninitializedException: The parameter 'fixed_string_no_default' is not initialized | ||
[ros2run]: Process exited with failure 1 | ||
``` |
Empty file.
36 changes: 36 additions & 0 deletions
36
example_cmake_python/cmake_generate_parameter_module_example/custom_validation.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2023 PickNik Inc. | ||
# | ||
# Redistribution and use in source and binary forms, with or without | ||
# modification, are permitted provided that the following conditions are met: | ||
# | ||
# * Redistributions of source code must retain the above copyright | ||
# notice, this list of conditions and the following disclaimer. | ||
# | ||
# * Redistributions in binary form must reproduce the above copyright | ||
# notice, this list of conditions and the following disclaimer in the | ||
# documentation and/or other materials provided with the distribution. | ||
# | ||
# * Neither the name of the PickNik Inc. nor the names of its | ||
# contributors may be used to endorse or promote products derived from | ||
# this software without specific prior written permission. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
# POSSIBILITY OF SUCH DAMAGE. | ||
|
||
|
||
def no_args_validator(param): | ||
return '' | ||
|
||
|
||
def validate_double_array_custom_func(param, arg1, arg2): | ||
return '' |
75 changes: 75 additions & 0 deletions
75
example_cmake_python/cmake_generate_parameter_module_example/minimal_publisher.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2023 PickNik Inc. | ||
# | ||
# Redistribution and use in source and binary forms, with or without | ||
# modification, are permitted provided that the following conditions are met: | ||
# | ||
# * Redistributions of source code must retain the above copyright | ||
# notice, this list of conditions and the following disclaimer. | ||
# | ||
# * Redistributions in binary form must reproduce the above copyright | ||
# notice, this list of conditions and the following disclaimer in the | ||
# documentation and/or other materials provided with the distribution. | ||
# | ||
# * Neither the name of the PickNik Inc. nor the names of its | ||
# contributors may be used to endorse or promote products derived from | ||
# this software without specific prior written permission. | ||
# | ||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
# POSSIBILITY OF SUCH DAMAGE. | ||
|
||
import rclpy | ||
import rclpy.node | ||
|
||
from cmake_generate_parameter_module_example.admittance_parameters import ( | ||
admittance_controller, | ||
) | ||
|
||
|
||
class MinimalParam(rclpy.node.Node): | ||
def __init__(self): | ||
super().__init__('admittance_controller') | ||
self.timer = self.create_timer(1, self.timer_callback) | ||
|
||
self.param_listener = admittance_controller.ParamListener(self) | ||
self.params = self.param_listener.get_params() | ||
self.get_logger().info( | ||
"Initial control frame parameter is: '%s'" % self.params.control.frame.id | ||
) | ||
self.get_logger().info("fixed string is: '%s'" % self.params.fixed_string) | ||
|
||
self.get_logger().info( | ||
"Original joints parameter is: '%s'" % str(self.params.joints) | ||
) | ||
for d in self.params.fixed_array: | ||
self.get_logger().info("value: '%s'" % str(d)) | ||
|
||
def timer_callback(self): | ||
if self.param_listener.is_old(self.params): | ||
self.param_listener.refresh_dynamic_parameters() | ||
self.params = self.param_listener.get_params() | ||
self.get_logger().info( | ||
"New control frame parameter is: '%s'" % self.params.control.frame.id | ||
) | ||
self.get_logger().info("fixed string is: '%s'" % self.params.fixed_string) | ||
for d in self.params.fixed_array: | ||
self.get_logger().info("value: '%s'" % str(d)) | ||
|
||
|
||
def main(args=None): | ||
rclpy.init(args=args) | ||
node = MinimalParam() | ||
rclpy.spin(node) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Oops, something went wrong.