Esempio n. 1
0
 def __init__(self):
     """Instantiates a SendableChooser.
     """
     from networktables import StringArray
     self.choices = StringArray()
     self.values = []
     self.defaultChoice = None
     self.defaultValue = None
Esempio n. 2
0
    def initTable(self, subtable):
        self.table = subtable
        from networktables import StringArray, NumberArray
        self.commands = StringArray()
        self.ids = NumberArray()
        self.toCancel = NumberArray()

        self.table.putValue("Names", self.commands)
        self.table.putValue("Ids", self.ids)
        self.table.putValue("Cancel", self.toCancel)
 def __init__(self):
     """Instantiates a SendableChooser.
     """
     from networktables import StringArray
     self.choices = StringArray()
     self.values = []
     self.defaultChoice = None
     self.defaultValue = None
Esempio n. 4
0
    def initTable(self, subtable):
        self.table = subtable
        from networktables import StringArray, NumberArray
        self.commands = StringArray()
        self.ids = NumberArray()
        self.toCancel = NumberArray()

        self.table.putValue("Names", self.commands)
        self.table.putValue("Ids", self.ids)
        self.table.putValue("Cancel", self.toCancel)
Esempio n. 5
0
class Scheduler(Sendable):
    """The Scheduler is a singleton which holds the top-level running commands.
    It is in charge of both calling the command's run() method and to make
    sure that there are no two commands with conflicting requirements running.

    It is fine if teams wish to take control of the Scheduler themselves, all
    that needs to be done is to call Scheduler.getInstance().run() often to
    have Commands function correctly. However, this is already done for you
    if you use the CommandBased Robot template.

    .. seealso:: :class:`.Command`
    """
    @staticmethod
    def _reset():
        try:
            del Scheduler.instance
        except:
            pass

    @staticmethod
    def getInstance():
        """Returns the Scheduler, creating it if one does not exist.

        :returns: the Scheduler
        """
        if not hasattr(Scheduler, "instance"):
            Scheduler.instance = Scheduler()
        return Scheduler.instance

    def __init__(self):
        """Instantiates a Scheduler.
        """
        hal.HALReport(hal.HALUsageReporting.kResourceType_Command,
                      hal.HALUsageReporting.kCommand_Scheduler)

        # Active Commands
        self.commandTable = collections.OrderedDict()
        # The set of all Subsystems
        self.subsystems = set()
        # Whether or not we are currently adding a command
        self.adding = False
        # Whether or not we are currently disabled
        self.disabled = False
        # A list of all Commands which need to be added
        self.additions = []
        # A list of all Buttons. It is created lazily.
        self.buttons = []
        self.runningCommandsChanged = False

    def add(self, command):
        """Adds the command to the Scheduler. This will not add the
        :class:`.Command` immediately, but will instead wait for the proper time in
        the :meth:`run` loop before doing so. The command returns immediately
        and does nothing if given null.

        Adding a :class:`.Command` to the :class:`.Scheduler` involves the
        Scheduler removing any Command which has shared requirements.

        :param command: the command to add
        """
        if command is not None:
            self.additions.append(command)

    def addButton(self, button):
        """Adds a button to the Scheduler. The Scheduler will poll
        the button during its :meth:`run`.

        :param button: the button to add
        """
        self.buttons.append(button)

    def _add(self, command):
        """Adds a command immediately to the Scheduler. This should only be
        called in the :meth:`run` loop. Any command with conflicting
        requirements will be removed, unless it is uninterruptable. Giving
        None does nothing.

        :param command: the :class:`.Command` to add
        """
        if command is None:
            return

        # Check to make sure no adding during adding
        if self.adding:
            warnings.warn(
                "Can not start command from cancel method.  Ignoring: %s" %
                command, RuntimeWarning)
            return

        # Only add if not already in
        if command not in self.commandTable:
            # Check that the requirements can be had
            for lock in command.getRequirements():
                if (lock.getCurrentCommand() is not None
                        and not lock.getCurrentCommand().isInterruptible()):
                    return

            # Give it the requirements
            self.adding = True
            for lock in command.getRequirements():
                if lock.getCurrentCommand() is not None:
                    lock.getCurrentCommand().cancel()
                    self.remove(lock.getCurrentCommand())
                lock.setCurrentCommand(command)
            self.adding = False

            # Add it to the list
            self.commandTable[command] = 1

            self.runningCommandsChanged = True

            command.startRunning()

    def run(self):
        """Runs a single iteration of the loop. This method should be called
        often in order to have a functioning Command system. The loop has five
        stages:

        - Poll the Buttons
        - Execute/Remove the Commands
        - Send values to SmartDashboard
        - Add Commands
        - Add Defaults
        """

        self.runningCommandsChanged = False

        if self.disabled:
            return  # Don't run when disabled

        # Get button input (going backwards preserves button priority)
        for button in reversed(self.buttons):
            button()

        # Loop through the commands
        for command in list(self.commandTable):
            if not command.run():
                self.remove(command)
                self.runningCommandsChanged = True

        # Add the new things
        for command in self.additions:
            self._add(command)
        self.additions.clear()

        # Add in the defaults
        for lock in self.subsystems:
            if lock.getCurrentCommand() is None:
                self._add(lock.getDefaultCommand())
            lock.confirmCommand()

        self.updateTable()

    def registerSubsystem(self, system):
        """Registers a :class:`.Subsystem` to this Scheduler, so that the
        Scheduler might know if a default Command needs to be
        run. All :class:`.Subsystem` objects should call this.

        :param system: the system
        """
        if system is not None:
            self.subsystems.add(system)

    def remove(self, command):
        """Removes the :class:`.Command` from the Scheduler.

        :param command: the command to remove
        """
        if command is None or command not in self.commandTable:
            return
        del self.commandTable[command]
        for reqt in command.getRequirements():
            reqt.setCurrentCommand(None)
        command.removed()

    def removeAll(self):
        """Removes all commands
        """
        # TODO: Confirm that this works with "uninteruptible" commands
        for command in self.commandTable:
            for reqt in command.getRequirements():
                reqt.setCurrentCommand(None)
            command.removed()
        self.commandTable.clear()

    def disable(self):
        """Disable the command scheduler.
        """
        self.disabled = True

    def enable(self):
        """Enable the command scheduler.
        """
        self.disabled = False

    def getName(self):
        return "Scheduler"

    def getType(self):
        return "Scheduler"

    def initTable(self, subtable):
        self.table = subtable
        from networktables import StringArray, NumberArray
        self.commands = StringArray()
        self.ids = NumberArray()
        self.toCancel = NumberArray()

        self.table.putValue("Names", self.commands)
        self.table.putValue("Ids", self.ids)
        self.table.putValue("Cancel", self.toCancel)

    def updateTable(self):
        table = self.getTable()
        if table is None:
            return
        # Get the commands to cancel
        self.table.retrieveValue("Cancel", self.toCancel)
        if self.toCancel:
            for command in self.commandTable:
                if id(command) in self.toCancel:
                    command.cancel()
            self.toCancel.clear()
            self.table.putValue("Cancel", self.toCancel)

        if self.runningCommandsChanged:
            self.commands.clear()
            self.ids.clear()
            # Set the the running commands
            for command in self.commandTable:
                self.commands.append(command.getName())
                self.ids.append(id(command))
            self.table.putValue("Names", self.commands)
            self.table.putValue("Ids", self.ids)

    def getSmartDashboardType(self):
        return "Scheduler"
