Exemplo n.º 1
0
    def __init__(self,
                 cmd,
                 shell=False,
                 window=None,
                 initial_state=None,
                 respawn=True,
                 env=None):
        """
        respawn handles whether or not the application shall be automatically
                respawned at all, default is True.

        """
        self.cmd = cmd
        self.window = window
        self.lock = threading.Lock()
        self.proc = ProcController(cmd,
                                   spawn_hooks=[self._handle_respawn],
                                   shell=shell,
                                   respawn=respawn,
                                   env=env)

        self._respawn_handlers = []
        self._state_handlers = []

        if initial_state and is_valid_state(initial_state):
            rospy.logdebug('setting initial state to %s' % initial_state)
            self.state = initial_state
            self.set_state(self.state)
        else:
            self.state = ApplicationState.STOPPED

        self.post_init()
Exemplo n.º 2
0
class TestCaptureViewport(unittest.TestCase):
    def setUp(self):
        display = CAPTURE_DISPLAY
        geometry = ManagedWindow.lookup_viewport_geometry(CAPTURE_VIEWPORT)
        geometry_str = '{}x{}x24'.format(CAPTURE_WIDTH, CAPTURE_HEIGHT)

        self.image_capture = TopicCapture()
        self.image_capture_sub = rospy.Subscriber(CAPTURE_TOPIC, CompressedImage, self.image_capture.handle_msg)

        # Run an Xvfb with the configured DISPLAY and geometry matching the
        # viewport exactly.
        self.xvfb = ProcController(
            ['Xvfb', display, '-noreset', '-screen', '0', geometry_str]
        )
        self.xvfb.start()
        rospy.sleep(3.0)

        self.pub = rospy.Publisher('/director/scene',
                                   GenericMessage,
                                   queue_size=100)
        rospy.sleep(1.0)

    def tearDown(self):
        self.pub.publish(BLANK_SCENE)
        rospy.sleep(0.5)
        self.xvfb.stop()

    def test_capture_image_and_info(self):
        self.assertEqual(0, len(self.image_capture.msgs))

        self.pub.publish(CAPTURE_SCENE)

        rospy.sleep(1.0)

        first_image = self.image_capture.msgs[0]
        first_image_data = StringIO(first_image.data)
        first_image_jpeg = Image.open(first_image_data)
        self.assertEqual(CAPTURE_WIDTH, first_image_jpeg.size[0])
        self.assertEqual(CAPTURE_HEIGHT, first_image_jpeg.size[1])

        # Now try a different viewport size.
        self.pub.publish(HALF_SCALE_SCENE)

        rospy.sleep(1.0)

        last_image = self.image_capture.msgs[-1]
        last_image_data = StringIO(last_image.data)
        last_image_jpeg = Image.open(last_image_data)
        self.assertEqual(CAPTURE_WIDTH / 2, last_image_jpeg.size[0])
        self.assertEqual(CAPTURE_HEIGHT / 2, last_image_jpeg.size[1])

        # We shouldn't get any more images after publishing blank scene.
        self.pub.publish(BLANK_SCENE)

        rospy.sleep(1.0)
        num_images = len(self.image_capture.msgs)
        rospy.sleep(1.0)
        self.assertEqual(num_images, len(self.image_capture.msgs))
