Go to the documentation of this file.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 
00061 
00062 #include <ros/ros.h>
00063 
00064 
00065 #include <std_msgs/ColorRGBA.h>
00066 #include <visualization_msgs/Marker.h>
00067 
00068 
00069 #include <unistd.h>
00070 #include <fcntl.h>
00071 #include <errno.h>
00072 #include <termios.h>
00073 #include <time.h>
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 #define TURN_OFF_LIGHT_ON_STARTUP
00082 
00083 class SerialCom
00084 {
00085 public:
00086         
00087         SerialCom() :
00088          _fd(-1), m_simulation(false)
00089         {
00090         }
00091         
00092         ~SerialCom()
00093         {
00094                 closePort();
00095         }
00096 
00097         
00098         int openPort(std::string devicestring, int baudrate)
00099         {
00100                 if(_fd != -1) return _fd;
00101 
00102                 ROS_INFO("Open Port on %s",devicestring.c_str());
00103                 _fd = open(devicestring.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
00104                 if(_fd != -1)
00105                 {
00106                         speed_t baud = getBaudFromInt(baudrate);
00107                         fcntl(_fd, F_SETFL, 0);
00108                         tcgetattr(_fd, &port_settings);
00109                         port_settings.c_cflag &= ~PARENB;
00110                         port_settings.c_cflag &= ~CSTOPB;
00111                         port_settings.c_cflag &= ~CSIZE;
00112                         port_settings.c_cflag = baud | CS8 | CLOCAL | CREAD;
00113                         port_settings.c_iflag = IGNPAR;
00114                         tcsetattr(_fd, TCSANOW, &port_settings);
00115                         ROS_INFO("Serial connection on %s succeeded.", devicestring.c_str());
00116                 }
00117                 else
00118                 {
00119                         ROS_ERROR("Serial connection on %s failed.", devicestring.c_str());
00120                 }
00121                 return _fd;
00122         }
00123 
00124         
00125         int sendData(std::string value)
00126         {
00127                 size_t wrote = -1;
00128                 if(_fd != -1)
00129                 {
00130                         wrote = write(_fd, value.c_str(), value.length());
00131                         ROS_DEBUG("Wrote [%s] with %i bytes from %i bytes", value.c_str(), (int)wrote, value.length());
00132                 }
00133                 else
00134                         ROS_WARN("Can not write to serial port. Port closed! Check if LED board is attached and device is opened correctly.");
00135 
00136                 return wrote;
00137         }
00138 
00139         
00140         int readData(std::string &value, size_t nBytes)
00141         {
00142                 char buffer[32];
00143                 size_t rec = -1;
00144                 rec = read(_fd, buffer, nBytes);
00145                 value = std::string(buffer);
00146                 return rec;
00147         }
00148 
00149         
00150         bool isOpen()
00151         {
00152                 return (_fd != -1);
00153         }
00154 
00155         
00156         void closePort()
00157         {
00158                 if(_fd != -1)
00159                         close(_fd);
00160         }
00161 
00162 private:
00163         
00164         int _fd;
00165         
00166         struct termios port_settings;
00167         bool m_simulation;
00168 
00169         speed_t getBaudFromInt(int baud)
00170         {
00171                 speed_t ret;
00172                 switch(baud)
00173                 {
00174                         case 0:         ret=B0;         break;
00175                         case 50:        ret=B50;        break;
00176                         case 75:        ret=B75;        break;
00177                         case 110:       ret=B110;       break;
00178                         case 134:       ret=B134;       break;
00179                         case 150:       ret=B150;       break;
00180                         case 200:       ret=B200;       break;
00181                         case 300:       ret=B300;       break;
00182                         case 1200:      ret=B1200;      break;
00183                         case 1800:      ret=B1800;      break;
00184                         case 2400:      ret=B2400;      break;
00185                         case 4800:      ret=B4800;      break;
00186                         case 9600:      ret=B9600;      break;
00187                         case 19200: ret=B19200; break;
00188                         case 38400: ret=B38400; break;
00189                         case 57600: ret=B57600; break;
00190                         case 115200: ret=B115200; break;
00191                         case 230400: ret=B230400; break;
00192                         default:
00193                                 ROS_WARN("Unsupported Baudrate [%i]. Using default [230400]", baud);
00194                                 ret=B230400;
00195                                 break;
00196                 }
00197                 return ret;
00198         }
00199 };
00200 
00201 class LightControl
00202 {
00203         public:
00204                 LightControl() :
00205                  _invertMask(0)
00206                 {
00207 
00208                         bool invert_output;
00209 
00210                         
00211                         _nh.param<bool>("invert_output", invert_output, false);
00212                         _invertMask = (int)invert_output;
00213 
00214                         _nh.param<std::string>("devicestring",_deviceString,"/dev/ttyLed");
00215                         _nh.param<int>("baudrate",_baudrate,230400);
00216                         _nh.param<bool>("pubmarker",_bPubMarker,true);
00217                         
00218                         _sub = _nh.subscribe("command", 1, &LightControl::setRGB, this);
00219 
00220                         _pubMarker = _nh.advertise<visualization_msgs::Marker>("marker",1);
00221 
00222 #ifndef __SIM__
00223                         
00224                         _serialCom.openPort(_deviceString, _baudrate);
00225 #endif
00226                                 
00227                         
00228                         if(_bPubMarker)
00229                                 _timerMarker = _nh.createTimer(ros::Duration(0.5),
00230                                                 &LightControl::markerCallback, this);
00231 
00232                         
00233                         #ifdef TURN_OFF_LIGHT_ON_STARTUP
00234                                 _color.a=0;
00235                                 setRGB(_color);
00236                         #endif
00237                 }
00238 
00239                 ~LightControl()
00240                 {
00241                 }
00242 
00243                 void setRGB(std_msgs::ColorRGBA color)
00244                 {
00245                         if(color.r <= 1.0 && color.g <=1.0 && color.b <= 1.0)
00246                         {
00247                                 _color = color;
00248                                 
00249                                 
00250                                 color.r *= color.a;
00251                                 color.g *= color.a;
00252                                 color.b *= color.a;
00253                                 
00254                                 
00255                                 color.r = (fabs(_invertMask-color.r) * 999.0);
00256                                 color.g = (fabs(_invertMask-color.g) * 999.0);
00257                                 color.b = (fabs(_invertMask-color.b) * 999.0);
00258 
00259                                 _ssOut.clear();
00260                                 _ssOut.str("");
00261                                 _ssOut << (int)color.r << " " << (int)color.g << " " << (int)color.b << "\n\r";
00262 
00263 #ifndef __SIM__
00264                                 _serialCom.sendData(_ssOut.str());
00265 #endif
00266 
00267                         }
00268                         else
00269                                 ROS_ERROR("Unsupported Color format. rgba values range is 0.0 - 1.0");
00270                 }
00271                 
00272         private:
00273                 SerialCom _serialCom;
00274 
00275                 std::string _deviceString;
00276                 int _baudrate;
00277                 int _invertMask;
00278                 bool _bPubMarker;
00279 
00280                 std::stringstream _ssOut;
00281 
00282                 ros::NodeHandle _nh;
00283                 ros::Publisher _pubMarker;
00284                 ros::Subscriber _sub;
00285                 ros::Timer _timerMarker;
00286 
00287                 std_msgs::ColorRGBA _color;
00288                 
00289                 
00290                 void markerCallback(const ros::TimerEvent &event)
00291                 {
00292                         visualization_msgs::Marker marker;
00293                         marker.header.frame_id = "/base_link";
00294                         marker.header.stamp = ros::Time();
00295                         marker.ns = "color";
00296                         marker.id = 0;
00297                         marker.type = visualization_msgs::Marker::SPHERE;
00298                         marker.action = visualization_msgs::Marker::ADD;
00299                         marker.pose.position.x = 0;
00300                         marker.pose.position.y = 0,
00301                         marker.pose.position.z = 1.5;
00302                         marker.pose.orientation.x = 0.0;
00303                         marker.pose.orientation.y = 0.0;
00304                         marker.pose.orientation.z = 0.0;
00305                         marker.pose.orientation.w = 1.0;
00306                         marker.scale.x = 0.1;
00307                         marker.scale.y = 0.1;
00308                         marker.scale.z = 0.1;
00309                         marker.color.a = _color.a;
00310                         marker.color.r = _color.r;
00311                         marker.color.g = _color.g;
00312                         marker.color.b = _color.b;
00313                         _pubMarker.publish(marker);
00314                 }
00315 };
00316 
00317 int main(int argc, char** argv)
00318 {
00319         
00320         ros::init(argc, argv, "light_controller");
00321         
00322         LightControl lightControl;
00323 
00324         ros::spin();
00325         return 0;
00326 }