def start_recipe_service(self, data, start_time=None):
        recipe_id = data.recipe_id
        if not recipe_id:
            return False, "No recipe id was specified"

        try:
            # Get the recipe document
            recipe = self.recipe_db[recipe_id]
        except Exception as e:
            return False, "\"{}\" does not reference a valid "\
            "recipe".format(recipe_id)

        trace("recipe_handler: PUBLISHERS=%s", PUBLISHERS)
        trace("recipe_handler: recipe=%s", recipe)

        try:
            # Set the recipe document
            self.set_recipe(recipe, start_time)
        except RecipeRunningError:
            return (False, "There is already a recipe running. Please stop it "
                    "before attempting to start a new one")
        return True, "Success"
 def recover_any_previous_recipe(self):
     """
     Attempt to resume any previous recipe that was started but
     not completed.
     """
     # Get the recipe that has been started most recently
     start_view = self.env_data_db.view(
         "openag/by_variable",
         startkey=[self.environment, "desired", RECIPE_START.name],
         endkey=[self.environment, "desired", RECIPE_START.name, {}],
         group_level=3)
     if len(start_view) == 0:
         trace(
             "recover_any_previous_recipe: No previous recipe to recover.")
         return
     start_doc = start_view.rows[0].value
     trace("recover_any_previous_recipe: start_doc=%s", start_doc)
     # If a recipe has been ended more recently than the most recent time a
     # recipe was started, don't run the recipe
     end_view = self.env_data_db.view(
         "openag/by_variable",
         startkey=[self.environment, "desired", RECIPE_END.name],
         endkey=[self.environment, "desired", RECIPE_END.name, {}],
         group_level=3)
     if len(end_view):
         end_doc = end_view.rows[0].value
         trace("recover_any_previous_recipe: end_doc=%s", end_doc)
         if (end_doc["timestamp"] > start_doc["timestamp"]):
             trace(
                 "recover_any_previous_recipe: RETURNING: '\
                 'end_time=%s > start_time=%s", end_doc["timestamp"],
                 start_doc["timestamp"])
             return
     # Run the recipe
     trace("recover_any_previous_recipe: restarting recipe=%s at time=%s",
           start_doc["value"], start_doc["timestamp"])
     self.start_recipe_service(
         StartRecipe._request_class(start_doc["value"]),
         start_doc["timestamp"])
示例#3
0
def interpret_simple_recipe(recipe, start_time, now_time):
    """
    Produces a tuple of ``(variable, value)`` pairs by building up
    a recipe state from walking through the recipe keyframes
    """
    _id = recipe["_id"]
    operations = recipe["operations"]
    rospy.loginfo(operations)
    end_time_relative = operations[-1][0]
    trace("recipe_handler: interpret_simple_recipe end_time_relative=%s",
          end_time_relative)
    end_time = start_time + end_time_relative
    # If start time is at some point in the future beyond the threshold
    if start_time - now_time > THRESHOLD:
        raise ValueError("Recipes cannot be scheduled for the future")
    # If there are no recipe operations, immediately start and stop
    # The recipe.
    if not len(operations):
        return (
            (RECIPE_START.name, _id),
            (RECIPE_END.name, _id),
        )
    if now_time >= (end_time + THRESHOLD):
        return ((RECIPE_END.name, _id), )
    if abs(now_time - start_time) < THRESHOLD:
        return ((RECIPE_START.name, _id), )

    now_relative = (now_time - start_time)

    # Create a state object to accrue recipe setpoint values.
    state = {}
    # Build up state up until now_time (inclusive).
    trace("recipe_handler: interpret_simple_recipe now=%s", now_relative)
    for timestamp, variable, value in operations:
        if timestamp > now_relative:
            break
        state[variable] = value
        trace("recipe_handler: interpret_simple_recipe: %s %s %s", timestamp,
              variable, value)
    rospy.loginfo(state)
    return tuple((variable, value) for variable, value in state.iteritems())
 def callback(data):
     recipe_handler.clear_recipe()
     trace("recipe_handler.Subscriber: clearing current recipe.")
                rospy.logwarn("Invalid recipe format: '%s'",
                              recipe_doc.get("format"))
                continue

            # Get recipe state and publish it
            setpoints = interpret_recipe(recipe_doc, start_time, now_time)
            for variable, value in setpoints:
                try:
                    pub = PUBLISHERS[variable]
                except KeyError:
                    msg = 'Recipe references invalid variable "{}"'
                    rospy.logwarn(msg.format(variable))
                    continue

                # Publish any setpoints that we can
                trace("recipe_handler publish: %s, %s", variable, value)
                if variable == RECIPE_END.name:
                    trace("recipe_handler publish: END!")
                    # Write an env. data pt. for when we stopped this recipe.
                    recipe_handler.save_recipe_dp(variable)
                elif variable == RECIPE_START.name:
                    # Write an env. data pt. for when we started this recipe.
                    recipe_handler.save_recipe_dp(variable)
                try:
                    pub.publish(value)
                except ValueError:
                    pass

        rate.sleep()
        # end of while loop in main