Go to the documentation of this file.
42 #include <dll/ethercat_dll.h>
43 #include <al/ethercat_AL.h>
44 #include <dll/ethercat_device_addressed_telegram.h>
45 #include <dll/ethercat_frame.h>
47 #include <boost/crc.hpp>
48 #include <boost/shared_ptr.hpp>
49 #include <boost/static_assert.hpp>
50 #include <boost/make_shared.hpp>
53 #define ERR_MODE "\033[41m"
54 #define STD_MODE "\033[0m"
55 #define WARN_MODE "\033[43m"
56 #define GOOD_MODE "\033[42m"
57 #define INFO_MODE "\033[44m"
59 #define ERROR_HDR "\033[41mERROR\033[0m"
60 #define WARN_HDR "\033[43mERROR\033[0m"
68 safety_disable_total_(0),
69 undervoltage_total_(0),
70 over_current_total_(0),
71 board_over_temp_total_(0),
72 bridge_over_temp_total_(0),
73 operate_disable_total_(0),
74 watchdog_disable_total_(0),
78 cached_zero_offset_(0)
137 boost::crc_32_type crc32_256, crc32_264;
140 return ((this->
crc32_264_ == crc32_264.checksum()) || (this->crc32_256_ == crc32_256.checksum()));
148 boost::crc_32_type crc32;
159 too_many_dropped_packets_(false),
160 status_checksum_error_(false),
161 timestamp_jump_detected_(false),
162 fpga_internal_reset_detected_(false),
163 encoder_errors_detected_(false),
164 cached_zero_offset_(0),
165 calibration_status_(NO_CALIBRATION),
166 app_ram_status_(APP_RAM_MISSING),
168 disable_motor_model_checking_(false)
185 ROS_ERROR(
"WG0X : init diagnostics mutex :%s", strerror(error));
192 delete sh_->get_fmmu_config();
193 delete sh_->get_pd_config();
203 fw_major_ = (sh->get_revision() >> 8) & 0xff;
223 out.name = std::string(in.
name_);
239 const string &device_description,
240 double max_pwm_ratio,
241 double board_resistance,
242 bool poor_measured_motor_voltage)
253 unsigned product_code =
sh_->get_product_code();
254 ethercat_hardware::BoardInfo bi;
255 bi.description = device_description;
256 bi.product_code = product_code;
259 bi.serial =
sh_->get_serial();
262 bi.board_resistance = board_resistance;
263 bi.max_pwm_ratio = max_pwm_ratio;
265 bi.poor_measured_motor_voltage = poor_measured_motor_voltage;
287 ROS_WARN(
"Disabling motor model on %s", ai.name.c_str());
303 ROS_FATAL(
"Unable to read motor heating model config parameters from EEPROM");
311 if (allow_unprogrammed)
313 ROS_WARN(
"%s EEPROM does not contain motor heating model parameters",
319 ROS_WARN(
"%s EEPROM does not contain motor heating model parameters",
323 ROS_FATAL(
"%s EEPROM does not contain motor heating model parameters",
343 std::ostringstream hwid;
344 hwid << unsigned(
sh_->get_product_code()) << std::setw(5) << std::setfill(
'0') << unsigned(
sh_->get_serial());
355 ROS_WARN(
"Motor heating model disabled for all devices");
359 ROS_WARN(
"Not loading motor heating model files");
363 ROS_WARN(
"Not saving motor heating model files");
373 boost::make_shared<ethercat_hardware::MotorHeatingModel>(config.
params_,
397 ROS_DEBUG(
"Device #%02d: WG0%d (%#08x) Firmware Revision %d.%02d, PCB Revision %c.%02d, Serial #: %d",
398 sh_->get_ring_position(),
399 sh_->get_product_code() % 100,
427 ROS_FATAL(
"Unable to load configuration information");
435 ROS_FATAL(
"Unable to read actuator info from EEPROM");
443 if (allow_unprogrammed)
470 ROS_FATAL(
"An actuator of the name '%s' already exists. Device #%02d has a duplicate name",
actuator_.
name_.c_str(),
sh_->get_ring_position());
480 ROS_FATAL(
"A digital out of the name '%s' already exists. Device #%02d has a duplicate name",
digital_out_.
name_.c_str(),
sh_->get_ring_position());
512 ROS_WARN(
"WARNING: Device #%02d : motor current limit (%f) greater than board current limit (%f)",
517 else if (allow_unprogrammed)
519 ROS_WARN(
"WARNING: Device #%02d (%d%05d) is not programmed",
520 sh_->get_ring_position(),
sh_->get_product_code(),
sh_->get_serial());
528 ROS_FATAL(
"Device #%02d (%d%05d) is not programmed, aborting...",
529 sh_->get_ring_position(),
sh_->get_product_code(),
sh_->get_serial());
536 #define GET_ATTR(a) \
539 attr = elt->Attribute((a)); \
541 c = elt->FirstChildElement((a)); \
542 if (!c || !(attr = c->GetText())) { \
543 ROS_FATAL("Actuator is missing the attribute "#a); \
544 exit(EXIT_FAILURE); \
687 return int32_t(new_timestamp - old_timestamp);
698 static const int USEC_PER_SEC = 1000000;
699 int sec = timediff_usec / USEC_PER_SEC;
700 int nsec = (timediff_usec % USEC_PER_SEC)*1000;
712 return int32_t(new_position - old_position);
722 int32_t old_position, uint32_t old_timestamp)
724 double timestamp_diff = double(
timestampDiff(new_timestamp, old_timestamp)) * 1e-6;
725 double position_diff = double(
positionDiff(new_position, old_position));
726 return (position_diff / timestamp_diff);
738 return 0.0078125 * double(raw_temp);
745 uint32_t timestamp_diff = (timestamp - last_timestamp);
746 return (timestamp_diff > amount);
763 s.supply_voltage = supply_voltage;
765 s.programmed_pwm = pwm_ratio;
766 s.executed_current = last_executed_current;
857 const char* reason =
"Publishing manually triggered";
861 reason = (undervoltage) ?
"Undervoltage Lockout" :
"Safety Lockout";
863 int level = (new_error) ? 2 : 0;
888 bool success =
false;
896 EC_Logic *logic = EC_Logic::instance();
897 unsigned char buf[1];
898 EC_UINT address = 0x0000;
899 NPRD_Telegram nprd_telegram(logic->get_idx(),
900 sh_->get_station_address(),
905 EC_Ethernet_Frame frame(&nprd_telegram);
910 if (nprd_telegram.get_wkc() != 1) {
965 boost::crc_32_type crc32;
966 crc32.process_bytes(&cfg,
sizeof(cfg)-
sizeof(cfg.
crc32_));
967 cfg.
crc32_ = crc32.checksum();
982 boost::crc_32_type crc32;
983 crc32.process_bytes(&cfg,
sizeof(cfg)-
sizeof(cfg.
crc32_));
984 if (cfg.
crc32_ != crc32.checksum()) {
1001 BOOST_STATIC_ASSERT(
sizeof(actuator_info) == 264);
1005 ROS_ERROR(
"Reading acutuator info from eeprom");
1020 BOOST_STATIC_ASSERT(
sizeof(config) == 256);
1024 ROS_ERROR(
"Reading motor heating model config from eeprom");
1055 ROS_ERROR(
"Writing actuator infomation to EEPROM");
1081 ROS_ERROR(
"Writing motor heating model configuration to EEPROM");
1111 fprintf(stderr,
"%s : " ERROR_HDR " getting diagnostics lock\n", __func__);
1122 if (error == EBUSY) {
1125 else if (error != 0) {
1126 fprintf(stderr,
"%s : " ERROR_HDR " getting diagnostics lock\n", __func__);
1138 fprintf(stderr,
"%s : " ERROR_HDR " freeing diagnostics lock\n", __func__);
1163 #define CHECK_SAFETY_BIT(bit) \
1164 do { if (status & SAFETY_##bit) { \
1165 str += prefix + #bit; \
1194 str += prefix +
"ENABLE";
1198 str += prefix +
"CURRENT";
1202 str += prefix +
"UNDERVOLTAGE";
1206 str += prefix +
"SAFETY_RESET";
1210 str += prefix +
"SAFETY_LOCKOUT";
1214 str += prefix +
"RESET";
1233 d.mergeSummary(
d.ERROR,
"Too many dropped packets");
1238 d.mergeSummary(
d.ERROR,
"Checksum error on status data");
1243 d.mergeSummary(
d.WARN,
"Have not yet collected WG0X diagnostics");
1247 d.mergeSummary(
d.WARN,
"Could not collect WG0X diagnostics");
1253 d.addf(
"Safety Disable Status",
"%s (%02x)",
safetyDisableString(
s.safety_disable_status_).c_str(),
s.safety_disable_status_);
1254 d.addf(
"Safety Disable Status Hold",
"%s (%02x)",
safetyDisableString(
s.safety_disable_status_hold_).c_str(),
s.safety_disable_status_hold_);
1265 uint8_t
status =
s.safety_disable_status_hold_;
1266 string prefix(
": ");
1267 string str(
"Safety Lockout");
1274 d.mergeSummary(
d.ERROR, str);
1284 d.mergeSummaryf(
d.ERROR,
"FPGA internal reset detected");
1289 d.mergeSummaryf(
d.WARN,
"Timestamp jumped");
1299 unsigned product =
sh_->get_product_code();
1305 static const double WG005B_SUPPLY_CURRENT_SCALE = (1.0 / (8152.0 * 0.851)) * 4.0;
1306 double bridge_supply_current = double(di.
supply_current_in_) * WG005B_SUPPLY_CURRENT_SCALE;
1307 d.addf(
"Bridge Supply Current",
"%f", bridge_supply_current);
1313 static const double WG005_SUPPLY_CURRENT_SCALE = ((82.0 * 2.5) / (0.01 * 5100.0 * 32768.0));
1315 d.addf(
"Supply Current",
"%f", supply_current);
1333 d.hardware_id = serial;
1335 d.summary(
d.OK,
"OK");
1340 d.addf(
"Position",
"%02d",
sh_->get_ring_position());
1341 d.addf(
"Product code",
1342 "WG0%d (%d) Firmware Revision %d.%02d, PCB Revision %c.%02d",
1349 d.add(
"Serial Number", serial);
1365 d.addf(
"Calibration Status",
"%s",
1372 d.addf(
"Digital out",
"%d",
status->digital_out_);
1373 d.addf(
"Programmed pwm value",
"%d",
status->programmed_pwm_value_);
1376 d.addf(
"Timestamp",
"%u",
status->timestamp_);
1377 d.addf(
"Encoder count",
"%d",
status->encoder_count_);
1378 d.addf(
"Encoder index pos",
"%d",
status->encoder_index_pos_);
1379 d.addf(
"Num encoder_errors",
"%d",
status->num_encoder_errors_);
1380 d.addf(
"Encoder status",
"%d",
status->encoder_status_);
1381 d.addf(
"Calibration reading",
"%d",
status->calibration_reading_);
1382 d.addf(
"Last calibration rising edge",
"%d",
status->last_calibration_rising_edge_);
1383 d.addf(
"Last calibration falling edge",
"%d",
status->last_calibration_falling_edge_);
1384 d.addf(
"Board temperature",
"%f", 0.0078125 *
status->board_temperature_);
1386 d.addf(
"Bridge temperature",
"%f", 0.0078125 *
status->bridge_temperature_);
1398 d.mergeSummaryf(
d.WARN,
"Motor model disabled");
1409 d.mergeSummaryf(
d.WARN,
"Encoder errors detected");
1412 d.addf(
"Packet count",
"%d",
status->packet_count_);
1414 d.addf(
"Drops",
"%d",
drops_);
int16_t programmed_pwm_value_
bool tryLockWG0XDiagnostics()
bool verifyChecksum(const void *buffer, unsigned size)
bool initialize(const ethercat_hardware::ActuatorInfo &actuator_info, const ethercat_hardware::BoardInfo &board_info)
Initializes motor trace publisher.
bool verifyCRC(void) const
Verify CRC stored in actuator info structure.
static const unsigned BASE_ADDR
bool unpackState(unsigned char *this_buffer, unsigned char *prev_buffer)
double last_executed_effort_
uint32_t device_serial_number_
bool publishTrace(const string &reason, unsigned level, unsigned delay)
Asks device to publish (motor) trace. Only works for devices that support it.
ethercat_hardware::WGEeprom eeprom_
Access to device eeprom.
uint16_t max_bridge_temperature_
virtual void collectDiagnostics(EthercatCom *com)
void update(const WG0XSafetyDisableStatus &new_status, const WG0XDiagnosticsInfo &new_diagnostics_info)
Use new updates WG0X diagnostics with new safety disable data.
bool verifyCRC(void) const
static string modeString(uint8_t mode)
uint16_t bridge_temperature_
bool addActuator(Actuator *actuator)
void publishMailboxDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &d)
WG0XActuatorInfo actuator_info_
ROSCPP_DECL bool get(const std::string &key, bool &b)
static const unsigned BASE_ADDR
uint16_t num_encoder_errors_
uint8_t calibration_reading_
int readMailbox(EthercatCom *com, unsigned address, void *data, unsigned length)
Read data from WG0X local bus using mailbox communication.
double last_measured_effort_
pthread_mutex_t wg0x_diagnostics_lock_
static boost::shared_ptr< ethercat_hardware::MotorHeatingModelCommon > motor_heating_model_common_
static const unsigned EEPROM_PAGE
void flagPublish(const std::string &reason, int level, int delay)
flags delayed publish of motor trace.
uint16_t absolute_current_limit_
bool disable_motor_model_checking_
static void copyActuatorInfo(ethercat_hardware::ActuatorInfo &out, const WG0XActuatorInfo &in)
Fills in ethercat_hardware::ActuatorInfo from WG0XActuatorInfo.
uint16_t board_temperature_
static double calcEncoderVelocity(int32_t new_position, uint32_t new_timestamp, int32_t old_position, uint32_t old_timestamp)
WG0XConfigInfo config_info_
void generateCRC(void)
Calculate CRC of structure and update crc32_256_ and crc32_264_ elements.
virtual void construct(EtherCAT_SlaveHandler *sh, int &start_address)
< Construct EtherCAT device
double last_commanded_effort_
pr2_hardware_interface::Actuator actuator_
bool timestamp_jump_detected_
bool readMotorHeatingModelParametersFromEeprom(EthercatCom *com, MotorHeatingModelParametersEepromConfig &config)
Reads actuator info from eeprom.
void checkPublish()
Publishes motor trace if delay time is up.
void unlockWG0XDiagnostics()
int32_t last_calibration_rising_edge_
MotorModel * motor_model_
void publishGeneralDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &d)
static ros::Duration timediffToDuration(int32_t timediff_usec)
WG0XDiagnostics wg0x_publish_diagnostics_
uint8_t mbx_command_irq_count_
uint16_t max_board_temperature_
double max_current_
min(board current limit, actuator current limit)
double encoder_reduction_
WG0XDiagnosticsInfo diagnostics_info_
int16_t config_offset_current_B_
static const unsigned ACTUATOR_INFO_PAGE
double motor_torque_constant_
uint8_t undervoltage_count_
bool writeAppRam(EthercatCom *com, double zero_offset)
bool status_checksum_error_
boost::shared_ptr< ethercat_hardware::MotorHeatingModel > motor_heating_model_
bool fpga_internal_reset_detected_
EtherCAT_SlaveHandler * sh_
uint8_t operate_disable_count_
int16_t config_offset_current_A_
uint32_t operate_disable_total_
bool enforce_
0 if heating model should be not be enforced, 0 otherwise
uint8_t watchdog_disable_count_
uint32_t safety_disable_total_
int32_t last_calibration_falling_edge_
MotorHeatingModelParameters params_
Motor parameters
double cached_zero_offset_
AppRamStatus app_ram_status_
DigitalOutCommand command_
uint8_t bridge_over_temp_count_
ethercat_hardware::WGMailbox mailbox_
Mailbox access to device.
double last_commanded_current_
bool calibration_falling_edge_valid_
pr2_hardware_interface::DigitalOut publish_motor_trace_
#define CHECK_SAFETY_BIT(bit)
void clearErrorFlags(void)
int16_t programmed_current_
pr2_hardware_interface::DigitalOut digital_out_
uint32_t board_over_temp_total_
static int32_t timestampDiff(uint32_t new_timestamp, uint32_t old_timestamp)
bool readActuatorInfoFromEeprom(EthercatCom *com, WG0XActuatorInfo &actuator_info)
Reads actuator info from eeprom.
bool initializeMotorHeatingModel(bool allow_unprogrammed)
unsigned computeChecksum(void const *data, unsigned length)
uint8_t over_current_count_
uint8_t pdi_timeout_error_count_
double last_executed_current_
uint16_t supply_current_in_
bool lockWG0XDiagnostics()
virtual void collectDiagnostics(EthercatCom *com)
static string safetyDisableString(uint8_t status)
int readMailbox(EthercatCom *com, unsigned address, void *data, unsigned length)
Read data from WG0X local bus using mailbox communication.
bool verifyState(WG0XStatus *this_status, WG0XStatus *prev_status)
ros::Duration sample_timestamp_
static double min(double a, double b)
uint32_t checksum_errors_
uint8_t board_minor_
Printed circuit assembly revision.
int writeMailbox(EthercatCom *com, unsigned address, void const *data, unsigned length)
Write data to WG0X local bus using mailbox communication.
ethercat_hardware::ActuatorInfo actuator_info_msg_
uint32_t over_current_total_
uint8_t pdi_checksum_error_count_
static int32_t positionDiff(int32_t new_position, int32_t old_position)
bool verify()
Check for errors between sample data and motor model.
uint8_t safety_disable_count_
float nominal_current_scale_
uint32_t watchdog_disable_total_
virtual bool txandrx_once(struct EtherCAT_Frame *frame)=0
bool addDigitalOut(DigitalOut *digital_out)
ethercat_hardware::MotorTraceSample motor_trace_sample_
int16_t programmed_current_
ros::Duration sample_timestamp_
void diagnostics(diagnostic_updater::DiagnosticStatusWrapper &d, unsigned char *)
For EtherCAT device that only publish one EtherCAT Status message. If sub-class implements multiDiagn...
bool calibration_rising_edge_valid_
int max_consecutive_drops_
bool encoder_errors_detected_
static const unsigned CONFIG_INFO_BASE_ADDR
bool too_many_dropped_packets_
bool readAppRam(EthercatCom *com, double &zero_offset)
void construct(EtherCAT_SlaveHandler *sh, int &start_address)
< Construct EtherCAT device
uint8_t board_major_
Printed circuit board revision (for this value 0=='A', 1=='B')
int16_t measured_current_
WG0XSafetyDisableStatus safety_disable_status_
WG0XSafetyDisableCounters safety_disable_counters_
double cached_zero_offset_
double last_measured_current_
int writeMailbox(EthercatCom *com, unsigned address, void const *data, unsigned length)
Write data to WG0X local bus using mailbox communication.
bool writeEepromPage(EthercatCom *com, WGMailbox *mbx, unsigned page, const void *data, unsigned length)
Write data to single eeprom page.
static bool timestamp_jump(uint32_t timestamp, uint32_t last_timestamp, uint32_t amount)
uint32_t undervoltage_total_
void diagnostics(diagnostic_updater::DiagnosticStatusWrapper &d)
Collects and publishes device diagnostics.
static double convertRawTemperature(int16_t raw_temp)
Converts raw 16bit temperature value returned by device into value in degress Celcius.
uint32_t bridge_over_temp_total_
virtual int initialize(pr2_hardware_interface::HardwareInterface *, bool allow_unprogrammed=true)
unsigned int command_size_
bool initializeMotorModel(pr2_hardware_interface::HardwareInterface *hw, const string &device_description, double max_pwm_ratio, double board_resistance, bool poor_measured_motor_voltage)
Allocates and initialized motor trace for WG0X devices than use it (WG006, WG005)
uint32_t last_last_timestamp_
bool program(EthercatCom *com, const WG0XActuatorInfo &actutor_info)
Programs acutator and heating parameters into device EEPROM.
bool calibration_reading_
double last_calibration_rising_edge_
double last_calibration_falling_edge_
void packCommand(unsigned char *buffer, bool halt, bool reset)
uint32_t pulses_per_revolution_
uint8_t configuration_status_
void sample(const ethercat_hardware::MotorTraceSample &s)
Call for each update.
unsigned int rotateRight8(unsigned in)
float nominal_voltage_scale_
bool initialize(EtherCAT_SlaveHandler *sh)
bool readEepromPage(EthercatCom *com, WGMailbox *mbx, unsigned page, void *data, unsigned length)
Read data from single eeprom page.
uint8_t board_over_temp_count_
void ethercatDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &d, unsigned numPorts)
Adds diagnostic information for EtherCAT ports.
WG0XDiagnostics wg0x_collect_diagnostics_
ethercat_hardware
Author(s): Rob Wheeler
, Derek King
autogenerated on Thu Sep 26 2024 02:44:04