Exemplo n.º 3
0
class CaptureWebcam:
    def __init__(self, janus_host, janus_port, device, width, height, framerate, max_quantizer, target_bitrate, flip=False):
        self.janus_host = janus_host
        self.janus_port = janus_port
        self.device = device
        self.width = width
        self.height = height
        self.framerate = framerate
        self.max_quantizer = max_quantizer
        self.target_bitrate = target_bitrate

        self.proc = None
        self.lock = threading.Lock()

        if flip:
            self.flip_method = 'rotate-180'
        else:
            self.flip_method = 'none'

        self.cmd = self._get_cmd()

    def _get_cmd(self):
        caps = 'video/x-raw'
        if self.width is not None:
            caps += ',width={}'.format(self.width)
        if self.height is not None:
            caps += ',height={}'.format(self.height)
        if self.framerate is not None:
            caps += ',framerate={}/1'.format(self.framerate)

        args = map(lambda arg: arg.format(
            device=self.device,
            caps=caps,
            max_quantizer=self.max_quantizer,
            target_bitrate=self.target_bitrate,
            addr=self.janus_host,
            port=self.janus_port,
            flip_method=self.flip_method,
        ), CAPTURE_ARGS)

        cmd = [CAPTURE_CMD]
        cmd.extend(args)

        return cmd

    def start_capture(self):
        self.end_capture()
        self.proc = ProcController(self.cmd)
        self.proc.start()

    def end_capture(self):
        if self.proc is not None:
            self.proc.stop()
    def __init__(self, cmd, shell=False, window=None, initial_state=None, respawn=True, env=None):
        """
        respawn handles whether or not the application shall be automatically
                respawned at all, default is True.

        """
        self.cmd = cmd
        self.window = window
        self.lock = threading.Lock()
        self.proc = ProcController(cmd,
                                   spawn_hooks=[self._handle_respawn],
                                   shell=shell,
                                   respawn=respawn,
                                   env=env)

        self._respawn_handlers = []
        self._state_handlers = []

        if initial_state and is_valid_state(initial_state):
            rospy.logdebug('setting initial state to %s' % initial_state)
            self.state = initial_state
            self.set_state(self.state)
        else:
            self.state = ApplicationState.STOPPED

        self.post_init()
    def test_respawn_flag_forward_to_runner(self):
        """
        Test forwarding of the respawn flag setting and associated
        behaviour. Both for True (default value) and False from the
        higher-lever proc_controller POV.

        """
        self.assertTrue(self.controller.respawn, "The 'respawn' flag is by default True.")
        self.controller.start()
        self.assertTrue(self.controller.watcher.respawn, "The 'respawn' flag is by default True.")
        self.controller.stop()
        time.sleep(0.1)
        self.controller = ProcController(TEST_CMD, respawn=False)
        self.assertFalse(self.controller.respawn, "The 'respawn' flag is False now.")
        self.controller.start()
        self.assertFalse(self.controller.watcher.respawn, "The 'respawn' flag is False now.")
        self.controller.stop()
        time.sleep(0.1)
Exemplo n.º 6
0
    def setUp(self):
        display = CAPTURE_DISPLAY
        geometry = ManagedWindow.lookup_viewport_geometry(CAPTURE_VIEWPORT)
        geometry_str = '{}x{}x24'.format(CAPTURE_WIDTH, CAPTURE_HEIGHT)

        self.image_capture = TopicCapture()
        self.image_capture_sub = rospy.Subscriber(CAPTURE_TOPIC, CompressedImage, self.image_capture.handle_msg)

        # Run an Xvfb with the configured DISPLAY and geometry matching the
        # viewport exactly.
        self.xvfb = ProcController(
            ['Xvfb', display, '-noreset', '-screen', '0', geometry_str]
        )
        self.xvfb.start()
        rospy.sleep(3.0)

        self.pub = rospy.Publisher('/director/scene',
                                   GenericMessage,
                                   queue_size=100)
        rospy.sleep(1.0)
class ManagedApplication(object):
    def __init__(self, cmd, shell=False, window=None, initial_state=None, respawn=True, env=None):
        """
        respawn handles whether or not the application shall be automatically
                respawned at all, default is True.

        """
        self.cmd = cmd
        self.window = window
        self.lock = threading.Lock()
        self.proc = ProcController(cmd,
                                   spawn_hooks=[self._handle_respawn],
                                   shell=shell,
                                   respawn=respawn,
                                   env=env)

        self._respawn_handlers = []
        self._state_handlers = []

        if initial_state and is_valid_state(initial_state):
            rospy.logdebug('setting initial state to %s' % initial_state)
            self.state = initial_state
            self.set_state(self.state)
        else:
            self.state = ApplicationState.STOPPED

        self.post_init()

    def close(self):
        """
        End this ManagedApplication immediately.  After closing, the instance
        can no longer be used.
        """
        self.set_state(ApplicationState.STOPPED)
        del self.lock
        del self.cmd
        del self.state
        del self.proc
        del self.window
        del self._respawn_handlers[:]
        del self._state_handlers[:]

    def post_init(self):
        pass

    def add_respawn_handler(self, handler):
        self._respawn_handlers.append(handler)

    def add_state_handler(self, handler):
        self._state_handlers.append(handler)

    def __str__(self):
        string_representation = "<ManagedApplication: state: %s, window: %s, cmd: %s, proc: %s" % (self.state, self.window, self.cmd, self.proc)
        return string_representation

    def __repr__(self):
        return self.__str__()

    def get_state(self):
        with self.lock:
            return self.state

    def set_state(self, state):
        with self.lock:
            state_changed = False
            if state != self.state:
                state_changed = True
            self.state = state

            if state == ApplicationState.STOPPED:
                rospy.logdebug("STOPPED")
                self.proc.stop()
                if self.window is not None:
                    self.window.set_visibility(False)

            elif state == ApplicationState.SUSPENDED:
                rospy.logdebug("SUSPENDED")
                if self.window is not None:
                    self.window.set_visibility(False)
                    self.window.converge()
                self.proc.start()

            elif state == ApplicationState.HIDDEN:
                rospy.logdebug("HIDDEN")
                if self.window is not None:
                    self.window.set_visibility(False)
                    self.window.converge()
                else:
                    rospy.logwarn(
                        'Tried to hide a ManagedApplication ' +
                        'without a ManagedWindow'
                    )
                self.proc.start()

            elif state == ApplicationState.STARTED:
                rospy.loginfo("STARTED")
                if self.window is not None:
                    self.window.set_visibility(False)
                    self.window.converge()
                self.proc.start()

            elif state == ApplicationState.VISIBLE:
                rospy.loginfo("VISIBLE")
                if self.window is not None:
                    self.window.set_visibility(True)
                    self.window.converge()
                self.proc.start()

            def run_handler(handler):
                try:
                    handler(state)
                except Exception as e:
                    rospy.logerr('caught an Exception in a state change handler')
                    rospy.logerr(e.message)

            map(run_handler, self._state_handlers)

    def handle_state_msg(self, msg):
        rospy.logdebug('Got state message: {}'.format(msg))
        self.set_state(msg.state)

    # TODO(mv): hook this up to ProcController
    def _handle_respawn(self):
        def run_handler(handler):
            try:
                handler()
            except Exception as e:
                rospy.logerr('caught an Exception in a respawn handler')
                rospy.logerr(e.message)

        map(run_handler, self._respawn_handlers)

    def handle_soft_relaunch(self, *args, **kwargs):
        rospy.logdebug('managed application relaunch...')
        self.proc.handle_soft_relaunch()
