4 static double min(
double a,
double b) {
return (a<b)?a:b;}
7 trace_size_(trace_size),
10 backemf_constant_(0.0),
11 motor_voltage_error_(0.2),
12 abs_motor_voltage_error_(0.02),
13 measured_voltage_error_(0.2),
14 abs_measured_voltage_error_(0.02),
16 abs_current_error_(0.02),
18 abs_measured_current_(0.02),
19 abs_board_voltage_(0.02),
20 abs_position_delta_(0.02)
54 const ethercat_hardware::BoardInfo &board_info)
56 std::string topic(
"motor_trace");
57 if (!actuator_info.name.empty())
58 topic = topic +
"/" + actuator_info.name;
77 msg.actuator_info = actuator_info;
78 msg.board_info = board_info;
107 msg.samples.reserve(size);
110 for (
unsigned i=0; i<size; ++i) {
129 else if (delay > 900) {
146 double motor_voltage_error;
147 double motor_voltage_error_max;
148 double abs_motor_voltage_error;
149 double abs_motor_voltage_error_max;
150 double current_error;
151 double current_error_max;
152 double abs_current_error;
153 double abs_current_error_max;
154 double est_motor_resistance;
177 d.
addf(
"Motor Voltage Error %",
"%f", 100.0 * motor_voltage_error);
178 d.
addf(
"Max Motor Voltage Error %",
"%f", 100.0 * motor_voltage_error_max);
179 d.
addf(
"Abs Filtered Voltage Error %",
"%f", 100.0 * abs_motor_voltage_error);
180 d.
addf(
"Max Abs Filtered Voltage Error %",
"%f", 100.0 * abs_motor_voltage_error_max);
183 d.
addf(
"Current Error",
"%f", current_error);
184 d.
addf(
"Max Current Error",
"%f", current_error_max);
185 d.
addf(
"Abs Filtered Current Error",
"%f", abs_current_error);
186 d.
addf(
"Max Abs Filtered Current Error",
"%f", abs_current_error_max);
188 d.
addf(
"Motor Resistance Estimate",
"%f", est_motor_resistance);
202 const ethercat_hardware::BoardInfo &bi(
board_info_);
205 double board_voltage = s.supply_voltage * s.programmed_pwm - bi.board_resistance * s.measured_current;
208 double resistance_voltage = s.measured_current * ai.motor_resistance;
210 double motor_voltage = resistance_voltage + backemf_voltage;
213 const double resistance_error = 2.00;
214 const double backemf_constant_error = 0.15;
215 double motor_voltage_error_limit = 4.0 + fabs(resistance_voltage*resistance_error) + fabs(backemf_voltage * backemf_constant_error);
217 motor_voltage_error_limit =
min(motor_voltage_error_limit, 10.0);
220 double est_motor_resistance = 0.0;
221 double est_motor_resistance_accuracy = 0.0;
223 if (fabs(s.measured_current) > (0.02 * bi.hw_max_current + 0.005))
225 est_motor_resistance = (board_voltage - backemf_voltage) / s.measured_current;
229 est_motor_resistance_accuracy = 1.0 / (1.0 + fabs(backemf_voltage / resistance_voltage));
245 bool pwm_saturated = ((s.programmed_pwm > bi.max_pwm_ratio*0.95) || (s.programmed_pwm < -bi.max_pwm_ratio*0.95));
246 double current_error = s.measured_current-s.executed_current;
247 bool new_max_current_error =
false;
296 s2.motor_voltage_error_limit = motor_voltage_error_limit;
322 double measured_voltage_error_limit =
board_info_.poor_measured_motor_voltage ? 10.0 : 4.0;
331 if (is_motor_voltage_error || is_measured_voltage_error)
335 reason =
"Problem with the MCB, motor, encoder, or actuator model.";
337 if( is_measured_voltage_error )
340 reason +=
" Board may be damaged.";
342 else if (is_motor_voltage_error)
346 const double current_epsilon = 0.010;
347 double encoder_tick_delta = 2 * M_PI /
actuator_info_.pulses_per_revolution;
353 reason +=
" Current near zero - check for unconnected motor leads.";
358 reason +=
" Voltage near zero - check for short circuit.";
363 reason +=
" Velocity near zero - check for encoder error.";
368 reason +=
" Encoder delta below 1 - check encoder wiring.";
377 reason =
"Current loop error too large (MCB failing to hit desired current)";
382 reason =
"Potential problem with the MCB, motor, encoder, or actuator model.";
387 reason =
"Potential current loop error (MCB failing to hit desired current)";
411 filtered_value_ += filter_coefficient * (value-filtered_value_);
420 bool new_max =
false;
422 if (fabs(filtered_value_) > max_filtered_value_) {
424 max_filtered_value_ = fabs(filtered_value_);
436 filter_coefficient_(filter_coefficient)
double filter_max() const
boost::mutex diagnostics_mutex_
bool verify()
Check for errors between sample data and motor model.
double current_error_limit_
void sample(double value, double filter_coefficient)
Updates filter with newly sampled value.
double max_filtered_value_
bool sample(double value)
Updates filter with newly sampled value, also tracks max value.
Filter abs_position_delta_
Filter abs_measured_voltage_error_
ethercat_hardware::BoardInfo board_info_
unsigned published_traces_
Filter motor_voltage_error_
Filter abs_measured_current_
void diagnostics(diagnostic_updater::DiagnosticStatusWrapper &d)
Collects and publishes device diagnostics.
SimpleFilter motor_resistance_
void addf(const std::string &key, const char *format,...)
Filter(double filter_coefficient)
realtime_tools::RealtimePublisher< ethercat_hardware::MotorTrace > * publisher_
std::string diagnostics_reason_
Filter measured_voltage_error_
void sample(const ethercat_hardware::MotorTraceSample &s)
Call for each update.
bool initialize(const ethercat_hardware::ActuatorInfo &actuator_info, const ethercat_hardware::BoardInfo &board_info)
Initializes motor trace publisher.
Filter abs_board_voltage_
Filter abs_motor_voltage_error_
std::vector< ethercat_hardware::MotorTraceSample > trace_buffer_
bool previous_pwm_saturated_
void checkPublish()
Publishes motor trace if delay time is up.
void flagPublish(const std::string &reason, int level, int delay)
flags delayed publish of motor trace.
void mergeSummary(unsigned char lvl, const std::string s)
std::string publish_reason_
ethercat_hardware::ActuatorInfo actuator_info_
static double min(double a, double b)
MotorModel(unsigned trace_size)
Filter abs_current_error_