00001 00028 #include <sr_edc_ethercat_drivers/motor_trace_buffer.h> 00029 #include <string> 00030 00031 namespace sr_edc_ethercat_drivers 00032 { 00036 MotorTraceBuffer::MotorTraceBuffer(unsigned trace_size) : 00037 trace_size_(trace_size), 00038 trace_index_(0), 00039 published_traces_(0) 00040 { 00041 assert(trace_size_ > 0); 00042 trace_buffer_.reserve(trace_size_); 00043 reset(); 00044 } 00045 00046 void MotorTraceBuffer::reset() 00047 { 00048 publish_delay_ = -1; 00049 publish_level_ = -1; 00050 publish_reason_ = "OK"; 00051 } 00052 00053 00056 bool MotorTraceBuffer::initialize(const sr_edc_ethercat_drivers::ActuatorInfo &actuator_info) 00057 { 00058 std::string topic("motor_trace"); 00059 if (!actuator_info.name.empty()) 00060 { 00061 topic = topic + "/" + actuator_info.name; 00062 } 00063 publisher_ = new realtime_tools::RealtimePublisher<sr_edc_ethercat_drivers::MotorTrace>(ros::NodeHandle(), topic, 1, 00064 true); 00065 if (publisher_ == NULL) 00066 { 00067 return false; 00068 } 00069 00070 sr_edc_ethercat_drivers::MotorTrace &msg(publisher_->msg_); 00071 msg.actuator_info = actuator_info; 00072 msg.samples.reserve(trace_size_); 00073 00074 return true; 00075 } 00076 00077 00080 void MotorTraceBuffer::checkPublish() 00081 { 00082 if (publish_delay_ < 0) 00083 { 00084 return; 00085 } 00086 --publish_delay_; 00087 if (publish_delay_ >= 0) 00088 { 00089 return; 00090 } 00091 00092 ++published_traces_; 00093 00094 assert(publisher_ != NULL); 00095 if ((publisher_ == NULL) || (!publisher_->trylock())) 00096 { 00097 return; 00098 } 00099 00100 sr_edc_ethercat_drivers::MotorTrace &msg(publisher_->msg_); 00101 00102 msg.header.stamp = ros::Time::now(); 00103 msg.reason = publish_reason_; 00104 unsigned size = trace_buffer_.size(); 00105 msg.samples.clear(); 00106 msg.samples.reserve(size); 00107 00108 // @todo is there a beter way to copy data between two std::vectors? 00109 for (unsigned i = 0; i < size; ++i) 00110 { 00111 msg.samples.push_back(trace_buffer_.at((trace_index_ + 1 + i) % size)); 00112 } 00113 00114 // Cancel any delayed publishing from occuring 00115 publish_delay_ = -1; 00116 publish_level_ = -1; 00117 00118 publisher_->unlockAndPublish(); 00119 } 00120 00121 00126 void MotorTraceBuffer::flagPublish(const std::string &reason, int level, int delay) 00127 { 00128 if (delay < 0) 00129 { 00130 delay = 0; 00131 } 00132 else if (delay > 900) 00133 { 00134 delay = 900; 00135 } 00136 if (level > publish_level_) 00137 { 00138 publish_reason_ = reason; 00139 publish_delay_ = delay; 00140 publish_level_ = level; 00141 } 00142 } 00143 00144 00147 void MotorTraceBuffer::sample(const sr_edc_ethercat_drivers::MotorTraceSample &s) 00148 { 00149 { // Add motor trace sample to trace buffer 00150 assert(trace_buffer_.size() <= trace_size_); 00151 if (trace_buffer_.size() >= trace_size_) 00152 { 00153 trace_index_ = (trace_index_ + 1) % trace_buffer_.size(); 00154 trace_buffer_.at(trace_index_) = s; 00155 } 00156 else 00157 { 00158 trace_index_ = trace_buffer_.size(); 00159 trace_buffer_.push_back(s); 00160 } 00161 } 00162 } 00163 } // namespace sr_edc_ethercat_drivers