32 #include <boost/foreach.hpp> 38 #include <controller_manager_msgs/ListControllers.h> 40 #define SERIOUS_ERROR_FLAGS PALM_0300_EDC_SERIOUS_ERROR_FLAGS 41 #define error_flag_names palm_0300_edc_error_flag_names 48 using std::ostringstream;
49 using sr_actuator::SrMuscleActuator;
59 using boost::static_pointer_cast;
64 template<
class StatusType,
class CommandType>
67 template<
class StatusType,
class CommandType>
70 string device_id,
string joint_prefix)
71 :
SrRobotLib<StatusType, CommandType>(hw, nh, nhtilde, device_id, joint_prefix),
76 check_init_timeout_timer(this->nh_tilde.createTimer(init_max_duration,
79 CommandType>::init_timer_callback,
81 pressure_calibration_map_(read_pressure_calibration())
83 #ifdef DEBUG_PUBLISHER 84 this->debug_muscle_indexes_and_data.resize(this->nb_debug_publishers_const);
85 for (
int i = 0; i < this->nb_debug_publishers_const; ++i)
88 ss <<
"srh/debug_" << i;
89 this->debug_publishers.push_back(this->node_handle.template advertise<std_msgs::Int16>(ss.str().c_str(), 100));
94 template<
class StatusType,
class CommandType>
97 ROS_INFO(
"Reading pressure calibration");
99 string param_name =
"sr_pressure_calibrations";
105 for (int32_t index_cal = 0; index_cal < calib.
size(); ++index_cal)
112 string joint_name =
static_cast<string> (calib[index_cal][0]);
113 vector<joint_calibration::Point> calib_table_tmp;
116 for (int32_t index_table = 0; index_table < calib[index_cal][1].
size(); ++index_table)
120 ROS_ASSERT(calib[index_cal][1][index_table].size() == 2);
125 joint_calibration::Point point_tmp;
126 point_tmp.raw_value =
static_cast<double> (calib[index_cal][1][index_table][0]);
127 point_tmp.calibrated_value =
static_cast<double> (calib[index_cal][1][index_table][1]);
128 calib_table_tmp.push_back(point_tmp);
132 new shadow_robot::JointCalibration(calib_table_tmp)));
135 return pressure_calibration;
138 template<
class StatusType,
class CommandType>
143 if (status_data->idle_time_us < this->main_pic_idle_time_min)
150 double timestamp = 0.0;
151 if (gettimeofday(&tv, NULL))
153 ROS_WARN(
"SrMuscleRobotLib: Failed to get system time, timestamp in state will be zero");
157 timestamp =
static_cast<double>(tv.tv_sec) + static_cast<double>(tv.tv_usec) / 1.0e+6;
172 for (vector<Joint>::iterator joint_tmp = this->
joints_vector.begin();
176 if (!joint_tmp->has_actuator)
187 actuator->muscle_state_.tactiles_ = this->
tactiles->get_tactile_data();
193 if ((muscle_wrapper->muscle_driver_id[0] == -1))
202 template<
class StatusType,
class CommandType>
227 for (vector<Joint>::iterator joint_tmp = this->
joints_vector.begin();
231 if (joint_tmp->has_actuator)
234 SrMuscleActuator *muscle_actuator =
static_cast<SrMuscleActuator *
> (muscle_wrapper->actuator);
236 unsigned int muscle_driver_id_0 = muscle_wrapper->muscle_driver_id[0];
237 unsigned int muscle_driver_id_1 = muscle_wrapper->muscle_driver_id[1];
238 unsigned int muscle_id_0 = muscle_wrapper->muscle_id[0];
239 unsigned int muscle_id_1 = muscle_wrapper->muscle_id[1];
243 set_valve_demand(&(command->muscle_data[(muscle_driver_id_0 * 10 + muscle_id_0) / 2]),
244 muscle_actuator->muscle_command_.valve_[0], ((uint8_t) muscle_id_0) & 0x01);
245 set_valve_demand(&(command->muscle_data[(muscle_driver_id_1 * 10 + muscle_id_1) / 2]),
246 muscle_actuator->muscle_command_.valve_[1], ((uint8_t) muscle_id_1) & 0x01);
248 muscle_actuator->muscle_state_.last_commanded_valve_[0] = muscle_actuator->muscle_command_.valve_[0];
249 muscle_actuator->muscle_state_.last_commanded_valve_[1] = muscle_actuator->muscle_command_.valve_[1];
254 set_valve_demand(&(command->muscle_data[(muscle_driver_id_0 * 10 + muscle_id_0) / 2]), 0,
255 ((uint8_t) muscle_id_0) & 0x01);
256 set_valve_demand(&(command->muscle_data[(muscle_driver_id_1 * 10 + muscle_id_1) / 2]), 0,
257 ((uint8_t) muscle_id_1) & 0x01);
259 muscle_actuator->muscle_state_.last_commanded_valve_[0] = 0;
260 muscle_actuator->muscle_state_.last_commanded_valve_[1] = 0;
263 #ifdef DEBUG_PUBLISHER 267 int publisher_index = 0;
269 if (this->debug_mutex.try_lock())
271 BOOST_FOREACH(debug_pair, this->debug_muscle_indexes_and_data)
273 if (debug_pair != NULL)
277 if (debug_pair->first == actuator_wrapper->
muscle_id[0])
280 if (debug_pair->second == -1)
282 this->msg_debug.data = joint_tmp->actuator_wrapper->
actuator->command_.effort_;
283 this->debug_publishers[publisher_index].publish(this->msg_debug);
290 this->debug_mutex.unlock();
312 if (driver->muscle_driver_id == muscle_driver_id)
314 driver->can_msgs_transmitted_ = 0;
315 driver->can_msgs_received_ = 0;
323 if (muscle_driver_id > 1)
325 to_send.
byte[0] = muscle_driver_id - 2;
329 to_send.
byte[0] = muscle_driver_id;
332 command->muscle_data[muscle_driver_id * 5] = to_send.
byte[0];
333 command->muscle_data[muscle_driver_id * 5 + 1] = to_send.
byte[1];
338 template<
class StatusType,
class CommandType>
340 int8_t valve_value, uint8_t shift)
342 uint8_t tmp_valve = 0;
350 tmp_valve = -valve_value;
352 tmp_valve = (~tmp_valve) & 0x0F;
354 tmp_valve = tmp_valve + 1;
358 tmp_valve = valve_value & 0x0F;
365 *muscle_data_byte_to_set &= (0xF0 >> (shift * 4));
367 *muscle_data_byte_to_set |= (tmp_valve << (shift * 4));
370 template<
class StatusType,
class CommandType>
374 for (vector<Joint>::iterator joint = this->
joints_vector.begin();
378 ostringstream name(
"");
380 name << prefix <<
"SRDMuscle " << joint->joint_name;
383 if (joint->has_actuator)
388 if (actuator_wrapper->actuator_ok)
390 if (actuator_wrapper->bad_data)
392 d.
summary(d.WARN,
"WARNING, bad CAN data received");
395 d.
addf(
"Muscle ID 0",
"%d", actuator_wrapper->muscle_id[0]);
396 d.
addf(
"Muscle driver ID 0",
"%d", actuator_wrapper->muscle_driver_id[0]);
397 d.
addf(
"Muscle ID 1",
"%d", actuator_wrapper->muscle_id[1]);
398 d.
addf(
"Muscle driver ID 1",
"%d", actuator_wrapper->muscle_driver_id[1]);
405 d.
addf(
"Muscle ID 0",
"%d", actuator_wrapper->muscle_id[0]);
406 d.
addf(
"Muscle driver ID 0",
"%d", actuator_wrapper->muscle_driver_id[0]);
407 d.
addf(
"Muscle ID 1",
"%d", actuator_wrapper->muscle_id[1]);
408 d.
addf(
"Muscle driver ID 1",
"%d", actuator_wrapper->muscle_driver_id[1]);
410 d.
addf(
"Unfiltered position",
"%f", actuator->muscle_state_.position_unfiltered_);
412 d.
addf(
"Last Commanded Valve 0",
"%d", actuator->muscle_state_.last_commanded_valve_[0]);
413 d.
addf(
"Last Commanded Valve 1",
"%d", actuator->muscle_state_.last_commanded_valve_[1]);
415 d.
addf(
"Unfiltered Pressure 0",
"%u", actuator->muscle_state_.pressure_[0]);
416 d.
addf(
"Unfiltered Pressure 1",
"%u", actuator->muscle_state_.pressure_[1]);
418 d.
addf(
"Position",
"%f", actuator->state_.position_);
423 d.
summary(d.ERROR,
"Muscle error");
425 d.
addf(
"Muscle ID 0",
"%d", actuator_wrapper->muscle_id[0]);
426 d.
addf(
"Muscle driver ID 0",
"%d", actuator_wrapper->muscle_driver_id[0]);
427 d.
addf(
"Muscle ID 1",
"%d", actuator_wrapper->muscle_id[1]);
428 d.
addf(
"Muscle driver ID 1",
"%d", actuator_wrapper->muscle_driver_id[1]);
433 d.
summary(d.OK,
"No muscle associated to this joint");
443 ostringstream name(
"");
444 name <<
"Muscle driver " << muscle_driver->muscle_driver_id;
447 if (muscle_driver->driver_ok)
449 if (muscle_driver->bad_data)
451 d.
summary(d.WARN,
"WARNING, bad CAN data received");
454 d.
addf(
"Muscle Driver ID",
"%d", muscle_driver->muscle_driver_id);
461 d.
addf(
"Muscle Driver ID",
"%d", muscle_driver->muscle_driver_id);
462 d.
addf(
"Serial Number",
"%d", muscle_driver->serial_number);
463 d.
addf(
"Assembly date",
"%d / %d / %d", muscle_driver->assembly_date_day, muscle_driver->assembly_date_month,
464 muscle_driver->assembly_date_year);
466 d.
addf(
"Number of CAN messages received",
"%lld", muscle_driver->can_msgs_received_);
467 d.
addf(
"Number of CAN messages transmitted",
"%lld", muscle_driver->can_msgs_transmitted_);
469 if (muscle_driver->firmware_modified_)
471 d.
addf(
"Firmware git revision (server / pic / modified)",
"%d / %d / True",
472 muscle_driver->server_firmware_git_revision_, muscle_driver->pic_firmware_git_revision_);
476 d.
addf(
"Firmware git revision (server / pic / modified)",
"%d / %d / False",
477 muscle_driver->server_firmware_git_revision_, muscle_driver->pic_firmware_git_revision_);
483 d.
summary(d.ERROR,
"Muscle Driver error");
485 d.
addf(
"Muscle Driver ID",
"%d", muscle_driver->muscle_driver_id);
492 template<
class StatusType,
class CommandType>
494 StatusType *status_data)
496 if (!joint_tmp->has_actuator)
501 int packet_offset_muscle_0 = 0;
502 int packet_offset_muscle_1 = 0;
509 packet_offset_muscle_0 = 1;
514 packet_offset_muscle_1 = 1;
521 muscle_wrapper->actuator_ok = sr_math_utils::is_bit_mask_index_true(status_data->which_muscle_data_arrived,
522 muscle_wrapper->muscle_driver_id[0] * 2 +
523 packet_offset_muscle_0)
524 && sr_math_utils::is_bit_mask_index_true(status_data->which_muscle_data_arrived,
525 muscle_wrapper->muscle_driver_id[1] * 2 +
526 packet_offset_muscle_1);
540 if (muscle_wrapper->actuator_ok)
542 SrMuscleActuator *actuator =
static_cast<SrMuscleActuator *
> (joint_tmp->actuator_wrapper->actuator);
545 #ifdef DEBUG_PUBLISHER 546 int publisher_index = 0;
552 if (this->debug_mutex.try_lock())
554 BOOST_FOREACH(debug_pair, this->debug_muscle_indexes_and_data)
556 if (debug_pair != NULL)
559 if (debug_pair->first == actuator_wrapper->
muscle_id[0])
562 if (debug_pair->second > 0)
565 if (debug_pair->second == status_data->muscle_data_type)
569 this->msg_debug.data = 0;
570 this->debug_publishers[publisher_index].publish(this->msg_debug);
578 this->debug_mutex.unlock();
584 switch (status_data->muscle_data_type)
588 for (
int i = 0; i < 2; ++i)
590 p1 =
get_muscle_pressure(muscle_wrapper->muscle_driver_id[i], muscle_wrapper->muscle_id[i], status_data);
591 string name = joint_tmp->joint_name +
"_" + boost::lexical_cast<
string>(i);
595 double bar = pressure_calibration_tmp_->compute(static_cast<double> (p1));
600 actuator->muscle_state_.pressure_[i] =
static_cast<int16u> (bar);
616 #ifdef DEBUG_PUBLISHER 633 template<
class StatusType,
class CommandType>
635 StatusType *status_data)
637 unsigned int muscle_pressure = 0;
638 int packet_offset = 0;
639 int muscle_index = muscle_id;
648 switch (muscle_index)
652 (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure0_H << 8)
653 + (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure0_M << 4)
654 + status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure0_L;
659 (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure1_H << 8)
660 + (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure1_M << 4)
661 + status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure1_L;
666 (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure2_H << 8)
667 + (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure2_M << 4)
668 + status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure2_L;
673 (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure3_H << 8)
674 + (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure3_M << 4)
675 + status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure3_L;
680 (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure4_H << 8)
681 + (status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure4_M << 4)
682 + status_data->muscle_data_packet[muscle_driver_id * 2 + packet_offset].packed.pressure4_L;
686 ROS_ERROR(
"Incorrect muscle index: %d", muscle_index);
690 return muscle_pressure;
693 template<
class StatusType,
class CommandType>
695 vector<MuscleDriver>::iterator muscle_driver_tmp, StatusType *status_data)
700 muscle_driver_tmp->driver_ok = sr_math_utils::is_bit_mask_index_true(status_data->which_muscle_data_arrived,
701 muscle_driver_tmp->muscle_driver_id * 2);
709 if (muscle_driver_tmp->driver_ok)
714 switch (status_data->muscle_data_type)
725 muscle_driver_tmp->can_msgs_received_ = sr_math_utils::counter_with_overflow(
726 muscle_driver_tmp->can_msgs_received_,
727 static_cast<int16u> (status_data->muscle_data_packet[muscle_driver_tmp->muscle_driver_id *
728 2].misc.can_msgs_rx));
729 muscle_driver_tmp->can_msgs_transmitted_ = sr_math_utils::counter_with_overflow(
730 muscle_driver_tmp->can_msgs_transmitted_,
731 static_cast<int16u> (status_data->muscle_data_packet[muscle_driver_tmp->muscle_driver_id *
732 2].misc.can_msgs_tx));
735 muscle_driver_tmp->can_err_rx =
static_cast<unsigned int> (status_data->muscle_data_packet[
736 muscle_driver_tmp->muscle_driver_id * 2].misc.can_err_rx);
737 muscle_driver_tmp->can_err_tx =
static_cast<unsigned int> (status_data->muscle_data_packet[
738 muscle_driver_tmp->muscle_driver_id * 2].misc.can_err_tx);
747 muscle_driver_tmp->pic_firmware_git_revision_ =
static_cast<unsigned int> (status_data->muscle_data_packet[
748 muscle_driver_tmp->muscle_driver_id * 2].slow_0.SVN_revision);
749 muscle_driver_tmp->server_firmware_git_revision_ =
static_cast<unsigned int> (status_data->muscle_data_packet[
750 muscle_driver_tmp->muscle_driver_id * 2].slow_0.SVN_server);
751 muscle_driver_tmp->firmware_modified_ =
752 static_cast<bool> (
static_cast<unsigned int> (status_data->muscle_data_packet[
753 muscle_driver_tmp->muscle_driver_id * 2].slow_0.SVN_modified));
755 muscle_driver_tmp->serial_number =
static_cast<unsigned int> (status_data->muscle_data_packet[
756 muscle_driver_tmp->muscle_driver_id * 2 + 1].slow_1.serial_number);
757 muscle_driver_tmp->assembly_date_year =
static_cast<unsigned int> (status_data->muscle_data_packet[
758 muscle_driver_tmp->muscle_driver_id * 2 + 1].slow_1.assembly_date_YYYY);
759 muscle_driver_tmp->assembly_date_month =
static_cast<unsigned int> (status_data->muscle_data_packet[
760 muscle_driver_tmp->muscle_driver_id * 2 + 1].slow_1.assembly_date_MM);
761 muscle_driver_tmp->assembly_date_day =
static_cast<unsigned int> (status_data->muscle_data_packet[
762 muscle_driver_tmp->muscle_driver_id * 2 + 1].slow_1.assembly_date_DD);
783 ROS_INFO(
"All muscle data initialized.");
789 template<
class StatusType,
class CommandType>
791 int muscle_driver_id)
798 it->second = it->second | (1 << muscle_driver_id);
803 template<
class StatusType,
class CommandType>
819 template<
class StatusType,
class CommandType>
821 StatusType *status_data)
825 actuator->muscle_state_.raw_sensor_values_.clear();
826 actuator->muscle_state_.calibrated_sensor_values_.clear();
828 if (joint_tmp->joint_to_sensor.calibrate_after_combining_sensors)
833 double raw_position = 0.0;
837 BOOST_FOREACH(
PartialJointToSensor joint_to_sensor, joint_tmp->joint_to_sensor.joint_to_sensor_vector)
839 int tmp_raw = status_data->sensors[joint_to_sensor.
sensor_id];
840 actuator->muscle_state_.raw_sensor_values_.push_back(tmp_raw);
841 raw_position +=
static_cast<double> (tmp_raw) * joint_to_sensor.
coeff;
846 actuator->muscle_state_.position_unfiltered_ = this->
calibration_tmp->compute(static_cast<double> (raw_position));
852 double calibrated_position = 0.0;
858 for (
unsigned int index_joint_to_sensor = 0;
859 index_joint_to_sensor < joint_tmp->joint_to_sensor.joint_to_sensor_vector.size();
860 ++index_joint_to_sensor)
862 joint_to_sensor = joint_tmp->joint_to_sensor.joint_to_sensor_vector[index_joint_to_sensor];
863 sensor_name = joint_tmp->joint_to_sensor.sensor_names[index_joint_to_sensor];
866 int raw_pos = status_data->sensors[joint_to_sensor.
sensor_id];
868 actuator->muscle_state_.raw_sensor_values_.push_back(raw_pos);
872 double tmp_cal_value = this->
calibration_tmp->compute(static_cast<double> (raw_pos));
875 actuator->muscle_state_.calibrated_sensor_values_.push_back(tmp_cal_value);
877 calibrated_position += tmp_cal_value * joint_to_sensor.
coeff;
879 ROS_DEBUG_STREAM(
" -> " << sensor_name <<
" raw = " << raw_pos <<
" calibrated = " << calibrated_position);
881 actuator->muscle_state_.position_unfiltered_ = calibrated_position;
886 template<
class StatusType,
class CommandType>
888 StatusType *status_data,
897 pair<double, double> pos_and_velocity = joint_tmp->pos_filter.compute(actuator->muscle_state_.position_unfiltered_,
900 actuator->state_.position_ = pos_and_velocity.first;
902 actuator->state_.velocity_ = pos_and_velocity.second;
905 template<
class StatusType,
class CommandType>
908 vector<pair<string, bool> > flags;
911 for (
unsigned int i = 0; i < 16; ++i)
913 pair<string, bool> new_flag;
915 if (sr_math_utils::is_bit_mask_index_true(flag, i))
919 new_flag.second =
true;
923 new_flag.second =
false;
927 flags.push_back(new_flag);
933 template<
class StatusType,
class CommandType>
951 template<
class StatusType,
class CommandType>
962 "Muscle Initialization Timeout: the static information in the diagnostics may not be up to date.");
void set_muscle_driver_data_received_flags(unsigned int msg_type, int muscle_driver_id)
std::queue< int16_t, std::list< int16_t > > reset_muscle_driver_queue
void init_timer_callback(const ros::TimerEvent &event)
std::vector< shadow_joints::MuscleDriver > muscle_drivers_vector_
#define MUSCLE_SYSTEM_RESET_KEY
std::vector< shadow_joints::Joint > joints_vector
The vector containing all the robot joints.
void summary(unsigned char lvl, const std::string s)
boost::shared_ptr< shadow_robot::JointCalibration > pressure_calibration_tmp_
A temporary calibration for a given joint.
#define SERIOUS_ERROR_FLAGS
void read_additional_muscle_data(std::vector< shadow_joints::Joint >::iterator joint_tmp, StatusType *status_data)
void setPeriod(const Duration &period, bool reset=true)
void build_command(CommandType *command)
ros::NodeHandle nodehandle_
a ros nodehandle to be able to access resources out of the node namespace
ros::Timer check_init_timeout_timer
virtual shadow_joints::CalibrationMap read_pressure_calibration()
void build_tactile_command(CommandType *command)
bool check_muscle_driver_data_received_flags()
shadow_joints::CalibrationMap calibration_map
The map used to calibrate each joint.
void set_valve_demand(uint8_t *muscle_data_byte_to_set, int8_t valve_value, uint8_t shifting_index)
Type const & getType() const
SrMuscleRobotLib(hardware_interface::HardwareInterface *hw, ros::NodeHandle nh, ros::NodeHandle nhtilde, std::string device_id, std::string joint_prefix)
void addf(const std::string &key, const char *format,...)
ros_ethercat_model::Actuator * actuator
std::map< unsigned int, unsigned int > from_muscle_driver_data_received_flags_
#define NUM_PRESSURE_SENSORS_PER_MESSAGE
boost::shared_ptr< shadow_robot::JointCalibration > calibration_tmp
A temporary calibration for a given joint.
operation_mode::device_update_state::DeviceUpdateState muscle_current_state
void process_position_sensor_data(std::vector< shadow_joints::Joint >::iterator joint_tmp, StatusType *status_data, double timestamp)
void read_muscle_driver_data(std::vector< shadow_joints::MuscleDriver >::iterator muscle_driver_tmp, StatusType *status_data)
#define ROS_DEBUG_STREAM(args)
static const double timeout
ros::Duration init_max_duration
boost::shared_ptr< generic_updater::MuscleUpdater< CommandType > > muscle_updater_
std::vector< std::pair< std::string, bool > > humanize_flags(int flag)
unsigned int get_muscle_pressure(int muscle_driver_id, int muscle_id, StatusType *status_data)
bool getParam(const std::string &key, std::string &s) const
std::string device_id_
Id of the ethercat device (alias)
void update_tactile_info(StatusType *status)
shadow_joints::CalibrationMap pressure_calibration_map_
The map used to calibrate each pressure sensor.
void calibrate_joint(std::vector< shadow_joints::Joint >::iterator joint_tmp, StatusType *status_data)
threadsafe::Map< boost::shared_ptr< shadow_robot::JointCalibration > > CalibrationMap
sr_actuator::SrMuscleActuator * get_joint_actuator(std::vector< shadow_joints::Joint >::iterator joint_tmp)
#define ROS_ERROR_STREAM(args)
void update(StatusType *status_data)
void reinitialize_motors()
std::vector< generic_updater::UpdateConfig > muscle_update_rate_configs_vector
#define NUM_MUSCLE_DRIVERS
int main_pic_idle_time_min
boost::shared_ptr< boost::mutex > lock_init_timeout_
int muscle_id[2]
id of the muscles for this joint (the id indicates the order from 0 to 9 of the muscle in its muscle ...
void add_diagnostics(std::vector< diagnostic_msgs::DiagnosticStatus > &vec, diagnostic_updater::DiagnosticStatusWrapper &d)