00001
00002
00003
00004
00005
00006
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"
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
00070 typedef int (IOadr::*poll_method_t)(int ch);
00071
00072 typedef struct
00073 {
00074 const char *name;
00075 poll_method_t function;
00076 int devnum;
00077 int field;
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_;
00093
00094
00095 std::string node_name_;
00096 int reset_relays_;
00097 std::string port_;
00098 bool do_shifter_;
00099
00100
00101 ros::Subscriber ioadr_cmd_;
00102 ros::Publisher ioadr_state_;
00103 ros::Subscriber shifter_cmd_;
00104 ros::Publisher shifter_state_;
00105 uint8_t shifter_gear_;
00106
00107
00108 uint8_t relay_mask_;
00109 uint8_t relay_bits_;
00110
00111
00112 art_msgs::IOadrState ioMsg_;
00113
00114
00115 dev8x *dev_;
00116 };
00117
00118 static IOadr::poll_parms_t poll_parms_table[] =
00119 {
00120
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
00145
00146 static const uint8_t relay_value_[5] = {0x00, 0x02, 0x04, 0x08, 0x10};
00147
00148
00149 IOadr::IOadr()
00150 {
00151 node_name_ = ros::this_node::getName();
00152 ROS_INFO_STREAM("initialize node: " << node_name_);
00153
00154
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
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
00179 }
00180 else
00181 {
00182
00183 if (do_shifter_)
00184 {
00185
00186 if (port_ != "/dev/null")
00187 poll_list_.push_back(LookupInput("ShifterInd"));
00188 }
00189 else
00190 {
00191
00192 poll_list_.push_back(LookupInput("AnalogA(10bit)"));
00193 poll_list_.push_back(LookupInput("DigitalB"));
00194 }
00195 }
00196 }
00197
00198
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
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
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
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
00239 int IOadr::Shutdown()
00240 {
00241 if (reset_relays_ >= 0)
00242 {
00243
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
00263
00264 void IOadr::processShifter(const art_msgs::Shifter::ConstPtr &shifterIn)
00265 {
00266
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;
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
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
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
00317
00318 int IOadr::poll_ShifterInd(int ch)
00319 {
00320
00321 int data;
00322 int rc = dev_->read_8bit_port(1, &data);
00323 if (rc == 0)
00324 {
00325
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
00338
00339 gear = art_msgs::Shifter::Reset;
00340
00341
00342 shifter_gear_ = gear;
00343 }
00344 return rc;
00345 }
00346
00347
00348
00349
00350
00351 void IOadr::PollDevice(void)
00352 {
00353 int rc = 0;
00354
00355
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
00368
00369
00370
00371 GetSetRelays();
00372
00373 if (do_shifter_)
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
00384 ioMsg_.header.stamp = ros::Time::now();
00385 ioadr_state_.publish(ioMsg_);
00386 }
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396 void IOadr::GetSetRelays(void)
00397 {
00398
00399 int rc = dev_->query_relays(&ioMsg_.relays);
00400 if (rc != 0)
00401 return;
00402
00403 if (relay_mask_)
00404 {
00405 uint8_t new_relays = (ioMsg_.relays & (~relay_mask_)) | relay_bits_;
00406 rc = dev_->set_relays(new_relays);
00407 if (rc == 0)
00408 {
00409
00410
00411
00412
00413
00414
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);
00426
00427
00428 while(ros::ok())
00429 {
00430
00431
00432
00433
00434
00435 cycle.sleep();
00436
00437 relay_mask_ = relay_bits_ = 0;
00438
00439 ros::spinOnce();
00440
00441 PollDevice();
00442 }
00443 }
00444
00445
00446 int main(int argc, char** argv)
00447 {
00448 ros::init(argc, argv, "ioadr");
00449 ros::NodeHandle node;
00450
00451 IOadr io;
00452
00453 if (io.Setup(node) != 0)
00454 return 2;
00455
00456 io.Main();
00457
00458 io.Shutdown();
00459
00460 return 0;
00461 }