class SendableChooser(Sendable):
    """A useful tool for presenting a selection of options to be displayed on
    the SmartDashboard

    For instance, you may wish to be able to select between multiple
    autonomous modes. You can do this by putting every possible Command
    you want to run as an autonomous into a SendableChooser and then put
    it into the SmartDashboard to have a list of options appear on the
    laptop. Once autonomous starts, simply ask the SendableChooser what
    the selected value is.

    Example::

        # This shows the user two options on the SmartDashboard
        chooser = wpilib.SendableChooser()
        chooser.addObject('option1', '1')
        chooser.addObject('option2', '2')

        wpilib.SmartDashboard.putData('Choice', chooser)

        # .. later, ask to see what the user selected?
        value = chooser.getSelected()

    """

    # The key for the default value
    DEFAULT = "default"
    # The key for the selected option
    SELECTED = "selected"
    # The key for the option array
    OPTIONS = "options"
    # A table linking strings to the objects the represent

    def __init__(self):
        """Instantiates a SendableChooser.
        """
        from networktables import StringArray
        self.choices = StringArray()
        self.values = []
        self.defaultChoice = None
        self.defaultValue = None

    def addObject(self, name, object):
        """Adds the given object to the list of options. On the
        SmartDashboard on the desktop, the object will appear as the
        given name.

        :param name: the name of the option
        :param object: the option
        """
        # if we don't have a default, set the default automatically
        if self.defaultChoice is None:
            self.addDefault(name, object)
            return
        for i, choice in enumerate(self.choices):
            if choice == name:
                self.values[i] = object
                return
        # not found
        self.choices.append(name)
        self.values.append(object)
        table = self.getTable()
        if table is not None:
            table.putValue(self.OPTIONS, self.choices)

    def addDefault(self, name, object):
        """Add the given object to the list of options and marks it as the
        default.  Functionally, this is very close to addObject(...) except
        that it will use this as the default option if none other is
        explicitly selected.

        :param name: the name of the option
        :param object: the option
        """
        if name is None:
            raise ValueError("Name cannot be None")
        self.defaultChoice = name
        self.defaultValue = object
        table = self.getTable()
        if table is not None:
            table.putString(self.DEFAULT, self.defaultChoice)
        self.addObject(name, object)

    def getSelected(self):
        """Returns the object associated with the selected option. If there
        is none selected, it will return the default. If there is none
        selected and no default, then it will return None.

        :returns: the object associated with the selected option
        """
        table = self.getTable()
        if table is None:
            return self.defaultValue
        selected = table.getString(self.SELECTED, None)
        for i, choice in enumerate(self.choices):
            if choice == selected:
                return self.values[i]
        return self.defaultValue

    def getSmartDashboardType(self):
        return "String Chooser"

    def initTable(self, table):
        self.table = table
        if table is not None:
            table.putValue(self.OPTIONS, self.choices)
            if self.defaultChoice is not None:
                table.putString(self.DEFAULT, self.defaultChoice)
