-
Notifications
You must be signed in to change notification settings - Fork 164
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
Enable ros2tpoic hz command #133
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.
Looks great thanks @yechun1 !
I made a few comments / questions below
ros2topic/ros2topic/verb/hz.py
Outdated
@@ -0,0 +1,239 @@ | |||
# Copyright 2017 Open Source Robotics Foundation, Inc. |
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 vast majority of this code is copied from here the license and copyright should stay the same.
If possible with a comment indicating what version of the file it was copied from (similar to https://github.com/ros2/turtlebot2_demo/blob/2017ddd2c5781434d9dbcb0c172d553e28f7ab02/depthimage_to_pointcloud2/include/depthimage_to_pointcloud2/depth_traits.hpp#L34)
We should also add a license tag with BSD in the package.xml of ros2topic
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.
Stayed with original license, but seems it does not match copyright test.
@pytest.mark.copyright
def test_copyright():
rc = main(argv=['.', 'test'])
assert rc == 0, 'Found errors'
E AssertionError: Found errors
E assert 1 == 0
test/test_copyright.py:23: AssertionError
Captured stderr call
ros2topic/verb/hz.py: copyright=Willow Garage, Inc. (2008), license=
1 errors
ros2topic/setup.py
Outdated
@@ -37,6 +37,7 @@ | |||
'info = ros2topic.verb.info:InfoVerb', | |||
'list = ros2topic.verb.list:ListVerb', | |||
'pub = ros2topic.verb.pub:PubVerb', | |||
'hz = ros2topic.verb.hz:HzVerb', |
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.
Nit: alphabetical order
ros2topic/ros2topic/verb/hz.py
Outdated
|
||
|
||
class HzVerb(VerbExtension): | ||
"""print the average publishing rate to screen.""" |
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.
Nit: print -> Print
ros2topic/ros2topic/verb/hz.py
Outdated
parser.add_argument( | ||
'--window', '-w', default=-1, | ||
help='window size, in # of messages, for calculating rate, ' | ||
'string to (default: -1)') |
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.
As this does not add the --filter
and --wall-time
arguments, would you mind adding a TODO or opening a ticket to track that these options still need to be ported?
ros2topic/ros2topic/verb/hz.py
Outdated
:param topic: Topic name | ||
""" | ||
with self.lock: | ||
curr = time.time() |
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.
It looks like the ROS 1 version of the tool uses ROSTime as the default time source and Walltime only if requested. Is it possible to do the same 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.
There is no simple API similar with rospy.get_rostime (for example rclpy.get_rostime). Added TODO to replace time later. Would you share me the ros2 rostime reference code?
ros2topic/ros2topic/verb/hz.py
Outdated
""" | ||
Calculate the average publising rate. | ||
|
||
@returns: tuple of stat results |
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.
Nit: please use the same docblock format for all functions
e0080ac
to
4cf4fa1
Compare
@mikaelarguedas thanks for your review and comments. Just fixed all those errors and added TODOs. One issue is running test_copyright.py will fail with original copyright. Will it make impact? or do you have suggest how to fix? thanks. |
thanks @yechun1 for iterating. Regarding the copyright, it looks like the formatting was diverging from the BSD license template. You can see this commit 8db6c67 for a fir that will make the copyright test pass. Regarding ROS Time, this is pretty new in rclpy but hopefully you will find some useful information in ros2/rclpy#210 |
@mikaelarguedas thanks for your suggestion. I have submitted new commits to fix TODOs. Would you please help to review? thanks. |
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.
Thanks @yechun1 for adding the missing features!
The code looks good to me with a couple minor comments (inline).
I faced a few inconsistencies when testing this patch for high frequency messages (the reported frequency was always lower but I didn't get a chance to investigate where the bottleneck was). Did you experience the same thing?
Example of commands I used for testing:
PYTHONOPTIMIZED=0 ros2 topic pub /image sensor_msgs/Image -r 1000 -p 1000
PYTHONOPTIMIZED=0 ros2 topic hz /image
.
Can you please comment here when you have all the tests passing locally? Someone from @ros2/team will review and rerun Ci.
Thanks!
ros2topic/ros2topic/verb/hz.py
Outdated
:param topic: topic name, ``list`` of ``str`` | ||
:param window_size: number of messages to average over, -1 for infinite, ``int`` | ||
:param filter_expr: Python filter expression that is called with m, the message instance | ||
:param blocking: pause hz until topic is published, ``True`` |
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.
Could you clarify what True
refers to here?
It appears that this argument defaults to False
, I think the docblock should either refer to the type bool
and / or list the default value False
.
ros2topic/ros2topic/verb/hz.py
Outdated
except ValueError as e: | ||
raise RuntimeError('Value must be non-negative integer') | ||
|
||
# #694 |
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 694 referring too?
Oh it comes from ROS 1. As this doesn't refer to any existing bug tracker I think it would be less confusing to remove it from here and everywhere else in this file.
ros2topic/ros2topic/verb/hz.py
Outdated
try: | ||
window_size = int(args.window) | ||
except ValueError as e: | ||
raise RuntimeError('Value must be non-negative integer') |
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.
It looks like both this check and the implementation accept negative-integers
ros2topic/ros2topic/verb/hz.py
Outdated
@@ -0,0 +1,315 @@ | |||
# Software License Agreement (BSD License) |
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.
Can you please move line 1 and 2 to line 3 and 4 (as recommended in previous review) this should be enough to fix the linter error (now that ament/ament_lint#106 has been merged)
A small changes to fix issues by code review. Code has been rebased and all tests passed in my local (by ament test). @ros2/team will you please help review and rerun Ci.
@mikaelarguedas |
I reproduced the frequency continually reduce issue, I am investigating it. |
fb030b5
to
06bdaa3
Compare
@yechun1 What is the status on this? |
this is pending on the publish issue #140. I have not found the root cause. |
The pending Issue #140 have been fixed. test results is good on my system: $ ros2 topic pub /Image sensor_msgs/Image -r 1000 -p 1000 $ ros2 topic hz /image -w 1 $ ros2 topic hz /image -w 10 $ ros2 topic hz /image -w 1000 $ ros2 topic hz /image |
@dirk-thomas @mikaelarguedas all found issues fixed in this PR. Function verified on my local. Would you please help to review and tell me if there is anything need to change? Thanks. |
Please use the same commit strategy as in this PR: #139 (comment) |
no problem, I'll handle this after #139(delay command) been merged. To save rework time. |
f69c469
to
fb8082a
Compare
Copy file from ROS1 and port to ros2. This file is originally from: https://github.com/ros/ros_comm/blob/6e5016f4b2266d8a60c9a1e163c4928b8fc7115e/tools/rostopic/src/rostopic/__init__.py Signed-off-by: Chris Ye <chris.ye@intel.com>
Signed-off-by: Chris Ye <chris.ye@intel.com>
* remove irrelevant code and reserve hz related code * port rostopic hz to ros2topic based on ROS2 API format Signed-off-by: Chris Ye <chris.ye@intel.com>
squashed the comments and resubmitted again, please help review again. |
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.
Most of my comments are small nits, so should be easy to fix. The one exception is the comment about using eval
, which seems dangerous to me.
ros2topic/ros2topic/verb/hz.py
Outdated
'--window', '-w', | ||
dest='window_size', type=unsigned_int, default=DEFAULT_WINDOW_SIZE, | ||
help='window size, in # of messages, for calculating rate, ' | ||
'string to (default: %d)' % DEFAULT_WINDOW_SIZE, metavar='WINDOW') |
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.
Nit: I'm not sure what "string to" means here. Can you reword or remove this piece of the help?
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.
removed. fixed in
0ba39d3
if args.filter_expr: | ||
def expr_eval(expr): | ||
def eval_fn(m): | ||
return eval(expr) |
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.
Hm. I know this is directly ported from the original ROS1 code, but having a naked eval
lying around here seems pretty dangerous. In particular, the string that is passed in here can do any arbitrary Python thing, including copying all of your hard drive out to the network, taking command-and-control inputs from the network, or deleting your filesystem. I don't think that sort of power is actually required here; I think a simple regular expression could probably get most of the uses. Could you maybe explain what you think the intended use case here is?
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 filter_expr code is directly ported from the original ROS1. No changes from the first commit ("rostopic into ros_comm" ros/ros_comm@a82674a). One comment from code is "#694: ignore messages that don't match filter", line to https://github.com/ros/ros_comm/blob/a82674ad87ab17e373e89d392bcf358c511026ae/tools/rostopic/src/rostopic.py#L116 ", I don't know what #694 means, I guess it is internal bug track of rostopic before open source, and may noted the intended use case there. I have no idea about the requirement of the option --filter
. Check with echo
command of ros2topic also do not remain this option. Could we also removed here on hz
command for code safety?
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.
Yeah, I did some similar code archaeology, and like you said, this option existed before history starts. I do not know the intended use case either. @tfoote, @dirk-thomas , do you have any further history on what the --filter
options was meant to achieve in ROS1, and whether we still need it? The options on the table here seem to be:
- Remove
--filter
entirely until a use-case comes up for it. - Restrict
--filter
to be a regex only. - Leave
--filter
as the currenteval
, which seems pretty dangerous.
I'd vote for 1 (we can always add it back later), but I'm interested to hear additional thoughts/opinions.
ros2topic/ros2topic/verb/hz.py
Outdated
|
||
def __init__(self, node, window_size, filter_expr=None, use_wtime=False): | ||
import threading | ||
from collections import defaultdict |
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.
Nit; looking elsewhere in ros2cli, it looks like we generally hoist defaultdict
to the top of the file: https://github.com/ros2/ros2cli/blob/master/ros2cli/ros2cli/entry_points.py#L16 . Mostly a matter of style/taste, just trying to be consistent 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.
fixed in
0ba39d3
ros2topic/ros2topic/verb/hz.py
Outdated
return | ||
|
||
curr = curr_rostime.nanoseconds | ||
if self.get_msg_t0(topic=topic) < 0 or self.get_msg_t0(topic=topic) > curr: |
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 would be slightly more efficient as:
msg_t0 = self.get_msg_t0(topic=topic)
if msg_t0 < 0 or msg_t0 > curr:
...
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.
thanks, fixed in 0ba39d3
ros2topic/ros2topic/verb/hz.py
Outdated
return | ||
with self.lock: | ||
# Get frequency every one minute | ||
n = len(self.get_times(topic=topic)) |
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.
Again, probably more efficient to call self.get_times(topic=topic)
right after taking the lock, then reuse the local variable.
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.
fixed in 0ba39d3
* remove confused "string to" on help * move import to the top of the file * use local variable instead of multiple funcion call. Signed-off-by: Chris Ye <chris.ye@intel.com>
I seem to recall using filter as a convenient way to create a frequency measurement around some value in the message, like if you wanted to measure the frequency of detections, or state changes, or the like. It is also present on |
Yeah, from the implementation, that would have been my guess as well. If we still think that is useful, that's fine, but I personally think that giving it |
Agree that |
|
About
|
Good point. We should continue with option 3 then. There is no "problem" from a security point of view. The user passes the filter string explicitly as a command line argument. Obviously a "malicious" parameter could be used. But the user could also just call |
I would like to keep with option 3, as rostopic echo/hz with --filter be used for a long time. Of course, if we have better solution, we could modify the code with new PR. |
ros2topic/ros2topic/verb/hz.py
Outdated
except ValueError: | ||
raise RuntimeError('The passed message type is invalid') | ||
module = importlib.import_module(package_name + '.msg') | ||
return getattr(module, message_name) |
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 two methods get_msg_class
and _get_msg_class
are a 1-to-1 copy from the delay
module. Please don't cop-n-paste the code but move it into the api
module and reuse it in both locations.
The two methods get_msg_class and _get_msg_class are both used in delay and hz module, avoid cop-n-paste the code but move it into the api module and reuse it in both locations. Signed-off-by: Chris Ye <chris.ye@intel.com>
Moved get_msg_class and get_msg_class_ from delay and hz modues to api module. Fixed in bbc2293. |
All the warnings are from other, known problems (they should be fixed now). Given that, I'm going to merge up. Thanks for the contribution. |
@mikaelarguedas @dirk-thomas @clalancette @mjcarroll thank you so much for taking effort on patch review and giving good comments. Glad to see this PR has been merged. |
Thank you for making this feature available! |
…ros2#133) Signed-off-by: William Woodall <william@osrfoundation.org>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
For performance test to print the average publishing rate to screen. Ported rostopic hz command from ros to ros2, based on the file as below
https://github.com/ros/ros_comm/blob/melodic-devel/tools/rostopic/src/rostopic/__init__.py
Signed-off-by: Chris Ye chris.ye@intel.com
Connects to #132