$search
00001 /* 00002 * Copyright (C) 2005, 2007, 2009 Austin Robot Technology 00003 * 00004 * License: Modified BSD Software License Agreement 00005 * 00006 * $Id: ioadr.cc 1876 2011-11-26 23:48:08Z jack.oquin $ 00007 */ 00008 00009 #include <ros/ros.h> 00010 00011 #include <art_msgs/ArtHertz.h> 00012 #include <art/conversions.h> 00013 00014 #include <art_msgs/Shifter.h> 00015 #include <art_msgs/IOadrCommand.h> 00016 #include <art_msgs/IOadrState.h> 00017 00018 #include "dev8x.h" // IOADR8x device interface 00019 00059 class IOadr 00060 { 00061 public: 00062 00063 IOadr(); 00064 00065 void Main(); 00066 int Setup(ros::NodeHandle node); 00067 int Shutdown(); 00068 00069 // pointer to any of the poll_* methods 00070 typedef int (IOadr::*poll_method_t)(int ch); 00071 00072 typedef struct 00073 { 00074 const char *name; // parameter name 00075 poll_method_t function; // function method to call 00076 int devnum; // IOadr8x device number 00077 int field; // analog voltage field index 00078 } poll_parms_t; 00079 00080 int poll_Analog_8bit(int ch); 00081 int poll_Analog_10bit(int ch); 00082 int poll_Digital(int ch); 00083 int poll_ShifterInd(int ch); 00084 00085 private: 00086 00087 void GetSetRelays(void); 00088 void PollDevice(void); 00089 void processOutput(const art_msgs::IOadrCommand::ConstPtr &cmd); 00090 void processShifter(const art_msgs::Shifter::ConstPtr &shifterIn); 00091 00092 std::vector<poll_parms_t *> poll_list_; // poll list 00093 00094 // .cfg variables: 00095 std::string node_name_; // actual node name assigned 00096 int reset_relays_; // initial/final relays setting 00097 std::string port_; // IOADR8x tty port name 00098 bool do_shifter_; // handle Shifter messages 00099 00100 // ROS topic interfaces 00101 ros::Subscriber ioadr_cmd_; // ioadr command 00102 ros::Publisher ioadr_state_; // ioadr state 00103 ros::Subscriber shifter_cmd_; // shifter command 00104 ros::Publisher shifter_state_; // shifter state 00105 uint8_t shifter_gear_; // current gear number 00106 00107 // requested relay settings 00108 uint8_t relay_mask_; 00109 uint8_t relay_bits_; 00110 00111 // current device input state 00112 art_msgs::IOadrState ioMsg_; // controller state message 00113 00114 // hardware IOADR8x interface 00115 dev8x *dev_; 00116 }; 00117 00118 static IOadr::poll_parms_t poll_parms_table[] = 00119 { 00120 // name method devnum field 00121 {"AnalogA", &IOadr::poll_Analog_8bit, 3, 0}, 00122 {"AnalogA(10bit)", &IOadr::poll_Analog_10bit, 3, 0}, 00123 {"AnalogB", &IOadr::poll_Analog_8bit, 4, 1}, 00124 {"AnalogB(10bit)", &IOadr::poll_Analog_10bit, 4, 1}, 00125 {"AnalogC", &IOadr::poll_Analog_8bit, 5, 2}, 00126 {"AnalogC(10bit)", &IOadr::poll_Analog_10bit, 5, 2}, 00127 {"DigitalB", &IOadr::poll_Digital, 1, -1}, 00128 {"ShifterInd", &IOadr::poll_ShifterInd, 1, -1}, 00129 {"", NULL, -1, -1}, 00130 {NULL, NULL, -1, -1}, 00131 }; 00132 00133 IOadr::poll_parms_t *LookupInput(const char *name) 00134 { 00135 int i; 00136 for (i = 0; poll_parms_table[i].name; ++i) 00137 { 00138 if (0 == strcmp(poll_parms_table[i].name, name)) 00139 break; 00140 } 00141 return &poll_parms_table[i]; 00142 } 00143 00144 // Relays bit values for gear indices: reset, park, rev, neut, drive. 00145 // NOTE: these are NOT the same as the digital B input values. 00146 static const uint8_t relay_value_[5] = {0x00, 0x02, 0x04, 0x08, 0x10}; 00147 00148 // constructor 00149 IOadr::IOadr() 00150 { 00151 node_name_ = ros::this_node::getName(); 00152 ROS_INFO_STREAM("initialize node: " << node_name_); 00153 00154 // use private node handle to get parameters 00155 ros::NodeHandle mynh("~"); 00156 00157 mynh.param("reset_relays", reset_relays_, 0); 00158 if (reset_relays_ >= 0) 00159 ROS_INFO("reset relays to 0x%02x", reset_relays_); 00160 00161 mynh.param("shifter", do_shifter_, false); 00162 if (do_shifter_) 00163 { 00164 ROS_INFO("providing shifter interface"); 00165 shifter_gear_ = art_msgs::Shifter::Park; 00166 port_ = "/dev/shifter"; 00167 } 00168 else 00169 { 00170 // default port name for main IOADR8x board 00171 port_ = "/dev/ioadr8x"; 00172 } 00173 mynh.getParam("port", port_); 00174 ROS_INFO_STREAM("IOADR8x port = " << port_); 00175 00176 if (mynh.hasParam("poll_list")) 00177 { 00178 // read list of poll strings 00179 } 00180 else 00181 { 00182 // set default poll list depending on node name 00183 if (do_shifter_) 00184 { 00185 // default shifter poll list 00186 if (port_ != "/dev/null") 00187 poll_list_.push_back(LookupInput("ShifterInd")); 00188 } 00189 else 00190 { 00191 // default ioadr poll list 00192 poll_list_.push_back(LookupInput("AnalogA(10bit)")); 00193 poll_list_.push_back(LookupInput("DigitalB")); 00194 } 00195 } 00196 } 00197 00198 // Set up the device. Return 0 if things go well, and -1 otherwise. 00199 int IOadr::Setup(ros::NodeHandle node) 00200 { 00201 static int qDepth = 1; 00202 ros::TransportHints noDelay = ros::TransportHints().tcpNoDelay(true); 00203 00204 if (do_shifter_) 00205 { 00206 // initialize shifter command and state topics 00207 shifter_cmd_ = node.subscribe("shifter/cmd", qDepth, 00208 &IOadr::processShifter, this, noDelay); 00209 shifter_state_ = 00210 node.advertise<art_msgs::Shifter>("shifter/state", qDepth); 00211 } 00212 else 00213 { 00214 // initialize ioadr command and state topics 00215 ioadr_cmd_ = node.subscribe("ioadr/cmd", qDepth, 00216 &IOadr::processOutput, this, noDelay); 00217 ioadr_state_ = 00218 node.advertise<art_msgs::IOadrState>("ioadr/state", qDepth); 00219 } 00220 00221 // create device interface class 00222 dev_ = new dev8x(port_.c_str()); 00223 int rc = dev_->dev8x::setup(); 00224 if (rc != 0) 00225 return rc; 00226 00227 ROS_INFO_STREAM(node_name_ << " device opened"); 00228 00229 if (reset_relays_ >= 0) 00230 { 00231 dev_->set_relays((uint8_t) reset_relays_); 00232 ROS_INFO("set relays to 0x%02x", reset_relays_); 00233 } 00234 00235 return 0; 00236 } 00237 00238 // Shutdown the device 00239 int IOadr::Shutdown() 00240 { 00241 if (reset_relays_ >= 0) 00242 { 00243 // make sure IOADR8x board is not busy before setting relays. 00244 usleep((useconds_t) rint(MIN_RELAY_WAIT*1000000.0)); 00245 dev_->set_relays((uint8_t) reset_relays_); 00246 ROS_INFO("set relays to 0x%02x", reset_relays_); 00247 } 00248 00249 dev_->dev8x::shutdown(); 00250 ROS_INFO_STREAM(node_name_ << " device closed"); 00251 delete dev_; 00252 return 0; 00253 } 00254 00255 void IOadr::processOutput(const art_msgs::IOadrCommand::ConstPtr &cmd) 00256 { 00257 relay_mask_ |= (cmd->relays_on | cmd->relays_off); 00258 relay_bits_ |= cmd->relays_on; 00259 ROS_DEBUG("relay bits, mask = 0x%02x, 0x%02x", relay_bits_, relay_mask_); 00260 } 00261 00262 // Callback when shifter command arrives. 00263 // (only subscribed when do_shifter_ is true) 00264 void IOadr::processShifter(const art_msgs::Shifter::ConstPtr &shifterIn) 00265 { 00266 // save requested gear when doing shifter simulation 00267 if (shifterIn->gear != art_msgs::Shifter::Reset 00268 && port_ == "/dev/null") 00269 shifter_gear_ = shifterIn->gear; 00270 ROS_INFO("Shifter command: gear %u", shifterIn->gear); 00271 relay_bits_ = relay_value_[shifterIn->gear]; 00272 relay_mask_ = 0xff; // set all relay bits 00273 } 00274 00275 int IOadr::poll_Analog_8bit(int ch) 00276 { 00277 int data; 00278 int rc = dev_->read_8bit_port(poll_list_[ch]->devnum, &data); 00279 if (rc == 0) 00280 { 00281 // convert A/D input to voltage (8-bit converter with 5-volt range) 00282 int i = poll_list_[ch]->field; 00283 ioMsg_.voltages[i] = analog_volts(data, 5.0, 8); 00284 ROS_DEBUG("%s input = %.3f volts (0x%04x)", 00285 poll_list_[i]->name, ioMsg_.voltages[ch], data); 00286 } 00287 return rc; 00288 } 00289 00290 int IOadr::poll_Analog_10bit(int ch) 00291 { 00292 int data; 00293 int rc = dev_->read_10bit_port(poll_list_[ch]->devnum, &data); 00294 if (rc == 0) 00295 { 00296 // convert A/D input to voltage (10-bit converter with 5-volt range) 00297 int i = poll_list_[ch]->field; 00298 ioMsg_.voltages[i] = analog_volts(data, 5.0, 10); 00299 ROS_DEBUG("%s input = %.3f volts (0x%04x)", 00300 poll_list_[ch]->name, ioMsg_.voltages[i], data); 00301 } 00302 return rc; 00303 } 00304 00305 int IOadr::poll_Digital(int ch) 00306 { 00307 int data; 00308 int rc = dev_->read_8bit_port(poll_list_[ch]->devnum, &data); 00309 if (rc == 0) 00310 { 00311 ioMsg_.digitalB = data; 00312 } 00313 return rc; 00314 } 00315 00316 // translate shifter indicator into shift request ID 00317 // (only used when do_shifter_ true and port is a real device) 00318 int IOadr::poll_ShifterInd(int ch) 00319 { 00320 // read shifter feedback from Digital port B 00321 int data; 00322 int rc = dev_->read_8bit_port(1, &data); 00323 if (rc == 0) 00324 { 00325 // ignore the results unless the I/O was successful 00326 uint8_t gear; 00327 uint8_t digitalB_bits = ~data; 00328 if (digitalB_bits & 0x80) 00329 gear = art_msgs::Shifter::Park; 00330 else if (digitalB_bits & 0x40) 00331 gear = art_msgs::Shifter::Reverse; 00332 else if (digitalB_bits & 0x20) 00333 gear = art_msgs::Shifter::Neutral; 00334 else if (digitalB_bits & 0x10) 00335 gear = art_msgs::Shifter::Drive; 00336 else 00337 // there should only be one bit on at a time, so this should 00338 // not occur 00339 gear = art_msgs::Shifter::Reset; 00340 00341 // save current gear number 00342 shifter_gear_ = gear; 00343 } 00344 return rc; 00345 } 00346 00347 // poll device for pending input 00348 // 00349 // if an I/O fails, the corresponding voltages[i] remains unchanged 00350 // 00351 void IOadr::PollDevice(void) 00352 { 00353 int rc = 0; 00354 00355 // First, poll any analog or digital ports that are configured. 00356 for (unsigned i = 0; i < poll_list_.size(); ++i) 00357 { 00358 poll_method_t poll_method = poll_list_[i]->function; 00359 if (poll_method) 00360 { 00361 rc = (this->*poll_method)(i); 00362 if (rc != 0) 00363 ROS_ERROR_THROTTLE(100, "poll method returns %d", rc); 00364 } 00365 } 00366 00367 // Get relay values, set new ones if requested. Note: setting the 00368 // relays MUST be the last IOADR8x operation of the cycle. After 00369 // that, the device seems to stay busy for a while. It hangs if 00370 // contacted again too soon. 00371 GetSetRelays(); 00372 00373 if (do_shifter_) // publishing shifter state? 00374 { 00375 art_msgs::Shifter shifter_msg; 00376 shifter_msg.header.stamp = ros::Time::now(); 00377 shifter_msg.gear = shifter_gear_; 00378 shifter_msg.relays = ioMsg_.relays; 00379 shifter_state_.publish(shifter_msg); 00380 } 00381 else 00382 { 00383 // publish ioadr state message 00384 ioMsg_.header.stamp = ros::Time::now(); 00385 ioadr_state_.publish(ioMsg_); 00386 } 00387 } 00388 00389 // Get relay values, set new ones if requested. 00390 // 00391 // Updates: relay_mask_, relay_bits_, ioMsg_.relays 00392 // 00393 // If we failed to set the relays this cycle, leave relay_mask_, 00394 // relay_bits_ alone and try again next time. 00395 // 00396 void IOadr::GetSetRelays(void) 00397 { 00398 // get current relay settings 00399 int rc = dev_->query_relays(&ioMsg_.relays); 00400 if (rc != 0) // device busy or not working? 00401 return; 00402 00403 if (relay_mask_) // new setting requested? 00404 { 00405 uint8_t new_relays = (ioMsg_.relays & (~relay_mask_)) | relay_bits_; 00406 rc = dev_->set_relays(new_relays); 00407 if (rc == 0) // successful? 00408 { 00409 // The device requires a wait after setting all relays 00410 // before accessing them again. Since set_relays() 00411 // returns immediately, we must leave them alone until 00412 // our next cycle, which should be long enough for the 00413 // device to finish. At 10Hz, that should not be a 00414 // problem. 00415 00416 relay_mask_ = relay_bits_ = 0; 00417 ioMsg_.relays = new_relays; 00418 ROS_DEBUG("set relays to 0x%02x", ioMsg_.relays); 00419 } 00420 } 00421 } 00422 00423 void IOadr::Main() 00424 { 00425 ros::Rate cycle(art_msgs::ArtHertz::IOADR); // set driver cycle rate 00426 00427 // Main loop; grab messages off our queue and republish them via ROS 00428 while(ros::ok()) 00429 { 00430 // wait for next cycle -- this must come first, because Setup() 00431 // may have initialized the relays. If we hit the device again 00432 // too soon, it locks up. Apparently, this is not just limited 00433 // to the relay ports. 00434 00435 cycle.sleep(); 00436 00437 relay_mask_ = relay_bits_ = 0; 00438 00439 ros::spinOnce(); // handle incoming commands 00440 00441 PollDevice(); // get & publish device status 00442 } 00443 } 00444 00445 00446 int main(int argc, char** argv) 00447 { 00448 ros::init(argc, argv, "ioadr"); // default node name 00449 ros::NodeHandle node; 00450 00451 IOadr io; 00452 00453 if (io.Setup(node) != 0) 00454 return 2; 00455 00456 io.Main(); // driver main loop 00457 00458 io.Shutdown(); 00459 00460 return 0; 00461 }