Exemplo n.º 8
0
 def start_capture(self):
     self.end_capture()
     self.proc = ProcController(self.cmd)
     self.proc.start()
Exemplo n.º 9
0
#!/usr/bin/env python

import rospy
from appctl_support import ProcController
from appctl_support import ModeHandler

if __name__ == '__main__':
    rospy.init_node('spin_test_node', anonymous=True)

    modes = ['test_appctl']
    cmd = ['/bin/sh', '-c', 'sleep 23023023']

    proc_controller = ProcController(cmd)
    mode_handler = ModeHandler(modes, proc_controller)
    mode_handler.begin_handling_modes()

    rospy.spin()

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
 def setUp(self):
     self.controller = ProcController(TEST_CMD)
class TestProcController(unittest.TestCase):
    def setUp(self):
        self.controller = ProcController(TEST_CMD)

    def tearDown(self):
        self.controller.stop()

    def test_start_and_stop(self):
        self.assertFalse(self.controller.started,
                         'Controller must not start on init')

        self.controller.start()
        self.assertTrue(self.controller.started,
                        'Controller must be started on start()')

        # Wait for the process to spin up
        time.sleep(0.1)

        watcher = self.controller.watcher
        self.assertTrue(watcher.is_alive(),
                        'Process watcher must be alive while started')

        self.controller.stop()
        self.assertFalse(self.controller.started,
                         'Controller must not be started after stop()')

        watcher.join()
        self.assertFalse(watcher.is_alive(),
                         'Process watcher must not be alive after joined')

    def test_concurrency(self):
        flippers = [StateFlipper(self.controller) for i in range(NUM_THREADS_TO_TEST)]
        map(lambda f: f.start(), flippers)
        map(lambda f: f.join(), flippers)
        self.assertFalse(any([f.failed for f in flippers]))

    def test_redundant_start(self):
        self.controller.start()

        watcher = self.controller.watcher

        self.controller.start()

        self.assertIs(watcher, self.controller.watcher,
                      'Stray process watcher on redundant start')

    def test_respawn_flag_forward_to_runner(self):
        """
        Test forwarding of the respawn flag setting and associated
        behaviour. Both for True (default value) and False from the
        higher-lever proc_controller POV.

        """
        self.assertTrue(self.controller.respawn, "The 'respawn' flag is by default True.")
        self.controller.start()
        self.assertTrue(self.controller.watcher.respawn, "The 'respawn' flag is by default True.")
        self.controller.stop()
        time.sleep(0.1)
        self.controller = ProcController(TEST_CMD, respawn=False)
        self.assertFalse(self.controller.respawn, "The 'respawn' flag is False now.")
        self.controller.start()
        self.assertFalse(self.controller.watcher.respawn, "The 'respawn' flag is False now.")
        self.controller.stop()
        time.sleep(0.1)
