00001
00028 #include <sr_edc_ethercat_drivers/sr06.h>
00029
00030 #include <dll/ethercat_dll.h>
00031 #include <al/ethercat_AL.h>
00032 #include <dll/ethercat_device_addressed_telegram.h>
00033 #include <dll/ethercat_frame.h>
00034 #include <realtime_tools/realtime_publisher.h>
00035
00036 #include <math.h>
00037 #include <sstream>
00038 #include <iomanip>
00039 #include <boost/foreach.hpp>
00040 #include <std_msgs/Int16.h>
00041 #include <math.h>
00042 #include <fcntl.h>
00043 #include <stdio.h>
00044 #include <pthread.h>
00045 #include <bfd.h>
00046
00047 #include <sr_utilities/sr_math_utils.hpp>
00048
00049 using namespace std;
00050
00051 #include <sr_external_dependencies/types_for_external.h>
00052 extern "C"
00053 {
00054 #include <sr_external_dependencies/external/simplemotor-bootloader/bootloader.h>
00055 }
00056
00057 #include <boost/static_assert.hpp>
00058 namespace is_edc_command_32_bits
00059 {
00060
00061
00062 BOOST_STATIC_ASSERT(sizeof(EDC_COMMAND) == 4);
00063 }
00064
00065 #define ETHERCAT_STATUS_DATA_SIZE sizeof(ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_STATUS)
00066 #define ETHERCAT_COMMAND_DATA_SIZE sizeof(ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_COMMAND)
00067
00068 const unsigned short int SR06::device_pub_freq_const = 1000;
00069 const unsigned short int SR06::ros_pub_freq_const = 1000;
00070 const unsigned short int SR06::max_iter_const = device_pub_freq_const / ros_pub_freq_const;
00071 const unsigned int SR06::nb_sensors_const = ETHERCAT_STATUS_DATA_SIZE/2;
00072 const unsigned char SR06::nb_publish_by_unpack_const = (nb_sensors_const % max_iter_const) ? (nb_sensors_const / max_iter_const) + 1 : (nb_sensors_const / max_iter_const);
00073 const unsigned int SR06::max_retry = 20;
00074
00075 #define ETHERCAT_CAN_BRIDGE_DATA_SIZE sizeof(ETHERCAT_CAN_BRIDGE_DATA)
00076
00077
00078 PLUGINLIB_REGISTER_CLASS(6, SR06, EthercatDevice);
00079
00080 #define check_for_pthread_mutex_init_error(x) switch(x) \
00081 { \
00082 case EAGAIN: \
00083 ROS_ERROR("The system temporarily lacks the resources to create another mutex : %s:%d", __FILE__, __LINE__); \
00084 exit(1); \
00085 break; \
00086 case EINVAL: \
00087 ROS_ERROR("The value specified as attribute is invalid for mutex init : %s:%d", __FILE__, __LINE__); \
00088 exit(1); \
00089 break; \
00090 case ENOMEM: \
00091 ROS_ERROR("The process cannot allocate enough memory to create another mutex : %s:%d", __FILE__, __LINE__); \
00092 exit(1); \
00093 break; \
00094 case 0: \
00095 break; \
00096 default: \
00097 ROS_ERROR("unknown error value, is this POSIX system ? : %s:%d", __FILE__, __LINE__); \
00098 exit(1); \
00099 }
00100
00101 #define unlock(x) switch ( pthread_mutex_unlock(x) ) \
00102 { \
00103 case EINVAL: \
00104 ROS_ERROR("The value specified as a mutex is invalid : %s:%d", __FILE__, __LINE__); \
00105 exit(1); \
00106 break; \
00107 case EPERM: \
00108 ROS_ERROR("The current thread does not hold a lock on the mutex : %s:%d", __FILE__, __LINE__); \
00109 exit(1); \
00110 break; \
00111 }
00112
00113 #define check_for_trylock_error(x) if (x == EINVAL) \
00114 { \
00115 ROS_ERROR("mutex error %s:%d", __FILE__, __LINE__); \
00116 exit(1); \
00117 }
00118
00119
00126 SR06::SR06()
00127 : SR0X(),
00128 flashing(false),
00129 can_message_sent(true),
00130 can_packet_acked(true),
00131 zero_buffer_read(0),
00132 cycle_count(0),
00133 can_bus_(0)
00134 {
00135 int res = 0;
00136 check_for_pthread_mutex_init_error(res);
00137 counter_ = 0;
00138
00139 ROS_INFO("There are %d sensors", nb_sensors_const);
00140 ROS_INFO( "device_pub_freq_const = %d", device_pub_freq_const );
00141 ROS_INFO( "ros_pub_freq_const = %d", ros_pub_freq_const );
00142 ROS_INFO( "max_iter_const = %d", max_iter_const );
00143 ROS_INFO( "nb_sensors_const = %d", nb_sensors_const );
00144 ROS_INFO("nb_publish_by_unpack_const = %d", nb_publish_by_unpack_const );
00145
00146 res = pthread_mutex_init(&producing, NULL);
00147 check_for_pthread_mutex_init_error(res);
00148
00149 serviceServer = nodehandle_.advertiseService("SimpleMotorFlasher", &SR06::simple_motor_flasher, this);
00150 }
00151
00156 SR06::~SR06()
00157 {
00158 delete sh_->get_fmmu_config();
00159 delete sh_->get_pd_config();
00160 }
00161
00195 void SR06::construct(EtherCAT_SlaveHandler *sh, int &start_address)
00196 {
00197 SR0X::construct(sh, start_address);
00198
00199 command_base_ = start_address;
00200 command_size_ = ETHERCAT_COMMAND_DATA_SIZE + ETHERCAT_CAN_BRIDGE_DATA_SIZE;
00201
00202 start_address += ETHERCAT_COMMAND_DATA_SIZE;
00203 start_address += ETHERCAT_CAN_BRIDGE_DATA_SIZE;
00204
00205 status_base_ = start_address;
00206 status_size_ = ETHERCAT_STATUS_DATA_SIZE + ETHERCAT_CAN_BRIDGE_DATA_SIZE;
00207
00208
00209
00210
00211
00212
00213 ROS_INFO("First FMMU (command) : start_address : 0x%08X ; size : %3d bytes ; phy addr : 0x%08X", command_base_, command_size_,
00214 static_cast<int>(ETHERCAT_COMMAND_DATA_ADDRESS) );
00215 EC_FMMU *commandFMMU = new EC_FMMU( command_base_,
00216 command_size_,
00217 0x00,
00218 0x07,
00219 ETHERCAT_COMMAND_DATA_ADDRESS,
00220 0x00,
00221 false,
00222 true,
00223 true
00224 );
00225
00226
00227
00228
00229
00230
00231
00232
00233 ROS_INFO("Second FMMU (status) : start_address : 0x%08X ; size : %3d bytes ; phy addr : 0x%08X", status_base_, status_size_,
00234 static_cast<int>(ETHERCAT_STATUS_DATA_ADDRESS) );
00235 EC_FMMU *statusFMMU = new EC_FMMU( status_base_,
00236 status_size_,
00237 0x00,
00238 0x07,
00239 ETHERCAT_STATUS_DATA_ADDRESS,
00240 0x00,
00241 true,
00242 false,
00243 true);
00244
00245
00246
00247 EtherCAT_FMMU_Config *fmmu = new EtherCAT_FMMU_Config(2);
00248
00249 (*fmmu)[0] = *commandFMMU;
00250 (*fmmu)[1] = *statusFMMU;
00251
00252 sh->set_fmmu_config(fmmu);
00253
00254 EtherCAT_PD_Config *pd = new EtherCAT_PD_Config(4);
00255
00256 (*pd)[0] = EC_SyncMan(ETHERCAT_COMMAND_DATA_ADDRESS, ETHERCAT_COMMAND_DATA_SIZE, EC_QUEUED, EC_WRITTEN_FROM_MASTER);
00257 (*pd)[1] = EC_SyncMan(ETHERCAT_CAN_BRIDGE_DATA_COMMAND_ADDRESS, ETHERCAT_CAN_BRIDGE_DATA_SIZE, EC_QUEUED, EC_WRITTEN_FROM_MASTER);
00258 (*pd)[2] = EC_SyncMan(ETHERCAT_STATUS_DATA_ADDRESS, ETHERCAT_STATUS_DATA_SIZE, EC_QUEUED);
00259 (*pd)[3] = EC_SyncMan(ETHERCAT_CAN_BRIDGE_DATA_STATUS_ADDRESS, ETHERCAT_CAN_BRIDGE_DATA_SIZE, EC_QUEUED);
00260
00261 status_size_ = ETHERCAT_STATUS_DATA_SIZE + ETHERCAT_CAN_BRIDGE_DATA_SIZE;
00262
00263 (*pd)[0].ChannelEnable = true;
00264 (*pd)[0].ALEventEnable = true;
00265 (*pd)[0].WriteEvent = true;
00266
00267 (*pd)[1].ChannelEnable = true;
00268 (*pd)[1].ALEventEnable = true;
00269 (*pd)[1].WriteEvent = true;
00270
00271 (*pd)[2].ChannelEnable = true;
00272 (*pd)[3].ChannelEnable = true;
00273
00274 sh->set_pd_config(pd);
00275
00276 ROS_INFO("status_size_ : %d ; command_size_ : %d", status_size_, command_size_);
00277
00278 ROS_INFO("Finished constructing the SR06 driver");
00279 }
00280
00284 int SR06::initialize(pr2_hardware_interface::HardwareInterface *hw, bool allow_unprogrammed)
00285 {
00286
00287 int retval = SR0X::initialize(hw, allow_unprogrammed);
00288
00289 if(retval != 0)
00290 return retval;
00291
00292 sr_hand_lib = boost::shared_ptr<shadow_robot::SrHandLib>( new shadow_robot::SrHandLib(hw) );
00293
00294 ROS_INFO("ETHERCAT_STATUS_DATA_SIZE = %4d bytes", static_cast<int>(ETHERCAT_STATUS_DATA_SIZE) );
00295 ROS_INFO("ETHERCAT_COMMAND_DATA_SIZE = %4d bytes", static_cast<int>(ETHERCAT_COMMAND_DATA_SIZE) );
00296 ROS_INFO("ETHERCAT_CAN_BRIDGE_DATA_SIZE = %4d bytes", static_cast<int>(ETHERCAT_CAN_BRIDGE_DATA_SIZE) );
00297
00298
00299 extra_analog_inputs_publisher.reset(new realtime_tools::RealtimePublisher<std_msgs::Float64MultiArray>(nodehandle_ , "palm_extras", 10));
00300
00301
00302
00303 debug_publisher = boost::shared_ptr<realtime_tools::RealtimePublisher<sr_robot_msgs::EthercatDebug> >( new realtime_tools::RealtimePublisher<sr_robot_msgs::EthercatDebug>(nodehandle_ , "debug_etherCAT_data", 4));
00304 return retval;
00305 }
00306
00312 void SR06::erase_flash(void)
00313 {
00314 unsigned char cmd_sent;
00315 unsigned int wait_time;
00316 bool timedout;
00317 unsigned int timeout;
00318 int err;
00319
00320 do {
00321 ROS_INFO("Erasing FLASH");
00322
00323 cmd_sent = 0;
00324 while (! cmd_sent )
00325 {
00326 if ( !(err = pthread_mutex_trylock(&producing)) )
00327 {
00328 can_message_.message_length = 1;
00329 can_message_.can_bus = can_bus_;
00330 can_message_.message_id = 0x0600 | (motor_being_flashed << 5) | ERASE_FLASH_COMMAND;
00331 cmd_sent = 1;
00332 unlock(&producing);
00333 }
00334 else
00335 {
00336 check_for_trylock_error(err);
00337 }
00338 }
00339 wait_time = 0;
00340 timeout = 3000;
00341 can_message_sent = false;
00342 can_packet_acked = false;
00343 timedout = false;
00344 while ( !can_packet_acked )
00345 {
00346 usleep(1000);
00347 if (wait_time > timeout)
00348 {
00349 timedout = true;
00350 break;
00351 }
00352 wait_time++;
00353 }
00354
00355 if (timedout)
00356 {
00357 ROS_ERROR("ERASE command timedout, resending it !");
00358 }
00359 } while (timedout);
00360 }
00361
00378 bool SR06::read_flash(unsigned int offset, unsigned int baddr)
00379 {
00380 unsigned int cmd_sent;
00381 int err;
00382 unsigned int wait_time;
00383 bool timedout;
00384 unsigned int timeout;
00385 cmd_sent = 0;
00386 while ( !cmd_sent )
00387 {
00388 if ( !(err = pthread_mutex_trylock(&producing)) )
00389 {
00390 ROS_DEBUG("Sending READ data ... position : %03x", pos);
00391 can_message_.can_bus = can_bus_;
00392 can_message_.message_length = 3;
00393 can_message_.message_id = 0x0600 | (motor_being_flashed << 5) | READ_FLASH_COMMAND;
00394 can_message_.message_data[2] = (offset + baddr) >> 16;
00395 can_message_.message_data[1] = (offset + baddr) >> 8;
00396 can_message_.message_data[0] = offset + baddr;
00397 cmd_sent = 1;
00398 unlock(&producing);
00399 }
00400 else
00401 {
00402 check_for_trylock_error(err);
00403 }
00404
00405 }
00406 timedout = false;
00407 wait_time = 0;
00408 timeout = 100;
00409 can_message_sent = false;
00410 can_packet_acked = false;
00411 while ( !can_packet_acked )
00412 {
00413 usleep(1000);
00414 if (wait_time > timeout)
00415 {
00416 timedout = true;
00417 break;
00418 }
00419 wait_time++;
00420 }
00421 return timedout;
00422 }
00423
00462 bool SR06::simple_motor_flasher(sr_robot_msgs::SimpleMotorFlasher::Request &req, sr_robot_msgs::SimpleMotorFlasher::Response &res)
00463 {
00464 bfd *fd;
00465 unsigned int base_addr;
00466 unsigned int smallest_start_address = 0x7fff;
00467 unsigned int biggest_end_address = 0;
00468 unsigned int total_size = 0;
00469 bool timedout;
00470
00471
00472
00473
00474 int motor_id_tmp = req.motor_id;
00475 if( motor_id_tmp > 9 )
00476 {
00477 motor_id_tmp -= 10;
00478 can_bus_ = 2;
00479 }
00480 else
00481 {
00482 can_bus_ = 1;
00483 }
00484
00485 motor_being_flashed = motor_id_tmp;
00486 binary_content = NULL;
00487 flashing = true;
00488
00489 ROS_INFO("Flashing the motor");
00490
00491
00492 bfd_init();
00493
00494
00495 fd = bfd_openr(req.firmware.c_str(), NULL);
00496 if (fd == NULL)
00497 {
00498 ROS_ERROR("error opening the file %s", get_filename(req.firmware).c_str());
00499 res.value = res.FAIL;
00500 flashing = false;
00501 return false;
00502 }
00503
00504
00505 if (!bfd_check_format (fd, bfd_object))
00506 {
00507 if (bfd_get_error () != bfd_error_file_ambiguously_recognized)
00508 {
00509 ROS_ERROR("Incompatible format");
00510 res.value = res.FAIL;
00511 flashing = false;
00512 return false;
00513 }
00514 }
00515
00516 ROS_INFO("firmware %s's format is : %s.", get_filename(req.firmware).c_str(), fd->xvec->name);
00517
00518
00519 ROS_DEBUG("Sending dummy packet");
00520 send_CAN_msg(can_bus_, 0, 0, NULL, 1, &timedout);
00521
00522 ROS_INFO_STREAM("Switching motor "<< motor_being_flashed << " on CAN bus " << can_bus_ << " into bootloader mode");
00523
00524 int8u magic_packet[] = {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
00525 send_CAN_msg(can_bus_, 0x0600 | (motor_being_flashed << 5) | 0b1010, 8, magic_packet, 100, &timedout);
00526
00527
00528 if ( timedout )
00529 {
00530 ROS_WARN("First magic CAN packet timedout");
00531 ROS_WARN("Sending another magic CAN packet to put the motor in bootloading mode");
00532 send_CAN_msg(can_bus_, 0x0600 | (motor_being_flashed << 5) | 0b1010, 8, magic_packet, 100, &timedout);
00533
00534 if (timedout)
00535 {
00536 ROS_ERROR("None of the magic packets were ACKed, didn't bootload the motor.");
00537 res.value = res.FAIL;
00538 flashing = false;
00539 return false;
00540 }
00541 }
00542
00543
00544 erase_flash();
00545
00546 sleep(1);
00547
00548
00549
00550 find_address_range(fd, &smallest_start_address, &biggest_end_address);
00551
00552
00553 total_size = biggest_end_address - smallest_start_address;
00554 base_addr = smallest_start_address;
00555
00556
00557
00558 binary_content = (bfd_byte *)malloc(total_size+8);
00559 if (binary_content == NULL)
00560 {
00561 ROS_ERROR("Error allocating memory for binary_content");
00562 res.value = res.FAIL;
00563 flashing = false;
00564 return false;
00565 }
00566
00567
00568
00569
00570 memset(binary_content, 0xFF, total_size+8);
00571
00572
00573 if(!read_content_from_object_file(fd, binary_content, base_addr))
00574 {
00575 ROS_ERROR("something went wrong while parsing %s.", get_filename(req.firmware).c_str());
00576 res.value = res.FAIL;
00577 free(binary_content);
00578 flashing = false;
00579 return false;
00580 }
00581
00582
00583 bfd_close(fd);
00584
00585
00586 if(!write_flash_data(base_addr, total_size))
00587 {
00588 res.value = res.FAIL;
00589 free(binary_content);
00590 flashing = false;
00591 return false;
00592 }
00593
00594
00595 ROS_INFO("Verifying");
00596
00597 if( !read_back_and_check_flash(base_addr, total_size))
00598 {
00599 res.value = res.FAIL;
00600 free(binary_content);
00601 flashing = false;
00602 return false;
00603 }
00604
00605
00606 free(binary_content);
00607
00608 ROS_INFO("Resetting microcontroller.");
00609
00610 do {
00611 send_CAN_msg(can_bus_, 0x0600 | (motor_being_flashed << 5) | RESET_COMMAND, 0, NULL, 1000, &timedout);
00612 } while ( timedout );
00613
00614
00615 flashing = false;
00616
00617 ROS_INFO("Flashing done");
00618
00619 res.value = res.SUCCESS;
00620
00621
00622 sr_hand_lib->reinitialize_motors();
00623
00624 return true;
00625 }
00626
00633 void SR06::multiDiagnostics(vector<diagnostic_msgs::DiagnosticStatus> &vec, unsigned char *buffer)
00634 {
00635 diagnostic_updater::DiagnosticStatusWrapper &d(diagnostic_status_);
00636
00637 stringstream name;
00638 d.name = "EtherCAT Dual CAN Palm";
00639 d.summary(d.OK, "OK");
00640 stringstream hwid;
00641 hwid << sh_->get_product_code() << "-" << sh_->get_serial();
00642 d.hardware_id = hwid.str();
00643
00644 d.clear();
00645 d.addf("Position", "%02d", sh_->get_ring_position());
00646 d.addf("Product Code", "%d", sh_->get_product_code());
00647 d.addf("Serial Number", "%d", sh_->get_serial());
00648 d.addf("Revision", "%d", sh_->get_revision());
00649 d.addf("Counter", "%d", ++counter_);
00650
00651 d.addf("PIC idle time (in microsecs)", "%d", sr_hand_lib->main_pic_idle_time);
00652 d.addf("Min PIC idle time (since last diagnostics)", "%d", sr_hand_lib->main_pic_idle_time_min);
00653
00654 sr_hand_lib->main_pic_idle_time_min = 1000;
00655
00656 this->ethercatDiagnostics(d,2);
00657 vec.push_back(d);
00658
00659
00660 sr_hand_lib->add_diagnostics(vec, d);
00661
00662
00663 if( sr_hand_lib->tactiles != NULL )
00664 sr_hand_lib->tactiles->add_diagnostics(vec, d);
00665 }
00666
00667
00668
00684 void SR06::packCommand(unsigned char *buffer, bool halt, bool reset)
00685 {
00686 int res;
00687
00688 SR0X::packCommand(buffer, halt, reset);
00689
00690 ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_COMMAND *command = (ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_COMMAND *)(buffer );
00691 ETHERCAT_CAN_BRIDGE_DATA *message = (ETHERCAT_CAN_BRIDGE_DATA *)(buffer + ETHERCAT_COMMAND_DATA_SIZE);
00692
00693 if ( !flashing )
00694 {
00695 command->EDC_command = EDC_COMMAND_SENSOR_DATA;
00696 }
00697 else
00698 {
00699 command->EDC_command = EDC_COMMAND_CAN_DIRECT_MODE;
00700 }
00701
00702
00703
00704 sr_hand_lib->build_motor_command(command);
00705
00706 ROS_DEBUG("Sending command : Type : 0x%02X ; data : 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X 0x%04X",
00707 command->to_motor_data_type,
00708 command->motor_data[0],
00709 command->motor_data[1],
00710 command->motor_data[2],
00711 command->motor_data[3],
00712 command->motor_data[4],
00713 command->motor_data[5],
00714 command->motor_data[6],
00715 command->motor_data[7],
00716 command->motor_data[8],
00717 command->motor_data[9],
00718 command->motor_data[10],
00719 command->motor_data[11],
00720 command->motor_data[12],
00721 command->motor_data[13],
00722 command->motor_data[14],
00723 command->motor_data[15],
00724 command->motor_data[16],
00725 command->motor_data[17],
00726 command->motor_data[18],
00727 command->motor_data[19]);
00728
00729 if (flashing && !can_packet_acked && !can_message_sent)
00730 {
00731 if ( !(res = pthread_mutex_trylock(&producing)) )
00732 {
00733 ROS_DEBUG_STREAM("Ethercat Command data size: "<< ETHERCAT_COMMAND_DATA_SIZE);
00734 ROS_DEBUG_STREAM("Ethercat bridge data size: "<< ETHERCAT_CAN_BRIDGE_DATA_SIZE);
00735
00736 ROS_DEBUG("We're sending a CAN message for flashing.");
00737 memcpy(message, &can_message_, sizeof(can_message_));
00738 can_message_sent = true;
00739
00740 ROS_DEBUG("Sending : SID : 0x%04X ; bus : 0x%02X ; length : 0x%02X ; data : 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
00741 message->message_id,
00742 message->can_bus,
00743 message->message_length,
00744 message->message_data[0],
00745 message->message_data[1],
00746 message->message_data[2],
00747 message->message_data[3],
00748 message->message_data[4],
00749 message->message_data[5],
00750 message->message_data[6],
00751 message->message_data[7]);
00752
00753 unlock(&producing);
00754 }
00755 else
00756 {
00757 ROS_ERROR("Mutex is locked, we don't send any CAN message !");
00758 check_for_trylock_error(res);
00759 }
00760 }
00761 else
00762 {
00763 message->can_bus = can_bus_;
00764 message->message_id = 0x00;
00765 message->message_length = 0;
00766 }
00767
00768 }
00769
00778 bool SR06::can_data_is_ack(ETHERCAT_CAN_BRIDGE_DATA * packet)
00779 {
00780 int i;
00781
00782 if (packet->message_id == 0)
00783 {
00784 ROS_DEBUG("ID is zero");
00785 return false;
00786 }
00787
00788 ROS_DEBUG("ack sid : %04X", packet->message_id);
00789
00790
00791 if ( (packet->message_id & 0b0000011111111111) == (0x0600 | (motor_being_flashed << 5) | 0x10 | READ_FLASH_COMMAND))
00792 {
00793 ROS_DEBUG("READ reply %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", packet->message_data[0],
00794 packet->message_data[1],
00795 packet->message_data[2],
00796 packet->message_data[3],
00797 packet->message_data[4],
00798 packet->message_data[5],
00799 packet->message_data[6],
00800 packet->message_data[7] );
00801 ROS_DEBUG("Should be %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", binary_content[pos+0],
00802 binary_content[pos+1],
00803 binary_content[pos+2],
00804 binary_content[pos+3],
00805 binary_content[pos+4],
00806 binary_content[pos+5],
00807 binary_content[pos+6],
00808 binary_content[pos+7] );
00809
00810 if ( !memcmp(packet->message_data, binary_content + pos, 8) )
00811 {
00812 ROS_DEBUG("data is good");
00813 return true;
00814 }
00815 else
00816 {
00817 ROS_DEBUG("data is bad");
00818 return false;
00819 }
00820 }
00821
00822 if (packet->message_length != can_message_.message_length)
00823 {
00824 ROS_DEBUG("Length is bad: %d", packet->message_length);
00825 return false;
00826 }
00827
00828 ROS_DEBUG("Length is OK");
00829
00830 for (i = 0 ; i < packet->message_length ; ++i)
00831 {
00832 ROS_DEBUG("packet sent, data[%d] : %02X ; ack, data[%d] : %02X", i, can_message_.message_data[i], i, packet->message_data[i]);
00833 if (packet->message_data[i] != can_message_.message_data[i])
00834 return false;
00835 }
00836 ROS_DEBUG("Data is OK");
00837
00838 if ( !(0x0010 & packet->message_id))
00839 return false;
00840
00841 ROS_DEBUG("This is an ACK");
00842
00843 if ( (packet->message_id & 0b0000000111101111) != (can_message_.message_id & 0b0000000111101111) )
00844 {
00845 ROS_WARN_STREAM("Bad packet id: " << packet->message_id);
00846 return false;
00847 }
00848
00849 ROS_DEBUG("SID is OK");
00850
00851 ROS_DEBUG("Everything is OK, this is our ACK !");
00852 return true;
00853 }
00854
00873 bool SR06::unpackState(unsigned char *this_buffer, unsigned char *prev_buffer)
00874 {
00875 ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_STATUS *status_data = (ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_STATUS *)(this_buffer + command_size_ );
00876 ETHERCAT_CAN_BRIDGE_DATA *can_data = (ETHERCAT_CAN_BRIDGE_DATA *)(this_buffer + command_size_ + ETHERCAT_STATUS_DATA_SIZE );
00877
00878 static unsigned int num_rxed_packets = 0;
00879
00880 ++num_rxed_packets;
00881
00882
00883
00884 if(debug_publisher->trylock())
00885 {
00886 debug_publisher->msg_.header.stamp = ros::Time::now();
00887
00888 debug_publisher->msg_.sensors.clear();
00889 for(unsigned int i=0; i<SENSORS_NUM_0220 + 1; ++i)
00890 debug_publisher->msg_.sensors.push_back( status_data->sensors[i] );
00891
00892 debug_publisher->msg_.motor_data_type.data = static_cast<int>(status_data->motor_data_type);
00893 debug_publisher->msg_.which_motors = status_data->which_motors;
00894 debug_publisher->msg_.which_motor_data_arrived = status_data->which_motor_data_arrived;
00895 debug_publisher->msg_.which_motor_data_had_errors = status_data->which_motor_data_had_errors;
00896
00897 debug_publisher->msg_.motor_data_packet_torque.clear();
00898 debug_publisher->msg_.motor_data_packet_misc.clear();
00899 for(unsigned int i=0; i < 10; ++i)
00900 {
00901 debug_publisher->msg_.motor_data_packet_torque.push_back( status_data->motor_data_packet[i].torque );
00902 debug_publisher->msg_.motor_data_packet_misc.push_back( status_data->motor_data_packet[i].misc );
00903 }
00904
00905 debug_publisher->msg_.tactile_data_type = static_cast<unsigned int>(static_cast<int32u>(status_data->tactile_data_type));
00906 debug_publisher->msg_.tactile_data_valid = static_cast<unsigned int>(static_cast<int16u>(status_data->tactile_data_valid));
00907 debug_publisher->msg_.tactile.clear();
00908 for(unsigned int i=0; i < 5; ++i)
00909 debug_publisher->msg_.tactile.push_back( static_cast<unsigned int>(static_cast<int16u>(status_data->tactile[i].word[0])) );
00910
00911 debug_publisher->msg_.idle_time_us = status_data->idle_time_us;
00912
00913 debug_publisher->unlockAndPublish();
00914 }
00915
00916 if (status_data->EDC_command == EDC_COMMAND_INVALID)
00917 {
00918
00919 ++zero_buffer_read;
00920 float percentage_packet_loss = 100.f * ((float)zero_buffer_read / (float)num_rxed_packets);
00921
00922 ROS_DEBUG("Reception error detected : %d errors out of %d rxed packets (%2.3f%%) ; idle time %dus", zero_buffer_read, num_rxed_packets, percentage_packet_loss, status_data->idle_time_us);
00923 return true;
00924 }
00925
00926
00927
00928
00929 sr_hand_lib->update(status_data);
00930
00931
00932 if( cycle_count >= 9)
00933 {
00934
00935 if( sr_hand_lib->tactiles != NULL )
00936 sr_hand_lib->tactiles->publish();
00937
00938
00939 std_msgs::Float64MultiArray extra_analog_msg;
00940 extra_analog_msg.layout.dim.resize(3);
00941 extra_analog_msg.data.resize(3+3+4);
00942 std::vector<double> data;
00943
00944 extra_analog_msg.layout.dim[0].label = "accelerometer";
00945 extra_analog_msg.layout.dim[0].size = 3;
00946 extra_analog_msg.data[0] = status_data->sensors[ACCX];
00947 extra_analog_msg.data[1] = status_data->sensors[ACCY];
00948 extra_analog_msg.data[2] = status_data->sensors[ACCZ];
00949
00950 extra_analog_msg.layout.dim[1].label = "gyrometer";
00951 extra_analog_msg.layout.dim[1].size = 3;
00952 extra_analog_msg.data[3] = status_data->sensors[GYRX];
00953 extra_analog_msg.data[4] = status_data->sensors[GYRY];
00954 extra_analog_msg.data[5] = status_data->sensors[GYRZ];
00955
00956 extra_analog_msg.layout.dim[2].label = "analog_inputs";
00957 extra_analog_msg.layout.dim[2].size = 4;
00958 extra_analog_msg.data[6] = status_data->sensors[AN0];
00959 extra_analog_msg.data[7] = status_data->sensors[AN1];
00960 extra_analog_msg.data[8] = status_data->sensors[AN2];
00961 extra_analog_msg.data[9] = status_data->sensors[AN3];
00962
00963 if( extra_analog_inputs_publisher->trylock() )
00964 {
00965 extra_analog_inputs_publisher->msg_ = extra_analog_msg;
00966 extra_analog_inputs_publisher->unlockAndPublish();
00967 }
00968
00969 cycle_count = 0;
00970 }
00971 ++cycle_count;
00972
00973
00974
00975 if (flashing & !can_packet_acked)
00976 {
00977 if (can_data_is_ack(can_data))
00978 {
00979 can_packet_acked = true;
00980 }
00981 }
00982
00983 return true;
00984 }
00985
00986 void SR06::send_CAN_msg(int8u can_bus, int16u msg_id, int8u msg_length, int8u msg_data[], int timeout, bool *timedout)
00987 {
00988 int err;
00989 unsigned char cmd_sent;
00990 int wait_time;
00991
00992 cmd_sent = 0;
00993 while ( !cmd_sent )
00994 {
00995 if ( !(err = pthread_mutex_trylock(&producing)) )
00996 {
00997 can_message_.message_length = msg_length;
00998 can_message_.can_bus = can_bus;
00999 can_message_.message_id = msg_id;
01000
01001 if (msg_data != NULL)
01002 {
01003 for(unsigned int i = 0; i<msg_length; i++)
01004 {
01005 can_message_.message_data[i] = msg_data[i];
01006 }
01007 }
01008
01009 cmd_sent = 1;
01010 unlock(&producing);
01011 }
01012 else
01013 {
01014 check_for_trylock_error(err);
01015 }
01016 }
01017 wait_time = 0;
01018 *timedout = false;
01019 can_message_sent = false;
01020 can_packet_acked = false;
01021 while ( !can_packet_acked )
01022 {
01023 usleep(1000);
01024 wait_time++;
01025 if (wait_time > timeout) {
01026 *timedout = true;
01027 break;
01028 }
01029 }
01030 }
01031
01032 bool SR06::read_back_and_check_flash(unsigned int baddr, unsigned int total_size)
01033 {
01034 bool timedout;
01035
01036
01037
01038
01039
01040 pos = 0;
01041 unsigned int retry;
01042 while (pos < total_size)
01043 {
01044 retry = 0;
01045 do {
01046 timedout = read_flash(pos, baddr);
01047 if ( ! timedout )
01048 pos += 8;
01049 retry++;
01050 if (retry > max_retry)
01051 {
01052 ROS_ERROR("Too much retry for READ back, try flashing again");
01053 return false;
01054 }
01055 } while ( timedout );
01056 }
01057 return true;
01058 }
01059
01060 void SR06::find_address_range(bfd *fd, unsigned int *smallest_start_address, unsigned int *biggest_end_address)
01061 {
01062 asection *s;
01063 unsigned int section_size = 0;
01064 unsigned int section_addr = 0;
01065
01066
01067
01068
01069
01070
01071
01072
01073 for (s = fd->sections ; s ; s = s->next)
01074 {
01075
01076 if (bfd_get_section_flags (fd, s) & (SEC_LOAD))
01077 {
01078
01079
01080 if (bfd_section_lma (fd, s) == bfd_section_vma (fd, s))
01081 {
01082 section_addr = (unsigned int) bfd_section_lma (fd, s);
01083 if (section_addr >= 0x7fff)
01084 continue;
01085 section_size = (unsigned int) bfd_section_size (fd, s);
01086 *smallest_start_address = min(section_addr, *smallest_start_address);
01087 *biggest_end_address = max(*biggest_end_address, section_addr + section_size);
01088 }
01089 }
01090 }
01091 }
01092
01093 bool SR06::read_content_from_object_file(bfd *fd, bfd_byte *content, unsigned int base_addr)
01094 {
01095 asection *s;
01096 unsigned int section_size = 0;
01097 unsigned int section_addr = 0;
01098
01099 for (s = fd->sections ; s ; s = s->next)
01100 {
01101
01102 if (bfd_get_section_flags (fd, s) & (SEC_LOAD))
01103 {
01104
01105
01106 if (bfd_section_lma (fd, s) == bfd_section_vma (fd, s))
01107 {
01108 section_addr = (unsigned int) bfd_section_lma (fd, s);
01109
01110
01111 if (section_addr >= 0x7fff)
01112 continue;
01113 section_size = (unsigned int) bfd_section_size (fd, s);
01114 bfd_get_section_contents(fd, s, content + (section_addr - base_addr), 0, section_size);
01115 }
01116 else
01117 {
01118 return false;
01119 }
01120 }
01121 else
01122 {
01123 return false;
01124 }
01125 }
01126 return true;
01127 }
01128
01129 bool SR06::write_flash_data(unsigned int base_addr, unsigned int total_size)
01130 {
01131 int err;
01132 unsigned char cmd_sent;
01133 int wait_time, timeout;
01134 bool timedout;
01135
01136 pos = 0;
01137 unsigned int packet = 0;
01138 ROS_INFO("Sending the firmware data");
01139 while ( pos < ((total_size % 32) == 0 ? total_size : (total_size + 32 - (total_size % 32))) )
01140 {
01141
01142
01143 if ((pos % 32) == 0)
01144 {
01145 packet = 0;
01146 do {
01147 cmd_sent = 0;
01148 while (! cmd_sent )
01149 {
01150 if ( !(err = pthread_mutex_trylock(&producing)) )
01151 {
01152 can_message_.message_length = 3;
01153 can_message_.can_bus = can_bus_;
01154 can_message_.message_id = 0x0600 | (motor_being_flashed << 5) | WRITE_FLASH_ADDRESS_COMMAND;
01155 can_message_.message_data[2] = (base_addr + pos) >> 16;
01156 can_message_.message_data[1] = (base_addr + pos) >> 8;
01157 can_message_.message_data[0] = base_addr + pos;
01158 ROS_DEBUG("Sending write address to motor %d : 0x%02X%02X%02X", motor_being_flashed, can_message_.message_data[2], can_message_.message_data[1], can_message_.message_data[0]);
01159 cmd_sent = 1;
01160 unlock(&producing);
01161 }
01162 else
01163 {
01164 check_for_trylock_error(err);
01165 }
01166 }
01167 wait_time = 0;
01168 timedout = false;
01169 timeout = 100;
01170 can_message_sent = false;
01171 can_packet_acked = false;
01172 while ( !can_packet_acked )
01173 {
01174 usleep(1000);
01175 if (wait_time > timeout)
01176 {
01177 timedout = true;
01178 break;
01179 }
01180 wait_time++;
01181 }
01182 if (timedout)
01183 {
01184 ROS_ERROR("WRITE ADDRESS timedout ");
01185 return false;
01186 }
01187 } while ( timedout );
01188 }
01189 cmd_sent = 0;
01190 while (! cmd_sent )
01191 {
01192 if ( !(err = pthread_mutex_trylock(&producing)) )
01193 {
01194 ROS_DEBUG("Sending data ... position == %d", pos);
01195 can_message_.message_length = 8;
01196 can_message_.can_bus = can_bus_;
01197 can_message_.message_id = 0x0600 | (motor_being_flashed << 5) | WRITE_FLASH_DATA_COMMAND;
01198 bzero(can_message_.message_data, 8);
01199 for (unsigned char j = 0 ; j < 8 ; ++j)
01200 can_message_.message_data[j] = (pos > total_size) ? 0xFF : *(binary_content + pos + j);
01201
01202 pos += 8;
01203 cmd_sent = 1;
01204 unlock(&producing);
01205 }
01206 else
01207 {
01208 check_for_trylock_error(err);
01209 }
01210 }
01211 packet++;
01212 timedout = false;
01213 wait_time = 0;
01214 timeout = 100;
01215 can_message_sent = false;
01216 can_packet_acked = false;
01217 while ( !can_packet_acked )
01218 {
01219 usleep(1000);
01220 if (wait_time > timeout)
01221 {
01222 timedout = true;
01223 break;
01224 }
01225 wait_time++;
01226 }
01227 if ( timedout )
01228 {
01229 ROS_ERROR("A WRITE data packet has been lost, resending the 32 bytes block !");
01230 pos -= packet*8;
01231 }
01232 }
01233 return true;
01234 }
01235
01236
01237
01238
01239
01240
01241