Esempio n. 7
0
class Scheduler(Sendable):
    """The Scheduler is a singleton which holds the top-level running commands.
    It is in charge of both calling the command's run() method and to make
    sure that there are no two commands with conflicting requirements running.

    It is fine if teams wish to take control of the Scheduler themselves, all
    that needs to be done is to call Scheduler.getInstance().run() often to
    have Commands function correctly. However, this is already done for you
    if you use the CommandBased Robot template.

    .. seealso:: :class:`.Command`
    """
    
    @staticmethod
    def _reset():
        try:
            del Scheduler.instance
        except:
            pass

    @staticmethod
    def getInstance():
        """Returns the Scheduler, creating it if one does not exist.

        :returns: the Scheduler
        """
        if not hasattr(Scheduler, "instance"):
            Scheduler.instance = Scheduler()
        return Scheduler.instance

    def __init__(self):
        """Instantiates a Scheduler.
        """
        hal.HALReport(hal.HALUsageReporting.kResourceType_Command,
                      hal.HALUsageReporting.kCommand_Scheduler)

        # Active Commands
        self.commandTable = collections.OrderedDict()
        # The set of all Subsystems
        self.subsystems = set()
        # Whether or not we are currently adding a command
        self.adding = False
        # Whether or not we are currently disabled
        self.disabled = False
        # A list of all Commands which need to be added
        self.additions = []
        # A list of all Buttons. It is created lazily.
        self.buttons = []
        self.runningCommandsChanged = False

    def add(self, command):
        """Adds the command to the Scheduler. This will not add the
        :class:`.Command` immediately, but will instead wait for the proper time in
        the :meth:`run` loop before doing so. The command returns immediately
        and does nothing if given null.

        Adding a :class:`.Command` to the :class:`.Scheduler` involves the
        Scheduler removing any Command which has shared requirements.

        :param command: the command to add
        """
        if command is not None:
            self.additions.append(command)

    def addButton(self, button):
        """Adds a button to the Scheduler. The Scheduler will poll
        the button during its :meth:`run`.

        :param button: the button to add
        """
        self.buttons.append(button)

    def _add(self, command):
        """Adds a command immediately to the Scheduler. This should only be
        called in the :meth:`run` loop. Any command with conflicting
        requirements will be removed, unless it is uninterruptable. Giving
        None does nothing.

        :param command: the :class:`.Command` to add
        """
        if command is None:
            return

        # Check to make sure no adding during adding
        if self.adding:
            warnings.warn("Can not start command from cancel method.  Ignoring: %s" % command, RuntimeWarning)
            return

        # Only add if not already in
        if command not in self.commandTable:
            # Check that the requirements can be had
            for lock in command.getRequirements():
                if (lock.getCurrentCommand() is not None and
                    not lock.getCurrentCommand().isInterruptible()):
                    return

            # Give it the requirements
            self.adding = True
            for lock in command.getRequirements():
                if lock.getCurrentCommand() is not None:
                    lock.getCurrentCommand().cancel()
                    self.remove(lock.getCurrentCommand())
                lock.setCurrentCommand(command)
            self.adding = False

            # Add it to the list
            self.commandTable[command] = 1

            self.runningCommandsChanged = True

            command.startRunning()

    def run(self):
        """Runs a single iteration of the loop. This method should be called
        often in order to have a functioning Command system. The loop has five
        stages:

        - Poll the Buttons
        - Execute/Remove the Commands
        - Send values to SmartDashboard
        - Add Commands
        - Add Defaults
        """

        self.runningCommandsChanged = False

        if self.disabled:
            return # Don't run when disabled

        # Get button input (going backwards preserves button priority)
        for button in reversed(self.buttons):
            button()

        # Loop through the commands
        for command in list(self.commandTable):
            if not command.run():
                self.remove(command)
                self.runningCommandsChanged = True

        # Add the new things
        for command in self.additions:
            self._add(command)
        self.additions.clear()

        # Add in the defaults
        for lock in self.subsystems:
            if lock.getCurrentCommand() is None:
                self._add(lock.getDefaultCommand())
            lock.confirmCommand()

        self.updateTable()

    def registerSubsystem(self, system):
        """Registers a :class:`.Subsystem` to this Scheduler, so that the
        Scheduler might know if a default Command needs to be
        run. All :class:`.Subsystem` objects should call this.

        :param system: the system
        """
        if system is not None:
            self.subsystems.add(system)

    def remove(self, command):
        """Removes the :class:`.Command` from the Scheduler.

        :param command: the command to remove
        """
        if command is None or command not in self.commandTable:
            return
        del self.commandTable[command]
        for reqt in command.getRequirements():
            reqt.setCurrentCommand(None)
        command.removed()

    def removeAll(self):
        """Removes all commands
        """
        # TODO: Confirm that this works with "uninteruptible" commands
        for command in self.commandTable:
            for reqt in command.getRequirements():
                reqt.setCurrentCommand(None)
            command.removed()
        self.commandTable.clear()

    def disable(self):
        """Disable the command scheduler.
        """
        self.disabled = True

    def enable(self):
        """Enable the command scheduler.
        """
        self.disabled = False

    def getName(self):
        return "Scheduler"

    def getType(self):
        return "Scheduler"

    def initTable(self, subtable):
        self.table = subtable
        from networktables import StringArray, NumberArray
        self.commands = StringArray()
        self.ids = NumberArray()
        self.toCancel = NumberArray()

        self.table.putValue("Names", self.commands)
        self.table.putValue("Ids", self.ids)
        self.table.putValue("Cancel", self.toCancel)

    def updateTable(self):
        table = self.getTable()
        if table is None:
            return
        # Get the commands to cancel
        self.table.retrieveValue("Cancel", self.toCancel)
        if self.toCancel:
            for command in self.commandTable:
                if id(command) in self.toCancel:
                    command.cancel()
            self.toCancel.clear()
            self.table.putValue("Cancel", self.toCancel)

        if self.runningCommandsChanged:
            self.commands.clear()
            self.ids.clear()
            # Set the the running commands
            for command in self.commandTable:
                self.commands.add(command.getName())
                self.ids.add(id(command))
            self.table.putValue("Names", self.commands)
            self.table.putValue("Ids", self.ids)

    def getSmartDashboardType(self):
        return "Scheduler"
