sr_motor_robot_lib.cpp
Go to the documentation of this file.
00001 
00028 #include "sr_robot_lib/sr_motor_robot_lib.hpp"
00029 #include <string>
00030 #include <vector>
00031 #include <utility>
00032 #include <boost/foreach.hpp>
00033 
00034 #include <sys/time.h>
00035 #include <cstdlib>
00036 
00037 #include <ros/ros.h>
00038 
00039 #include <controller_manager_msgs/ListControllers.h>
00040 
00041 #define SERIOUS_ERROR_FLAGS PALM_0200_EDC_SERIOUS_ERROR_FLAGS
00042 #define error_flag_names palm_0200_edc_error_flag_names
00043 
00044 using std::vector;
00045 using std::string;
00046 using std::pair;
00047 using std::ostringstream;
00048 using sr_actuator::SrMotorActuator;
00049 using shadow_joints::Joint;
00050 using shadow_joints::JointToSensor;
00051 using shadow_joints::MotorWrapper;
00052 using shadow_joints::PartialJointToSensor;
00053 using generic_updater::MotorUpdater;
00054 using generic_updater::MotorDataChecker;
00055 using boost::shared_ptr;
00056 using boost::static_pointer_cast;
00057 
00058 namespace shadow_robot
00059 {
00060 
00061   template<class StatusType, class CommandType>
00062   SrMotorRobotLib<StatusType, CommandType>::SrMotorRobotLib(hardware_interface::HardwareInterface *hw,
00063                                                             ros::NodeHandle nh, ros::NodeHandle nhtilde,
00064                                                             string device_id, string joint_prefix)
00065           : SrRobotLib<StatusType, CommandType>(hw, nh, nhtilde, device_id, joint_prefix),
00066             motor_current_state(operation_mode::device_update_state::INITIALIZATION),
00067             config_index(MOTOR_CONFIG_FIRST_VALUE),
00068             control_type_changed_flag_(false),
00069             change_control_type_(this->nh_tilde.advertiseService("change_control_type",
00070                                                                  &SrMotorRobotLib::change_control_type_callback_,
00071                                                                  this)),
00072             motor_system_control_server_(
00073                     this->nh_tilde.advertiseService("change_motor_system_controls",
00074                                                     &SrMotorRobotLib::motor_system_controls_callback_,
00075                                                     this)),
00076             lock_command_sending_(new boost::mutex())
00077   {
00078     // reading the parameters to check for a specified default control type
00079     // using FORCE control if no parameters are set
00080     string default_control_mode;
00081     this->nh_tilde.template param<string>("default_control_mode", default_control_mode, "FORCE");
00082     if (default_control_mode.compare("PWM") == 0)
00083     {
00084       control_type_.control_type = sr_robot_msgs::ControlType::PWM;
00085       ROS_INFO("Using PWM control.");
00086     }
00087     else
00088     {
00089       control_type_.control_type = sr_robot_msgs::ControlType::FORCE;
00090       ROS_INFO("Using TORQUE control.");
00091     }
00092 
00093 #ifdef DEBUG_PUBLISHER
00094     this->debug_motor_indexes_and_data.resize(this->nb_debug_publishers_const);
00095     for (int i = 0; i < this->nb_debug_publishers_const; ++i)
00096     {
00097       ostringstream ss;
00098       ss << "srh/debug_" << i;
00099       this->debug_publishers.push_back(this->node_handle.template advertise<std_msgs::Int16>(ss.str().c_str(), 100));
00100     }
00101 #endif
00102   }
00103 
00104   template<class StatusType, class CommandType>
00105   void SrMotorRobotLib<StatusType, CommandType>::update(StatusType *status_data)
00106   {
00107     // read the PIC idle time
00108     this->main_pic_idle_time = status_data->idle_time_us;
00109     if (status_data->idle_time_us < this->main_pic_idle_time_min)
00110     {
00111       this->main_pic_idle_time_min = status_data->idle_time_us;
00112     }
00113 
00114     // get the current timestamp
00115     struct timeval tv;
00116     double timestamp = 0.0;
00117     if (gettimeofday(&tv, NULL))
00118       ROS_WARN("SrMotorRobotLib: Failed to get system time, timestamp in state will be zero");
00119     else
00120     {
00121       timestamp = static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1.0e+6;
00122     }
00123 
00124     // First we read the joints information
00125     for (vector<Joint>::iterator joint_tmp = this->joints_vector.begin();
00126          joint_tmp != this->joints_vector.end();
00127          ++joint_tmp)
00128     {
00129       if (!joint_tmp->has_actuator)
00130       {
00131         continue;
00132       }
00133 
00134       SrMotorActuator *motor_actuator = this->get_joint_actuator(joint_tmp);
00135 
00136       shared_ptr<MotorWrapper> motor_wrapper = static_pointer_cast<MotorWrapper>(joint_tmp->actuator_wrapper);
00137 
00138       motor_index_full = motor_wrapper->motor_id;
00139       motor_actuator->state_.device_id_ = motor_index_full;
00140 
00141       // Fill in the tactiles.
00142       if (this->tactiles != NULL)
00143       {
00144         motor_actuator->motor_state_.tactiles_ = this->tactiles->get_tactile_data();
00145       }
00146 
00147       this->process_position_sensor_data(joint_tmp, status_data, timestamp);
00148 
00149       // filter the effort
00150       pair<double, double> effort_and_effort_d = joint_tmp->effort_filter.compute(
00151               motor_actuator->motor_state_.force_unfiltered_, timestamp);
00152       motor_actuator->state_.last_measured_effort_ = effort_and_effort_d.first;
00153 
00154       // get the remaining information.
00155       bool read_motor_info = false;
00156 
00157       if (status_data->which_motors == 0)
00158       {
00159         // We sampled the even motor numbers
00160         if (motor_index_full % 2 == 0)
00161         {
00162           read_motor_info = true;
00163         }
00164       }
00165       else
00166       {
00167         // we sampled the odd motor numbers
00168         if (motor_index_full % 2 == 1)
00169         {
00170           read_motor_info = true;
00171         }
00172       }
00173 
00174       // the position of the motor in the message
00175       // is different from the motor index:
00176       // the motor indexes range from 0 to 19
00177       // while the message contains information
00178       // for only 10 motors.
00179       index_motor_in_msg = motor_index_full / 2;
00180 
00181       // setting the position of the motor in the message,
00182       // we'll print that in the diagnostics.
00183       motor_wrapper->msg_motor_id = index_motor_in_msg;
00184 
00185       // OK now we read the info and add it to the actuator state
00186       if (read_motor_info)
00187       {
00188         read_additional_data(joint_tmp, status_data);
00189       }
00190     }  // end for joint
00191 
00192     // then we read the tactile sensors information
00193     this->update_tactile_info(status_data);
00194   }  // end update()
00195 
00196   template<class StatusType, class CommandType>
00197   void SrMotorRobotLib<StatusType, CommandType>::build_command(CommandType *command)
00198   {
00199     // Mutual exclusion with the change_control_type service.
00200     // We have to wait until the control_type_ variable has been set.
00201     boost::mutex::scoped_lock l(*lock_command_sending_);
00202 
00203     if (control_type_changed_flag_)
00204     {
00205       if (!change_control_parameters(control_type_.control_type))
00206       {
00207         ROS_FATAL("Changing control parameters failed. Stopping real time loop to protect the robot.");
00208         exit(EXIT_FAILURE);
00209       }
00210 
00211       control_type_changed_flag_ = false;
00212     }
00213 
00214     if (motor_current_state == operation_mode::device_update_state::INITIALIZATION)
00215     {
00216       motor_current_state = motor_updater_->build_init_command(command);
00217     }
00218     else
00219     {
00220       // build the motor command
00221       motor_current_state = motor_updater_->build_command(command);
00222     }
00223 
00224     // Build the tactile sensors command
00225     this->build_tactile_command(command);
00226 
00228     // Now we chose the command to send to the motor
00229     // by default we send a torque demand (we're running
00230     // the force control on the motors), but if we have a waiting
00231     // configuration, a reset command, or a motor system control
00232     // request then we send the configuration
00233     // or the reset.
00234     if (reconfig_queue.empty() && reset_motors_queue.empty()
00235         && motor_system_control_flags_.empty())
00236     {
00237       // no config to send
00238       switch (control_type_.control_type)
00239       {
00240         case sr_robot_msgs::ControlType::FORCE:
00241           command->to_motor_data_type = MOTOR_DEMAND_TORQUE;
00242           break;
00243         case sr_robot_msgs::ControlType::PWM:
00244           command->to_motor_data_type = MOTOR_DEMAND_PWM;
00245           break;
00246 
00247         default:
00248           command->to_motor_data_type = MOTOR_DEMAND_TORQUE;
00249           break;
00250       }
00251 
00252       // loop on all the joints and update their motor: we're sending commands to all the motors.
00253       for (vector<Joint>::iterator joint_tmp = this->joints_vector.begin();
00254            joint_tmp != this->joints_vector.end();
00255            ++joint_tmp)
00256       {
00257         if (!joint_tmp->has_actuator)
00258         {
00259           continue;
00260         }
00261 
00262         shared_ptr<MotorWrapper> motor_wrapper = static_pointer_cast<MotorWrapper>(joint_tmp->actuator_wrapper);
00263 
00264         if (!this->nullify_demand_)
00265         {
00266           // We send the computed demand
00267           command->motor_data[motor_wrapper->motor_id] = motor_wrapper->actuator->command_.effort_;
00268         }
00269         else
00270         {
00271           // We want to send a demand of 0
00272           command->motor_data[motor_wrapper->motor_id] = 0;
00273         }
00274 
00275         joint_tmp->actuator_wrapper->actuator->state_.last_commanded_effort_ =
00276                 joint_tmp->actuator_wrapper->actuator->command_.effort_;
00277 
00278 #ifdef DEBUG_PUBLISHER
00279          // publish the debug values for the given motors.
00280          // NB: debug_motor_indexes_and_data is smaller
00281          //     than debug_publishers.
00282          int publisher_index = 0;
00283          shared_ptr<pair<int, int> > debug_pair;
00284          if (this->debug_mutex.try_lock())
00285          {
00286            BOOST_FOREACH(debug_pair, this->debug_motor_indexes_and_data)
00287            {
00288              if (debug_pair != NULL)
00289              {
00290                MotorWrapper* actuator_wrapper = static_cast<MotorWrapper*> (joint_tmp->actuator_wrapper.get());
00291                // check if we want to publish some data for the current motor
00292                if (debug_pair->first == actuator_wrapper->motor_id)
00293                {
00294                  // check if it's the correct data
00295                  if (debug_pair->second == -1)
00296                  {
00297                    this->msg_debug.data = joint_tmp->actuator_wrapper->actuator->command_.effort_;
00298                    this->debug_publishers[publisher_index].publish(this->msg_debug);
00299                  }
00300                }
00301              }
00302              publisher_index++;
00303            }
00304 
00305            this->debug_mutex.unlock();
00306          }  // end try_lock
00307 #endif
00308       }  // end for each joint
00309     }  // end if reconfig_queue.empty()
00310     else
00311     {
00312       if (!motor_system_control_flags_.empty())
00313       {
00314         // treat the first waiting system control and remove it from the queue
00315         vector<sr_robot_msgs::MotorSystemControls> system_controls_to_send;
00316         system_controls_to_send = motor_system_control_flags_.front();
00317         motor_system_control_flags_.pop();
00318 
00319         // set the correct type of command to send to the hand.
00320         command->to_motor_data_type = MOTOR_SYSTEM_CONTROLS;
00321 
00322         for (vector<sr_robot_msgs::MotorSystemControls>::iterator it = system_controls_to_send.begin();
00323              it != system_controls_to_send.end();
00324              ++it)
00325         {
00326           int16_t combined_flags = 0;
00327           if (it->enable_backlash_compensation)
00328           {
00329             combined_flags |= MOTOR_SYSTEM_CONTROL_BACKLASH_COMPENSATION_ENABLE;
00330           }
00331           else
00332           {
00333             combined_flags |= MOTOR_SYSTEM_CONTROL_BACKLASH_COMPENSATION_DISABLE;
00334           }
00335 
00336           if (it->increase_sgl_tracking)
00337           {
00338             combined_flags |= MOTOR_SYSTEM_CONTROL_SGL_TRACKING_INC;
00339           }
00340           if (it->decrease_sgl_tracking)
00341           {
00342             combined_flags |= MOTOR_SYSTEM_CONTROL_SGL_TRACKING_DEC;
00343           }
00344 
00345           if (it->increase_sgr_tracking)
00346           {
00347             combined_flags |= MOTOR_SYSTEM_CONTROL_SGR_TRACKING_INC;
00348           }
00349           if (it->decrease_sgr_tracking)
00350           {
00351             combined_flags |= MOTOR_SYSTEM_CONTROL_SGR_TRACKING_DEC;
00352           }
00353 
00354           if (it->initiate_jiggling)
00355           {
00356             combined_flags |= MOTOR_SYSTEM_CONTROL_INITIATE_JIGGLING;
00357           }
00358 
00359           if (it->write_config_to_eeprom)
00360           {
00361             combined_flags |= MOTOR_SYSTEM_CONTROL_EEPROM_WRITE;
00362           }
00363 
00364           command->motor_data[it->motor_id] = combined_flags;
00365         }
00366       }  // end if motor_system_control_flags_.empty
00367       else
00368       {
00369         if (!reset_motors_queue.empty())
00370         {
00371           // reset the CAN messages counters for the motor we're going to reset.
00372           int16_t motor_id = reset_motors_queue.front();
00373 
00374           for (vector<Joint>::iterator joint_tmp = this->joints_vector.begin();
00375                joint_tmp != this->joints_vector.end();
00376                ++joint_tmp)
00377           {
00378             if (!joint_tmp->has_actuator)
00379             {
00380               continue;
00381             }
00382 
00383             shared_ptr<MotorWrapper> motor_wrapper = static_pointer_cast<MotorWrapper>(joint_tmp->actuator_wrapper);
00384             SrMotorActuator *actuator = this->get_joint_actuator(joint_tmp);
00385 
00386             if (motor_wrapper->motor_id == motor_id)
00387             {
00388               actuator->motor_state_.can_msgs_transmitted_ = 0;
00389               actuator->motor_state_.can_msgs_received_ = 0;
00390             }
00391           }
00392 
00393           // we have some reset command waiting.
00394           // We'll send all of them
00395           command->to_motor_data_type = MOTOR_SYSTEM_RESET;
00396 
00397           while (!reset_motors_queue.empty())
00398           {
00399             motor_id = reset_motors_queue.front();
00400             reset_motors_queue.pop();
00401 
00402             // we send the MOTOR_RESET_SYSTEM_KEY
00403             // and the motor id (on the bus)
00404             crc_unions::union16 to_send;
00405             to_send.byte[1] = MOTOR_SYSTEM_RESET_KEY >> 8;
00406             if (motor_id > 9)
00407             {
00408               to_send.byte[0] = motor_id - 10;
00409             }
00410             else
00411             {
00412               to_send.byte[0] = motor_id;
00413             }
00414 
00415             command->motor_data[motor_id] = to_send.word;
00416           }
00417         }  // end if reset queue not empty
00418         else
00419         {
00420           if (!reconfig_queue.empty())
00421           {
00422             // we have a waiting config:
00423             // we need to send all the config, finishing by the
00424             // CRC. We'll remove the config from the queue only
00425             // when the whole config has been sent
00426 
00427             // the motor data type correspond to the index
00428             // in the config array.
00429             command->to_motor_data_type = static_cast<TO_MOTOR_DATA_TYPE> (config_index);
00430 
00431             // convert the motor index to the index of the motor in the message
00432             int motor_index = reconfig_queue.front().first;
00433 
00434             // set the data we want to send to the given motor
00435             command->motor_data[motor_index] = reconfig_queue.front().second[config_index].word;
00436 
00437             // We're now sending the CRC. We need to send the correct CRC to
00438             // the motor we updated, and CRC=0 to all the other motors in its
00439             // group (odd/even) to tell them to ignore the new
00440             // configuration.
00441             // Once the config has been transmitted, pop the element
00442             // and reset the config_index to the beginning of the
00443             // config values
00444             if (config_index == static_cast<int> (MOTOR_CONFIG_CRC))
00445             {
00446               // loop on all the motors and send a CRC of 0
00447               // except for the motor we're reconfiguring
00448               for (int i = 0; i < NUM_MOTORS; ++i)
00449               {
00450                 if (i != motor_index)
00451                 {
00452                   command->motor_data[i] = 0;
00453                 }
00454               }
00455 
00456               // reset the config_index and remove the configuration
00457               // we just sent from the configurations queue
00458               reconfig_queue.pop();
00459               config_index = MOTOR_CONFIG_FIRST_VALUE;
00460             }
00461             else
00462             {
00463               ++config_index;
00464             }
00465           }  // end if reconfig queue not empty
00466         }  // end else reset_queue.empty
00467       }  // end else motor_system_control_flags_.empty
00468     }  // end else reconfig_queue.empty() && reset_queue.empty()
00469   }
00470 
00471   template<class StatusType, class CommandType>
00472   void SrMotorRobotLib<StatusType, CommandType>::add_diagnostics(vector<diagnostic_msgs::DiagnosticStatus> &vec,
00473                                                                  diagnostic_updater::DiagnosticStatusWrapper &d)
00474   {
00475     for (vector<Joint>::iterator joint = this->joints_vector.begin();
00476          joint != this->joints_vector.end();
00477          ++joint)
00478     {
00479       ostringstream name("");
00480       string prefix = this->device_id_.empty() ? this->device_id_ : (this->device_id_ + " ");
00481       name << prefix << "SRDMotor " << joint->joint_name;
00482       d.name = name.str();
00483 
00484       if (joint->has_actuator)
00485       {
00486         shared_ptr<MotorWrapper> actuator_wrapper = static_pointer_cast<MotorWrapper>(joint->actuator_wrapper);
00487         SrMotorActuator *actuator = this->get_joint_actuator(joint);
00488 
00489         if (actuator_wrapper->actuator_ok)
00490         {
00491           if (actuator_wrapper->bad_data)
00492           {
00493             d.summary(d.WARN, "WARNING, bad CAN data received");
00494 
00495             d.clear();
00496             d.addf("Motor ID", "%d", actuator_wrapper->motor_id);
00497           }
00498           else  // the data is good
00499           {
00500             d.summary(d.OK, "OK");
00501 
00502             d.clear();
00503             d.addf("Motor ID", "%d", actuator_wrapper->motor_id);
00504             d.addf("Motor ID in message", "%d", actuator_wrapper->msg_motor_id);
00505             d.addf("Serial Number", "%d", actuator->motor_state_.serial_number);
00506             d.addf("Assembly date", "%d / %d / %d",
00507                    actuator->motor_state_.assembly_data_day,
00508                    actuator->motor_state_.assembly_data_month,
00509                    actuator->motor_state_.assembly_data_year);
00510 
00511             d.addf("Strain Gauge Left", "%d", actuator->motor_state_.strain_gauge_left_);
00512             d.addf("Strain Gauge Right", "%d", actuator->motor_state_.strain_gauge_right_);
00513 
00514             // if some flags are set
00515             ostringstream ss;
00516             if (actuator->motor_state_.flags_.size() > 0)
00517             {
00518               int flags_seriousness = d.OK;
00519               pair<string, bool> flag;
00520 
00521               BOOST_FOREACH(flag, actuator->motor_state_.flags_)
00522                     {
00523                       // Serious error flag
00524                       if (flag.second)
00525                       {
00526                         flags_seriousness = d.ERROR;
00527                       }
00528 
00529                       if (flags_seriousness != d.ERROR)
00530                       {
00531                         flags_seriousness = d.WARN;
00532                       }
00533                       ss << flag.first << " | ";
00534                     }
00535               d.summary(flags_seriousness, ss.str().c_str());
00536             }
00537             else
00538             {
00539               ss << " None";
00540             }
00541             d.addf("Motor Flags", "%s", ss.str().c_str());
00542 
00543             d.addf("Measured PWM", "%d", actuator->motor_state_.pwm_);
00544             d.addf("Measured Current", "%f", actuator->state_.last_measured_current_);
00545             d.addf("Measured Voltage", "%f", actuator->state_.motor_voltage_);
00546             d.addf("Measured Effort", "%f", actuator->state_.last_measured_effort_);
00547             d.addf("Temperature", "%f", actuator->motor_state_.temperature_);
00548 
00549             d.addf("Unfiltered position", "%f", actuator->motor_state_.position_unfiltered_);
00550             d.addf("Unfiltered force", "%f", actuator->motor_state_.force_unfiltered_);
00551 
00552             d.addf("Gear Ratio", "%d", actuator->motor_state_.motor_gear_ratio);
00553 
00554             d.addf("Number of CAN messages received", "%lld", actuator->motor_state_.can_msgs_received_);
00555             d.addf("Number of CAN messages transmitted", "%lld", actuator->motor_state_.can_msgs_transmitted_);
00556 
00557             d.addf("Force control Pterm", "%d", actuator->motor_state_.force_control_pterm);
00558             d.addf("Force control Iterm", "%d", actuator->motor_state_.force_control_iterm);
00559             d.addf("Force control Dterm", "%d", actuator->motor_state_.force_control_dterm);
00560 
00561             d.addf("Force control F", "%d", actuator->motor_state_.force_control_f_);
00562             d.addf("Force control P", "%d", actuator->motor_state_.force_control_p_);
00563             d.addf("Force control I", "%d", actuator->motor_state_.force_control_i_);
00564             d.addf("Force control D", "%d", actuator->motor_state_.force_control_d_);
00565             d.addf("Force control Imax", "%d", actuator->motor_state_.force_control_imax_);
00566             d.addf("Force control Deadband", "%d", actuator->motor_state_.force_control_deadband_);
00567             d.addf("Force control Frequency", "%d", actuator->motor_state_.force_control_frequency_);
00568 
00569             if (actuator->motor_state_.force_control_sign_ == 0)
00570             {
00571               d.addf("Force control Sign", "+");
00572             }
00573             else
00574             {
00575               d.addf("Force control Sign", "-");
00576             }
00577 
00578             d.addf("Last Commanded Effort", "%f", actuator->state_.last_commanded_effort_);
00579 
00580             d.addf("Encoder Position", "%f", actuator->state_.position_);
00581 
00582             if (actuator->motor_state_.firmware_modified_)
00583             {
00584               d.addf("Firmware git revision (server / pic / modified)", "%d / %d / True",
00585                      actuator->motor_state_.server_firmware_git_revision_,
00586                      actuator->motor_state_.pic_firmware_git_revision_);
00587             }
00588             else
00589             {
00590               d.addf("Firmware git revision (server / pic / modified)", "%d / %d / False",
00591                      actuator->motor_state_.server_firmware_git_revision_,
00592                      actuator->motor_state_.pic_firmware_git_revision_);
00593             }
00594           }
00595         }
00596         else
00597         {
00598           d.summary(d.ERROR, "Motor error");
00599           d.clear();
00600           d.addf("Motor ID", "%d", actuator_wrapper->motor_id);
00601         }
00602       }
00603       else
00604       {
00605         d.summary(d.OK, "No motor associated to this joint");
00606         d.clear();
00607       }
00608       vec.push_back(d);
00609     }  // end for each joints
00610   }
00611 
00612   template<class StatusType, class CommandType>
00613   void SrMotorRobotLib<StatusType, CommandType>::read_additional_data(vector<Joint>::iterator joint_tmp,
00614                                                                       StatusType *status_data)
00615   {
00616     if (!joint_tmp->has_actuator)
00617     {
00618       return;
00619     }
00620 
00621     // check the masks to see if the CAN messages arrived to the motors
00622     // the flag should be set to 1 for each motor
00623     joint_tmp->actuator_wrapper->actuator_ok = sr_math_utils::is_bit_mask_index_true(
00624             status_data->which_motor_data_arrived,
00625             motor_index_full);
00626 
00627     // check the masks to see if a bad CAN message arrived
00628     // the flag should be 0
00629     joint_tmp->actuator_wrapper->bad_data = sr_math_utils::is_bit_mask_index_true(
00630             status_data->which_motor_data_had_errors,
00631             index_motor_in_msg);
00632 
00633     crc_unions::union16 tmp_value;
00634 
00635     if (joint_tmp->actuator_wrapper->actuator_ok && !(joint_tmp->actuator_wrapper->bad_data))
00636     {
00637       SrMotorActuator *actuator = static_cast<SrMotorActuator *> (joint_tmp->actuator_wrapper->actuator);
00638       MotorWrapper *actuator_wrapper = static_cast<MotorWrapper *> (joint_tmp->actuator_wrapper.get());
00639 
00640 #ifdef DEBUG_PUBLISHER
00641       int publisher_index = 0;
00642       // publish the debug values for the given motors.
00643       // NB: debug_motor_indexes_and_data is smaller
00644       //     than debug_publishers.
00645       shared_ptr<pair<int, int> > debug_pair;
00646 
00647       if (this->debug_mutex.try_lock())
00648       {
00649         BOOST_FOREACH(debug_pair, this->debug_motor_indexes_and_data)
00650         {
00651           if (debug_pair != NULL)
00652           {
00653             MotorWrapper* actuator_wrapper = static_cast<MotorWrapper*> (joint_tmp->actuator_wrapper.get());
00654 
00655             // check if we want to publish some data for the current motor
00656             if (debug_pair->first == actuator_wrapper->motor_id)
00657             {
00658               // if < 0, then we're not asking for a FROM_MOTOR_DATA_TYPE
00659               if (debug_pair->second > 0)
00660               {
00661                 // check if it's the correct data
00662                 if (debug_pair->second == status_data->motor_data_type)
00663                 {
00664                   this->msg_debug.data = status_data->motor_data_packet[index_motor_in_msg].misc;
00665                   this->debug_publishers[publisher_index].publish(this->msg_debug);
00666                 }
00667               }
00668             }
00669           }
00670           publisher_index++;
00671         }
00672 
00673         this->debug_mutex.unlock();
00674       }  // end try_lock
00675 #endif
00676 
00677       // we received the data and it was correct
00678       bool read_torque = true;
00679       switch (status_data->motor_data_type)
00680       {
00681         case MOTOR_DATA_SGL:
00682           actuator->motor_state_.strain_gauge_left_ =
00683                   static_cast<int16s> (status_data->motor_data_packet[index_motor_in_msg].misc);
00684 
00685 #ifdef DEBUG_PUBLISHER
00686         if (actuator_wrapper->motor_id == 19)
00687         {
00688          // ROS_ERROR_STREAM("SGL " <<actuator->motor_state_.strain_gauge_left_);
00689           this->msg_debug.data = actuator->motor_state_.strain_gauge_left_;
00690           this->debug_publishers[0].publish(this->msg_debug);
00691         }
00692 #endif
00693           break;
00694         case MOTOR_DATA_SGR:
00695           actuator->motor_state_.strain_gauge_right_ =
00696                   static_cast<int16s> (status_data->motor_data_packet[index_motor_in_msg].misc);
00697 
00698 #ifdef DEBUG_PUBLISHER
00699         if (actuator_wrapper->motor_id == 19)
00700         {
00701          // ROS_ERROR_STREAM("SGR " <<actuator->motor_state_.strain_gauge_right_);
00702           this->msg_debug.data = actuator->motor_state_.strain_gauge_right_;
00703           this->debug_publishers[1].publish(this->msg_debug);
00704         }
00705 #endif
00706           break;
00707         case MOTOR_DATA_PWM:
00708           actuator->motor_state_.pwm_ =
00709                   static_cast<int> (static_cast<int16s> (status_data->motor_data_packet[index_motor_in_msg].misc));
00710 
00711 #ifdef DEBUG_PUBLISHER
00712         if (actuator_wrapper->motor_id == 19)
00713         {
00714          // ROS_ERROR_STREAM("SGR " <<actuator->motor_state_.strain_gauge_right_);
00715           this->msg_debug.data = actuator->motor_state_.pwm_;
00716           this->debug_publishers[2].publish(this->msg_debug);
00717         }
00718 #endif
00719           break;
00720         case MOTOR_DATA_FLAGS:
00721           actuator->motor_state_.flags_ = humanize_flags(status_data->motor_data_packet[index_motor_in_msg].misc);
00722           break;
00723         case MOTOR_DATA_CURRENT:
00724           // we're receiving the current in milli amps
00725           actuator->state_.last_measured_current_ =
00726                   static_cast<double> (static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc))
00727                   / 1000.0;
00728 
00729 #ifdef DEBUG_PUBLISHER
00730         if (actuator_wrapper->motor_id == 19)
00731         {
00732          // ROS_ERROR_STREAM("Current " <<actuator->motor_state_.last_measured_current_);
00733           this->msg_debug.data = static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc);
00734           this->debug_publishers[3].publish(this->msg_debug);
00735         }
00736 #endif
00737           break;
00738         case MOTOR_DATA_VOLTAGE:
00739           actuator->state_.motor_voltage_ =
00740                   static_cast<double> (static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc)) /
00741                   256.0;
00742 
00743 #ifdef DEBUG_PUBLISHER
00744         if (actuator_wrapper->motor_id == 19)
00745         {
00746          // ROS_ERROR_STREAM("Voltage " <<actuator->motor_state_.motor_voltage_);
00747           this->msg_debug.data = static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc);
00748           this->debug_publishers[4].publish(this->msg_debug);
00749         }
00750 #endif
00751           break;
00752         case MOTOR_DATA_TEMPERATURE:
00753           actuator->motor_state_.temperature_ =
00754                   static_cast<double> (static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc)) /
00755                   256.0;
00756           break;
00757         case MOTOR_DATA_CAN_NUM_RECEIVED:
00758           // those are 16 bits values and will overflow -> we compute the real value.
00759           // This needs to be updated faster than the overflowing period (which should be roughly every 30s)
00760           actuator->motor_state_.can_msgs_received_ = sr_math_utils::counter_with_overflow(
00761                   actuator->motor_state_.can_msgs_received_,
00762                   static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00763           break;
00764         case MOTOR_DATA_CAN_NUM_TRANSMITTED:
00765           // those are 16 bits values and will overflow -> we compute the real value.
00766           // This needs to be updated faster than the overflowing period (which should be roughly every 30s)
00767           actuator->motor_state_.can_msgs_transmitted_ = sr_math_utils::counter_with_overflow(
00768                   actuator->motor_state_.can_msgs_transmitted_,
00769                   static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00770           break;
00771 
00772         case MOTOR_DATA_SLOW_MISC:
00773           // We received a slow data:
00774           // the slow data type is contained in .torque, while
00775           // the actual data is in .misc.
00776           // so we won't read torque information from .torque
00777           read_torque = false;
00778 
00779           switch (static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].torque))
00780           {
00781             case MOTOR_SLOW_DATA_SVN_REVISION:
00782               actuator->motor_state_.pic_firmware_git_revision_ =
00783                       static_cast<unsigned int> (
00784                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00785               break;
00786             case MOTOR_SLOW_DATA_SVN_SERVER_REVISION:
00787               actuator->motor_state_.server_firmware_git_revision_ =
00788                       static_cast<unsigned int> (
00789                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00790               break;
00791             case MOTOR_SLOW_DATA_SVN_MODIFIED:
00792               actuator->motor_state_.firmware_modified_ =
00793                       static_cast<bool> (
00794                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00795               break;
00796             case MOTOR_SLOW_DATA_SERIAL_NUMBER_LOW:
00797               actuator->motor_state_.set_serial_number_low(
00798                       static_cast<unsigned int> (
00799                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc)));
00800               break;
00801             case MOTOR_SLOW_DATA_SERIAL_NUMBER_HIGH:
00802               actuator->motor_state_.set_serial_number_high(
00803                       static_cast<unsigned int> (
00804                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc)));
00805               break;
00806             case MOTOR_SLOW_DATA_GEAR_RATIO:
00807               actuator->motor_state_.motor_gear_ratio =
00808                       static_cast<unsigned int> (
00809                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00810               break;
00811             case MOTOR_SLOW_DATA_ASSEMBLY_DATE_YYYY:
00812               actuator->motor_state_.assembly_data_year =
00813                       static_cast<unsigned int> (
00814                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00815               break;
00816             case MOTOR_SLOW_DATA_ASSEMBLY_DATE_MMDD:
00817               actuator->motor_state_.assembly_data_month =
00818                       static_cast<unsigned int> (
00819                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc)
00820                               >> 8);
00821               actuator->motor_state_.assembly_data_day =
00822                       static_cast<unsigned int> (
00823                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc)
00824                               && 0x00FF);
00825               break;
00826             case MOTOR_SLOW_DATA_CONTROLLER_F:
00827               actuator->motor_state_.force_control_f_ =
00828                       static_cast<unsigned int> (
00829                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00830               break;
00831             case MOTOR_SLOW_DATA_CONTROLLER_P:
00832               actuator->motor_state_.force_control_p_ =
00833                       static_cast<unsigned int> (
00834                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00835               break;
00836             case MOTOR_SLOW_DATA_CONTROLLER_I:
00837               actuator->motor_state_.force_control_i_ =
00838                       static_cast<unsigned int> (
00839                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00840               break;
00841             case MOTOR_SLOW_DATA_CONTROLLER_D:
00842               actuator->motor_state_.force_control_d_ =
00843                       static_cast<unsigned int> (
00844                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00845               break;
00846             case MOTOR_SLOW_DATA_CONTROLLER_IMAX:
00847               actuator->motor_state_.force_control_imax_ =
00848                       static_cast<unsigned int> (
00849                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00850               break;
00851             case MOTOR_SLOW_DATA_CONTROLLER_DEADSIGN:
00852               tmp_value.word = status_data->motor_data_packet[index_motor_in_msg].misc;
00853               actuator->motor_state_.force_control_deadband_ = static_cast<int> (tmp_value.byte[0]);
00854               actuator->motor_state_.force_control_sign_ = static_cast<int> (tmp_value.byte[1]);
00855               break;
00856             case MOTOR_SLOW_DATA_CONTROLLER_FREQUENCY:
00857               actuator->motor_state_.force_control_frequency_ =
00858                       static_cast<unsigned int> (
00859                               static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc));
00860               break;
00861 
00862             default:
00863               break;
00864           }
00865           break;
00866 
00867         case MOTOR_DATA_CAN_ERROR_COUNTERS:
00868           actuator->motor_state_.can_error_counters =
00869                   static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc);
00870           break;
00871         case MOTOR_DATA_PTERM:
00872           actuator->motor_state_.force_control_pterm =
00873                   static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc);
00874           break;
00875         case MOTOR_DATA_ITERM:
00876           actuator->motor_state_.force_control_iterm =
00877                   static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc);
00878           break;
00879         case MOTOR_DATA_DTERM:
00880           actuator->motor_state_.force_control_dterm =
00881                   static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].misc);
00882           break;
00883 
00884         default:
00885           break;
00886       }
00887 
00888       if (read_torque)
00889       {
00890         actuator->motor_state_.force_unfiltered_ =
00891                 static_cast<double> (static_cast<int16s> (status_data->motor_data_packet[index_motor_in_msg].torque));
00892 
00893 #ifdef DEBUG_PUBLISHER
00894         if (actuator_wrapper->motor_id == 19)
00895         {
00896           this->msg_debug.data = static_cast<int16s> (status_data->motor_data_packet[index_motor_in_msg].torque);
00897           this->debug_publishers[5].publish(this->msg_debug);
00898         }
00899 #endif
00900       }
00901 
00902       // Check the message to see if everything has already been received
00903       if (motor_current_state == operation_mode::device_update_state::INITIALIZATION)
00904       {
00905         if (motor_data_checker->check_message(
00906                 joint_tmp, status_data->motor_data_type,
00907                 static_cast<int16u> (status_data->motor_data_packet[index_motor_in_msg].torque)))
00908         {
00909           motor_updater_->update_state = operation_mode::device_update_state::OPERATION;
00910           motor_current_state = operation_mode::device_update_state::OPERATION;
00911 
00912           ROS_INFO("All motors were initialized.");
00913         }
00914       }
00915     }
00916   }
00917 
00918   template<class StatusType, class CommandType>
00919   void SrMotorRobotLib<StatusType, CommandType>::calibrate_joint(vector<Joint>::iterator joint_tmp,
00920                                                                  StatusType *status_data)
00921   {
00922     SrMotorActuator *actuator = get_joint_actuator(joint_tmp);
00923 
00924     actuator->motor_state_.raw_sensor_values_.clear();
00925     actuator->motor_state_.calibrated_sensor_values_.clear();
00926 
00927     if (joint_tmp->joint_to_sensor.calibrate_after_combining_sensors)
00928     {
00929       // first we combine the different sensors and then we
00930       // calibrate the value we obtained. This is used for
00931       // some compound sensors ( THJ5 = cal(THJ5A + THJ5B))
00932       double raw_position = 0.0;
00933       // when combining the values, we use the coefficient imported
00934       // from the sensor_to_joint.yaml file (in sr_edc_launch/config)
00935 
00936       BOOST_FOREACH(PartialJointToSensor joint_to_sensor, joint_tmp->joint_to_sensor.joint_to_sensor_vector)
00937             {
00938               int tmp_raw = status_data->sensors[joint_to_sensor.sensor_id];
00939               actuator->motor_state_.raw_sensor_values_.push_back(tmp_raw);
00940               raw_position += static_cast<double> (tmp_raw) * joint_to_sensor.coeff;
00941             }
00942 
00943       // and now we calibrate
00944       this->calibration_tmp = this->calibration_map.find(joint_tmp->joint_name);
00945       actuator->motor_state_.position_unfiltered_ = this->calibration_tmp->compute(static_cast<double> (raw_position));
00946     }
00947     else
00948     {
00949       // we calibrate the different sensors first and we combine the calibrated
00950       // values. This is used in the joint 0s for example ( J0 = cal(J1)+cal(J2) )
00951       double calibrated_position = 0.0;
00952       PartialJointToSensor joint_to_sensor;
00953       string sensor_name;
00954 
00955       ROS_DEBUG_STREAM("Combining actuator " << joint_tmp->joint_name);
00956 
00957       for (unsigned int index_joint_to_sensor = 0;
00958            index_joint_to_sensor < joint_tmp->joint_to_sensor.joint_to_sensor_vector.size();
00959            ++index_joint_to_sensor)
00960       {
00961         joint_to_sensor = joint_tmp->joint_to_sensor.joint_to_sensor_vector[index_joint_to_sensor];
00962         sensor_name = joint_tmp->joint_to_sensor.sensor_names[index_joint_to_sensor];
00963 
00964         // get the raw position
00965         int raw_pos = status_data->sensors[joint_to_sensor.sensor_id];
00966         // push the new raw values
00967         actuator->motor_state_.raw_sensor_values_.push_back(raw_pos);
00968 
00969         // calibrate and then combine
00970         this->calibration_tmp = this->calibration_map.find(sensor_name);
00971         double tmp_cal_value = this->calibration_tmp->compute(static_cast<double> (raw_pos));
00972 
00973         // push the new calibrated values.
00974         actuator->motor_state_.calibrated_sensor_values_.push_back(tmp_cal_value);
00975 
00976         calibrated_position += tmp_cal_value * joint_to_sensor.coeff;
00977 
00978         ROS_DEBUG_STREAM("      -> " << sensor_name << " raw = " << raw_pos << " calibrated = " << calibrated_position);
00979       }
00980       actuator->motor_state_.position_unfiltered_ = calibrated_position;
00981       ROS_DEBUG_STREAM("          => " << actuator->motor_state_.position_unfiltered_);
00982     }
00983   }  // end calibrate_joint()
00984 
00985   template<class StatusType, class CommandType>
00986   void SrMotorRobotLib<StatusType, CommandType>::process_position_sensor_data(vector<Joint>::iterator joint_tmp,
00987                                                                               StatusType *status_data, double timestamp)
00988   {
00989     SrMotorActuator *actuator = get_joint_actuator(joint_tmp);
00990 
00991     // calibrate the joint and update the position.
00992     calibrate_joint(joint_tmp, status_data);
00993 
00994     // filter the position and velocity
00995     pair<double, double> pos_and_velocity = joint_tmp->pos_filter.compute(actuator->motor_state_.position_unfiltered_,
00996                                                                           timestamp);
00997     // reset the position to the filtered value
00998     actuator->state_.position_ = pos_and_velocity.first;
00999     // set the velocity to the filtered velocity
01000     actuator->state_.velocity_ = pos_and_velocity.second;
01001   }
01002 
01003   template<class StatusType, class CommandType>
01004   vector<pair<string, bool> > SrMotorRobotLib<StatusType, CommandType>::humanize_flags(int flag)
01005   {
01006     vector<pair<string, bool> > flags;
01007 
01008     // 16 is the number of flags
01009     for (unsigned int i = 0; i < 16; ++i)
01010     {
01011       pair<string, bool> new_flag;
01012       // if the flag is set add the name
01013       if (sr_math_utils::is_bit_mask_index_true(flag, i))
01014       {
01015         if (sr_math_utils::is_bit_mask_index_true(SERIOUS_ERROR_FLAGS, i))
01016         {
01017           new_flag.second = true;
01018         }
01019         else
01020         {
01021           new_flag.second = false;
01022         }
01023 
01024         new_flag.first = error_flag_names[i];
01025         flags.push_back(new_flag);
01026       }
01027     }
01028     return flags;
01029   }
01030 
01031   template<class StatusType, class CommandType>
01032   void SrMotorRobotLib<StatusType, CommandType>::generate_force_control_config(int motor_index, int max_pwm,
01033                                                                                int sg_left, int sg_right, int f, int p,
01034                                                                                int i, int d, int imax, int deadband,
01035                                                                                int sign)
01036   {
01037     ROS_INFO_STREAM("Setting new pid values for motor" << motor_index <<
01038                     ": max_pwm=" << max_pwm <<
01039                     " sgleftref=" << sg_left <<
01040                     " sgrightref=" << sg_right <<
01041                     " f=" << f <<
01042                     " p=" << p <<
01043                     " i=" << i <<
01044                     " d=" << d <<
01045                     " imax=" << imax <<
01046                     " deadband=" << deadband <<
01047                     " sign=" << sign);
01048 
01049     // the vector is of the size of the TO_MOTOR_DATA_TYPE enum.
01050     // the value of the element at a given index is the value
01051     // for the given MOTOR_CONFIG.
01052     vector<crc_unions::union16> full_config(MOTOR_CONFIG_CRC + 1);
01053     crc_unions::union16 value;
01054 
01055     value.word = max_pwm;
01056     full_config.at(MOTOR_CONFIG_MAX_PWM) = value;
01057 
01058     value.byte[0] = sg_left;
01059     value.byte[1] = sg_right;
01060     full_config.at(MOTOR_CONFIG_SG_REFS) = value;
01061 
01062     value.word = f;
01063     full_config.at(MOTOR_CONFIG_F) = value;
01064 
01065     value.word = p;
01066     full_config.at(MOTOR_CONFIG_P) = value;
01067 
01068     value.word = i;
01069     full_config.at(MOTOR_CONFIG_I) = value;
01070 
01071     value.word = d;
01072     full_config.at(MOTOR_CONFIG_D) = value;
01073 
01074     value.word = imax;
01075     full_config.at(MOTOR_CONFIG_IMAX) = value;
01076 
01077     value.byte[0] = deadband;
01078     value.byte[1] = sign;
01079     full_config.at(MOTOR_CONFIG_DEADBAND_SIGN) = value;
01080     ROS_DEBUG_STREAM("deadband: " << static_cast<int> (static_cast<int8u> (value.byte[0])) << " value: " <<
01081                      static_cast<int16u> (value.word));
01082 
01083     // compute crc
01084     crc_result = 0;
01085     for (unsigned int i = MOTOR_CONFIG_FIRST_VALUE; i <= MOTOR_CONFIG_LAST_VALUE; ++i)
01086     {
01087       crc_byte = full_config.at(i).byte[0];
01088       INSERT_CRC_CALCULATION_HERE;
01089 
01090       crc_byte = full_config.at(i).byte[1];
01091       INSERT_CRC_CALCULATION_HERE;
01092     }
01093 
01094     // never send a CRC of 0, send 1 if the
01095     // computed CRC is 0 (0 is a code for
01096     // ignoring the config)
01097     if (crc_result == 0)
01098     {
01099       crc_result = 1;
01100     }
01101     value.word = crc_result;
01102     full_config.at(MOTOR_CONFIG_CRC) = value;
01103 
01104     ForceConfig config;
01105     config.first = motor_index;
01106     config.second = full_config;
01107     // push the new config to the configuration queue
01108     reconfig_queue.push(config);
01109   }
01110 
01111   template<class StatusType, class CommandType>
01112   void SrMotorRobotLib<StatusType, CommandType>::reinitialize_motors()
01113   {
01114     // Create a new MotorUpdater object
01115     motor_updater_ = shared_ptr<MotorUpdater<CommandType> >(
01116             new MotorUpdater<CommandType>(motor_update_rate_configs_vector,
01117                                           operation_mode::device_update_state::INITIALIZATION));
01118     motor_current_state = operation_mode::device_update_state::INITIALIZATION;
01119     // Initialize the motor data checker
01120     motor_data_checker = shared_ptr<MotorDataChecker>(
01121             new MotorDataChecker(this->joints_vector, motor_updater_->initialization_configs_vector));
01122   }
01123 
01124   template<class StatusType, class CommandType>
01125   bool SrMotorRobotLib<StatusType, CommandType>::change_control_type_callback_(
01126           sr_robot_msgs::ChangeControlType::Request &request,
01127           sr_robot_msgs::ChangeControlType::Response &response)
01128   {
01129     // querying which we're control type we're using currently.
01130     if (request.control_type.control_type == sr_robot_msgs::ControlType::QUERY)
01131     {
01132       response.result = control_type_;
01133       return true;
01134     }
01135 
01136     // We're not querying the control type
01137     if ((request.control_type.control_type != sr_robot_msgs::ControlType::PWM) &&
01138         (request.control_type.control_type != sr_robot_msgs::ControlType::FORCE))
01139     {
01140       string ctrl_type_text = "";
01141       if (control_type_.control_type == sr_robot_msgs::ControlType::FORCE)
01142       {
01143         ctrl_type_text = "FORCE";
01144       }
01145       else
01146       {
01147         ctrl_type_text = "PWM";
01148       }
01149 
01150       ROS_ERROR_STREAM(" The value you specified for the control type (" << request.control_type
01151                        << ") is incorrect. Using " << ctrl_type_text << " control.");
01152 
01153       response.result = control_type_;
01154       return false;
01155     }
01156 
01157     if (control_type_.control_type != request.control_type.control_type)
01158     {
01159       // Mutual exclusion with the build_command() function.
01160       // We have to wait until the current motor command has been built.
01161       boost::mutex::scoped_lock l(*lock_command_sending_);
01162 
01163       ROS_WARN("Changing control type");
01164 
01165       control_type_ = request.control_type;
01166       // Flag to signal that there has been a change in the value of control_type_ and certain actions are required.
01167       // The flag is set in the callback function of the change_control_type_ service.
01168       // The flag is checked in build_command() and the necessary actions are taken there.
01169       // These actions involve calling services in the controller manager and all the active controllers. This is the
01170       // reason why we don't do it directly in the callback function. As we use a single thread to serve the callbacks,
01171       // doing so would cause a deadlock, thus we do it in the realtime loop thread instead.
01172       control_type_changed_flag_ = true;
01173     }
01174 
01175     response.result = control_type_;
01176     return true;
01177   }
01178 
01179   template<class StatusType, class CommandType>
01180   bool SrMotorRobotLib<StatusType, CommandType>::change_control_parameters(int16_t control_type)
01181   {
01182     bool success = true;
01183     string env_variable;
01184     string param_value;
01185 
01186     if (control_type == sr_robot_msgs::ControlType::PWM)
01187     {
01188       env_variable = "PWM_CONTROL=1";
01189       param_value = "PWM";
01190     }
01191     else
01192     {
01193       env_variable = "PWM_CONTROL=0";
01194       param_value = "FORCE";
01195     }
01196 
01197     string arguments = "";
01198 
01199     // Read the hand_id prefix from the parameter server
01200     // The hand_id will be passed as an argument to the sr_edc_default_controllers.launch
01201     // so that the parameters in it will be read from the correct files
01202     string hand_id = "";
01203     this->nodehandle_.template param<string>("hand_id", hand_id, "");
01204     ROS_DEBUG("hand_id: %s", hand_id.c_str());
01205     arguments += " hand_id:=" + hand_id;
01206     ROS_INFO("arguments: %s", arguments.c_str());
01207 
01208     int result = system((env_variable + " roslaunch sr_ethercat_hand_config sr_edc_default_controllers.launch" +
01209                          arguments).c_str());
01210 
01211     if (result == 0)
01212     {
01213       ROS_WARN("New parameters loaded successfully on Parameter Server");
01214 
01215       this->nh_tilde.setParam("default_control_mode", param_value);
01216 
01217       // We need another node handle here, that is at the node's base namespace,
01218       // as the controllers and the controller manager are unique per ethercat loop.
01219       ros::NodeHandle nh;
01220       ros::ServiceClient list_ctrl_client = nh.template serviceClient<controller_manager_msgs::ListControllers>(
01221               "controller_manager/list_controllers");
01222       controller_manager_msgs::ListControllers controllers_list;
01223 
01224       if (list_ctrl_client.call(controllers_list))
01225       {
01226         for (unsigned int i = 0; i < controllers_list.response.controller.size(); ++i)
01227         {
01228           if (controllers_list.response.controller[i].name.compare("joint_state_controller") == 0)
01229           {
01230             continue;
01231           }
01232           if (controllers_list.response.controller[i].name.find("trajectory_controller") != std::string::npos)
01233           {
01234             continue;
01235           }
01236           if (controllers_list.response.controller[i].name.find("sr_ur_controller") != std::string::npos)
01237           {
01238             continue;
01239           }
01240           if (controllers_list.response.controller[i].name.find("tactile_sensor_controller") != std::string::npos)
01241           {
01242             continue;
01243           }
01244           ros::ServiceClient reset_gains_client = nh.template serviceClient<std_srvs::Empty>(
01245                   controllers_list.response.controller[i].name + "/reset_gains");
01246           std_srvs::Empty empty_message;
01247           if (!reset_gains_client.call(empty_message))
01248           {
01249             ROS_ERROR_STREAM("Failed to reset gains for controller: " << controllers_list.response.controller[i].name);
01250             return false;
01251           }
01252         }
01253       }
01254       else
01255       {
01256         return false;
01257       }
01258     }
01259     else
01260     {
01261       return false;
01262     }
01263 
01264     return success;
01265   }
01266 
01267   template<class StatusType, class CommandType>
01268   bool SrMotorRobotLib<StatusType, CommandType>::motor_system_controls_callback_(
01269           sr_robot_msgs::ChangeMotorSystemControls::Request &request,
01270           sr_robot_msgs::ChangeMotorSystemControls::Response &response)
01271   {
01272     vector<sr_robot_msgs::MotorSystemControls> tmp_motor_controls;
01273 
01274     response.result = sr_robot_msgs::ChangeMotorSystemControls::Response::SUCCESS;
01275     bool no_motor_id_out_of_range = true;
01276 
01277     for (unsigned int i = 0; i < request.motor_system_controls.size(); ++i)
01278     {
01279       if (request.motor_system_controls[i].motor_id >= NUM_MOTORS ||
01280           request.motor_system_controls[i].motor_id < 0)
01281       {
01282         response.result = sr_robot_msgs::ChangeMotorSystemControls::Response::MOTOR_ID_OUT_OF_RANGE;
01283         no_motor_id_out_of_range = false;
01284       }
01285       else
01286       {
01287         // only pushes the demands with a correct motor_id
01288         tmp_motor_controls.push_back(request.motor_system_controls[i]);
01289       }
01290     }
01291 
01292     // add the request to the queue if it's not empty
01293     if (tmp_motor_controls.size() > 0)
01294     {
01295       motor_system_control_flags_.push(tmp_motor_controls);
01296     }
01297 
01298     return no_motor_id_out_of_range;
01299   }
01300 
01301   // Only to ensure that the template class is compiled for the types we are interested in
01302   template
01303   class SrMotorRobotLib<ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_STATUS, ETHERCAT_DATA_STRUCTURE_0200_PALM_EDC_COMMAND>;
01304 
01305   template
01306   class SrMotorRobotLib<ETHERCAT_DATA_STRUCTURE_0230_PALM_EDC_STATUS, ETHERCAT_DATA_STRUCTURE_0230_PALM_EDC_COMMAND>;
01307 }  // namespace shadow_robot
01308 
01309 /* For the emacs weenies in the crowd.
01310  Local Variables:
01311  c-basic-offset: 2
01312  End:
01313  */


sr_robot_lib
Author(s): Ugo Cupcic, Toni Oliver
autogenerated on Mon Jul 1 2019 20:06:26