requester

Python interface for ROCON services making scheduler requests.

class concert_scheduler_requests.requester.Requester(feedback, uuid=None, priority=0, topic=None, frequency=0.25, lock=None)[source]

This class is used by a ROCON service to handle its resource requests. When an instance of Requester is created, it creates its own scheduler feedback topic and connects to the ROCON scheduler topic.

Parameters:
  • feedback – Callback function invoked with the current RequestSet when feedback arrives.
  • uuid (uuid.UUID) – UUID of this requester. If None provided, a random UUID will be assigned.
  • priority – default priority for requests from this requester.
  • topic (str or None) – Base name of of resource allocation request topic. If None, search for a ROS topic_name parameter, or else assume rocon_scheduler.
  • frequency (float) – requester heartbeat frequency in Hz. Use the default, except in exceptional situations or for testing.
  • lock (threading.RLock()) – The big requester serialization lock, allocated internally, if None.

As long as the Requester object remains, it will periodically send request messages to the scheduler, even when no requests are outstanding. The scheduler will provide feedback for them if anything has changed. The caller-provided feedback function will be invoked each time a feedback message arrives, like this:

feedback(rset)
Param rset:The current set of requests including any updates from the scheduler.
Type rset:RequestSet

The feedback function is called when new feedback is received from the scheduler, already holding the Big Requester Lock. It is expected to iterate over its RequestSet, checking the status of every ResourceRequest it contains, modifying them appropriately, then return without waiting. If any changes occur, the scheduler will be notified after this callback returns.

Usage example:

#!/usr/bin/env python
""" Requester usage example. """
import rospy
from scheduler_msgs.msg import Request, Resource
from concert_scheduler_requests import Requester


class ExampleRequester:

    def __init__(self):
        rospy.init_node("example_requester")
        self.rqr = Requester(self.feedback)
        self.request_turtlebot()
        self.timer = rospy.Timer(rospy.Duration(2.0), self.periodic_update)
        rospy.spin()

    def feedback(self, rset):
        """ Scheduler feedback function. """
        for rq in rset.values():
            if rq.msg.status == Request.WAITING:
                rospy.loginfo('Request queued: ' + str(rq.uuid))
            elif rq.msg.status == Request.GRANTED:
                rospy.loginfo('Request granted: ' + str(rq.uuid))
            elif rq.msg.status == Request.CLOSED:
                rospy.loginfo('Request closed: ' + str(rq.uuid))
            elif rq.msg.status == Request.PREEMPTING:
                rospy.loginfo('Request preempted (reason='
                              + str(rq.msg.reason) + '): ' + str(rq.uuid))
                rq.cancel()     # release preempted resource immediately

    def periodic_update(self, event):
        """ Timer event handler for periodic request updates. """
        try:
            # cancel the previous request, holding the Big Requester Lock
            with self.rqr.lock:
                self.rqr.rset[self.request_id].cancel()
        except KeyError:
            # previous request is gone, request another similar robot
            self.request_turtlebot()

    def request_turtlebot(self):
        """ Request any tutlebot able to run *example_rapp*. """
        bot = Resource(rapp='example_rapp', uri='rocon:/turtlebot')
        self.request_id = self.rqr.new_request([bot])
        self.rqr.send_requests()

if __name__ == '__main__':
    node = ExampleRequester()
lock = None

Big Requester Lock.

This recursive Python threading lock serializes access to requester data. The requester feedback function is always invoked holding it. All Requester methods acquire it automatically, whenever needed.

In any other thread, acquire it when updating shared request set objects. Never hold it when sleeping or waiting for I/O.

requester_id = None

uuid.UUID of this requester.

rset = None

RequestSet containing the current status of every ResourceRequest made by this requester. All requester operations are done using this object and its contents.

priority = None

Default for new requests’ priorities if none specified.

cancel_all()[source]

Cancel all current requests to the scheduler.

After calling this method to cancel all your requests, invoke send_requests() to notify the scheduler immediately.

new_request(resources, priority=None, uuid=None, reservation=rospy.Time[0], hold_time=rospy.Duration[0])[source]

Add a new scheduler request.

Call this method for each desired new request, then invoke send_requests() to notify the scheduler.

Parameters:
  • resources (list of scheduler_msgs/Resource) – ROCON resources requested
  • priority (int) – Scheduling priority of this request. If None provided, use this requester’s default priority.
  • uuid (uuid.UUID or None) – UUID of this request. If None provided, a random UUID will be assigned.
  • reservation (rospy.Time) – time when request desired, default: immediately.
  • hold_time (rospy.Duration) – estimated duration the resource will be held, default: unknown.
Returns:

UUID (uuid.UUID) assigned.

Raises:

WrongRequestError if request already exists.

send_requests()[source]

Send all current requests to the scheduler.

Use this method after updating rset or calling new_request() one or more times. It will send them to the scheduler immediately. Otherwise, they would not go out until the next heartbeat timer event.

Note

A recent heartbeat may already have sent some recent requests. This method just ensures they are all sent without further delay.

Previous topic

priority_queue

Next topic

scheduler

This Page