Go to the documentation of this file.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 #include <math.h>
00032 #include <unistd.h>
00033 #include <set>
00034
00035 #include <boost/thread.hpp>
00036
00037 #include "pr2_hardware_interface/hardware_interface.h"
00038 #include "pr2_controller_manager/controller_manager.h"
00039 #include "pr2_mechanism_model/robot.h"
00040 #include "tinyxml.h"
00041
00042 #include <XmlRpcValue.h>
00043 #include <XmlRpcException.h>
00044
00045 #include <ros/ros.h>
00046
00047 #include <urdf/model.h>
00048
00049 class LoopbackControllerManager
00050 {
00051 public:
00052 LoopbackControllerManager();
00053 virtual ~LoopbackControllerManager();
00054
00055
00056 void init();
00057 void update();
00058 void fini();
00059
00060 void run();
00061 private:
00062
00063 pr2_hardware_interface::HardwareInterface hw_;
00064 pr2_controller_manager::ControllerManager *cm_;
00065
00066 pr2_mechanism_model::RobotState *state_;
00067
00068 void readUrdf();
00069
00070 ros::NodeHandle* rosnode_;
00071 ros::Subscriber desired_angles_sub_;
00072
00073 void ControllerManagerROSThread();
00074 void jointCallback(const sensor_msgs::JointState::ConstPtr &joints);
00075 boost::thread* ros_spinner_thread_;
00076 boost::mutex lock;
00077
00078 double dt_;
00079 double damping_;
00080 double mass_;
00081
00082 void simulateJoints();
00083 };
00084
00085
00086 using namespace std;
00087 using namespace XmlRpc;
00088
00089
00090 LoopbackControllerManager::LoopbackControllerManager()
00091 : hw_(), state_(NULL), dt_(0.0)
00092 {
00093 }
00094
00095
00096 LoopbackControllerManager::~LoopbackControllerManager()
00097 {
00098 delete cm_;
00099 delete rosnode_;
00100 delete ros_spinner_thread_;
00101 }
00102
00103 void LoopbackControllerManager::jointCallback(const sensor_msgs::JointState::ConstPtr &joints)
00104 {
00105 boost::mutex::scoped_lock mutex(lock);
00106
00107 if(joints->name.size() != joints->position.size())
00108 {
00109 ROS_ERROR("received invalid desired joints.");
00110 return;
00111 }
00112
00113 for(unsigned int i=0; i < joints->name.size(); ++i)
00114 {
00115
00116
00117 state_->getJointState(joints->name[i])->position_ = joints->position[i];
00118 }
00119
00120 }
00121
00122 void LoopbackControllerManager::init()
00123 {
00124 rosnode_ = new ros::NodeHandle("/");
00125 cm_ = new pr2_controller_manager::ControllerManager(&hw_,*rosnode_);
00126 readUrdf();
00127
00128 ros::NodeHandle private_node = ros::NodeHandle("~");
00129 private_node.param("dt", dt_, 0.01);
00130 private_node.param("damping", damping_, 0.1);
00131 private_node.param("mass", mass_, 0.1);
00132
00133 desired_angles_sub_ = private_node.subscribe("desired_joints", 1, &LoopbackControllerManager::jointCallback, this);
00134
00135 state_ = cm_->state_;
00136
00137
00138 for(unsigned int i = 0; i < state_->joint_states_.size(); i++)
00139 {
00140 pr2_mechanism_model::JointState &s = state_->joint_states_[i];
00141 s.position_ = 0.0;
00142 s.velocity_ = 0.0;
00143 s.measured_effort_ = 0.0;
00144 s.commanded_effort_ = 0.0;
00145 }
00146
00147
00148 try
00149 {
00150 XmlRpcValue jointLists, nameList, valueList;
00151 if(private_node.getParam("joints", jointLists))
00152 {
00153 nameList = jointLists["name"];
00154 valueList = jointLists["position"];
00155 for (int index = 0; index < nameList.size(); index++)
00156 {
00157 pr2_mechanism_model::JointState *s =
00158 state_->getJointState((string) nameList[index]);
00159 if(s)
00160 s->position_ = (double) valueList[index];
00161 }
00162 }
00163 }
00164 catch(XmlRpcException e)
00165 {
00166
00167 ROS_WARN("Error parsing initial joint positions: %s", e.getMessage().c_str());
00168 }
00169
00170
00171
00172 for(unsigned int i = 0; i < state_->joint_states_.size(); i++)
00173 {
00174 pr2_mechanism_model::JointState &s = state_->joint_states_[i];
00175 const boost::shared_ptr<urdf::JointSafety> safety = s.joint_->safety;
00176
00177 if(safety)
00178 {
00179 double lower = safety->soft_lower_limit;
00180 double upper = safety->soft_upper_limit;
00181 if(lower != 0.0 || upper != 0.0)
00182 {
00183 double margin = (upper - lower) * 0.001;
00184 lower += margin;
00185 upper -= margin;
00186 double pos_old = s.position_;
00187
00188 s.position_ = (s.position_ < lower) ? lower : s.position_;
00189 s.position_ = (s.position_ > upper) ? upper : s.position_;
00190
00191 if(s.position_ != pos_old)
00192 ROS_INFO("adjusted joint %s to %f", s.joint_->name.c_str(), s.position_);
00193 }
00194 }
00195 }
00196
00197 hw_.current_time_ = ros::Time::now();
00198
00199
00200 ros_spinner_thread_ = new boost::thread( boost::bind( &LoopbackControllerManager::ControllerManagerROSThread,this ) );
00201
00202 }
00203
00204
00205 void LoopbackControllerManager::simulateJoints()
00206 {
00207
00208
00209 for (unsigned int i = 0; i < state_->joint_states_.size(); ++i)
00210 {
00211 pr2_mechanism_model::JointState &s = state_->joint_states_[i];
00212 const boost::shared_ptr<urdf::JointDynamics> dynamics = state_->joint_states_[i].joint_->dynamics;
00213
00214
00215 double damp = (dynamics) ? dynamics->damping : damping_;
00216 double effort = s.commanded_effort_ - damp*s.velocity_;
00217
00218 double dv = effort/mass_*dt_;
00219 s.velocity_ += dv;
00220
00221 double dx = s.velocity_*dt_;
00222 s.position_ += dx;
00223 }
00224 }
00225
00226
00227 void LoopbackControllerManager::update()
00228 {
00229 boost::mutex::scoped_lock mutex(lock);
00230
00231
00232 for (unsigned int i = 0; i < state_->joint_states_.size(); ++i)
00233 {
00234 state_->joint_states_[i].measured_effort_ = state_->joint_states_[i].commanded_effort_;
00235 }
00236
00237
00238 state_->propagateJointPositionToActuatorPosition();
00239
00240
00241
00242
00243
00244
00245 hw_.current_time_ = ros::Time::now();
00246
00247 try
00248 {
00249 cm_->update();
00250 }
00251 catch (const char* c)
00252 {
00253 if (strcmp(c,"dividebyzero")==0)
00254 ROS_WARN("pid controller reports divide by zero error");
00255 else
00256 ROS_WARN("unknown const char* exception: %s", c);
00257 }
00258
00259
00260
00261
00262
00263
00264 state_->propagateActuatorEffortToJointEffort();
00265
00266 simulateJoints();
00267 }
00268
00269 void LoopbackControllerManager::fini()
00270 {
00271 ROS_DEBUG("calling LoopbackControllerManager::fini");
00272
00273
00274
00275
00276 cm_->~ControllerManager();
00277 rosnode_->shutdown();
00278
00279 ros_spinner_thread_->join();
00280 }
00281
00282 void LoopbackControllerManager::readUrdf()
00283 {
00284 std::string urdf_string;
00285 rosnode_->getParam("/robot_description", urdf_string);
00286
00287
00288 TiXmlDocument doc;
00289 if (!doc.Parse(urdf_string.c_str()))
00290 {
00291 ROS_ERROR("Failed to load robot description");
00292 abort();
00293 }
00294
00295 struct GetActuators : public TiXmlVisitor
00296 {
00297 std::set<std::string> actuators;
00298 virtual bool VisitEnter(const TiXmlElement &elt, const TiXmlAttribute *)
00299 {
00300 if (elt.Attribute("name") &&
00301 ( elt.ValueStr() == std::string("actuator")
00302 || elt.ValueStr() == std::string("rightActuator")
00303 || elt.ValueStr() == std::string("leftActuator") ))
00304 actuators.insert(elt.Attribute("name"));
00305 return true;
00306 }
00307 } get_actuators;
00308 doc.RootElement()->Accept(&get_actuators);
00309
00310
00311 std::set<std::string>::iterator it;
00312 for (it = get_actuators.actuators.begin(); it != get_actuators.actuators.end(); ++it)
00313 {
00314
00315 pr2_hardware_interface::Actuator* pr2_actuator = new pr2_hardware_interface::Actuator(*it);
00316 pr2_actuator->state_.is_enabled_ = true;
00317 hw_.addActuator(pr2_actuator);
00318 }
00319
00320
00321 cm_->initXml(doc.RootElement());
00322
00323 for (unsigned int i = 0; i < cm_->state_->joint_states_.size(); ++i)
00324 cm_->state_->joint_states_[i].calibrated_ = true;
00325 }
00326
00327
00328 void LoopbackControllerManager::ControllerManagerROSThread()
00329 {
00330 ROS_INFO_STREAM("Callback thread id=" << boost::this_thread::get_id());
00331
00332 ros::Rate rate(0.2/dt_);
00333
00334 while (rosnode_->ok())
00335 {
00336 rate.sleep();
00337 ros::spinOnce();
00338 }
00339 }
00340
00341
00342 void LoopbackControllerManager::run()
00343 {
00344
00345 ros::Rate rate(1.0/dt_);
00346 while(rosnode_->ok())
00347 {
00348 update();
00349 rate.sleep();
00350 }
00351 }
00352
00353
00354 int main(int argc, char *argv[])
00355 {
00356 ros::init(argc,argv,"loopback_controllers");
00357
00358
00359 LoopbackControllerManager m;
00360
00361 m.init();
00362 m.run();
00363 m.fini();
00364 }