config_manager.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Software License Agreement (BSD License)
00003 #
00004 # Copyright (c) 2008, Willow Garage, Inc.
00005 # All rights reserved.
00006 #
00007 # Redistribution and use in source and binary forms, with or without
00008 # modification, are permitted provided that the following conditions
00009 # are met:
00010 #
00011 #  * Redistributions of source code must retain the above copyright
00012 #    notice, this list of conditions and the following disclaimer.
00013 #  * Redistributions in binary form must reproduce the above
00014 #    copyright notice, this list of conditions and the following
00015 #    disclaimer in the documentation and/or other materials provided
00016 #    with the distribution.
00017 #  * Neither the name of Willow Garage, Inc. nor the names of its
00018 #    contributors may be used to endorse or promote products derived
00019 #    from this software without specific prior written permission.
00020 #
00021 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 # POSSIBILITY OF SUCH DAMAGE.
00033 
00034 import roslib; roslib.load_manifest('calibration_launch')
00035 import rospy
00036 import yaml
00037 import sys
00038 import actionlib
00039 import joint_states_settler.msg
00040 import monocam_settler.msg
00041 import image_cb_detector.msg
00042 import laser_cb_detector.msg
00043 import interval_intersection.msg
00044 import time
00045 from trajectory_msgs.msg import JointTrajectory
00046 from trajectory_msgs.msg import JointTrajectoryPoint
00047 
00048 # Puts the system in a specific configuration, in preparation for collecting a sample
00049 class ConfigManager:
00050     def __init__(self, cam_config, chain_config, laser_config, controller_config):
00051 
00052         # Set up Cameras
00053         rospy.logdebug("Constructing Cameras:")
00054         self._cam_managers = dict()
00055         for name in cam_config.keys():
00056             rospy.logdebug("  Constructing CamID [%s]" % name)
00057             self._cam_managers[name] = CameraConfigManager(name, cam_config[name])
00058 
00059         # Set up Chains
00060         rospy.logdebug("Constructing Chains:")
00061         self._chain_managers = dict()
00062         for name in chain_config.keys():
00063             rospy.logdebug("  Constructing ChainID [%s]" % name)
00064             self._chain_managers[name] = ChainConfigManager(name, chain_config[name])
00065 
00066         # Set up lasers
00067         rospy.logdebug("Constructing Lasers:")
00068         self._laser_managers = dict()
00069         for laser_id in laser_config.keys():
00070             rospy.logdebug("  Constructing LaserID [%s]" % laser_id)
00071             self._laser_managers[laser_id] = LaserConfigManager(laser_id, laser_config[laser_id])
00072 
00073         # Set up Controllers
00074         rospy.logdebug("Constructing Controllers:")
00075         self._controller_managers = dict()
00076         for controller_id in controller_config.keys():
00077             rospy.logdebug("  Constructing ControllerID [%s]" % controller_id)
00078             self._controller_managers[controller_id] = ControllerCmdManager(controller_id, controller_config[controller_id])
00079 
00080         # Set up interval_intersection
00081         self._intersect_ac = actionlib.SimpleActionClient("interval_intersection_config", interval_intersection.msg.ConfigAction)
00082 
00083     def reconfigure(self, config):
00084         # Reconfigure Interval Intersection
00085 
00086         intersect_goal = interval_intersection.msg.ConfigGoal();
00087         intersect_goal.topics = [x['cam_id'] for x in config["camera_measurements"]] + [x['chain_id'] for x in config["joint_measurements"]] + [x['laser_id'] for x in config["laser_measurements"]]
00088         #intersect_goal.topics = [x['cam_id'] for x in config["camera_measurements"]] + [x['chain_id'] for x in config["joint_measurements"]]
00089         self._intersect_ac.send_goal(intersect_goal)
00090 
00091         # Reconfigure the cameras
00092         rospy.logdebug("Reconfiguring The Cameras")
00093         for cur_cam in config["camera_measurements"]:
00094             self._cam_managers[cur_cam["cam_id"]].reconfigure(cur_cam["config"])
00095 
00096         # Reconfigure the chains
00097         rospy.logdebug("Reconfiguring The Chains")
00098         for cur_chain in config["joint_measurements"]:
00099             self._chain_managers[cur_chain["chain_id"]].reconfigure(cur_chain["config"])
00100 
00101         # Reconfigure the lasers
00102         rospy.logdebug("Reconfiguring The Lasers")
00103         for cur_laser in config["laser_measurements"]:
00104             self._laser_managers[cur_laser["laser_id"]].reconfigure(cur_laser["config"])
00105 
00106         # Send controller commands
00107         rospy.logdebug("Sending Controller Commands")
00108         for cur_controller in config["joint_commands"]:
00109             self._controller_managers[cur_controller["controller"]].send_command(cur_controller)
00110 
00111     def stop(self):
00112         pass
00113 
00114 # Handles changing the configuration of a joint_states_settler
00115 class ChainConfigManager:
00116     def __init__(self, chain_id, configs):
00117         self._chain_id = chain_id
00118         self._configs = configs
00119         if not self.validate():
00120             raise Exception("Invalid chain description")
00121 
00122         # Initialize the ActionClient and state
00123         self._settler_ac  = actionlib.SimpleActionClient(self._configs["settler_config"], joint_states_settler.msg.ConfigAction)
00124         self._state = "idle"
00125 
00126     # Check to make sure that config dict has all the necessary fields. TODO: Currently a stub
00127     def validate(self):
00128         return True
00129 
00130     # Reconfigure this chain's processing pipeline to the specified configuration. Do nothing if
00131     # we're already in the correct configuration
00132     def reconfigure(self, next_config_name):
00133         if self._state == next_config_name:
00134             rospy.logdebug("  %s: Configured correctly as [%s]" % (self_.chain_id, self._state))
00135         else:
00136             rospy.logdebug("  %s: Need to transition [%s] -> [%s]" % (self._chain_id, self._state, next_config_name))
00137 
00138             next_config   = self._configs["configs"][next_config_name]
00139             settler_config = next_config["settler"]
00140             # Convert the settler's configuration from a dictionary to a ROS message
00141             goal = joint_states_settler.msg.ConfigGoal()
00142             goal.joint_names = settler_config["joint_names"]
00143             goal.tolerances  = settler_config["tolerances"]
00144             goal.max_step    = rospy.Duration(settler_config["max_step"])
00145             goal.cache_size  = settler_config["cache_size"]
00146 
00147             # Send the goal out
00148             self._settler_ac.send_goal(goal)
00149 
00150             # TODO: Need to add code that waits for goal to activate
00151 
00152 
00153 # Handles changing the configuration of the image pipeline associated with a camera
00154 class CameraConfigManager:
00155     def __init__(self, cam_id, configs):
00156         self._cam_id = cam_id
00157         self._configs = configs
00158         if not self.validate():
00159             raise Exception("Invalid camera description")
00160 
00161         # Initialize the ActionClients and state
00162         self._settler_ac   = actionlib.SimpleActionClient(self._configs["settler_config"], monocam_settler.msg.ConfigAction)
00163         self._led_detector_ac  = actionlib.SimpleActionClient(self._configs["cb_detector_config"], image_cb_detector.msg.ConfigAction)
00164         self._state = "idle"
00165 
00166     # Check to make sure that config dict has all the necessary fields. TODO: Currently a stub
00167     def validate(self):
00168         return True
00169 
00170     # Reconfigure this chain's processing pipeline to the specified configuration. Do nothing if
00171     # we're already in the correct configuration
00172     def reconfigure(self, next_config_name):
00173         if self._state == next_config_name:
00174             rospy.logdebug("  %s: Configured correctly as [%s]" % (self_.cam_id, self._state))
00175         else:
00176             rospy.logdebug("  %s: Need to transition [%s] -> [%s]" % (self._cam_id, self._state, next_config_name))
00177 
00178             next_config   = self._configs["configs"][next_config_name]
00179 
00180             # Send the Settler's Goal
00181             settler_config = next_config["settler"]
00182             goal = monocam_settler.msg.ConfigGoal()
00183             goal.tolerance = settler_config["tolerance"]
00184             goal.ignore_failures = settler_config["ignore_failures"]
00185             goal.max_step = rospy.Duration(settler_config["max_step"])
00186             goal.cache_size  = settler_config["cache_size"]
00187             self._settler_ac.send_goal(goal)
00188 
00189             # Send the CB Detector Goal
00190             cb_detector_config = next_config["cb_detector"]
00191             if not cb_detector_config["active"]:
00192                 rospy.logerr("Can't deal with inactive cb_detector")
00193             goal = image_cb_detector.msg.ConfigGoal()
00194             goal.num_x = cb_detector_config["num_x"]
00195             goal.num_y = cb_detector_config["num_y"]
00196             goal.spacing_x = 1.0    # Hardcoded garbage value. Should eventually be removed from the msg
00197             goal.spacing_y = 1.0    # Hardcoded garbage value. Should eventually be removed from the msg
00198             goal.width_scaling = cb_detector_config["width_scaling"]
00199             goal.height_scaling = cb_detector_config["height_scaling"]
00200             goal.subpixel_window = cb_detector_config["subpixel_window"]
00201             goal.subpixel_zero_zone = cb_detector_config["subpixel_zero_zone"]
00202             self._led_detector_ac.send_goal(goal)
00203 
00204             # Send the LED Detector Goal
00205             led_detector_config = next_config["led_detector"]
00206             if led_detector_config["active"]:
00207                 rospy.logerr("Can't deal with an active led_detector")
00208 
00209             # TODO: Need to add code that waits for goal to activate
00210 
00211 # Handles changing the configuration of the image pipeline associated with a camera
00212 class LaserConfigManager:
00213     def __init__(self, laser_id, configs):
00214         self._laser_id = laser_id
00215         self._configs = configs
00216         if not self.validate():
00217             raise Exception("Invalid laser description")
00218 
00219         # Initialize the ActionClients and state
00220         self._settler_ac   = actionlib.SimpleActionClient(self._configs["settler_config"], monocam_settler.msg.ConfigAction)
00221         self._cb_detector_ac  = actionlib.SimpleActionClient(self._configs["cb_detector_config"], laser_cb_detector.msg.ConfigAction)
00222         self._state = "idle"
00223 
00224     # Check to make sure that config dict has all the necessary fields. TODO: Currently a stub
00225     def validate(self):
00226         return True
00227 
00228     # Reconfigure this chain's processing pipeline to the specified configuration. Do nothing if
00229     # we're already in the correct configuration
00230     def reconfigure(self, next_config_name):
00231         if self._state == next_config_name:
00232             rospy.logdebug("  %s: Configured correctly as [%s]" % (self_.laser_id, self._state))
00233         else:
00234             rospy.logdebug("  %s: Need to transition [%s] -> [%s]" % (self._laser_id, self._state, next_config_name))
00235 
00236             next_config   = self._configs["configs"][next_config_name]
00237 
00238             # Send the Settler's Goal
00239             settler_config = next_config["settler"]
00240             goal = monocam_settler.msg.ConfigGoal()
00241             goal.tolerance = settler_config["tolerance"]
00242             goal.ignore_failures = settler_config["ignore_failures"]
00243             goal.max_step = rospy.Duration(settler_config["max_step"])
00244             goal.cache_size  = settler_config["cache_size"]
00245             self._settler_ac.send_goal(goal)
00246 
00247             # Send the CB Detector Goal
00248             cb_detector_config = next_config["cb_detector"]
00249             if not cb_detector_config["active"]:
00250                 rospy.logerr("Not sure yet how to deal with inactive cb_detector")
00251             goal = laser_cb_detector.msg.ConfigGoal()
00252             goal.num_x = cb_detector_config["num_x"]
00253             goal.num_y = cb_detector_config["num_y"]
00254             goal.spacing_x = cb_detector_config["spacing_x"]
00255             goal.spacing_y = cb_detector_config["spacing_y"]
00256             goal.width_scaling = cb_detector_config["width_scaling"]
00257             goal.height_scaling = cb_detector_config["height_scaling"]
00258             goal.subpixel_window = cb_detector_config["subpixel_window"]
00259             goal.subpixel_zero_zone = cb_detector_config["subpixel_zero_zone"]
00260             goal.flip_horizontal = cb_detector_config["flip_horizontal"]
00261             goal.min_intensity = cb_detector_config["min_intensity"]
00262             goal.max_intensity = cb_detector_config["max_intensity"]
00263             self._cb_detector_ac.send_goal(goal)
00264 
00265             # TODO: Need to add code that waits for goal to activate
00266 
00267 
00268 
00269 # Handles publishing commands to a trajectory controller
00270 class ControllerCmdManager:
00271     def __init__(self, controller_id, config):
00272         self._controller_id = controller_id
00273         self._config = config
00274         if not self.validate():
00275             raise Exception("Invalid chain description")
00276 
00277         # Initialize the Publisher
00278         self._pub  = rospy.Publisher(self._config["topic"], JointTrajectory)
00279 
00280     # Check to make sure that config dict has all the necessary fields. TODO: Currently a stub
00281     def validate(self):
00282         return True
00283 
00284     # Reconfigure this chain's processing pipeline to the specified configuration. Do nothing if
00285     # we're already in the correct configuration
00286     def send_command(self, cmd):
00287         rospy.logdebug("  Sending cmd to controller [%s]"%self._controller_id)
00288         cmd_msg = JointTrajectory()
00289         cmd_msg.header.stamp = rospy.Time().now()
00290         cmd_msg.joint_names = self._config["joint_names"]
00291         cmd_msg.points = [self._build_segment(x) for x in cmd["segments"]]
00292         self._pub.publish(cmd_msg)
00293 
00294     def _build_segment(self, config):
00295         segment = JointTrajectoryPoint()
00296         segment.positions = config["positions"]
00297         segment.velocities = [0] * len(config["positions"])
00298         segment.time_from_start = rospy.Duration(config["duration"])
00299         return segment
00300 
00301 
00302 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


calibration_launch
Author(s): Michael Ferguson
autogenerated on Thu Aug 15 2013 10:16:12