00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "netft_rdt_driver.h"
00036 #include <stdint.h>
00037 #include <exception>
00038
00039 using boost::asio::ip::udp;
00040
00041 namespace netft_rdt_driver
00042 {
00043
00044 struct RDTRecord
00045 {
00046 uint32_t rdt_sequence_;
00047 uint32_t ft_sequence_;
00048 uint32_t status_;
00049 int32_t fx_;
00050 int32_t fy_;
00051 int32_t fz_;
00052 int32_t tx_;
00053 int32_t ty_;
00054 int32_t tz_;
00055
00056 enum {RDT_RECORD_SIZE = 36};
00057 void unpack(const uint8_t *buffer);
00058 static uint32_t unpack32(const uint8_t *buffer);
00059 };
00060
00061 uint32_t RDTRecord::unpack32(const uint8_t *buffer)
00062 {
00063 return
00064 ( uint32_t(buffer[0]) << 24) |
00065 ( uint32_t(buffer[1]) << 16) |
00066 ( uint32_t(buffer[2]) << 8 ) |
00067 ( uint32_t(buffer[3]) << 0 ) ;
00068 }
00069
00070 void RDTRecord::unpack(const uint8_t *buffer)
00071 {
00072 rdt_sequence_ = unpack32(buffer + 0);
00073 ft_sequence_ = unpack32(buffer + 4);
00074 status_ = unpack32(buffer + 8);
00075 fx_ = unpack32(buffer + 12);
00076 fy_ = unpack32(buffer + 16);
00077 fz_ = unpack32(buffer + 20);
00078 tx_ = unpack32(buffer + 24);
00079 ty_ = unpack32(buffer + 28);
00080 tz_ = unpack32(buffer + 32);
00081 }
00082
00083
00084 struct RDTCommand
00085 {
00086 uint16_t command_header_;
00087 uint16_t command_;
00088 uint32_t sample_count_;
00089
00090 RDTCommand() : command_header_(HEADER)
00091 {
00092
00093 }
00094
00095 enum {HEADER=0x1234};
00096
00097
00098 enum {
00099 CMD_STOP_STREAMING=0,
00100 CMD_START_HIGH_SPEED_STREAMING=2,
00101
00102 };
00103
00104
00105 enum { INFINITE_SAMPLES=0 };
00106
00107 enum {RDT_COMMAND_SIZE = 8};
00108
00110
00111 void pack(uint8_t *buffer) const;
00112 };
00113
00114 void RDTCommand::pack(uint8_t *buffer) const
00115 {
00116
00117 buffer[0] = (command_header_ >> 8) & 0xFF;
00118 buffer[1] = (command_header_ >> 0) & 0xFF;
00119 buffer[2] = (command_ >> 8) & 0xFF;
00120 buffer[3] = (command_ >> 0) & 0xFF;
00121 buffer[4] = (sample_count_ >> 8) & 0xFF;
00122 buffer[5] = (sample_count_ >> 0) & 0xFF;
00123 buffer[6] = (sample_count_ >> 8) & 0xFF;
00124 buffer[7] = (sample_count_ >> 0) & 0xFF;
00125 }
00126
00127
00128 NetFTRDTDriver::NetFTRDTDriver(const std::string &address) :
00129 address_(address),
00130 socket_(io_service_),
00131 stop_recv_thread_(false),
00132 recv_thread_running_(false),
00133 packet_count_(0),
00134 lost_packets_(0),
00135 out_of_order_count_(0),
00136 seq_counter_(0),
00137 diag_packet_count_(0),
00138 last_diag_pub_time_(ros::Time::now()),
00139 last_rdt_sequence_(0),
00140 system_status_(0)
00141 {
00142
00143 udp::endpoint netft_endpoint( boost::asio::ip::address_v4::from_string(address), RDT_PORT);
00144 socket_.open(udp::v4());
00145 socket_.connect(netft_endpoint);
00146
00147
00148
00149
00150
00151 static const double counts_per_force = 1000000;
00152 static const double counts_per_torque = 1000000;
00153 force_scale_ = 1.0 / counts_per_force;
00154 torque_scale_ = 1.0 / counts_per_torque;
00155
00156
00157 recv_thread_ = boost::thread(&NetFTRDTDriver::recvThreadFunc, this);
00158
00159
00160
00161 for (int i=0; i<10; ++i)
00162 {
00163 startStreaming();
00164 if (waitForNewData())
00165 break;
00166 }
00167 { boost::unique_lock<boost::mutex> lock(mutex_);
00168 if (packet_count_ == 0)
00169 {
00170 throw std::runtime_error("No data received from NetFT device");
00171 }
00172 }
00173
00174 }
00175
00176
00177 NetFTRDTDriver::~NetFTRDTDriver()
00178 {
00179
00180
00181 stop_recv_thread_ = true;
00182 if (!recv_thread_.timed_join(boost::posix_time::time_duration(0,0,1,0)))
00183 {
00184 ROS_WARN("Interrupting recv thread");
00185 recv_thread_.interrupt();
00186 if (!recv_thread_.timed_join(boost::posix_time::time_duration(0,0,1,0)))
00187 {
00188 ROS_WARN("Failed second join to recv thread");
00189 }
00190 }
00191 socket_.close();
00192 }
00193
00194
00195 bool NetFTRDTDriver::waitForNewData()
00196 {
00197
00198 bool got_new_data = false;
00199 {
00200 boost::mutex::scoped_lock lock(mutex_);
00201 unsigned current_packet_count = packet_count_;
00202 condition_.timed_wait(lock, boost::posix_time::milliseconds(100));
00203 got_new_data = packet_count_ != current_packet_count;
00204 }
00205
00206 return got_new_data;
00207 }
00208
00209
00210 void NetFTRDTDriver::startStreaming(void)
00211 {
00212
00213 RDTCommand start_transmission;
00214 start_transmission.command_ = RDTCommand::CMD_START_HIGH_SPEED_STREAMING;
00215 start_transmission.sample_count_ = RDTCommand::INFINITE_SAMPLES;
00216
00217 uint8_t buffer[RDTCommand::RDT_COMMAND_SIZE];
00218 start_transmission.pack(buffer);
00219 socket_.send(boost::asio::buffer(buffer, RDTCommand::RDT_COMMAND_SIZE));
00220 }
00221
00222
00223
00224 void NetFTRDTDriver::recvThreadFunc()
00225 {
00226 try {
00227 recv_thread_running_ = true;
00228 RDTRecord rdt_record;
00229 geometry_msgs::WrenchStamped tmp_data;
00230 uint8_t buffer[RDTRecord::RDT_RECORD_SIZE+1];
00231 while (!stop_recv_thread_)
00232 {
00233 size_t len = socket_.receive(boost::asio::buffer(buffer, RDTRecord::RDT_RECORD_SIZE+1));
00234 if (len != RDTRecord::RDT_RECORD_SIZE)
00235 {
00236 ROS_WARN("Receive size of %d bytes does not match expected size of %d",
00237 int(len), int(RDTRecord::RDT_RECORD_SIZE));
00238 }
00239 else
00240 {
00241 rdt_record.unpack(buffer);
00242 if (rdt_record.status_ != 0)
00243 {
00244
00245 boost::unique_lock<boost::mutex> lock(mutex_);
00246 system_status_ = rdt_record.status_;
00247 }
00248 int32_t seqdiff = int32_t(rdt_record.rdt_sequence_ - last_rdt_sequence_);
00249 last_rdt_sequence_ = rdt_record.rdt_sequence_;
00250 if (seqdiff < 1)
00251 { boost::unique_lock<boost::mutex> lock(mutex_);
00252
00253 ++out_of_order_count_;
00254 }
00255 else
00256 {
00257 tmp_data.header.seq = seq_counter_++;
00258 tmp_data.header.stamp = ros::Time::now();
00259 tmp_data.header.frame_id = "base_link";
00260 tmp_data.wrench.force.x = double(rdt_record.fx_) * force_scale_;
00261 tmp_data.wrench.force.y = double(rdt_record.fy_) * force_scale_;
00262 tmp_data.wrench.force.z = double(rdt_record.fz_) * force_scale_;
00263 tmp_data.wrench.torque.x = double(rdt_record.tx_) * torque_scale_;
00264 tmp_data.wrench.torque.y = double(rdt_record.ty_) * torque_scale_;
00265 tmp_data.wrench.torque.z = double(rdt_record.tz_) * torque_scale_;
00266 { boost::unique_lock<boost::mutex> lock(mutex_);
00267 new_data_ = tmp_data;
00268 lost_packets_ += (seqdiff - 1);
00269 ++packet_count_;
00270 condition_.notify_all();
00271 }
00272 }
00273 }
00274 }
00275 }
00276 catch (std::exception &e)
00277 {
00278 recv_thread_running_ = false;
00279 { boost::unique_lock<boost::mutex> lock(mutex_);
00280 recv_thread_error_msg_ = e.what();
00281 }
00282 }
00283 }
00284
00285
00286 void NetFTRDTDriver::getData(geometry_msgs::WrenchStamped &data)
00287 {
00288 { boost::unique_lock<boost::mutex> lock(mutex_);
00289 data = new_data_;
00290 }
00291 }
00292
00293
00294 void NetFTRDTDriver::diagnostics(diagnostic_updater::DiagnosticStatusWrapper &d)
00295 {
00296
00297 d.name = "NetFT RDT Driver : " + address_;
00298
00299 d.summary(d.OK, "OK");
00300 d.hardware_id = "0";
00301
00302 if (diag_packet_count_ == packet_count_)
00303 {
00304 d.mergeSummary(d.ERROR, "No new data in last second");
00305 }
00306
00307 if (!recv_thread_running_)
00308 {
00309 d.mergeSummaryf(d.ERROR, "Receive thread has stopped : %s", recv_thread_error_msg_.c_str());
00310 }
00311
00312 if (system_status_ != 0)
00313 {
00314 d.mergeSummaryf(d.ERROR, "NetFT reports error 0x%08x", system_status_);
00315 }
00316
00317 ros::Time current_time(ros::Time::now());
00318 double recv_rate = double(int32_t(packet_count_ - diag_packet_count_)) / (current_time - last_diag_pub_time_).toSec();
00319
00320 d.clear();
00321 d.addf("IP Address", "%s", address_.c_str());
00322 d.addf("System status", "0x%08x", system_status_);
00323 d.addf("Good packets", "%u", packet_count_);
00324 d.addf("Lost packets", "%u", lost_packets_);
00325 d.addf("Out-of-order packets", "%u", out_of_order_count_);
00326 d.addf("Recv rate (pkt/sec)", "%.2f", recv_rate);
00327 d.addf("Force scale (N/bit)", "%f", force_scale_);
00328 d.addf("Torque scale (Nm/bit)", "%f", torque_scale_);
00329
00330 geometry_msgs::WrenchStamped data;
00331 getData(data);
00332 d.addf("Force X (N)", "%f", data.wrench.force.x);
00333 d.addf("Force Y (N)", "%f", data.wrench.force.y);
00334 d.addf("Force Z (N)", "%f", data.wrench.force.z);
00335 d.addf("Torque X (Nm)", "%f", data.wrench.torque.x);
00336 d.addf("Torque Y (Nm)", "%f", data.wrench.torque.y);
00337 d.addf("Torque Z (Nm)", "%f", data.wrench.torque.z);
00338
00339 last_diag_pub_time_ = current_time;
00340 diag_packet_count_ = packet_count_;
00341 }
00342
00343
00344 }
00345