cob_light.cpp
Go to the documentation of this file.
00001 /****************************************************************
00002  *
00003  * Copyright (c) 2010
00004  *
00005  * Fraunhofer Institute for Manufacturing Engineering   
00006  * and Automation (IPA)
00007  *
00008  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00009  *
00010  * Project name: care-o-bot
00011  * ROS stack name: cob_driver
00012  * ROS package name: cob_light
00013  * Description: Switch robots led color by sending data to
00014  * the led-µC over serial connection.
00015  *                                                              
00016  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00017  *                      
00018  * Author: Benjamin Maidel, email:benjamin.maidel@ipa.fraunhofer.de
00019  * Supervised by: Benjamin Maidel, email:benjamin.maidel@ipa.fraunhofer.de
00020  *
00021  * Date of creation: August 2012
00022  * ToDo:
00023  *
00024  * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00025  *
00026  * Redistribution and use in source and binary forms, with or without
00027  * modification, are permitted provided that the following conditions are met:
00028  *
00029  *     * Redistributions of source code must retain the above copyright
00030  *       notice, this list of conditions and the following disclaimer.
00031  *     * Redistributions in binary form must reproduce the above copyright
00032  *       notice, this list of conditions and the following disclaimer in the
00033  *       documentation and/or other materials provided with the distribution.
00034  *     * Neither the name of the Fraunhofer Institute for Manufacturing 
00035  *       Engineering and Automation (IPA) nor the names of its
00036  *       contributors may be used to endorse or promote products derived from
00037  *       this software without specific prior written permission.
00038  *
00039  * This program is free software: you can redistribute it and/or modify
00040  * it under the terms of the GNU Lesser General Public License LGPL as 
00041  * published by the Free Software Foundation, either version 3 of the 
00042  * License, or (at your option) any later version.
00043  * 
00044  * This program is distributed in the hope that it will be useful,
00045  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00046  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00047  * GNU Lesser General Public License LGPL for more details.
00048  * 
00049  * You should have received a copy of the GNU Lesser General Public 
00050  * License LGPL along with this program. 
00051  * If not, see <http://www.gnu.org/licenses/>.
00052  *
00053  ****************************************************************/
00054 
00055 // standard includes
00056 #include <stdio.h>
00057 #include <string.h>
00058 #include <sstream>
00059 #include <math.h>
00060 #include <signal.h>
00061 
00062 // ros includes
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 // ros message includes
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 // serial connection includes
00078  #include <serialIO.h>
00079 
00080 // additional includes
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; // Set flag
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                         //diagnostics
00122                         _pubDiagnostic = _nh.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
00123 
00124                         diagnostic_msgs::DiagnosticStatus status;
00125                 status.name = "light";
00126                 
00127 
00128                         //Get Parameter from Parameter Server
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                         //Subscribe to LightController Command Topic
00177                         _sub = _nh.subscribe("command", 1, &LightControl::topicCallback, this);
00178 
00179                         //Advertise light mode Service
00180                         _srvServer = _nh.advertiseService("mode", &LightControl::serviceCallback, this);
00181 
00182                         //Start light mode Action Server
00183                         _as = new ActionServer(_nh, "set_lightmode", boost::bind(&LightControl::actionCallback, this, _1), false);
00184                         _as->start();
00185 
00186                         //Advertise visualization marker topic
00187                         _pubMarker = _nh.advertise<visualization_msgs::Marker>("marker",1);
00188 
00189                         if(!_bSimEnabled)
00190                         {
00191                                 //open serial port
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                         //ROS_DEBUG("Service Callback [Mode: %i with prio: %i freq: %f timeout: %f pulses: %i ]",
00277                         //      req.mode.mode, req.mode.priority, req.mode.frequency, req.mode.timeout, req.mode.pulses);
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         // init node
00392         ros::init(argc, argv, "light_controller", ros::init_options::NoSigintHandler);
00393         signal(SIGINT, sigIntHandler);
00394 
00395         // Override XMLRPC shutdown
00396         ros::XMLRPCManager::instance()->unbind("shutdown");
00397         ros::XMLRPCManager::instance()->bind("shutdown", shutdownCallback);
00398 
00399         // create LightControl instance
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 }


cob_light
Author(s): Benjamin Maidel
autogenerated on Thu Aug 27 2015 12:46:10