00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 #include <stdio.h>
00057 #include <string.h>
00058 #include <sstream>
00059 #include <math.h>
00060 #include <signal.h>
00061 
00062 
00063 #include <ros/ros.h>
00064 #include <actionlib/server/simple_action_server.h>
00065 #include <diagnostic_msgs/DiagnosticArray.h>
00066 #include <ros/xmlrpc_manager.h>
00067 
00068 
00069 #include <std_msgs/ColorRGBA.h>
00070 #include <visualization_msgs/Marker.h>
00071 #include <cob_light/LightMode.h>
00072 #include <cob_light/SetLightMode.h>
00073 #include <cob_light/SetLightModeAction.h>
00074 #include <cob_light/SetLightModeActionGoal.h>
00075 #include <cob_light/SetLightModeActionResult.h>
00076 
00077 
00078  #include <serialIO.h>
00079 
00080 
00081 #include <colorUtils.h>
00082 #include <modeExecutor.h>
00083 #include <colorO.h>
00084 #include <colorOSim.h>
00085 #include <ms35.h>
00086 
00087 sig_atomic_t volatile gShutdownRequest = 0;
00088 
00089 void sigIntHandler(int signal)
00090 {
00091   ::gShutdownRequest = 1;
00092 }
00093 
00094 void shutdownCallback(XmlRpc::XmlRpcValue& params, XmlRpc::XmlRpcValue& result)
00095 {
00096   int num_params = 0;
00097   if (params.getType() == XmlRpc::XmlRpcValue::TypeArray)
00098     num_params = params.size();
00099   if (num_params > 1)
00100   {
00101     std::string reason = params[1];
00102     ROS_WARN("Shutdown request received. Reason: [%s]", reason.c_str());
00103     ::gShutdownRequest = 1; 
00104   }
00105 
00106   result = ros::xmlrpc::responseInt(1, "", 0);
00107 }
00108 
00109 class LightControl
00110 {
00111         public:
00112                 LightControl() :
00113                  _invertMask(0), _topic_priority(0)
00114                 {
00115                         bool invert_output;
00116                         XmlRpc::XmlRpcValue param_list;
00117                         std::string startup_mode;
00118                         p_colorO = NULL;
00119                         p_modeExecutor = NULL;
00120 
00121                         
00122                         _pubDiagnostic = _nh.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
00123 
00124                         diagnostic_msgs::DiagnosticStatus status;
00125                 status.name = "light";
00126                 
00127 
00128                         
00129                         _nh = ros::NodeHandle("~");
00130                         if(!_nh.hasParam("invert_output"))
00131                                 ROS_WARN("Parameter 'invert_output' is missing. Using default Value: false");
00132                         _nh.param<bool>("invert_output", invert_output, false);
00133                         _invertMask = (int)invert_output;
00134 
00135                         if(!_nh.hasParam("devicedriver"))
00136                                 ROS_WARN("Parameter 'devicedriver' is missing. Using default Value: cob_ledboard");
00137                         _nh.param<std::string>("devicedriver",_deviceDriver,"cob_ledboard");
00138 
00139                         if(!_nh.hasParam("devicestring"))
00140                                 ROS_WARN("Parameter 'devicestring' is missing. Using default Value: /dev/ttyLed");
00141                         _nh.param<std::string>("devicestring",_deviceString,"/dev/ttyLed");
00142 
00143                         if(!_nh.hasParam("baudrate"))
00144                                 ROS_WARN("Parameter 'baudrate' is missing. Using default Value: 230400");
00145                         _nh.param<int>("baudrate",_baudrate,230400);
00146 
00147                         if(!_nh.hasParam("pubmarker"))
00148                                 ROS_WARN("Parameter 'pubmarker' is missing. Using default Value: true");
00149                         _nh.param<bool>("pubmarker",_bPubMarker,true);
00150 
00151                         if(!_nh.hasParam("sim_enabled"))
00152                                 ROS_WARN("Parameter 'sim_enabled' is missing. Using default Value: false");
00153                         _nh.param<bool>("sim_enabled", _bSimEnabled, false);
00154 
00155                         if(!_nh.hasParam("startup_color"))
00156                         {
00157                                 ROS_WARN("Parameter 'startup_color' is missing. Using default Value: off");
00158                                 _color.r=0;_color.g=0;_color.b=0;_color.a=0;
00159                         }
00160                         else
00161                         {
00162                                 _nh.getParam("startup_color", param_list);
00163                                 ROS_ASSERT(param_list.getType() == XmlRpc::XmlRpcValue::TypeArray);
00164                                 ROS_ASSERT(param_list.size() == 4);
00165 
00166                                 _color.r = static_cast<double>(param_list[0]);
00167                                 _color.g = static_cast<double>(param_list[1]);
00168                                 _color.b = static_cast<double>(param_list[2]);
00169                                 _color.a = static_cast<double>(param_list[3]);
00170                         }
00171 
00172                         if(!_nh.hasParam("startup_mode"))
00173                                 ROS_WARN("Parameter 'startup_mode' is missing. Using default Value: None");
00174                         _nh.param<std::string>("startup_mode", startup_mode, "None");
00175 
00176                         
00177                         _sub = _nh.subscribe("command", 1, &LightControl::topicCallback, this);
00178 
00179                         
00180                         _srvServer = _nh.advertiseService("mode", &LightControl::serviceCallback, this);
00181 
00182                         
00183                         _as = new ActionServer(_nh, "set_lightmode", boost::bind(&LightControl::actionCallback, this, _1), false);
00184                         _as->start();
00185 
00186                         
00187                         _pubMarker = _nh.advertise<visualization_msgs::Marker>("marker",1);
00188 
00189                         if(!_bSimEnabled)
00190                         {
00191                                 
00192                                 ROS_INFO("Open Port on %s",_deviceString.c_str());
00193                                 if(_serialIO.openPort(_deviceString, _baudrate) != -1)
00194                                 {
00195                                         ROS_INFO("Serial connection on %s succeeded.", _deviceString.c_str());
00196                                         if(_deviceDriver == "cob_ledboard")
00197                                                 p_colorO = new ColorO(&_serialIO);
00198                                         else if(_deviceDriver == "ms-35")
00199                                                 p_colorO = new MS35(&_serialIO);
00200                                         if(p_colorO)
00201                                                 p_colorO->setMask(_invertMask);
00202 
00203                                         status.level = 0;
00204                                         status.message = "light controller running";
00205                                 }
00206                                 else
00207                                 {
00208                                         ROS_WARN("Serial connection on %s failed.", _deviceString.c_str());
00209                                         ROS_INFO("Simulation Mode Enabled");
00210                                         p_colorO = new ColorOSim(&_nh);
00211 
00212                                         status.level = 2;
00213                                         status.message = "Serial connection failed. Running in simulation mode";
00214                                 }
00215                         }
00216                         else
00217                         {
00218                                 ROS_INFO("Simulation Mode Enabled");
00219                                 p_colorO = new ColorOSim(&_nh);
00220                                 status.level = 0;
00221                                 status.message = "light controller running in simulation";
00222                         }
00223                 
00224                 _diagnostics.status.push_back(status);
00225                 _diagnostics.header.stamp = ros::Time::now();
00226                 _pubDiagnostic.publish(_diagnostics);
00227                 _diagnostics.status.resize(0);
00228 
00229                         if(_bPubMarker)
00230                                 p_colorO->signalColorSet()->connect(boost::bind(&LightControl::markerCallback, this, _1));
00231 
00232                         p_modeExecutor = new ModeExecutor(p_colorO);
00233 
00234                         Mode * mode = ModeFactory::create(startup_mode, _color);
00235                         if(mode == NULL)
00236                                 p_colorO->setColor(_color);
00237                         else
00238                                 p_modeExecutor->execute(mode);
00239                 }
00240 
00241                 ~LightControl()
00242                 {
00243                         if(p_modeExecutor != NULL)
00244                         {
00245                                 p_modeExecutor->stop();
00246                                 delete p_modeExecutor;
00247                         }
00248                         if(p_colorO != NULL)
00249                         {
00250                                 delete p_colorO;
00251                         }
00252                 }
00253 
00254                 void topicCallback(std_msgs::ColorRGBA color)
00255                 {
00256                         if(color.r <= 1.0 && color.g <=1.0 && color.b <= 1.0)
00257                         {
00258                                 if(p_modeExecutor->getExecutingPriority() <= _topic_priority)
00259                                 {
00260                                         p_modeExecutor->stop();
00261                                         _color.r = color.r;
00262                                         _color.g = color.g;
00263                                         _color.b = color.b;
00264                                         _color.a = color.a;
00265                                         p_colorO->setColor(_color);
00266                                 }
00267                         }
00268                         else
00269                                 ROS_ERROR("Unsupported Color format. rgba values range is between 0.0 - 1.0");
00270                 }
00271 
00272                 bool serviceCallback(cob_light::SetLightMode::Request &req, cob_light::SetLightMode::Response &res)
00273                 {
00274                         bool ret = false;
00275 
00276                         
00277                         
00278 
00279                         if(req.mode.color.r > 1.0 || req.mode.color.g > 1.0 || req.mode.color.b > 1.0 || req.mode.color.a > 1.0)
00280                         {
00281                                 res.active_mode = p_modeExecutor->getExecutingMode();
00282                                 res.active_priority = p_modeExecutor->getExecutingPriority();
00283                                 ROS_ERROR("Unsupported Color format. rgba values range is between 0.0 - 1.0");
00284                         }
00285                         else if(req.mode.mode == cob_light::LightMode::NONE)
00286                         {
00287                                 p_modeExecutor->stop();
00288                                 _color.a = 0;
00289                                 p_colorO->setColor(_color);
00290                                 res.active_mode = p_modeExecutor->getExecutingMode();
00291                                 res.active_priority = p_modeExecutor->getExecutingPriority();
00292                                 ret = true;
00293                         }
00294                         else
00295                         {
00296                                 p_modeExecutor->execute(req.mode);
00297                                 res.active_mode = p_modeExecutor->getExecutingMode();
00298                                 res.active_priority = p_modeExecutor->getExecutingPriority();
00299                                 ret = true;
00300                         }
00301                         
00302                         return ret;
00303                 }
00304 
00305                 void actionCallback(const cob_light::SetLightModeGoalConstPtr &goal)
00306                 {
00307                         cob_light::SetLightModeResult result;
00308                         if(goal->mode.color.r > 1.0 || goal->mode.color.g > 1.0 || goal->mode.color.b > 1.0 || goal->mode.color.a > 1.0)
00309                         {
00310                                 result.active_mode = p_modeExecutor->getExecutingMode();
00311                                 result.active_priority = p_modeExecutor->getExecutingPriority();
00312                                 _as->setAborted(result, "Unsupported Color format. rgba values range is between 0.0 - 1.0");
00313                                 
00314                                 ROS_ERROR("Unsupported Color format. rgba values range is between 0.0 - 1.0");
00315                         }
00316                         else if(goal->mode.mode == cob_light::LightMode::NONE)
00317                         {
00318                                 p_modeExecutor->stop();
00319                                 _color.a = 0;
00320                                 p_colorO->setColor(_color);
00321 
00322                                 result.active_mode = p_modeExecutor->getExecutingMode();
00323                                 result.active_priority = p_modeExecutor->getExecutingPriority();
00324                                 _as->setSucceeded(result, "Mode switched");
00325                         }
00326                         else
00327                         {
00328                                 p_modeExecutor->execute(goal->mode);
00329                                 result.active_mode = p_modeExecutor->getExecutingMode();
00330                                 result.active_priority = p_modeExecutor->getExecutingPriority();
00331                                 _as->setSucceeded(result, "Mode switched");
00332                         }
00333                 }
00334 
00335                 void markerCallback(color::rgba color)
00336                 {
00337                         visualization_msgs::Marker marker;
00338                         marker.header.frame_id = "/base_link";
00339                         marker.header.stamp = ros::Time();
00340                         marker.ns = "color";
00341                         marker.id = 0;
00342                         marker.type = visualization_msgs::Marker::SPHERE;
00343                         marker.action = visualization_msgs::Marker::ADD;
00344                         marker.pose.position.x = 0;
00345                         marker.pose.position.y = 0,
00346                         marker.pose.position.z = 1.5;
00347                         marker.pose.orientation.x = 0.0;
00348                         marker.pose.orientation.y = 0.0;
00349                         marker.pose.orientation.z = 0.0;
00350                         marker.pose.orientation.w = 1.0;
00351                         marker.scale.x = 0.1;
00352                         marker.scale.y = 0.1;
00353                         marker.scale.z = 0.1;
00354                         marker.color.a = color.a;
00355                         marker.color.r = color.r;
00356                         marker.color.g = color.g;
00357                         marker.color.b = color.b;
00358                         _pubMarker.publish(marker);
00359                 }
00360                 
00361         private:
00362                 std::string _deviceDriver;
00363                 std::string _deviceString;
00364                 int _baudrate;
00365                 int _invertMask;
00366                 bool _bPubMarker;
00367                 bool _bSimEnabled;
00368 
00369                 int _topic_priority;
00370 
00371                 ros::NodeHandle _nh;
00372                 ros::Subscriber _sub;
00373                 ros::Publisher _pubMarker;
00374                 ros::ServiceServer _srvServer;
00375 
00376                 diagnostic_msgs::DiagnosticArray _diagnostics;
00377                 ros::Publisher _pubDiagnostic;
00378 
00379                 typedef actionlib::SimpleActionServer<cob_light::SetLightModeAction> ActionServer;
00380                 ActionServer *_as;
00381 
00382                 color::rgba _color;
00383                 
00384                 IColorO* p_colorO;
00385                 SerialIO _serialIO;
00386                 ModeExecutor* p_modeExecutor;
00387 };
00388 
00389 int main(int argc, char** argv)
00390 {
00391         
00392         ros::init(argc, argv, "light_controller", ros::init_options::NoSigintHandler);
00393         signal(SIGINT, sigIntHandler);
00394 
00395         
00396         ros::XMLRPCManager::instance()->unbind("shutdown");
00397         ros::XMLRPCManager::instance()->bind("shutdown", shutdownCallback);
00398 
00399         
00400         LightControl *lightControl = new LightControl();
00401 
00402         ros::AsyncSpinner spinner(1);
00403         spinner.start();
00404 
00405         while (!gShutdownRequest)
00406         {
00407                 ros::WallDuration(0.05).sleep();
00408         }
00409 
00410         delete lightControl;
00411 
00412         ros::shutdown();
00413 
00414         return 0;
00415 }