Libbarrett
1.2.4
|
00001 /* 00002 * ex11_master_master.h 00003 * 00004 * Created on: Feb 22, 2010 00005 * Author: Christopher Dellin 00006 * Author: Dan Cody 00007 */ 00008 00009 #ifndef MASTER_MASTER_H_ 00010 #define MASTER_MASTER_H_ 00011 00012 00013 #include <stdexcept> 00014 00015 #include <syslog.h> 00016 #include <unistd.h> /* for close() */ 00017 #include <sys/socket.h> /* For sockets */ 00018 #include <fcntl.h> /* To change socket to nonblocking mode */ 00019 #include <arpa/inet.h> /* For inet_pton() */ 00020 00021 #include <barrett/detail/ca_macro.h> 00022 #include <barrett/thread/abstract/mutex.h> 00023 #include <barrett/thread/disable_secondary_mode_warning.h> 00024 #include <barrett/units.h> 00025 #include <barrett/systems/abstract/single_io.h> 00026 00027 00028 template <size_t DOF> 00029 class MasterMaster : public barrett::systems::SingleIO<typename barrett::units::JointPositions<DOF>::type, typename barrett::units::JointPositions<DOF>::type> { 00030 BARRETT_UNITS_TEMPLATE_TYPEDEFS(DOF); 00031 00032 public: 00033 explicit MasterMaster(barrett::systems::ExecutionManager* em, char* remoteHost, int port = 5555, const std::string& sysName = "MasterMaster") : 00034 barrett::systems::SingleIO<jp_type,jp_type>(sysName), sock(-1), linked(false), numMissed(NUM_MISSED_LIMIT), theirJp(0.0) 00035 { 00036 int err; 00037 long flags; 00038 int buflen; 00039 unsigned int buflenlen; 00040 struct sockaddr_in bind_addr; 00041 struct sockaddr_in their_addr; 00042 00043 /* Create socket */ 00044 sock = socket(PF_INET, SOCK_DGRAM, 0); 00045 if (sock == -1) 00046 { 00047 syslog(LOG_ERR,"%s: Could not create socket.",__func__); 00048 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00049 } 00050 00051 /* Set socket to non-blocking, set flag associated with open file */ 00052 flags = fcntl(sock, F_GETFL, 0); 00053 if (flags < 0) 00054 { 00055 syslog(LOG_ERR,"%s: Could not get socket flags.",__func__); 00056 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00057 } 00058 flags |= O_NONBLOCK; 00059 err = fcntl(sock, F_SETFL, flags); 00060 if (err < 0) 00061 { 00062 syslog(LOG_ERR,"%s: Could not set socket flags.",__func__); 00063 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00064 } 00065 00066 /* Maybe set UDP buffer size? */ 00067 buflenlen = sizeof(buflen); 00068 err = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&buflen, &buflenlen); 00069 if (err) 00070 { 00071 syslog(LOG_ERR,"%s: Could not get output buffer size.",__func__); 00072 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00073 } 00074 syslog(LOG_ERR,"%s: Note, output buffer is %d bytes.",__func__,buflen); 00075 00076 buflenlen = sizeof(buflen); 00077 buflen = 5 * SIZE_OF_MSG; 00078 err = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&buflen, buflenlen); 00079 if (err) 00080 { 00081 syslog(LOG_ERR,"%s: Could not set output buffer size.",__func__); 00082 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00083 } 00084 00085 buflenlen = sizeof(buflen); 00086 err = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&buflen, &buflenlen); 00087 if (err) 00088 { 00089 syslog(LOG_ERR,"%s: Could not get output buffer size.",__func__); 00090 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00091 } 00092 syslog(LOG_ERR,"%s: Note, output buffer is %d bytes.",__func__,buflen); 00093 00094 /* Set up the bind address */ 00095 bind_addr.sin_family = AF_INET; 00096 bind_addr.sin_port = htons(port); 00097 bind_addr.sin_addr.s_addr = htonl(INADDR_ANY); 00098 err = bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); 00099 if (err == -1) 00100 { 00101 syslog(LOG_ERR,"%s: Could not bind to socket on port %d.",__func__,port); 00102 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00103 } 00104 00105 /* Set up the other guy's address */ 00106 their_addr.sin_family = AF_INET; 00107 their_addr.sin_port = htons(port); 00108 err = ! inet_pton(AF_INET, remoteHost, &their_addr.sin_addr); 00109 if (err) 00110 { 00111 syslog(LOG_ERR,"%s: Bad IP argument '%s'.",__func__,remoteHost); 00112 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00113 } 00114 00115 /* Call "connect" to set datagram destination */ 00116 err = connect(sock, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)); 00117 if (err) 00118 { 00119 syslog(LOG_ERR,"%s: Could not set datagram destination.",__func__); 00120 throw std::runtime_error("(MasterMaster::MasterMaster): Ctor failed. Check /var/log/syslog."); 00121 } 00122 00123 00124 if (em != NULL) { 00125 em->startManaging(*this); 00126 } 00127 } 00128 00129 virtual ~MasterMaster() { 00130 this->mandatoryCleanUp(); 00131 00132 close(sock); 00133 } 00134 00135 bool isLinked() const { return linked; } 00136 void tryLink() { 00137 BARRETT_SCOPED_LOCK(this->getEmMutex()); 00138 00139 if (numMissed < NUM_MISSED_LIMIT) { 00140 linked = true; 00141 } 00142 } 00143 void unlink() { linked = false; } 00144 00145 protected: 00146 static const int SIZE_OF_MSG = DOF*sizeof(double); 00147 static const int NUM_MISSED_LIMIT = 10; 00148 00149 virtual void operate() { 00150 00151 { 00152 // send() and recv() cause switches to secondary mode. The socket is 00153 // non-blocking, so this *probably* won't impact the control-loop 00154 // timing that much... 00155 barrett::thread::DisableSecondaryModeWarning dsmw; 00156 00157 00158 send(sock, this->input.getValue().data(), SIZE_OF_MSG, 0); 00159 00160 if (numMissed < NUM_MISSED_LIMIT) { // prevent numMissed from wrapping 00161 ++numMissed; 00162 } 00163 while (recv(sock, theirJp.data(), SIZE_OF_MSG, 0) == SIZE_OF_MSG) { 00164 numMissed = 0; 00165 } 00166 } 00167 00168 if ( !linked || numMissed >= NUM_MISSED_LIMIT) { 00169 linked = false; 00170 theirJp = this->input.getValue(); 00171 } 00172 00173 this->outputValue->setData(&theirJp); 00174 } 00175 00176 int sock; 00177 bool linked; 00178 int numMissed; 00179 jp_type theirJp; 00180 00181 private: 00182 DISALLOW_COPY_AND_ASSIGN(MasterMaster); 00183 }; 00184 00185 00186 #endif /* MASTER_MASTER_H_ */