Skip to content

Commit ce0b4eb

Browse files
committed
Implement long_callback Python decorator addressing #218
Clover package Python library added.
1 parent ccbd1cb commit ce0b4eb

5 files changed

Lines changed: 64 additions & 1 deletion

File tree

builder/test/tests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from led_msgs.srv import SetLEDs
2323
from led_msgs.msg import LEDStateArray, LEDState
2424
from aruco_pose.msg import Marker, MarkerArray, Point2D
25+
from clover import long_callback
2526

2627
import dynamic_reconfigure.client
2728

clover/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ find_package(OpenCV ${_opencv_version} REQUIRED
5353
## Uncomment this if the package has a setup.py. This macro ensures
5454
## modules and global scripts declared therein get installed
5555
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
56-
# catkin_python_setup()
56+
catkin_python_setup()
5757

5858
################################################
5959
## Declare ROS messages, services and actions ##

clover/setup.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD
2+
3+
from distutils.core import setup
4+
from catkin_pkg.python_setup import generate_distutils_setup
5+
6+
# fetch values from package.xml
7+
setup_args = generate_distutils_setup(
8+
packages=['clover'],
9+
package_dir={'': 'src'})
10+
11+
setup(**setup_args)

clover/src/clover/__init__.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import rospy
2+
from threading import Thread, Event
3+
4+
def long_callback(fn):
5+
"""
6+
Decorator fixing a rospy issue for long-running topic callbacks, primarily
7+
for image processing.
8+
9+
See: https://github.com/ros/ros_comm/issues/1901.
10+
11+
Usage example:
12+
13+
@long_callback
14+
def image_callback(msg):
15+
# perform image processing
16+
# ...
17+
18+
rospy.Subscriber('main_camera/image_raw', Image, image_callback)
19+
"""
20+
e = Event()
21+
22+
def thread():
23+
while not rospy.is_shutdown():
24+
e.wait()
25+
e.clear()
26+
fn(thread.current_msg)
27+
28+
thread.current_msg = None
29+
Thread(target=thread, daemon=True).start()
30+
31+
def wrapper(msg):
32+
thread.current_msg = msg
33+
e.set()
34+
35+
return wrapper

clover/test/basic.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44
from mavros_msgs.msg import State
55
from clover import srv
6+
import time
67

78
@pytest.fixture()
89
def node():
@@ -60,3 +61,18 @@ def wait_print():
6061

6162
t.join()
6263
assert wait_print.result == 'test'
64+
65+
def test_long_callback():
66+
from clover import long_callback
67+
from time import sleep
68+
69+
# very basic test for long_callback
70+
@long_callback
71+
def cb(i):
72+
cb.counter += i
73+
cb.counter = 0
74+
cb(2)
75+
sleep(0.1)
76+
cb(3)
77+
sleep(1)
78+
assert cb.counter == 5

0 commit comments

Comments
 (0)