ur_communication.cpp
Go to the documentation of this file.
00001 /*
00002  * ur_communication.cpp
00003  *
00004  * Copyright 2015 Thomas Timm Andersen
00005  *
00006  * Licensed under the Apache License, Version 2.0 (the "License");
00007  * you may not use this file except in compliance with the License.
00008  * You may obtain a copy of the License at
00009  *
00010  *     http://www.apache.org/licenses/LICENSE-2.0
00011  *
00012  * Unless required by applicable law or agreed to in writing, software
00013  * distributed under the License is distributed on an "AS IS" BASIS,
00014  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015  * See the License for the specific language governing permissions and
00016  * limitations under the License.
00017  */
00018 
00019 #include "ur_modern_driver/ur_communication.h"
00020 
00021 UrCommunication::UrCommunication(std::condition_variable& msg_cond,
00022                 std::string host) {
00023         robot_state_ = new RobotState(msg_cond);
00024         bzero((char *) &pri_serv_addr_, sizeof(pri_serv_addr_));
00025         bzero((char *) &sec_serv_addr_, sizeof(sec_serv_addr_));
00026         pri_sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
00027         if (pri_sockfd_ < 0) {
00028                 print_fatal("ERROR opening socket pri_sockfd");
00029         }
00030         sec_sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
00031         if (sec_sockfd_ < 0) {
00032                 print_fatal("ERROR opening socket sec_sockfd");
00033         }
00034         server_ = gethostbyname(host.c_str());
00035         if (server_ == NULL) {
00036                 print_fatal("ERROR, unknown host");
00037         }
00038         pri_serv_addr_.sin_family = AF_INET;
00039         sec_serv_addr_.sin_family = AF_INET;
00040         bcopy((char *) server_->h_addr, (char *)&pri_serv_addr_.sin_addr.s_addr, server_->h_length);
00041         bcopy((char *) server_->h_addr, (char *)&sec_serv_addr_.sin_addr.s_addr, server_->h_length);
00042         pri_serv_addr_.sin_port = htons(30001);
00043         sec_serv_addr_.sin_port = htons(30002);
00044         flag_ = 1;
00045         setsockopt(pri_sockfd_, IPPROTO_TCP, TCP_NODELAY, (char *) &flag_,
00046                         sizeof(int));
00047         setsockopt(pri_sockfd_, IPPROTO_TCP, TCP_QUICKACK, (char *) &flag_,
00048                         sizeof(int));
00049         setsockopt(pri_sockfd_, SOL_SOCKET, SO_REUSEADDR, (char *) &flag_,
00050                         sizeof(int));
00051         setsockopt(sec_sockfd_, IPPROTO_TCP, TCP_NODELAY, (char *) &flag_,
00052                         sizeof(int));
00053         setsockopt(sec_sockfd_, IPPROTO_TCP, TCP_QUICKACK, (char *) &flag_,
00054                         sizeof(int));
00055         setsockopt(sec_sockfd_, SOL_SOCKET, SO_REUSEADDR, (char *) &flag_,
00056                         sizeof(int));
00057         fcntl(sec_sockfd_, F_SETFL, O_NONBLOCK);
00058         connected_ = false;
00059         keepalive_ = false;
00060 }
00061 
00062 bool UrCommunication::start() {
00063         keepalive_ = true;
00064         uint8_t buf[512];
00065         unsigned int bytes_read;
00066         std::string cmd;
00067         bzero(buf, 512);
00068         print_debug("Acquire firmware version: Connecting...");
00069         if (connect(pri_sockfd_, (struct sockaddr *) &pri_serv_addr_,
00070                         sizeof(pri_serv_addr_)) < 0) {
00071                 print_fatal("Error connecting to get firmware version");
00072                 return false;
00073         }
00074         print_debug("Acquire firmware version: Got connection");
00075         bytes_read = read(pri_sockfd_, buf, 512);
00076         setsockopt(pri_sockfd_, IPPROTO_TCP, TCP_QUICKACK, (char *) &flag_,
00077                         sizeof(int));
00078         robot_state_->unpack(buf, bytes_read);
00079         //wait for some traffic so the UR socket doesn't die in version 3.1.
00080         std::this_thread::sleep_for(std::chrono::milliseconds(500));
00081         char tmp[64];
00082         sprintf(tmp, "Firmware version detected: %.7f", robot_state_->getVersion());
00083         print_debug(tmp);
00084         close(pri_sockfd_);
00085 
00086         print_debug(
00087                         "Switching to secondary interface for masterboard data: Connecting...");
00088 
00089         fd_set writefds;
00090         struct timeval timeout;
00091 
00092         connect(sec_sockfd_, (struct sockaddr *) &sec_serv_addr_,
00093                         sizeof(sec_serv_addr_));
00094         FD_ZERO(&writefds);
00095         FD_SET(sec_sockfd_, &writefds);
00096         timeout.tv_sec = 10;
00097         timeout.tv_usec = 0;
00098         select(sec_sockfd_ + 1, NULL, &writefds, NULL, &timeout);
00099         unsigned int flag_len;
00100         getsockopt(sec_sockfd_, SOL_SOCKET, SO_ERROR, &flag_, &flag_len);
00101         if (flag_ < 0) {
00102                 print_fatal("Error connecting to secondary interface");
00103                 return false;
00104         }
00105         print_debug("Secondary interface: Got connection");
00106         comThread_ = std::thread(&UrCommunication::run, this);
00107         return true;
00108 }
00109 
00110 void UrCommunication::halt() {
00111         keepalive_ = false;
00112         comThread_.join();
00113 }
00114 
00115 void UrCommunication::run() {
00116         uint8_t buf[2048];
00117         int bytes_read;
00118         bzero(buf, 2048);
00119         struct timeval timeout;
00120         fd_set readfds;
00121         FD_ZERO(&readfds);
00122         FD_SET(sec_sockfd_, &readfds);
00123         connected_ = true;
00124         while (keepalive_) {
00125                 while (connected_ && keepalive_) {
00126                         timeout.tv_sec = 0; //do this each loop as selects modifies timeout
00127                         timeout.tv_usec = 500000; // timeout of 0.5 sec
00128                         select(sec_sockfd_ + 1, &readfds, NULL, NULL, &timeout);
00129                         bytes_read = read(sec_sockfd_, buf, 2048); // usually only up to 1295 bytes
00130                         if (bytes_read > 0) {
00131                                 setsockopt(sec_sockfd_, IPPROTO_TCP, TCP_QUICKACK,
00132                                                 (char *) &flag_, sizeof(int));
00133                                 robot_state_->unpack(buf, bytes_read);
00134                         } else {
00135                                 connected_ = false;
00136                                 robot_state_->setDisconnected();
00137                                 close(sec_sockfd_);
00138                         }
00139                 }
00140                 if (keepalive_) {
00141                         //reconnect
00142                         print_warning("Secondary port: No connection. Is controller crashed? Will try to reconnect in 10 seconds...");
00143                         sec_sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
00144                         if (sec_sockfd_ < 0) {
00145                                 print_fatal("ERROR opening secondary socket");
00146                         }
00147                         flag_ = 1;
00148                         setsockopt(sec_sockfd_, IPPROTO_TCP, TCP_NODELAY, (char *) &flag_,
00149                                         sizeof(int));
00150                         setsockopt(sec_sockfd_, IPPROTO_TCP, TCP_QUICKACK, (char *) &flag_,
00151                                         sizeof(int));
00152                         setsockopt(sec_sockfd_, SOL_SOCKET, SO_REUSEADDR, (char *) &flag_,
00153                                         sizeof(int));
00154                         fcntl(sec_sockfd_, F_SETFL, O_NONBLOCK);
00155                         while (keepalive_ && !connected_) {
00156                                 std::this_thread::sleep_for(std::chrono::seconds(10));
00157                                 fd_set writefds;
00158 
00159                                 connect(sec_sockfd_, (struct sockaddr *) &sec_serv_addr_,
00160                                                 sizeof(sec_serv_addr_));
00161                                 FD_ZERO(&writefds);
00162                                 FD_SET(sec_sockfd_, &writefds);
00163                                 select(sec_sockfd_ + 1, NULL, &writefds, NULL, NULL);
00164                                 unsigned int flag_len;
00165                                 getsockopt(sec_sockfd_, SOL_SOCKET, SO_ERROR, &flag_,
00166                                                 &flag_len);
00167                                 if (flag_ < 0) {
00168                                         print_error("Error re-connecting to port 30002. Is controller started? Will try to reconnect in 10 seconds...");
00169                                 } else {
00170                                         connected_ = true;
00171                                         print_info("Secondary port: Reconnected");
00172                                 }
00173                         }
00174                 }
00175         }
00176 
00177         //wait for some traffic so the UR socket doesn't die in version 3.1.
00178         std::this_thread::sleep_for(std::chrono::milliseconds(500));
00179         close(sec_sockfd_);
00180 }
00181 


ur_modern_driver
Author(s): Thomas Timm Andersen
autogenerated on Wed Apr 3 2019 02:55:31