patrol_tree.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 import rospy
00004 from std_msgs.msg import Float32
00005 from geometry_msgs.msg import Twist
00006 from rbx2_msgs.srv import *
00007 from pi_trees_ros.pi_trees_ros import *
00008 from pi_trees_lib.task_setup import *
00009 
00010 class BlackBoard():
00011     def __init__(self):
00012         self.battery_level = None
00013         self.charging = None
00014 
00015 class Patrol():
00016     def __init__(self):
00017         rospy.init_node("patrol_tree")
00018 
00019         # Set the shutdown function (stop the robot)
00020         rospy.on_shutdown(self.shutdown)
00021         
00022         # Initialize a number of parameters and variables
00023         setup_task_environment(self)
00024         
00025         # Initialize the black board
00026         self.blackboard = BlackBoard()
00027         
00028         # How frequently do we "tic" the tree?
00029         rate = rospy.get_param('~rate', 10)
00030         
00031         # Convert tic rate to a ROS rate
00032         tic = rospy.Rate(rate)
00033         
00034         # Where should the DOT file be stored.  Default location is $HOME/.ros/tree.dot
00035         dotfilepath = rospy.get_param('~dotfilepath', None)
00036 
00037         # Create a list to hold the move_base tasks
00038         MOVE_BASE_TASKS = list()
00039         
00040         n_waypoints = len(self.waypoints)
00041         
00042         # Create simple action navigation task for each waypoint
00043         for i in range(n_waypoints):
00044             goal = MoveBaseGoal()
00045             goal.target_pose.header.frame_id = 'map'
00046             goal.target_pose.header.stamp = rospy.Time.now()
00047             goal.target_pose.pose = self.waypoints[i % n_waypoints]
00048             
00049             move_base_task = SimpleActionTask("MOVE_BASE_TASK_" + str(i), "move_base", MoveBaseAction, goal, reset_after=False)
00050             
00051             MOVE_BASE_TASKS.append(move_base_task)
00052         
00053         # Set the docking station pose
00054         goal = MoveBaseGoal()
00055         goal.target_pose.header.frame_id = 'map'
00056         goal.target_pose.header.stamp = rospy.Time.now()
00057         goal.target_pose.pose = self.docking_station_pose
00058         
00059         # Assign the docking station pose to a move_base action task
00060         NAV_DOCK_TASK = SimpleActionTask("NAV_DOC_TASK", "move_base", MoveBaseAction, goal, reset_after=False)
00061         
00062         # Create the root node
00063         BEHAVE = Sequence("BEHAVE")
00064         
00065         # Create the "stay healthy" selector
00066         STAY_HEALTHY = Selector("STAY_HEALTHY")
00067         
00068         # Create the patrol loop decorator
00069         LOOP_PATROL = Loop("LOOP_PATROL", iterations=self.n_patrols)
00070         
00071         # Add the two subtrees to the root node in order of priority
00072         BEHAVE.add_child(STAY_HEALTHY)
00073         BEHAVE.add_child(LOOP_PATROL)
00074         
00075         # Create the patrol iterator
00076         PATROL = Iterator("PATROL")
00077         
00078         # Add the move_base tasks to the patrol task
00079         for task in MOVE_BASE_TASKS:
00080             PATROL.add_child(task)
00081   
00082         # Add the patrol to the loop decorator
00083         LOOP_PATROL.add_child(PATROL)
00084         
00085         # Add the battery check and recharge tasks to the "stay healthy" task
00086         with STAY_HEALTHY:
00087             # Monitor the fake battery level by subscribing to the /battery_level topic
00088             MONITOR_BATTERY = MonitorTask("MONITOR_BATTERY", "battery_level", Float32, self.monitor_battery)
00089             
00090             # Is the fake battery level below threshold?
00091             CHECK_BATTERY = CallbackTask("BATTERY_OK?", self.check_battery)  
00092             
00093             # Set the fake battery level back to 100 using a ServiceTask
00094             CHARGE_COMPLETE = ServiceTask("CHARGE_COMPLETE", "/battery_simulator/set_battery_level", SetBatteryLevel, 100, result_cb=self.recharge_cb)
00095             
00096             # Sleep for the given interval to simulate charging
00097             CHARGING = RechargeRobot("CHARGING", interval=3, blackboard=self.blackboard)
00098       
00099             # Build the recharge sequence using inline construction
00100             RECHARGE = Sequence("RECHARGE", [NAV_DOCK_TASK, CHARGING, CHARGE_COMPLETE], reset_after=True)
00101                 
00102             # Add the check battery and recharge tasks to the stay healthy selector
00103             STAY_HEALTHY.add_child(CHECK_BATTERY)
00104             STAY_HEALTHY.add_child(RECHARGE)
00105                 
00106         # Display the tree before beginning execution
00107         print "Patrol Behavior Tree"
00108         print_tree(BEHAVE)
00109         
00110         # Run the tree
00111         while not rospy.is_shutdown():
00112             BEHAVE.status = BEHAVE.run()
00113             tic.sleep()
00114             print_dot_tree(BEHAVE, dotfilepath)
00115             
00116     def monitor_battery(self, msg):
00117         # Store the battery level as published on the fake battery level topic
00118         self.blackboard.battery_level = msg.data
00119         return True
00120     
00121     def check_battery(self):
00122         # Don't run the check if we are charging
00123         if self.blackboard.charging:
00124             return False
00125         
00126         if self.blackboard.battery_level is None:
00127             return None
00128         elif self.blackboard.battery_level < self.low_battery_threshold:
00129             rospy.loginfo("LOW BATTERY - level: " + str(int(self.blackboard.battery_level)))
00130             return False
00131         else:
00132             return True
00133     
00134     def recharge_cb(self, result):
00135         rospy.loginfo("BATTERY CHARGED!")
00136         self.blackboard.battery_level = 100
00137         self.blackboard.charging = False
00138         rospy.sleep(2)
00139         return True
00140             
00141     def shutdown(self):
00142         rospy.loginfo("Stopping the robot...")
00143         self.move_base.cancel_all_goals()
00144         self.cmd_vel_pub.publish(Twist())
00145         rospy.sleep(1)
00146         
00147 class RechargeRobot(Task):
00148     def __init__(self, name, interval=3, blackboard=None):
00149         super(RechargeRobot, self).__init__(name)
00150        
00151         self.name = name
00152         self.interval = interval
00153         self.blackboard = blackboard
00154         
00155         self.timer = 0
00156          
00157     def run(self):
00158         if self.timer == 0:
00159             rospy.loginfo("CHARGING THE ROBOT!")
00160             
00161         if self.timer < self.interval:
00162             self.timer += 0.1
00163             rospy.sleep(0.1)
00164             self.blackboard.charging = True
00165             return TaskStatus.RUNNING
00166         else:
00167             return TaskStatus.SUCCESS
00168     
00169     def reset(self):
00170         self.status = None
00171         self.timer = 0
00172 
00173 if __name__ == '__main__':
00174     tree = Patrol()
00175 


pi_trees_lib
Author(s): Patrick Goebel
autogenerated on Thu Jun 6 2019 17:33:29