-
Notifications
You must be signed in to change notification settings - Fork 79
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
String parameter with digits and E
or e
(e.g. "123E5") is always interpreted as double
#384
Comments
…rpreted as double https://github.com/ros2/ros2cli/issues/862 Signed-off-by: Tomoya Fujita <[email protected]>
I think this problem is related to https://github.com/ros2/launch_ros/tree/rolling/ros2launch, not in here @clalancette can you move this issue to https://github.com/ros2/launch_ros? note: this problem is reproducible with ros2/ros2@1f5bd8e current head today. |
I ran into this as well (using rclcpp / jazzy binaries) and spent some time digging into what might be the cause. TL;DRThe issue seems to lie with how the param is dumped to a temporary YAML file (launch_ros/actions/node.py#L376) by the Longer descriptionRegardless of how the param is given to the
It gets juggled around a bit by Then the following happens:
So for me this does not look like a problem in https://github.com/ros2/launch_ros, but rather that the consuming code is at fault for failing to parse the YAML value as a string. What do you think @fujitatomoya @clalancette? How to address this?I can see a couple of ways to tackle this:
Related questions and comments
I'd be happy to contribute if I could get some more direction on the above. |
I found some answers:
So it is indeed client library code. Specifically it's in
https://github.com/ros2/libyaml_vendor i.e. https://github.com/yaml/libyaml. AFAICT both PYYAML and |
So here's an executive summary of the issue:
At this point I feel solution 1 (see "On the dumper side") is the best approach. Unless there's something I'm missing, it should always be safe to dump strings explicitly with quotes. Indeed https://www.yaml.info/learn/quote.html even advocates for using explicit quotes (see "Special types"). As for this comment:
This tests data (Linked from yaml.info, so seem credible) implies that PYAML is correct to treat them as strings, and that |
@danielcranston 1st of all, thank you very much for checking all the details and good explanation! ROS 2 https://github.com/ros2/libyaml_vendor/blob/rolling/CMakeLists.txt#L14 specifies the version of libyaml, that only supports YAML 1.1 now.
this can be true if it uses YAML 1.2. after all, i think
related to the following comment(more like guess).
i think pyyaml module uses libyaml internally, but pyyaml addresses this specific case, so that it can support "round-trip-consistent".
So do I. and i do not think there is downside for this i will try to patch it, give me some time. |
@danielcranston @chrmel it would be appreciated if you guys can try #436 to see if that fixes the problem. |
Thanks for making the PR @fujitatomoya, and thanks for shedding more light on the background and checking some of my assumptions. Some replies:
Oh, I wasn't aware of that! But I think that, unless PYYAML was installed with --with-libyaml and some CLoader/CDumper stuff is setup, it uses it's own pure Python implementation. And indeed they mention that there are "some subtle (but not really significant) differences between pure Python and LibYAML based parsers and emitters." I wonder what they might be referring to 😄 But regardless, your point about "round-trip-consistent" still stands.
Provided the "tests data" linked above is a correct representation of how the specs should be behaving, I think it's the other way around?
(but it's a bit ambiguous since it only makes clear what the behavior is for lower case) |
I tried the following with rolling ubuntu noble envirnoment. import yaml
# Data with float and string
data = {
"float_value": 123e5,
"string_value": "123e5"
}
# Dump YAML to a file
with open("output.yaml", "w") as file:
yaml.dump(data, file, default_flow_style=False)
# Read and Load YAML back
with open("output.yaml", "r") as file:
loaded_data = yaml.safe_load(file)
# Print loaded values and their types
print("Loaded Data:", loaded_data)
print("Type of float_value:", type(loaded_data["float_value"]))
print("Type of string_value:", type(loaded_data["string_value"]))
print("Using libyaml:", yaml.__with_libyaml__) # True if libyaml is used
data = yaml.safe_load("""
"float_value": 123e5
""")
print(data)
yaml_data = "value: 123E5"
# Load YAML
loaded_data = yaml.safe_load(yaml_data)
# Print loaded value and its type
print("Loaded Data:", loaded_data)
print("Type of value:", type(loaded_data["value"])) # Expected: <class 'float'>
print(yaml.__version__) root@tomoyafujita:~/ros2_ws/colcon_ws# python3 test.py
Loaded Data: {'float_value': 12300000.0, 'string_value': '123e5'}
Type of float_value: <class 'float'>
Type of string_value: <class 'str'>
Using libyaml: True
{'float_value': '123e5'}
Loaded Data: {'value': '123E5'}
Type of value: <class 'str'>
6.0.1
root@tomoyafujita:~/ros2_ws/colcon_ws# cat output.yaml
float_value: 12300000.0
string_value: 123e5
root@tomoyafujita:~/ros2_ws/colcon_ws# dpkg -l libyaml-0-2
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-=================-=============-============-========================================
ii libyaml-0-2:amd64 0.2.5-1build1 amd64 Fast YAML 1.1 parser and emitter library according to the result above,
this is correct. sorry i mixed up... 😅 thanks for clarification. based on the above result, the root cause is when we change the python dictionary into yaml via after all, i think your deduction is correct. there is nothing wrong with libyaml or pyyaml, they do support |
I agree that the quote representor is a good solution, yeah 👍 To ensure we eliminate any misunderstanding for other readers, I can't resist responding to this though:
Almost 🙂
daniel@daniel:~$ python3
>>> import yaml
>>> yaml.dump
>>> with open("/tmp/temp_params.yaml", "w") as f:
... yaml.dump({"param": "123E4"}, f)
...
>>>
daniel@daniel:~$ cat /tmp/temp_params.yaml
param: 123E4
daniel@daniel:~$ python3
>>> import yaml
>>> with open("/tmp/temp_params.yaml") as f:
... d = yaml.safe_load(f)
...
>>> print(d)
{'param': '123E5'}
>>> print(type(d["param"]))
<class 'str'> Instead the root cause is that
So I would even go so far as to say that Which leads into this line in the code you shared: print("Type of value:", type(loaded_data["value"])) # Expected: <class 'float'> I would expect string, due to the above (again, provided the "tests data" is a valid reference). |
really, this is what i got from Ubuntu Focal/Noble. root@tomoyafujita:~/ros2_ws/work# cat test.py
import yaml
# Data with float and string
data = {
"float_value": 123e5,
"string_value": "123e5"
}
# Dump YAML to a file
with open("output.yaml", "w") as file:
yaml.dump(data, file, default_flow_style=False)
root@tomoyafujita:~/ros2_ws/work# python3 test.py
root@tomoyafujita:~/ros2_ws/work# cat output.yaml
float_value: 12300000.0
string_value: 123e5
|
Ah sorry, you are absolutely right. When I was talking about Sorry for the confusion 🙇 |
@danielcranston no worries. this is really complicated, i lost many times 😅 |
Bug report
When launching a ROS2 node with
ros2 launch ...
a parameter containing digits and E or e is always interpreted as a double value. Even when the parameter is defined as a string parameter and even when the whole parameter is passed as string.Steps to reproduce issue
Create a Python package and have a simple node and launchfile
param_test.py
test.launch.py
Expected behavior
$ ros2 launch param_test test.launch.py param:="123E5" [INFO] [1697811050.937763500] [param_test]: String Param: 123E5
Actual behavior
Additional information
Mirght be related to ros2/ros2cli#677?
ros2 run ...
can be forced to interpret the parameter as a string:$ ros2 run param_test param_test --ros-args -p "param:='123E5'" [INFO] [1697811050.937763500] [param_test]: String Param: 123E5
ros2 launch ...
cannot be forced to take this parameter as a string:The text was updated successfully, but these errors were encountered: