00001 #include "ax2550/ax2550.h"
00002
00003 #include <iostream>
00004 #include <sstream>
00005 #include <cstdio>
00006 #include <cstdarg>
00007
00008 #include <boost/algorithm/string.hpp>
00009
00010 using namespace ax2550;
00011
00012 using std::string;
00013 using std::stringstream;
00014 using serial::Serial;
00015 using serial::utils::SerialListener;
00016 using serial::utils::BufferedFilterPtr;
00017 using serial::utils::TokenPtr;
00018
00019 inline void defaultInfo(const string &msg) {
00020 std::cout << "AX2550 Info: " << msg << std::endl;
00021 }
00022
00023
00024 inline void tokenizer(const std::string &data,
00025 std::vector<TokenPtr> &tokens)
00026 {
00027
00028 size_t number_of_Ws =
00029 (size_t) std::count(data.begin(), data.end(), 'W');
00030
00031 for(size_t i = 0; i < number_of_Ws; ++i) {
00032 tokens.push_back(TokenPtr( new std::string("W") ));
00033 }
00034
00035 typedef std::vector<std::string> find_vector_type;
00036 find_vector_type t;
00037 boost::split(t, data, boost::is_any_of("W"));
00038
00039 string new_data = "";
00040 for (find_vector_type::iterator it = t.begin(); it != t.end(); ++it) {
00041 new_data.append((*it));
00042 }
00043
00044 find_vector_type t2;
00045 boost::split(t2, new_data, boost::is_any_of("\r\n"));
00046 for (find_vector_type::iterator it = t2.begin(); it != t2.end(); ++it) {
00047 tokens.push_back(TokenPtr( new std::string(*it) ));
00048 }
00049 }
00050
00051 AX2550::AX2550 (string port)
00052 : port_(""), serial_port_(NULL), serial_listener_(1),
00053 connected_(false), synced_(false)
00054 {
00055 this->port_ = port;
00056
00057 this->info = defaultInfo;
00058 this->watch_dog_callback = NULL;
00059
00060 this->serial_listener_.setTokenizer(tokenizer);
00061
00062 if (!this->port_.empty()) {
00063 this->connect();
00064 }
00065 }
00066
00067 AX2550::~AX2550 () {
00068 this->disconnect();
00069 }
00070
00071 void
00072 AX2550::connect (string port) {
00073
00074 if (this->connected_) {
00075 AX2550_THROW(ConnectionException, "already connected");
00076 }
00077
00078 if (!port.empty()) {
00079 this->port_ = port;
00080 }
00081
00082 if (this->port_.empty()) {
00083 AX2550_THROW(ConnectionException, "serial port name is empty");
00084 }
00085
00086 this->disconnect();
00087
00088 this->setupFilters_();
00089
00090 this->serial_port_ = new Serial();
00091 this->serial_port_->setPort(this->port_);
00092 this->serial_port_->setBaudrate(9600);
00093 this->serial_port_->setParity(serial::parity_even);
00094 this->serial_port_->setStopbits(serial::stopbits_one);
00095 this->serial_port_->setBytesize(serial::sevenbits);
00096 serial::Timeout to = serial::Timeout::simpleTimeout(10);
00097 this->serial_port_->setTimeout(to);
00098
00099 this->serial_port_->open();
00100
00101 this->serial_listener_.setChunkSize(2);
00102 this->serial_listener_.startListening((*this->serial_port_));
00103
00104 this->sync_();
00105 this->connected_ = true;
00106 }
00107
00108 void
00109 AX2550::disconnect () {
00110 this->connected_ = false;
00111 if (this->serial_listener_.isListening()) {
00112 this->serial_listener_.stopListening();
00113 }
00114 if (this->serial_port_ != NULL) {
00115 delete this->serial_port_;
00116 this->serial_port_ = NULL;
00117 }
00118 }
00119
00120 bool
00121 AX2550::isConnected () {
00122 return this->connected_;
00123 }
00124
00125 bool
00126 AX2550::issueCommand (const string &command, string &fail_why) {
00127
00128 BufferedFilterPtr echo_filt = this->serial_listener_.createBufferedFilter(
00129 SerialListener::exactly(command));
00130 this->serial_port_->write(command+"\r");
00131
00132 if (echo_filt->wait(50).empty()) {
00133 fail_why = "failed to receive an echo";
00134 return false;
00135 }
00136 return true;
00137 }
00138
00139 inline string
00140 string_format(const string &fmt, ...) {
00141 int size = 100;
00142 string str;
00143 va_list ap;
00144 while (1) {
00145 str.resize(size);
00146 va_start(ap, fmt);
00147 int n = vsnprintf((char *)str.c_str(), size, fmt.c_str(), ap);
00148 va_end(ap);
00149 if (n > -1 && n < size) {
00150 str.resize(n);
00151 return str;
00152 }
00153 if (n > -1) {
00154 size = n + 1;
00155 } else {
00156 size *= 2;
00157 }
00158 }
00159 return str;
00160 }
00161
00162 void
00163 AX2550::move (double speed, double direction) {
00164 if(!this->connected_) {
00165 AX2550_THROW(CommandFailedException, "must be connected to move");
00166 }
00167
00168 boost::mutex::scoped_lock lock(this->mc_mutex);
00169 string serial_buffer;
00170 unsigned char speed_hex, direction_hex;
00171 string fail_why;
00172
00173 speed_hex = (unsigned char) (fabs(speed));
00174 if(speed < 0) {
00175 serial_buffer = string_format("!a%.2X", speed_hex);
00176 } else {
00177 serial_buffer = string_format("!A%.2X", speed_hex);
00178 }
00179
00180 if (!this->issueCommand(serial_buffer, fail_why)) {
00181 AX2550_THROW(CommandFailedException, fail_why.c_str());
00182 }
00183
00184 this->ack_nak_filt_->clear();
00185 string result = this->ack_nak_filt_->wait(100);
00186 if (result != "+") {
00187 if (result == "-") {
00188 AX2550_THROW(CommandFailedException, "nak received, command failed");
00189 }
00190 AX2550_THROW(CommandFailedException, "did not receive an ack or nak");
00191 }
00192
00193 direction_hex = (unsigned char) (fabs(direction));
00194 if(direction < 0) {
00195 serial_buffer = string_format("!b%.2X", direction_hex);
00196 } else {
00197 serial_buffer = string_format("!B%.2X", direction_hex);
00198 }
00199
00200 if (!this->issueCommand(string(serial_buffer), fail_why)) {
00201 AX2550_THROW(CommandFailedException, fail_why.c_str());
00202 }
00203
00204 this->ack_nak_filt_->clear();
00205 result = this->ack_nak_filt_->wait(100);
00206 if (result != "+") {
00207 if (result == "-") {
00208 AX2550_THROW(CommandFailedException, "nak received, command failed");
00209 }
00210 AX2550_THROW(CommandFailedException, "did not receive an ack or nak");
00211 }
00212 }
00213
00214 void
00215 AX2550::queryEncoders (long &encoder1, long &encoder2, bool relative) {
00216 if(!this->connected_) {
00217 AX2550_THROW(CommandFailedException, "must be connected to query "
00218 "the encoders");
00219 }
00220
00221 if (this->encoders_filt_->count()) {
00222 stringstream ss;
00223 ss << "There were " << this->encoders_filt_->count()
00224 << " orphaned encoder messages in the filter...";
00225 this->warn(ss.str());
00226 }
00227
00228 this->encoders_filt_->clear();
00229
00230 boost::mutex::scoped_lock lock(this->mc_mutex);
00231
00232 string cmd1, cmd2, fail_why;
00233 if (relative) {
00234 cmd1 = "?q4";
00235 } else {
00236 cmd1 = "?q0";
00237 }
00238 this->serial_port_->write(cmd1+"\r");
00239
00240 if (relative) {
00241 cmd2 = "?q5";
00242 } else {
00243 cmd2 = "?q1";
00244 }
00245 this->serial_port_->write(cmd2+"\r");
00246
00247 string response = this->encoders_filt_->wait(100);
00248 if (response.empty()) {
00249 string msg = string("failed to receive a response from ")+cmd1;
00250 AX2550_THROW(CommandFailedException, msg.c_str());
00251 }
00252
00253 char fillbyte;
00254
00255 if(response.substr(0,1).find_first_of("01234567") != std::string::npos) {
00256
00257 fillbyte = '0';
00258 } else {
00259
00260 fillbyte = 'F';
00261 }
00262
00263 size_t difference = 8 - response.length();
00264 string filler(difference, fillbyte);
00265 response.insert(0, filler);
00266
00267 signed int encoder = 0;
00268 sscanf(response.c_str(), "%X", &encoder);
00269 encoder1 = encoder;
00270
00271 fillbyte = '0';
00272 difference = 0;
00273 filler = "";
00274 encoder = 0;
00275
00276 response = this->encoders_filt_->wait(100);
00277 if (response.empty()) {
00278 string msg = "failed to receive a response from "+cmd2;
00279 AX2550_THROW(CommandFailedException, msg.c_str());
00280 }
00281
00282
00283 if(response.substr(0,1).find_first_of("01234567") != std::string::npos) {
00284
00285 fillbyte = '0';
00286 } else {
00287
00288 fillbyte = 'F';
00289 }
00290
00291 difference = 8 - response.length();
00292 filler = string(difference, fillbyte);
00293 response.insert(0, filler);
00294
00295 encoder = 0;
00296 sscanf(response.c_str(), "%X", &encoder);
00297 encoder2 = encoder;
00298 }
00299
00300 void
00301 AX2550::sync_ () {
00302 if (this->synced_)
00303 return;
00304 boost::mutex::scoped_lock lock(this->mc_mutex);
00305
00306 this->serial_port_->write("%rrrrrr\r");
00307
00308 {
00309 BufferedFilterPtr rc_msg_filt =
00310 this->serial_listener_.createBufferedFilter(
00311 SerialListener::startsWith(":"));
00312 rc_msg_filt->clear();
00313 if (rc_msg_filt->wait(2000).empty()) {
00314 AX2550_THROW(SynchronizationException,
00315 "did not receive an R/C message after reset");
00316 }
00317 }
00318
00319 BufferedFilterPtr ok_filt =
00320 this->serial_listener_.createBufferedFilter(
00321 SerialListener::contains("OK"));
00322 bool got_ok = false;
00323 for (int i = 0; i < 20; ++i) {
00324 this->serial_port_->write("\r");
00325 if (!ok_filt->wait(50).empty()) {
00326 got_ok = true;
00327 break;
00328 }
00329 }
00330
00331 if (!got_ok) {
00332 AX2550_THROW(SynchronizationException, "failed to get into serial mode");
00333 }
00334 this->synced_ = true;
00335 this->info("Synchronized with the ax2550");
00336 }
00337
00338 inline bool
00339 isAnEncoderMsg (const string &token) {
00340 string test = "0123456789abcdefABCDEF";
00341 #if 0
00342 std::cout << "isAnEncoderMsg: Is `" << token
00343 << "` an encoder message?: ";
00344 if (token.substr(0,1).find_first_of(test) != string::npos) {
00345 std::cout << "True";
00346 } else {
00347 std::cout << "False";
00348 }
00349 std::cout << std::endl;
00350 #endif
00351
00352 if (token.substr(0,1).find_first_of(test) != string::npos) {
00353 return true;
00354 }
00355 return false;
00356 }
00357
00358 void
00359 AX2550::watchDogCallback_ (const string &token) {
00360 if (this->watch_dog_callback != NULL) {
00361 this->watch_dog_callback();
00362 }
00363 }
00364
00365 inline bool
00366 isAckOrNak (const string &token) {
00367 #if 0
00368 std::cout << "isAckOrNak: Is `" << token
00369 << "` an ack or nak?: ";
00370 if (token.find_first_of("+-") != string::npos) {
00371 std::cout << "True";
00372 } else {
00373 std::cout << "False";
00374 }
00375 std::cout << std::endl;
00376 #endif
00377 if (token.find_first_of("+-") != string::npos) {
00378 return true;
00379 }
00380 return false;
00381 }
00382
00383 void
00384 AX2550::setupFilters_ () {
00385
00386 this->encoders_filt_ =
00387 this->serial_listener_.createBufferedFilter(isAnEncoderMsg);
00388
00389 this->watch_dog_filt_ = this->serial_listener_.createFilter(
00390 SerialListener::exactly("W"),
00391 boost::bind(&AX2550::watchDogCallback_, this, _1));
00392
00393 this->ack_nak_filt_ =
00394 this->serial_listener_.createBufferedFilter(isAckOrNak);
00395
00396
00397
00398 }
00399
00400
00401
00402
00403