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 #include "SensorNet.h"
00038 
00039 SensorNet::SensorNet(std::string port_name, int baud_rate)
00040 {
00041         serial_port = new cereal::CerealPort();
00042         
00043         try{ serial_port->open(port_name.c_str(), baud_rate); }
00044         catch(cereal::Exception& e)
00045         {
00046                 ROS_FATAL("SensorNet -- Could not connect to the network!");
00047                 ROS_BREAK();
00048         }
00049         
00050         start_time = ros::Time::now();
00051         
00052         timeout = 200; 
00053 }
00054 
00055 SensorNet::~SensorNet()
00056 {
00057         try{ serial_port->close(); }
00058         catch(cereal::Exception& e)
00059         { 
00060                 ROS_ERROR("SensorNet -- Could not close the serial port!");
00061         }
00062 
00063         delete serial_port;
00064 }
00065 
00066 bool SensorNet::sendCommand(char address, char command)
00067 {
00068         std::string data;
00069         
00070         data+=SN_START;
00071         data+=address;
00072         data+=command;
00073         data+=CR;
00074         
00075         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Sending command %c to address %c - %s", command, address, data.c_str());
00076         
00077         try{ serial_port->write(data.c_str()); }
00078         catch(cereal::Exception& e)
00079         {
00080                 ROS_ERROR("SensorNet - sendCommand - Error sending command %c to node %c.", command, address);
00081                 return false;
00082         }
00083         return true;
00084 }
00085 
00086 bool SensorNet::waitForIt(char address)
00087 {
00088         std::string reply;
00089 
00090         try{ serial_port->readBetween(&reply, SN_START, (char)CR, timeout); }
00091         catch(cereal::TimeoutException& te)
00092         { 
00093                 ROS_ERROR("SensorNet - waitForIt - Timeout waiting for ack from node %c.", address);
00094                 return false;
00095         }
00096         catch(cereal::Exception& e)
00097         { 
00098                 ROS_ERROR("SensorNet - waitForIt - Error reading ack from node %c: \n%s", address, e.what());
00099                 return false;
00100         }
00101         
00102         if(reply[1]==address) return true;
00103         ROS_ERROR("SensorNet - waitForIt - Wrong ack received: got %c instead of %c", reply[1], address);
00104         return false;
00105 }
00106 
00107 bool SensorNet::scanNodes(int period)
00108 {
00109         std::string reply;
00110         bool timedout;
00111         
00112         for(char i='A' ; i<SN_BROADCAST ; i++)
00113         {
00114                 timedout=false;
00115                 if(sendCommand(i, SN_GET_INFO))
00116                 {
00117                         try{ serial_port->readBetween(&reply, SN_START, (char)CR, timeout); }
00118                         catch(cereal::TimeoutException& te)
00119                         { 
00120                                 if(DEBUG) ROS_WARN("SensorNet - scanNodes - Timeout, skipping node %c.", i);
00121                                 timedout=true;
00122                         }
00123                         catch(cereal::Exception& e)
00124                         { 
00125                                 ROS_ERROR("SensorNet - scanNodes - Error reading from node %c: \n%s", i, e.what());
00126                                 return false;
00127                         }
00128                         
00129                         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Scanning... Reply from node %c - %s", i, reply.c_str());
00130                         
00131                         if(!timedout)
00132                         {
00133                                 int version = extractInt(reply.substr(4,reply.size()-4));
00134                                 if(version==SN_VERSION)
00135                                 {
00136                                         nodes.push_back(SensorNet::Node(reply[1], reply[2], period));
00137                                         ROS_INFO("SensorNet - Found %s node on address %c with software version %d.", reply[2]==SN_SENSOR ? "a sensor" : "an actuator", i, SN_VERSION);
00138                                 }
00139                                 else
00140                                 {
00141                                         ROS_WARN("SensorNet - Found node %c but its software version %d is not compatible with version %d. Discarding this node->..", i, version, SN_VERSION);
00142                                 }
00143                         }
00144                 }
00145         }
00146         return true;
00147 }
00148 
00149 bool SensorNet::syncNodes()
00150 {
00151         std::string data;
00152 
00153         data+=SN_START;
00154         data+=SN_BROADCAST;
00155         data+=SN_SYNC_TIME;
00156         appendTime(&data, ros::Time::now());
00157         data+=CR;
00158         
00159         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Syncing all nodes - %s", data.c_str());
00160 
00161         try{ serial_port->write(data.c_str()); }
00162         catch(cereal::Exception& e)
00163         {
00164                 ROS_ERROR("SensorNet - syncTime - Failed to sync nodes.");
00165                 return false;
00166         }
00167         return true;
00168 }
00169 
00170 void SensorNet::appendTime(std::string * data, ros::Time time)
00171 {
00172         ros::Duration t = time - start_time;
00173 
00174         int hh = 0;
00175         int mm = 0;
00176         int ss = (int)t.toSec();
00177         int d = (int)((t.toSec()-(double)ss)*10);
00178         
00179         if(ss>60)
00180         {
00181                 mm = (int)(ss/60);
00182                 ss -= 60*mm;
00183         }
00184         if(mm>60)
00185         {
00186                 hh = (int)(mm/60);
00187                 mm -= 60*hh;
00188         }
00189         if(hh>99)
00190         {
00191                 hh=99;
00192                 mm=99;
00193                 ss=99;
00194                 d=9;
00195         }
00196         
00197         char time_chars[8];
00198         sprintf(time_chars, "%02d%02d%02d%1d", hh, mm, ss, d);
00199         data->append(time_chars);
00200 }
00201 
00202 ros::Time SensorNet::extractTime(std::string data)
00203 {
00204         char time_chars[3] = {0,0,0};
00205         double secs = 0.0;
00206         int temp;
00207         
00208         
00209         time_chars[0] = data.at(0);
00210         time_chars[1] = data.at(1);
00211         sscanf(time_chars, "%d", &temp);
00212         secs = temp*60*60;
00213         
00214         time_chars[0] = data.at(2);
00215         time_chars[1] = data.at(3);
00216         sscanf(time_chars, "%d", &temp);
00217         secs += temp*60;
00218         
00219         time_chars[0] = data.at(4);
00220         time_chars[1] = data.at(5);
00221         sscanf(time_chars, "%d", &temp);
00222         secs += temp;
00223         
00224         time_chars[0] = data.at(6);
00225         time_chars[1] = 0;
00226         sscanf(time_chars, "%d", &temp);
00227         secs += temp/10;
00228         
00229         return start_time + ros::Duration(secs);
00230 }
00231 
00232 void SensorNet::appendInt(std::string * data, int value)
00233 {
00234         char value_str[8];
00235         sprintf(value_str, "%d", value);
00236         
00237         data->append(value_str);
00238 }
00239 
00240 int SensorNet::extractInt(std::string data)
00241 {
00242         int value;
00243 
00244         sscanf(data.c_str(), "%d", &value);
00245         
00246         return value;
00247 }
00248 
00249 
00250 bool SensorNet::syncTime(SensorNet::Node * node)
00251 {
00252         std::string data;
00253 
00254         data+=SN_START;
00255         data+=node->address();
00256         data+=SN_SYNC_TIME;
00257         appendTime(&data, ros::Time::now());
00258         data+=CR;
00259         
00260         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Syncing time on node %c - %s", node->address(), data.c_str());
00261 
00262         try{ serial_port->write(data.c_str()); }
00263         catch(cereal::Exception& e)
00264         {
00265                 ROS_ERROR("SensorNet - syncTime - Failed to sync node %c.", node->address());
00266                 return false;
00267         }
00268         return waitForIt(node->address());
00269 }
00270 
00271 bool SensorNet::setTime(SensorNet::Node * node, ros::Time time)
00272 {
00273         std::string data;
00274 
00275         data+=SN_START;
00276         data+=node->address();
00277         data+=SN_SET_TIME;
00278         appendTime(&data, time);
00279         data+=SN_SEP;
00280         appendInt(&data, node->period());
00281         data+=CR;
00282 
00283         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Setting time on node %c - %s", node->address(), data.c_str());
00284 
00285         try{ serial_port->write(data.c_str()); }
00286         catch(cereal::Exception& e)
00287         {
00288                 ROS_ERROR("SensorNet - setTime - Failed to set time on node %c.", node->address());
00289                 return false;
00290         }
00291         return waitForIt(node->address());
00292 }
00293 
00294 bool SensorNet::getTime(SensorNet::Node * node, ros::Time * current_time, ros::Time * next_reading)
00295 {
00296         std::string reply;
00297         
00298         if(!sendCommand(node->address(), SN_GET_TIME)) return false;
00299         
00300         try{ serial_port->readBetween(&reply, SN_START, (char)CR, timeout); }
00301         catch(cereal::TimeoutException& te)
00302         { 
00303                 ROS_ERROR("SensorNet - getTime - Timeout getting time on node %c.", node->address());
00304                 return false;
00305         }
00306         catch(cereal::Exception& e)
00307         { 
00308                 ROS_ERROR("SensorNet - getTime - Error getting time from node %c: \n%s", node->address(), e.what());
00309                 return false;
00310         }
00311         
00312         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Getting time from node %c - %s", node->address(), reply.c_str());
00313         
00314         *current_time = extractTime(reply.substr(reply.find_first_of(node->address())+1,7));
00315         *next_reading = extractTime(reply.substr(reply.find_first_of(SN_SEP)+1,7));
00316         node->setPeriod(extractInt(reply.substr(reply.find_last_of(SN_SEP)+1,reply.size()-reply.find_last_of(SN_SEP)+1)));
00317         
00318         return true;
00319 }
00320 
00321 bool SensorNet::getSensorReadings(SensorNet::Node * node, std::vector<lse_sensor_msgs::Nostril> * mox, std::vector<lse_sensor_msgs::Anemometer> * thermistor)
00322 {
00323         if(!node->sensor()) return false;
00324         
00325         std::string reply;
00326         
00327         if(!sendCommand(node->address(), SN_READ_SENSORS)) return false;
00328         
00329         try{ serial_port->readBetween(&reply, SN_START, (char)CR, timeout); }
00330         catch(cereal::TimeoutException& te)
00331         { 
00332                 ROS_ERROR("SensorNet - getSensorReadings - Timeout getting sensor readings header on node %c.", node->address());
00333                 return false;
00334         }
00335         catch(cereal::Exception& e)
00336         { 
00337                 ROS_ERROR("SensorNet - getSensorReadings - Error reading sensors header from node %c: \n%s", node->address(), e.what());
00338                 return false;
00339         }
00340         
00341         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Getting sensors from node %c - %s", node->address(), reply.c_str());
00342         
00343         ros::Time first_reading = extractTime(reply.substr(reply.find_first_of(node->address())+1,7));
00344         
00345         int n = extractInt(reply.substr(reply.find_last_of(SN_SEP)+1,reply.size()-reply.find_last_of(SN_SEP)+1));
00346         
00347         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - %d sensor readings coming this way!!!", n);
00348         
00349         for(int i=0 ; i<n ; i++)
00350         {
00351                 try{ serial_port->readBetween(&reply, SN_START, (char)CR, timeout); }
00352                 catch(cereal::TimeoutException& te)
00353                 { 
00354                         ROS_ERROR("SensorNet - getSensorReadings - Timeout getting sensor readings on node %c.", node->address());
00355                         return false;
00356                 }
00357                 catch(cereal::Exception& e)
00358                 { 
00359                         ROS_ERROR("SensorNet - getSensorReadings - Error reading sensors from node %c: \n%s", node->address(), e.what());
00360                         return false;
00361                 }
00362                 
00363                 if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Getting sensor readings from node %c - %s", node->address(), reply.c_str());
00364         
00365                 int sep = reply.find_first_of(SN_SEP);
00366                 int next_sep = reply.find_first_of(SN_SEP,sep+1);
00367                 if(next_sep==-1) next_sep = reply.size()-1;
00368                 for(int j=0 ; j<4 ; j++)
00369                 {
00370                         if(node->sensors(j))
00371                         {
00372                                 lse_sensor_msgs::Nostril moxMsg;
00373                         
00374                                 char frame_id[32];
00375                                 sprintf(frame_id, "/base_node_%c_S%d", node->address(), j+1);
00376                                 moxMsg.header.frame_id = frame_id;
00377                                 moxMsg.header.stamp = first_reading + ros::Duration(node->period()*i);
00378                                 moxMsg.sensor_model = "Figaro 2620";
00379                                 moxMsg.gas_type.push_back(lse_sensor_msgs::Nostril::ORGANIC_SOLVENTS);
00380                                 moxMsg.reading = extractInt(reply.substr(sep+1,next_sep-sep));
00381                                 moxMsg.min_reading = 0.0;
00382                                 moxMsg.max_reading = 3300.0;
00383                         
00384                                 if(mox!=NULL) mox->push_back(moxMsg);
00385                                 
00386                                 sep=next_sep;
00387                                 next_sep=reply.find_first_of(SN_SEP,sep+1);
00388                                 if(next_sep==-1) next_sep = reply.size()-1;
00389                         }
00390                 }
00391                 for(int j=0 ; j<2 ; j++)
00392                 {
00393                         if(node->sensors(j+4))
00394                         {
00395                                 lse_sensor_msgs::Anemometer termMsg;
00396                                 
00397                                 char frame_id[32];
00398                                 sprintf(frame_id, "/base_node_%c_W%d", node->address(), j+1);
00399                                 termMsg.header.frame_id = frame_id;
00400                                 termMsg.header.stamp = first_reading + ros::Duration(node->period()/10*i);
00401                                 
00402                                 termMsg.wind_speed = extractInt(reply.substr(sep+1,next_sep-sep));
00403                                 termMsg.wind_direction = 0.0;
00404                                 
00405                                 if(thermistor!=NULL) thermistor->push_back(termMsg);
00406                                 
00407                                 sep=next_sep;
00408                                 next_sep=reply.find_first_of(SN_SEP,sep+1);
00409                                 if(next_sep==-1) next_sep = reply.size()-1;
00410                         }
00411                 }
00412                 
00413         }
00414         return true;
00415 }
00416 
00417 bool SensorNet::setAllPWM(SensorNet::Node * node, int pwm1, int pwm2, int pwm3, int pwm4)
00418 {
00419         if(!node->actuator()) return false;
00420         
00421         if(pwm1>100) pwm1=100;
00422         if(pwm1<0) pwm1=0;
00423         if(pwm2>100) pwm2=100;
00424         if(pwm2<0) pwm2=0;
00425         if(pwm3>100) pwm3=100;
00426         if(pwm3<0) pwm3=0;
00427         if(pwm4>100) pwm4=100;
00428         if(pwm4<0) pwm4=0;
00429         
00430         std::string data;
00431 
00432         data+=SN_START;
00433         data+=node->address();
00434         data+=SN_SET_ALL_PWM;
00435         appendInt(&data, pwm1);
00436         data+=SN_SEP;
00437         appendInt(&data, pwm2);
00438         data+=SN_SEP;
00439         appendInt(&data, pwm3);
00440         data+=SN_SEP;
00441         appendInt(&data, pwm4);
00442         data+=CR;
00443         
00444         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Setting all PWMs on node %c - %s", node->address(), data.c_str());
00445 
00446         try{ serial_port->write(data.c_str()); }
00447         catch(cereal::Exception& e)
00448         {
00449                 ROS_ERROR("SensorNet - setAllPWM - Failed to set pwm on node %c.", node->address());
00450                 return false;
00451         }
00452         return waitForIt(node->address());
00453 }
00454 
00455 bool SensorNet::setPWM(SensorNet::Node * node, ros::Time time, unsigned int id, int pwm)
00456 {
00457         if(!node->actuator()) return false;
00458         
00459         if(pwm>100) pwm=100;
00460         if(pwm<0) pwm=0;
00461         
00462         std::string data;
00463 
00464         data+=SN_START;
00465         data+=node->address();
00466         data+=SN_SET_ALL_PWM;
00467         appendTime(&data, time);
00468         data+=SN_SEP;
00469         appendInt(&data, id);
00470         data+=SN_SEP;
00471         appendInt(&data, pwm);
00472         data+=CR;
00473 
00474         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Setting PWM on node %c - %s", node->address(), data.c_str());
00475 
00476         try{ serial_port->write(data.c_str()); }
00477         catch(cereal::Exception& e)
00478         {
00479                 ROS_ERROR("SensorNet - setPWM - Failed to set pwm on node %c.", node->address());
00480                 return false;
00481         }
00482         return waitForIt(node->address());
00483 }
00484 
00485 
00486 bool SensorNet::getInfo(SensorNet::Node * node)
00487 {
00488         std::string reply;
00489         
00490         char version[8];
00491         sprintf(version, "%d", SN_VERSION);
00492         
00493         if(!sendCommand(node->address(), SN_GET_INFO)) return false;
00494         
00495         try{ serial_port->readBetween(&reply, SN_START, (char)CR, timeout); }
00496         catch(cereal::TimeoutException& te)
00497         { 
00498                 ROS_ERROR("SensorNet - getInfo - Timeout getting info on node %c.", node->address());
00499                 return false;
00500         }
00501         catch(cereal::Exception& e)
00502         { 
00503                 ROS_ERROR("SensorNet - getInfo - Error getting info from node %c: \n%s", node->address(), e.what());
00504                 return false;
00505         }
00506         
00507         if(node->address()!=reply[1])
00508         {
00509                 ROS_ERROR("SensorNet - getInfo - Node %c came back with a different address: %c!", node->address(), reply[1]);
00510                 return false;
00511         }
00512         
00513         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Getting info on node %c - %s", node->address(), reply.c_str());
00514         
00515         node->setType(reply[2]);
00516         
00517         if(reply.compare(reply.size()-3,3,version)==0)
00518         {       
00519                 ROS_WARN("SensorNet - getInfo - Node %c seems to have an incompatible version of the software.", node->address());
00520         }
00521         
00522         return true;
00523 }
00524 
00525 bool SensorNet::setSensors(SensorNet::Node * node, int s1, int s2, int s3, int s4, int w1, int w2)
00526 {
00527         if(!node->sensor()) return false;
00528         
00529         std::string data;
00530 
00531         data+=SN_START;
00532         data+=node->address();
00533         data+=SN_SET_SENSORS;
00534         appendInt(&data, s1==0 ? 0 : 1);
00535         appendInt(&data, s2==0 ? 0 : 1);
00536         appendInt(&data, s3==0 ? 0 : 1);
00537         appendInt(&data, s4==0 ? 0 : 1);
00538         appendInt(&data, w1==0 ? 0 : 1);
00539         appendInt(&data, w2==0 ? 0 : 1);
00540         data+=CR;
00541         
00542         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Setting sensors on node %c - %s", node->address(), data.c_str());
00543 
00544         try{ serial_port->write(data.c_str()); }
00545         catch(cereal::Exception& e)
00546         {
00547                 ROS_ERROR("SensorNet - setSensors - Failed to set sensors on node %c.", node->address());
00548                 return false;
00549         }
00550         
00551         if(!waitForIt(node->address())) return false;
00552         
00553         node->setSensors(s1,s2,s3,s4,w1,w2);
00554         return true;
00555 }
00556 
00557 bool SensorNet::getSensors(SensorNet::Node * node)
00558 {
00559         if(!node->sensor()) return false;
00560 
00561         std::string reply;
00562         
00563         if(!sendCommand(node->address(), SN_GET_SENSORS)) return false;
00564         
00565         try{ serial_port->readBetween(&reply, SN_START, (char)CR, timeout); }
00566         catch(cereal::TimeoutException& te)
00567         { 
00568                 ROS_ERROR("SensorNet - getSensors - Timeout getting sensors on node %c.", node->address());
00569                 return false;
00570         }
00571         catch(cereal::Exception& e)
00572         { 
00573                 ROS_ERROR("SensorNet - getSensors - Error getting sensors from node %c: \n%s", node->address(), e.what());
00574                 return false;
00575         }
00576         
00577         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Getting sensors from node %c - %s", node->address(), reply.c_str());
00578         
00579         node->setSensors((int)(reply[2]-48),(int)(reply[3]-48),(int)(reply[4]-48),(int)(reply[5]-48),(int)(reply[6]-48),(int)(reply[7]-48));
00580         
00581         return true;
00582 }
00583 
00584 bool SensorNet::setAddress(SensorNet::Node * node, char new_address)
00585 {
00586         std::string data;
00587 
00588         data+=SN_START;
00589         data+=node->address();
00590         data+=SN_SET_ADDRESS;
00591         data+=new_address;
00592         data+=CR;
00593         
00594         if(DEBUG) ROS_INFO("SensorNet [DEBUG] - Setting a new address %c on node %c - %s", new_address, node->address(), data.c_str());
00595         
00596         try{ serial_port->write(data.c_str()); }
00597         catch(cereal::Exception& e)
00598         {
00599                 ROS_ERROR("SensorNet - setAddress - Failed to set a new address %c on node %c.", new_address, node->address());
00600                 return false;
00601         }
00602 
00603         if(!waitForIt(new_address)) return false;
00604         node->setAddress(new_address);
00605         return true;                    
00606 }
00607 
00608