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 #include <map>
00036 #include <stdio.h>
00037 #include <getopt.h>
00038 #include <sys/mman.h>
00039
00040 #include <tinyxml.h>
00041
00042 #include <ethercat/ethercat_xenomai_drv.h>
00043 #include <dll/ethercat_dll.h>
00044 #include <al/ethercat_AL.h>
00045 #include <al/ethercat_master.h>
00046 #include <al/ethercat_slave_handler.h>
00047
00048 #include "ethercat_hardware/motor_heating_model.h"
00049 #include <ethercat_hardware/wg0x.h>
00050 #include <ethercat_hardware/wg05.h>
00051 #include <ethercat_hardware/wg06.h>
00052 #include <ethercat_hardware/wg021.h>
00053 #include <ethercat_hardware/wg014.h>
00054
00055 #include <boost/crc.hpp>
00056 #include <boost/foreach.hpp>
00057
00058 #include <net/if.h>
00059 #include <sys/ioctl.h>
00060 #include <netinet/in.h>
00061
00062 using namespace ethercat_hardware;
00063
00064 vector<EthercatDevice *> devices;
00065
00066 struct Actuator {
00067 string motor;
00068 string board;
00069 bool enforce_heating_model;
00070 };
00071 typedef pair<string, Actuator> ActuatorPair;
00072 map<string, Actuator> actuators;
00073
00074 struct Config
00075 {
00076 Config(const WG0XActuatorInfo &actuator_info, const MotorHeatingModelParametersEepromConfig &heating_config) :
00077 actuator_info_(actuator_info), heating_config_(heating_config)
00078 { }
00079 Config() {}
00080 WG0XActuatorInfo actuator_info_;
00081 MotorHeatingModelParametersEepromConfig heating_config_;
00082 };
00083 typedef pair<string, Config> MotorPair;
00084 map<string, Config> motors;
00085
00086 void init(char *interface)
00087 {
00088
00089 int sock = socket(PF_INET, SOCK_DGRAM, 0);
00090 if (sock < 0) {
00091 int error = errno;
00092 fprintf(stderr,"Couldn't open temp socket : %s", strerror(error));
00093 exit(-1);
00094 }
00095
00096 struct ifreq ifr;
00097 strncpy(ifr.ifr_name, interface, IFNAMSIZ);
00098 if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
00099 int error = errno;
00100 fprintf(stderr,"Cannot get interface flags for %s: %s\n", interface, strerror(error));
00101 exit(-1);
00102 }
00103
00104 close(sock);
00105 sock = -1;
00106
00107 if (!(ifr.ifr_flags & IFF_UP)) {
00108 fprintf(stderr,"Interface %s is not UP. Try : ifup %s\n", interface, interface);
00109 exit(-1);
00110 }
00111 if (!(ifr.ifr_flags & IFF_RUNNING)) {
00112 fprintf(stderr,"Interface %s is not RUNNING. Is cable plugged in and device powered?\n", interface);
00113 exit(-1);
00114 }
00115
00116 struct netif *ni;
00117
00118
00119 if ((ni = init_ec(interface)) == NULL)
00120 {
00121 fprintf(stderr, "Unable to initialize interface: %s\n", interface);
00122 exit(-1);
00123 }
00124
00125
00126 EtherCAT_DataLinkLayer::instance()->attach(ni);
00127 EtherCAT_AL *al;
00128 if ((al = EtherCAT_AL::instance()) == NULL)
00129 {
00130 fprintf(stderr, "Unable to initialize Application Layer (AL): %p\n", al);
00131 exit(-1);
00132 }
00133
00134 uint32_t num_slaves = al->get_num_slaves();
00135 if (num_slaves == 0)
00136 {
00137 fprintf(stderr, "Unable to locate any slaves\n");
00138 exit(-1);
00139 }
00140
00141
00142 EtherCAT_Master *em;
00143 if ((em = EtherCAT_Master::instance()) == NULL)
00144 {
00145 fprintf(stderr, "Unable to initialize EtherCAT_Master: %p", em);
00146 exit(-1);
00147 }
00148
00149 static int start_address = 0x00010000;
00150
00151 for (unsigned int slave = 0; slave < num_slaves; ++slave)
00152 {
00153 EC_FixedStationAddress fsa(slave + 1);
00154 EtherCAT_SlaveHandler *sh = em->get_slave_handler(fsa);
00155 if (sh == NULL)
00156 {
00157 fprintf(stderr, "Unable to get slave handler #%d", slave);
00158 exit(-1);
00159 }
00160
00161 if (sh->get_product_code() == WG05::PRODUCT_CODE)
00162 {
00163 WG05 *dev = new WG05();
00164 dev->construct(sh, start_address);
00165 devices.push_back(dev);
00166 }
00167 else if (sh->get_product_code() == WG06::PRODUCT_CODE)
00168 {
00169 WG06 *dev = new WG06();
00170 dev->construct(sh, start_address);
00171 devices.push_back(dev);
00172 }
00173 else if (sh->get_product_code() == WG021::PRODUCT_CODE)
00174 {
00175 WG021 *dev = new WG021();
00176 dev->construct(sh, start_address);
00177 devices.push_back(dev);
00178 }
00179 else if (sh->get_product_code() == WG014::PRODUCT_CODE)
00180 {
00181 WG014 *dev = new WG014();
00182 dev->construct(sh, start_address);
00183 devices.push_back(dev);
00184 }
00185 else
00186 {
00187 devices.push_back(NULL);
00188 }
00189 }
00190
00191 BOOST_FOREACH(EthercatDevice *device, devices)
00192 {
00193 if (!device) continue;
00194 if (!device->sh_->to_state(EC_OP_STATE))
00195 {
00196 fprintf(stderr, "Unable set device %d into OP_STATE", device->sh_->get_ring_position());
00197 }
00198 }
00199
00200 BOOST_FOREACH(EthercatDevice *device, devices)
00201 {
00202 if (!device) continue;
00203 device->use_ros_ = false;
00204 device->initialize(NULL, true);
00205 }
00206 }
00207
00208 string boardName(EthercatDevice *d)
00209 {
00210 if (dynamic_cast<WG021 *>(d)) {
00211 return "wg021";
00212 } else if (dynamic_cast<WG06 *>(d)) {
00213 return "wg006";
00214 } else if (dynamic_cast<WG05 *>(d)) {
00215 return "wg005";
00216 }
00217 return "unknown";
00218 }
00219
00220
00221 WG0X* getWGDevice(int device)
00222 {
00223 uint32_t num_slaves = EtherCAT_AL::instance()->get_num_slaves();
00224 if ((device >= (int)num_slaves) || (device < 0))
00225 {
00226 ROS_FATAL("Invalid device number %d. Must be value between 0 and %d", device, num_slaves-1);
00227 return NULL;
00228 }
00229
00230 if (devices[device] == NULL)
00231 {
00232 ROS_FATAL("There is no device at position #%d", device);
00233 return NULL;
00234 }
00235
00236 WG0X *wg = dynamic_cast<WG0X *>(devices[device]);
00237 if (wg==NULL)
00238 {
00239 ROS_FATAL("The device a position #%d is not programmable", device);
00240 return NULL;
00241 }
00242
00243 return wg;
00244 }
00245
00246
00247 bool programDevice(int device,
00248 const Config &config,
00249 char *name, string expected_board, bool enforce_heating_model)
00250 {
00251 WG0X *wg = getWGDevice(device);
00252 if (wg == NULL)
00253 {
00254 return false;
00255 }
00256
00257 string board = boardName(devices[device]);
00258 if (expected_board != board)
00259 {
00260 ROS_FATAL("Device #%02d is a %s, but %s expects a %s\n", device, board.c_str(), name, expected_board.c_str());
00261 return false;
00262 }
00263 ROS_INFO("Programming device %d, to be named: %s\n", device, name);
00264
00265 WG0XActuatorInfo actuator_info = config.actuator_info_;
00266 if (strlen(name) >= sizeof(actuator_info.name_))
00267 {
00268 ROS_FATAL("Device name '%s' is too long", name);
00269 }
00270 strncpy(actuator_info.name_, name, sizeof(actuator_info.name_));
00271 actuator_info.generateCRC();
00272
00273 ROS_INFO("Programming actuator version %d.%d",
00274 int(actuator_info.major_), int(actuator_info.minor_));
00275
00276 EthercatDirectCom com(EtherCAT_DataLinkLayer::instance());
00277 if (!wg->program(&com, actuator_info))
00278 {
00279 ROS_FATAL("Error writing actuator info to device #%d", device);
00280 return false;
00281 }
00282
00283 MotorHeatingModelParametersEepromConfig heating_config = config.heating_config_;
00284 heating_config.enforce_ = enforce_heating_model;
00285 heating_config.generateCRC();
00286 if (!wg->program(&com, config.heating_config_))
00287 {
00288 ROS_FATAL("Writing heating model config to device #%d", device);
00289 return false;
00290 }
00291
00292 return true;
00293 }
00294
00295
00296
00297
00298
00299 bool updateHeatingConfig(int device)
00300 {
00301 WG0XActuatorInfo actuator_info;
00302 EthercatDirectCom com(EtherCAT_DataLinkLayer::instance());
00303 WG0X *wg = getWGDevice(device);
00304 if (wg == NULL)
00305 {
00306 ROS_WARN("Skipping update of device %d", device);
00307 return false;
00308 }
00309
00310 if (!wg->readActuatorInfoFromEeprom(&com, actuator_info))
00311 {
00312 ROS_ERROR("Could not read actuator info from device %d", device);
00313 return false;
00314 }
00315
00316 if (!actuator_info.verifyCRC())
00317 {
00318 ROS_ERROR("Device %d has not actuator configuration", device);
00319 return false;
00320 }
00321
00322 if (actuators.find(actuator_info.name_) == actuators.end())
00323 {
00324 ROS_ERROR("Could not find actuator info for device %d with name '%s'",
00325 device, actuator_info.name_);
00326 return false;
00327 }
00328
00329 const Actuator &actuator(actuators[actuator_info.name_]);
00330 const string &motor_name(actuator.motor);
00331 bool enforce_heating_model = actuator.enforce_heating_model;
00332
00333 if (motors.find(motor_name) == motors.end())
00334 {
00335 ROS_ERROR("Could not find motor '%s' for device %d with actuator name '%s'",
00336 motor_name.c_str(), device, actuator_info.name_);
00337 return false;
00338 }
00339
00340 const Config &config(motors[motor_name]);
00341
00342 if (strcmp(config.actuator_info_.motor_model_, actuator_info.motor_model_) != 0)
00343 {
00344 ROS_ERROR("For device %d '%s' : the motor name stored in EEPROM '%s' does not match the motor name '%s' from XML file",
00345 device, actuator_info.name_, actuator_info.motor_model_, config.actuator_info_.motor_model_);
00346 return false;
00347 }
00348
00349 MotorHeatingModelParametersEepromConfig heating_config = config.heating_config_;
00350 heating_config.enforce_ = enforce_heating_model;
00351 heating_config.generateCRC();
00352 if (!wg->program(&com, heating_config))
00353 {
00354 ROS_FATAL("Writing heating model config to device #%d", device);
00355 return false;
00356 }
00357
00358 ROS_INFO("Updated device %d (%s) with heating config for motor '%s'",
00359 device, actuator_info.name_, config.actuator_info_.motor_model_);
00360
00361 return true;
00362 }
00363
00364
00365
00366 bool updateAllHeatingConfig()
00367 {
00368 for (unsigned device=0; device<devices.size(); ++device)
00369 {
00370 updateHeatingConfig(device);
00371 }
00372 return true;
00373 }
00374
00375
00376 static struct
00377 {
00378 char *program_name_;
00379 char *interface_;
00380 char *name_;
00381 bool program_;
00382 bool help_;
00383 int device_;
00384 string motor_;
00385 string actuators_;
00386 string board_;
00387 bool update_motor_heating_config_;
00388 bool enforce_heating_model_;
00389 } g_options;
00390
00391 void Usage(string msg = "")
00392 {
00393 fprintf(stderr, "Usage: %s [options]\n", g_options.program_name_);
00394 fprintf(stderr, " -i, --interface <i> Use the network interface <i>\n");
00395 fprintf(stderr, " -a, --actuators <file> Get the actuator definitions from file (default: actuators.conf)\n");
00396 fprintf(stderr, " -d, --device <d> Select the device to program\n");
00397 fprintf(stderr, " -b, --board <b> Set the expected board type (wg005, wg006, wg021)\n");
00398 fprintf(stderr, " -p, --program Program a motor control board\n");
00399 fprintf(stderr, " -n, --name <n> Set the name of the motor control board to <n>\n");
00400 fprintf(stderr, " -U, --update_heating_config Update motor heating model configuration of all boards\n");
00401 fprintf(stderr, " Known actuator names:\n");
00402 BOOST_FOREACH(ActuatorPair p, actuators)
00403 {
00404 string name = p.first;
00405 fprintf(stderr, " %s\n", name.c_str());
00406 }
00407 fprintf(stderr, " -m, --motor <m> Set the configuration for motor <m>\n");
00408 fprintf(stderr, " Legal motor values are:\n");
00409 BOOST_FOREACH(MotorPair p, motors)
00410 {
00411 const string &name(p.first);
00412 const WG0XActuatorInfo &info(p.second.actuator_info_);
00413 fprintf(stderr, " %s - %s %s\n", name.c_str(), info.motor_make_, info.motor_model_);
00414 }
00415 fprintf(stderr, " -h, --help Print this message and exit\n");
00416 if (msg != "")
00417 {
00418 fprintf(stderr, "Error: %s\n", msg.c_str());
00419 exit(-1);
00420 }
00421 else
00422 {
00423 exit(0);
00424 }
00425 }
00426
00427
00428 bool getDoubleAttribute(TiXmlElement *params, const char* motor_name, const char* param_name, double& value)
00429 {
00430 const char *val_str = params->Attribute(param_name);
00431 if (val_str == NULL)
00432 {
00433 ROS_ERROR("Attribute '%s' for motor '%s' is not defined", param_name, motor_name);
00434 return false;
00435 }
00436
00437 char *endptr=NULL;
00438 value = strtod(val_str, &endptr);
00439 if ((endptr == val_str) || (endptr < (val_str+strlen(val_str))))
00440 {
00441 ROS_ERROR("Couldn't convert '%s' to double for attribute '%s' of motor '%s'",
00442 val_str, param_name, motor_name);
00443 return false;
00444 }
00445
00446 return true;
00447 }
00448
00449 bool getIntegerAttribute(TiXmlElement *params, const char* motor_name, const char* param_name, int& value)
00450 {
00451 const char *val_str = params->Attribute(param_name);
00452 if (val_str == NULL)
00453 {
00454 ROS_ERROR("Attribute '%s' for motor '%s' is not defined", param_name, motor_name);
00455 return false;
00456 }
00457
00458 char *endptr=NULL;
00459 value = strtol(val_str, &endptr, 0);
00460 if ((endptr == val_str) || (endptr < (val_str+strlen(val_str))))
00461 {
00462 ROS_ERROR("Couldn't convert '%s' to integer for attribute '%s' of motor '%s'",
00463 val_str, param_name, motor_name);
00464 return false;
00465 }
00466
00467 return true;
00468 }
00469
00470 bool getStringAttribute(TiXmlElement *params, const char* motor_name, const char* param_name, char* strbuf, unsigned buflen)
00471 {
00472 const char *val = params->Attribute(param_name);
00473 if (val == NULL)
00474 {
00475 ROS_ERROR("No '%s' attribute for motor '%s'", param_name, motor_name);
00476 return false;
00477 }
00478 if (strlen(val) >= buflen)
00479 {
00480 ROS_ERROR("'%s' value '%s' for motor '%s' is too long. Limit value to %d characters.",
00481 param_name, val, motor_name, buflen-1);
00482 return false;
00483 }
00484 strncpy(strbuf, val, buflen);
00485 strbuf[buflen-1] = '\0';
00486 return true;
00487 }
00488
00489
00490 bool parseConfig(TiXmlElement *config)
00491 {
00492 TiXmlElement *actuatorElt = config->FirstChildElement("actuators");
00493 TiXmlElement *motorElt = config->FirstChildElement("motors");
00494
00495 for (TiXmlElement *elt = actuatorElt->FirstChildElement("actuator");
00496 elt;
00497 elt = elt->NextSiblingElement("actuator"))
00498 {
00499 const char *name = elt->Attribute("name");
00500 if (name == NULL)
00501 {
00502 ROS_ERROR("Acutuator attribute 'name' not specified");
00503 return false;
00504 }
00505
00506 struct Actuator a;
00507
00508 const char *motor = elt->Attribute("motor");
00509 if (motor == NULL)
00510 {
00511 ROS_ERROR("For actuator '%s', 'motor' attribute not specified", name);
00512 return false;
00513 }
00514 a.motor = motor;
00515
00516 const char *board = elt->Attribute("board");
00517 if (board == NULL)
00518 {
00519 ROS_ERROR("For actuator '%s', 'board' attribute not specified", name);
00520 return false;
00521 }
00522 a.board = board;
00523
00524 const char *enforce_heating_model = elt->Attribute("enforce_heating_model");
00525 if (enforce_heating_model == NULL)
00526 {
00527
00528
00529 a.enforce_heating_model=false;
00530 }
00531 else if (strcmp(enforce_heating_model, "true") == 0)
00532 {
00533 a.enforce_heating_model=true;
00534 }
00535 else if (strcmp(enforce_heating_model, "false") == 0)
00536 {
00537 a.enforce_heating_model=false;
00538 }
00539 else
00540 {
00541 ROS_ERROR("For actuator '%s' : 'enforce_heating_model' attribute should be 'true' or 'false' not '%s'",
00542 name, enforce_heating_model);
00543 return false;
00544 }
00545
00546 actuators[name] = a;
00547 }
00548
00549 WG0XActuatorInfo info;
00550 memset(&info, 0, sizeof(info));
00551 info.major_ = 0;
00552 info.minor_ = 2;
00553 strcpy(info.robot_name_, "PR2");
00554 ethercat_hardware::MotorHeatingModelParametersEepromConfig heating_config;
00555 memset(&heating_config, 0, sizeof(heating_config));
00556 heating_config.major_ = 0;
00557 heating_config.minor_ = 1;
00558 heating_config.enforce_ = 0;
00559
00560 for (TiXmlElement *elt = motorElt->FirstChildElement("motor");
00561 elt;
00562 elt = elt->NextSiblingElement("motor"))
00563 {
00564 bool success = true;
00565 const char *name = elt->Attribute("name");
00566 if (name == NULL)
00567 {
00568 ROS_ERROR("Motor 'name' attribute is not specified");
00569 return false;
00570 }
00571
00572 TiXmlElement *params = elt->FirstChildElement("params");
00573 if (params == NULL)
00574 {
00575 ROS_ERROR("No 'params' tag available for motor '%s'", name);
00576 return false;
00577 }
00578
00579 TiXmlElement *encoder = elt->FirstChildElement("encoder");
00580 if (encoder == NULL)
00581 {
00582 ROS_ERROR("No 'encoder' tag available for motor '%s'", name);
00583 return false;
00584 }
00585
00586 success &= getStringAttribute(params, name, "make", info.motor_make_, sizeof(info.motor_make_));
00587 success &= getStringAttribute(params, name, "model", info.motor_model_, sizeof(info.motor_model_));
00588
00589 double fvalue;
00590
00591 success &= getDoubleAttribute(params, name, "max_current", fvalue);
00592 info.max_current_ = fvalue;
00593 success &= getDoubleAttribute(params, name, "speed_constant", fvalue);
00594 info.speed_constant_ = fvalue;
00595 success &= getDoubleAttribute(params, name, "resistance", fvalue);
00596 info.resistance_ = fvalue;
00597 success &= getDoubleAttribute(params, name, "motor_torque_constant", fvalue);
00598 info.motor_torque_constant_ = fvalue;
00599 success &= getDoubleAttribute(encoder, name, "reduction", fvalue);
00600 info.encoder_reduction_ = fvalue;
00601
00602 int ivalue=-1;
00603 success &= getIntegerAttribute(encoder, name, "pulses_per_revolution", ivalue);
00604 info.pulses_per_revolution_ = ivalue;
00605
00606 ethercat_hardware::MotorHeatingModelParameters &hmp(heating_config.params_);
00607 success &= getDoubleAttribute(params, name, "housing_to_ambient_thermal_resistance", fvalue);
00608 hmp.housing_to_ambient_thermal_resistance_ = fvalue;
00609 success &= getDoubleAttribute(params, name, "winding_to_housing_thermal_resistance", fvalue);
00610 hmp.winding_to_housing_thermal_resistance_ = fvalue;
00611 success &= getDoubleAttribute(params, name, "winding_thermal_time_constant", fvalue);
00612 hmp.winding_thermal_time_constant_ = fvalue;
00613 success &= getDoubleAttribute(params, name, "housing_thermal_time_constant", fvalue);
00614 hmp.housing_thermal_time_constant_ = fvalue;
00615 success &= getDoubleAttribute(params, name, "max_winding_temperature", fvalue);
00616 hmp.max_winding_temperature_ = fvalue;
00617
00618 if (!success)
00619 {
00620 return false;
00621 }
00622
00623 if (motors.find(name) != motors.end())
00624 {
00625 ROS_ERROR("Motor named '%s' exists motor than once",name);
00626 return false;
00627 }
00628
00629 motors[name] = Config(info, heating_config);
00630 }
00631 return true;
00632 }
00633
00634
00635
00636
00637 int main(int argc, char *argv[])
00638 {
00639
00640
00641
00642 log4cxx::LoggerPtr logger = log4cxx::Logger::getLogger(ROSCONSOLE_DEFAULT_NAME);
00643 logger->setLevel(ros::console::g_level_lookup[ros::console::levels::Debug]);
00644 ros::console::notifyLoggerLevelsChanged();
00645
00646
00647 g_options.program_name_ = argv[0];
00648 g_options.device_ = -1;
00649 g_options.help_ = false;
00650 g_options.board_ = "";
00651 g_options.update_motor_heating_config_ = false;
00652 g_options.enforce_heating_model_ = false;
00653 while (1)
00654 {
00655 static struct option long_options[] = {
00656 {"help", no_argument, 0, 'h'},
00657 {"interface", required_argument, 0, 'i'},
00658 {"name", required_argument, 0, 'n'},
00659 {"device", required_argument, 0, 'd'},
00660 {"board", required_argument, 0, 'b'},
00661 {"motor", required_argument, 0, 'm'},
00662 {"program", no_argument, 0, 'p'},
00663 {"actuators", required_argument, 0, 'a'},
00664 {"update_heating_config", no_argument, 0, 'U'},
00665 {"enforce_heating_model", no_argument, 0, 'H'},
00666 };
00667 int option_index = 0;
00668 int c = getopt_long(argc, argv, "d:b:hi:m:n:pa:UH", long_options, &option_index);
00669 if (c == -1) break;
00670 switch (c)
00671 {
00672 case 'h':
00673 g_options.help_ = true;
00674 break;
00675 case 'd':
00676 g_options.device_ = atoi(optarg);
00677 break;
00678 case 'b':
00679 g_options.board_ = optarg;
00680 break;
00681 case 'i':
00682 g_options.interface_ = optarg;
00683 break;
00684 case 'n':
00685 g_options.name_ = optarg;
00686 break;
00687 case 'm':
00688 g_options.motor_ = optarg;
00689 break;
00690 case 'p':
00691 g_options.program_ = 1;
00692 break;
00693 case 'a':
00694 g_options.actuators_ = optarg;
00695 break;
00696 case 'U':
00697 g_options.update_motor_heating_config_ = true;
00698 break;
00699 case 'H':
00700 g_options.enforce_heating_model_ = true;
00701 break;
00702 }
00703 }
00704
00705
00706 string filename = "actuators.conf";
00707 if (g_options.actuators_ != "")
00708 filename = g_options.actuators_;
00709 TiXmlDocument xml(filename);
00710
00711 if (!xml.LoadFile())
00712 {
00713 Usage("Unable to load configuration file");
00714 }
00715
00716
00717 if (!parseConfig(xml.RootElement()))
00718 {
00719 exit(EXIT_FAILURE);
00720 }
00721
00722 if (g_options.help_)
00723 Usage();
00724
00725 if (optind < argc)
00726 {
00727 Usage("Extra arguments");
00728 }
00729
00730 if (!g_options.interface_)
00731 Usage("You must specify a network interface");
00732
00733
00734 int test_sock = socket(PF_PACKET, SOCK_RAW, htons(0x88A4));
00735 if ((test_sock < 0) && (errno == EPERM))
00736 {
00737 ROS_FATAL("Insufficient priviledges to obtain raw socket. Try running as root.");
00738 exit(-1);
00739 }
00740 close(test_sock);
00741
00742
00743 if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0)
00744 {
00745 ROS_WARN("mlockall failed : %s", strerror(errno));
00746 }
00747
00748 init(g_options.interface_);
00749
00750 if (g_options.update_motor_heating_config_)
00751 {
00752 updateAllHeatingConfig();
00753 }
00754
00755 if (g_options.program_)
00756 {
00757 string board = "wg005";
00758 bool enforce_heating_model = false;
00759 if (!g_options.name_)
00760 Usage("You must specify a name");
00761 if (g_options.motor_ == "")
00762 {
00763 if (actuators.find(g_options.name_) == actuators.end())
00764 Usage("No default motor for this name");
00765 g_options.motor_ = actuators[g_options.name_].motor;
00766 board = actuators[g_options.name_].board;
00767 enforce_heating_model = actuators[g_options.name_].enforce_heating_model;
00768 }
00769 if (g_options.board_ != "") {
00770 board = g_options.board_;
00771 }
00772 if (g_options.device_ == -1)
00773 Usage("You must specify a device #");
00774 if (motors.find(g_options.motor_) == motors.end())
00775 Usage("You must specify a valid motor");
00776 if (g_options.enforce_heating_model_)
00777 enforce_heating_model = true;
00778
00779 programDevice(g_options.device_, motors[g_options.motor_], g_options.name_, board, enforce_heating_model);
00780 }
00781
00782 return 0;
00783 }
00784
00785