Esempio n. 8
0
class SendableChooser(Sendable):
    """A useful tool for presenting a selection of options to be displayed on
    the SmartDashboard

    For instance, you may wish to be able to select between multiple
    autonomous modes. You can do this by putting every possible Command
    you want to run as an autonomous into a SendableChooser and then put
    it into the SmartDashboard to have a list of options appear on the
    laptop. Once autonomous starts, simply ask the SendableChooser what
    the selected value is.

    Example::

        # This shows the user two options on the SmartDashboard
        chooser = wpilib.SendableChooser()
        chooser.addObject('option1', '1')
        chooser.addObject('option2', '2')

        wpilib.SmartDashboard.putData('Choice', chooser)

        # .. later, ask to see what the user selected?
        value = chooser.getSelected()

    """

    # The key for the default value
    DEFAULT = "default"
    # The key for the selected option
    SELECTED = "selected"
    # The key for the option array
    OPTIONS = "options"

    # A table linking strings to the objects the represent

    def __init__(self):
        """Instantiates a SendableChooser.
        """
        from networktables import StringArray
        self.choices = StringArray()
        self.values = []
        self.defaultChoice = None
        self.defaultValue = None

    def addObject(self, name, object):
        """Adds the given object to the list of options. On the
        SmartDashboard on the desktop, the object will appear as the
        given name.

        :param name: the name of the option
        :param object: the option
        """
        # if we don't have a default, set the default automatically
        if self.defaultChoice is None:
            self.addDefault(name, object)
            return
        for i, choice in enumerate(self.choices):
            if choice == name:
                self.values[i] = object
                return
        # not found
        self.choices.append(name)
        self.values.append(object)
        table = self.getTable()
        if table is not None:
            table.putValue(self.OPTIONS, self.choices)

    def addDefault(self, name, object):
        """Add the given object to the list of options and marks it as the
        default.  Functionally, this is very close to addObject(...) except
        that it will use this as the default option if none other is
        explicitly selected.

        :param name: the name of the option
        :param object: the option
        """
        if name is None:
            raise ValueError("Name cannot be None")
        self.defaultChoice = name
        self.defaultValue = object
        table = self.getTable()
        if table is not None:
            table.putString(self.DEFAULT, self.defaultChoice)
        self.addObject(name, object)

    def getSelected(self):
        """Returns the object associated with the selected option. If there
        is none selected, it will return the default. If there is none
        selected and no default, then it will return None.

        :returns: the object associated with the selected option
        """
        table = self.getTable()
        if table is None:
            return self.defaultValue
        selected = table.getString(self.SELECTED, None)
        for i, choice in enumerate(self.choices):
            if choice == selected:
                return self.values[i]
        return self.defaultValue

    def getSmartDashboardType(self):
        return "String Chooser"

    def initTable(self, table):
        self.table = table
        if table is not None:
            table.putValue(self.OPTIONS, self.choices)
            if self.defaultChoice is not None:
                table.putString(self.DEFAULT, self.defaultChoice)