00001
00002
00003 #include "ROSComm.hh"
00004 #include "FRIComm.hh"
00005 #include "FRICheck.hh"
00006 #include <signal.h>
00007 #include <pthread.h>
00008
00009 using namespace std;
00010
00011 ROSComm::ROSComm() :
00012 soft_runstop_handler_(0), n_(0), diagnostic_(0),
00013 running_(false), exitRequested_(false)
00014 {
00015 memset(&status_, 0, sizeof(status_));
00016 }
00017
00018 ROSComm::~ROSComm()
00019 {
00020 delete n_;
00021 delete diagnostic_;
00022 delete soft_runstop_handler_;
00023 }
00024
00025 bool ROSComm::configure(FRIThread *fri)
00026 {
00027 if(!ros::master::check())
00028 return false;
00029
00030 if(!n_)
00031 n_ = new ros::NodeHandle("~");
00032
00033 int local_port=0, remote_port=0;
00034 std::string remote_ip;
00035 bool ok = true;
00036
00037 ok &= n_->getParam("local_port", local_port);
00038 ok &= n_->getParam("remote_port", remote_port);
00039 ok &= n_->getParam("remote_ip", remote_ip);
00040
00041 if(ok)
00042 fri->configureNetwork(local_port, remote_ip.c_str(), remote_port);
00043
00044 n_->param("side", side_, std::string("none"));
00045
00046 if(side_ == "left")
00047 fri->limitChecker()->setHandSide(FRICheck::LEFT);
00048 else if(side_ == "right")
00049 fri->limitChecker()->setHandSide(FRICheck::RIGHT);
00050 else
00051 fri->limitChecker()->setHandSide(FRICheck::NONE);
00052
00053 if(ok)
00054 ROS_INFO("connecting to %s arm: [%d -> %s:%d]",
00055 side_.c_str(), local_port, remote_ip.c_str(), remote_port);
00056
00057 joint_state_.name.resize(7);
00058 joint_state_.position.resize(7);
00059 joint_state_.velocity.resize(7);
00060 joint_state_.effort.resize(7);
00061
00062 for(int i=0; i < 7; i++) {
00063 joint_state_.name[i] = side_+string("_arm_")+string(1,'0'+i)+string("_joint");
00064 }
00065
00066 n_->param("rate", rate_, 125.0);
00067
00068 return ok;
00069 }
00070
00071 #define CLAMP(v, min, max) ((v <= min) ? min : ((v >= max) ? max : v))
00072
00073 void ROSComm::status_update(diagnostic_updater::DiagnosticStatusWrapper &s)
00074 {
00075 int quality = CLAMP(status_.quality, 0, 3);
00076 int state = CLAMP(status_.state, 0, 2);
00077 int control_mode = CLAMP(status_.controlMode, 0, 3);
00078
00079 char qualities[] = {'x', '-', '+', '*'};
00080 char comm_states[] = {'0', 'M', 'C'};
00081
00082 unsigned char level = (state == 2 && status_.power == 0x7f)
00083 ? (unsigned char) diagnostic_msgs::DiagnosticStatus::OK
00084 : (unsigned char) diagnostic_msgs::DiagnosticStatus::ERROR;
00085
00086 s.summaryf(level, "%c%c",
00087 comm_states[state],
00088 qualities[quality]);
00089
00090 const char *quality_strings[] = {"Unacceptable", "Bad", "Okay", "Perfect"};
00091 const char *state_strings[] = {"Reset", "Monitor", "Command"};
00092 const char *control_modes[] = {"Other", "Position", "Cartesian Impedance", "Joint Impedance"};
00093
00094 double freq = (status_.cmdSampleTime==0.0) ? 0.0 : 1.0/status_.cmdSampleTime;
00095
00096 s.addf("Runstop", "%s", (status_.runstop) ? "ON" : "off");
00097 s.addf("Interface Mode", "%s", state_strings[state]);
00098 s.addf("Control Mode", "%s", control_modes[control_mode]);
00099 s.addf("Comm. Status", "%s", (status_.connected) ? "Connected": "Offline");
00100 s.addf("Comm. frequency", "%3.1f Hz", freq);
00101 s.addf("Comm. answer rate", "%3.3f", status_.answerRate);
00102 s.addf("Comm. latency", "%5.5f", status_.latency);
00103 s.addf("Comm. jitter", "%5.5f", status_.jitter);
00104 s.addf("Comm. miss rate", "%5.5f", status_.missRate);
00105 s.addf("Comm. miss counter", "%d", status_.missCounter);
00106 s.addf("Comm. quality", "%s", quality_strings[quality]);
00107 s.addf("Safety Factor", "%f", status_.safety);
00108 s.addf("Mean computation time", "%d us", status_.calcTimeMean);
00109 s.addf("Max computation time", "%d us", status_.calcTimeMax);
00110 s.addf("Motor State", "%s", (status_.power == 0x7f) ? "ON" : "OFF");
00111
00112 float *t=status_.temperature;
00113 s.addf("Temperatures [deg C]", "%3.1f %3.1f %3.1f %3.1f %3.1f %3.1f %3.1f",
00114 t[0], t[1], t[2], t[3], t[4], t[5], t[6]);
00115 }
00116
00117 bool ROSComm::open()
00118 {
00119
00120 if(!ros::master::check())
00121 return false;
00122
00123 if(!n_)
00124 n_ = new ros::NodeHandle("~");
00125
00126 soft_runstop_handler_ = new soft_runstop::Handler(Duration(0.5));
00127 pub_ = n_->advertise<sensor_msgs::JointState>("/joint_states", 1);
00128 sub_ = n_->subscribe("command", 1, &ROSComm::impedanceCommand, this);
00129
00130 string Side = side_;
00131 Side[0] = side_[0] + ('A'-'a');
00132
00133 diagnostic_ = new diagnostic_updater::Updater();
00134 diagnostic_->setHardwareID(string("kuka_lwr_")+string(side_));
00135 diagnostic_->add("Arm "+Side, this, &ROSComm::status_update);
00136
00137 return true;
00138 }
00139
00140
00141 void ROSComm::publishData(const RobotData &data, const RobotCommand &cmd)
00142 {
00143
00144 joint_state_.header.stamp = ros::Time::now();
00145
00146 for(int i=0; i < 7; i++) {
00147 joint_state_.position[i] = data.position[i];
00148 joint_state_.velocity[i] = 0.0;
00149 double dist = cmd.stiffness[i]*fabs(data.position[i] - data.commanded[i]);
00150 double stiffness = cmd.stiffness[i];
00151 joint_state_.effort[i] = stiffness*dist;
00152 }
00153
00154 pub_.publish(joint_state_);
00155 }
00156
00157
00158 void ROSComm::publishStatus(const RobotStatus &status)
00159 {
00160 status_ = status;
00161 diagnostic_->update();
00162 }
00163
00164
00165 void ROSComm::impedanceCommand(const kuka_fri::ImpedanceCommand::ConstPtr& msg)
00166 {
00167 RobotCommand cmd = fri_->cmd();
00168
00169 if (msg->velocity.size() == 7)
00170 for (int i=0; i<7; i++)
00171 cmd.command[i] = msg->velocity[i];
00172
00173 if (msg->stiffness.size() == 7)
00174 for (int i=0; i<7; i++)
00175 cmd.stiffness[i] = msg->stiffness[i];
00176
00177 if (msg->damping.size() == 7)
00178 for (int i=0; i<7; i++)
00179 cmd.damping[i] = msg->damping[i];
00180
00181 if (msg->add_torque.size() == 7)
00182 for (int i=0; i<7; i++)
00183 cmd.addTorque[i] = msg->add_torque[i];
00184
00185 fri_->setCmd(cmd);
00186 }
00187
00188
00189 bool ROSComm::runstop()
00190 {
00191 return soft_runstop_handler_->getState();
00192 }
00193
00194
00195 void ROSComm::start(FRIThread *fri)
00196 {
00197 fri_ = fri;
00198 pthread_create(&thread_, 0, &ROSComm::run_s, (void *) this);
00199 }
00200
00201
00202 void* ROSComm::run()
00203 {
00204 while(!open() && !exitRequested_)
00205 usleep(200000);
00206
00207 running_ = true;
00208
00209
00210 RobotData data;
00211 RobotStatus status;
00212 RobotCommand cmd;
00213
00214 memset(&status, 0, sizeof(status));
00215
00216 int seq=0;
00217
00218 ros::Rate loop_rate(rate_);
00219
00220 while(!exitRequested_) {
00221
00222 fri_->setRunstop(runstop());
00223
00224 cmd = fri_->cmd();
00225 data = fri_->data();
00226 status = fri_->status();
00227
00228 if(seq != data.seq) {
00229 publishData(data, cmd);
00230 }
00231 publishStatus(status);
00232
00233 seq = data.seq;
00234
00235 ros::spinOnce();
00236 loop_rate.sleep();
00237 }
00238 running_ = false;
00239
00240 return 0;
00241 }
00242
00243
00244 void ROSComm::finish()
00245 {
00246 exitRequested_=true;
00247 ros::requestShutdown();
00248 pthread_join(thread_, 0);
00249 }