Skip to content

Commit ed62aed

Browse files
authored
Fix newline issue (#176)
* fix new line rendering for Python Signed-off-by: Paul Gesel <paul.gesel@picknik.ai>
1 parent 42c8f8a commit ed62aed

File tree

7 files changed

+92
-9
lines changed

7 files changed

+92
-9
lines changed

example/src/parameters.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,35 @@ admittance_controller:
276276
default_value: [3,3,3],
277277
read_only: true,
278278
}
279+
hover_override: {
280+
type: int,
281+
default_value: 1,
282+
description: "Override hover action:\n0: Hover\n1: Push\n2: Pull\n-1: Do not override",
283+
validation: {
284+
one_of<>: [ [ 0, 1, 2, -1 ] ],
285+
},
286+
}
287+
angle_wraparound: {
288+
type: bool,
289+
default_value: false,
290+
description: 'For joints that wrap around (without end stop, ie. are continuous),
291+
where the shortest rotation to the target position is the desired motion.
292+
If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`.
293+
Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured
294+
position :math:`s` from the state interface.'
295+
}
296+
open_loop_control: {
297+
type: bool,
298+
default_value: false,
299+
description: "Use controller in open-loop control mode
300+
\n\n
301+
* The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation.\n
302+
* It deactivates the feedback control, see the ``gains`` structure.
303+
\n\n
304+
This is useful if hardware states are not following commands, i.e., an offset between those (typical for hydraulic manipulators).
305+
\n\n
306+
If this flag is set, the controller tries to read the values from the command interfaces on activation.
307+
If they have real numeric values, those will be used instead of state interfaces.
308+
Therefore it is important set command interfaces to NaN (i.e., ``std::numeric_limits<double>::quiet_NaN()``) or state values when the hardware is started.\n",
309+
read_only: true,
310+
}

example_python/generate_parameter_module_example/parameters.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,3 +284,35 @@ admittance_controller:
284284
default_value: [3,3,3],
285285
read_only: true,
286286
}
287+
hover_override: {
288+
type: int,
289+
default_value: 1,
290+
description: "Override hover action:\n0: Hover\n1: Push\n2: Pull\n-1: Do not override",
291+
validation: {
292+
one_of<>: [ [ 0, 1, 2, -1 ] ],
293+
},
294+
}
295+
angle_wraparound: {
296+
type: bool,
297+
default_value: false,
298+
description: 'For joints that wrap around (without end stop, ie. are continuous),
299+
where the shortest rotation to the target position is the desired motion.
300+
If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`.
301+
Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured
302+
position :math:`s` from the state interface.'
303+
}
304+
open_loop_control: {
305+
type: bool,
306+
default_value: false,
307+
description: "Use controller in open-loop control mode
308+
\n\n
309+
* The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation.\n
310+
* It deactivates the feedback control, see the ``gains`` structure.
311+
\n\n
312+
This is useful if hardware states are not following commands, i.e., an offset between those (typical for hydraulic manipulators).
313+
\n\n
314+
If this flag is set, the controller tries to read the values from the command interfaces on activation.
315+
If they have real numeric values, those will be used instead of state interfaces.
316+
Therefore it is important set command interfaces to NaN (i.e., ``std::numeric_limits<double>::quiet_NaN()``) or state values when the hardware is started.\n",
317+
read_only: true,
318+
}

generate_parameter_library_py/generate_parameter_library_py/generate_python_module.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838

3939
def run(output_file, yaml_file, validation_module=''):
40+
print(f'Running {__file__} {output_file} {yaml_file} {validation_module}')
4041
gen_param_struct = GenerateCode('python')
4142
output_dir = os.path.dirname(output_file)
4243
if not os.path.isdir(output_dir):