class TestCleanup(unittest.TestCase):
    def setUp(self):
        self.controller = ProcController(TEST_CMD)

    def test_cleanup_started(self):
        c_ref = weakref.ref(self.controller)
        self.controller.start()
        w_ref = weakref.ref(self.controller.watcher)
        self.controller = None
        gc.collect()
        self.assertIsNone(c_ref())
        time.sleep(0.5)
        self.assertIsNone(w_ref())

    def test_cleanup_stopped(self):
        c_ref = weakref.ref(self.controller)
        self.controller.start()
        w_ref = weakref.ref(self.controller.watcher)
        time.sleep(0.5)
        self.controller.stop()
        self.controller = None
        gc.collect()
        self.assertIsNone(c_ref())
        time.sleep(0.5)
        self.assertIsNone(w_ref())

    def test_close_started(self):
        c_ref = weakref.ref(self.controller)
        self.controller.start()
        w_ref = weakref.ref(self.controller.watcher)
        self.controller.close()
        gc.collect()
        time.sleep(0.5)
        self.assertIsNone(w_ref())

    def test_close_stopped(self):
        c_ref = weakref.ref(self.controller)
        self.controller.start()
        w_ref = weakref.ref(self.controller.watcher)
        time.sleep(0.5)
        self.controller.stop()
        self.controller.close()
        gc.collect()
        time.sleep(0.5)
        self.assertIsNone(w_ref())
Exemplo n.º 13
0
class ManagedApplication(object):
    def __init__(self,
                 cmd,
                 shell=False,
                 window=None,
                 initial_state=None,
                 respawn=True,
                 env=None):
        """
        respawn handles whether or not the application shall be automatically
                respawned at all, default is True.

        """
        self.cmd = cmd
        self.window = window
        self.lock = threading.Lock()
        self.proc = ProcController(cmd,
                                   spawn_hooks=[self._handle_respawn],
                                   shell=shell,
                                   respawn=respawn,
                                   env=env)

        self._respawn_handlers = []
        self._state_handlers = []

        if initial_state and is_valid_state(initial_state):
            rospy.logdebug('setting initial state to %s' % initial_state)
            self.state = initial_state
            self.set_state(self.state)
        else:
            self.state = ApplicationState.STOPPED

        self.post_init()

    def close(self):
        """
        End this ManagedApplication immediately.  After closing, the instance
        can no longer be used.
        """
        self.set_state(ApplicationState.STOPPED)
        del self.lock
        del self.cmd
        del self.state
        del self.proc
        del self.window
        del self._respawn_handlers[:]
        del self._state_handlers[:]

    def post_init(self):
        pass

    def add_respawn_handler(self, handler):
        self._respawn_handlers.append(handler)

    def add_state_handler(self, handler):
        self._state_handlers.append(handler)

    def __str__(self):
        string_representation = "<ManagedApplication: state: %s, window: %s, cmd: %s, proc: %s" % (
            self.state, self.window, self.cmd, self.proc)
        return string_representation

    def __repr__(self):
        return self.__str__()

    def get_state(self):
        with self.lock:
            return self.state

    def set_state(self, state):
        with self.lock:
            state_changed = False
            if state != self.state:
                state_changed = True
            self.state = state

            if state == ApplicationState.STOPPED:
                rospy.logdebug("STOPPED")
                self.proc.stop()
                if self.window is not None:
                    self.window.set_visibility(False)

            elif state == ApplicationState.SUSPENDED:
                rospy.logdebug("SUSPENDED")
                if self.window is not None:
                    self.window.set_visibility(False)
                    self.window.converge()
                self.proc.start()

            elif state == ApplicationState.HIDDEN:
                rospy.logdebug("HIDDEN")
                if self.window is not None:
                    self.window.set_visibility(False)
                    self.window.converge()
                else:
                    rospy.logwarn('Tried to hide a ManagedApplication ' +
                                  'without a ManagedWindow')
                self.proc.start()

            elif state == ApplicationState.STARTED:
                rospy.loginfo("STARTED")
                if self.window is not None:
                    self.window.set_visibility(False)
                    self.window.converge()
                self.proc.start()

            elif state == ApplicationState.VISIBLE:
                rospy.loginfo("VISIBLE")
                if self.window is not None:
                    self.window.set_visibility(True)
                    self.window.converge()
                self.proc.start()

            def run_handler(handler):
                try:
                    handler(state)
                except Exception as e:
                    rospy.logerr(
                        'caught an Exception in a state change handler')
                    rospy.logerr(e.message)

            map(run_handler, self._state_handlers)

    def handle_state_msg(self, msg):
        rospy.logdebug('Got state message: {}'.format(msg))
        self.set_state(msg.state)

    # TODO(mv): hook this up to ProcController
    def _handle_respawn(self):
        def run_handler(handler):
            try:
                handler()
            except Exception as e:
                rospy.logerr('caught an Exception in a respawn handler')
                rospy.logerr(e.message)

        map(run_handler, self._respawn_handlers)

    def handle_soft_relaunch(self, *args, **kwargs):
        rospy.logdebug('managed application relaunch...')
        self.proc.handle_soft_relaunch()