generate_parameter_library_py/generate_parameter_library_py/jinja_templates/python/declare_parameter

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
if not self.node_.has_parameter(self.prefix_ + "{{parameter_name}}"):
22
{%- filter indent(width=4) %}
3-
descriptor = ParameterDescriptor(description="{{parameter_description}}", read_only = {{parameter_read_only}})
3+
descriptor = ParameterDescriptor(description="{{parameter_description|valid_string_python}}", read_only = {{parameter_read_only}})
44
{%- for validation in parameter_validations if ("bounds" in validation.function_name or "lt" in validation.function_name or "gt" in validation.function_name) %}
55
{%- if "DOUBLE" in parameter_type %}
66
{%- if validation.arguments|length == 2 %}

generate_parameter_library_py/generate_parameter_library_py/jinja_templates/python/declare_runtime_parameter

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ entry = {{param_struct_instance}}.{{struct_name}}.get_entry(value)
55
param_name = f"{self.prefix_}{{struct_name}}.{value}.{{parameter_field}}"
66
if not self.node_.has_parameter(self.prefix_ + param_name):
77
{%- filter indent(width=4) %}
8-
descriptor = ParameterDescriptor(description="{{parameter_description}}", read_only = {{parameter_read_only}})
8+
descriptor = ParameterDescriptor(description="{{parameter_description|valid_string_python}}", read_only = {{parameter_read_only}})
99
{%- for validation in parameter_validations if ("bounds" in validation.function_name or "lt" in validation.function_name or "gt" in validation.function_name) %}
1010
{%- if "DOUBLE" in parameter_type %}
1111
{%- if validation.arguments|length == 2 %}

generate_parameter_library_py/generate_parameter_library_py/parse_yaml.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939

4040
from generate_parameter_library_py.cpp_convertions import CPPConverstions
4141
from generate_parameter_library_py.python_convertions import PythonConvertions
42-
from generate_parameter_library_py.string_filters_cpp import valid_string_cpp
42+
from generate_parameter_library_py.string_filters_cpp import (
43+
valid_string_cpp,
44+
valid_string_python,
45+
)
4346

4447

4548
# YAMLSyntaxError standardizes compiler error messages
@@ -513,6 +516,7 @@ def __str__(self):
513516
# Create a Jinja2 environment to register the custom filter
514517
env = Environment()
515518
env.filters['valid_string_cpp'] = valid_string_cpp
519+
env.filters['valid_string_python'] = valid_string_python
516520
j2_template = env.from_string(GenerateCode.templates['declare_parameter'])
517521
code = j2_template.render(data, trim_blocks=True)
518522
return code
@@ -575,6 +579,7 @@ def __str__(self):
575579
# Create a Jinja2 environment to register the custom filter
576580
env = Environment()
577581
env.filters['valid_string_cpp'] = valid_string_cpp
582+
env.filters['valid_string_python'] = valid_string_python
578583
j2_template = env.from_string(
579584
GenerateCode.templates['declare_runtime_parameter']
580585
)

generate_parameter_library_py/generate_parameter_library_py/string_filters_cpp.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,26 @@ def valid_string_cpp(description):
1010
str: The filtered string that is a valid C++ string.
1111
"""
1212
if description:
13+
# remove possible markdown/rst syntax, but add proper indent for cpp-header files.
1314
filtered_description = (
14-
description.replace('\\', '\\\\').replace('"', '\\"').replace('`', '')
15+
description.replace('\\', '\\\\').replace('`', '').replace('\n', '\\n ')
1516
)
16-
# create a quote delimited string for every line
17-
filtered_description = '\n'.join(
18-
f'"{line}"' for line in filtered_description.splitlines()
19-
)
20-
return filtered_description
17+
return f'"{filtered_description}"'
2118
else:
2219
return '""'
20+
21+
22+
def valid_string_python(description):
23+
"""
24+
Filter a string to make it a valid Python string literal.
25+
26+
Args:
27+
description (str): The input string to be filtered.
28+
29+
Returns:
30+
str: The filtered string that is a valid Python string.
31+
"""
32+
if description:
33+
return description.replace('\n', '\\n ')
34+
else:
35+
return ''

0 commit comments

Comments
 (0)