00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <sensor_msgs/JointState.h>
00019
00020 #include <diagnostic_msgs/DiagnosticArray.h>
00021
00022 #include <XmlRpcValue.h>
00023
00024 #include "naoqi_dcm_driver/robot.hpp"
00025 #include "naoqi_dcm_driver/tools.hpp"
00026
00027 QI_REGISTER_OBJECT( Robot,
00028 isConnected,
00029 connect,
00030 stopService);
00031
00032 Robot::Robot(qi::SessionPtr session):
00033 _session(session),
00034 session_name_("naoqi_dcm_driver"),
00035 is_connected_(false),
00036 nhPtr_(new ros::NodeHandle("")),
00037 body_type_(""),
00038 topic_queue_(10),
00039 prefix_("naoqi_dcm"),
00040 high_freq_(50.0),
00041 controller_freq_(15.0),
00042 joint_precision_(0.1),
00043 odom_frame_("odom"),
00044 use_dcm_(false),
00045 stiffness_value_(0.9f)
00046 {
00047 }
00048
00049 Robot::~Robot()
00050 {
00051 stopService();
00052 }
00053
00054 void Robot::stopService() {
00055 ROS_INFO_STREAM(session_name_ << " stopping the service...");
00056
00057 if (motion_)
00058 {
00059
00060
00061 if(use_dcm_)
00062 motion_->setStiffnessArms(0.0f, 2.0f);
00063
00064
00065 if (motor_groups_.size() == 1)
00066 if (motor_groups_[0] == "Body")
00067 motion_->rest();
00068
00069
00070
00071 motion_->setStiffnessArms(0.0f, 2.0f);
00072 }
00073
00074 is_connected_ = false;
00075
00076 if(nhPtr_)
00077 {
00078 nhPtr_->shutdown();
00079 ros::shutdown();
00080 }
00081 }
00082
00083 bool Robot::initializeControllers(const std::vector <std::string> &joints)
00084 {
00085 int joints_nbr = joints.size();
00086
00087
00088 hw_angles_.reserve(joints_nbr);
00089 hw_velocities_.reserve(joints_nbr);
00090 hw_efforts_.reserve(joints_nbr);
00091 hw_commands_.reserve(joints_nbr);
00092
00093 hw_angles_.resize(joints_nbr);
00094 hw_velocities_.resize(joints_nbr);
00095 hw_efforts_.resize(joints_nbr);
00096 hw_commands_.resize(joints_nbr);
00097
00098 try
00099 {
00100 for(int i=0; i<joints_nbr; ++i)
00101 {
00102 hardware_interface::JointStateHandle state_handle(joints.at(i),
00103 &hw_angles_[i],
00104 &hw_velocities_[i],
00105 &hw_efforts_[i]);
00106 jnt_state_interface_.registerHandle(state_handle);
00107
00108 hardware_interface::JointHandle pos_handle(jnt_state_interface_.getHandle(joints.at(i)),
00109 &hw_commands_[i]);
00110 jnt_pos_interface_.registerHandle(pos_handle);
00111 }
00112
00113 registerInterface(&jnt_state_interface_);
00114 registerInterface(&jnt_pos_interface_);
00115 }
00116 catch(const ros::Exception& e)
00117 {
00118 ROS_ERROR("Could not initialize hardware interfaces!\n\tTrace: %s", e.what());
00119 return false;
00120 }
00121
00122 return true;
00123 }
00124
00125
00126 bool Robot::connect()
00127 {
00128 is_connected_ = false;
00129
00130
00131 if (!loadParams())
00132 return false;
00133
00134
00135 if (use_dcm_)
00136 dcm_ = boost::shared_ptr<DCM>(new DCM(_session, controller_freq_));
00137
00138
00139 memory_ = boost::shared_ptr<Memory>(new Memory(_session));
00140
00141
00142 std::string robot = memory_->getData("RobotConfig/Body/Type");
00143 std::transform(robot.begin(), robot.end(), robot.begin(), ::tolower);
00144
00145
00146 motion_ = boost::shared_ptr<Motion>(new Motion(_session));
00147
00148
00149 if (motor_groups_.size() == 1)
00150 {
00151 if (motor_groups_[0] == "Body")
00152 motion_->wakeUp();
00153 }
00154 else if (!use_dcm_)
00155 motion_->wakeUp();
00156 if (!motion_->robotIsWakeUp())
00157 {
00158 ROS_ERROR("Please, wakeUp the robot to be able to set stiffness");
00159 stopService();
00160 return false;
00161 }
00162
00163 if (use_dcm_)
00164 motion_->manageConcurrence();
00165
00166
00167 qi_joints_ = motion_->getBodyNamesFromGroup(motor_groups_);
00168 if (qi_joints_.empty())
00169 ROS_ERROR("Controlled joints are not known.");
00170
00171 if (hw_joints_.empty())
00172 {
00173 ROS_INFO_STREAM("Initializing the HW controlled joints with Naoqi joints.");
00174 hw_joints_.reserve(qi_joints_.size());
00175 copy(qi_joints_.begin(), qi_joints_.end(), back_inserter(hw_joints_));
00176 }
00177 ROS_INFO_STREAM("HW controlled joints are : " << print(hw_joints_));
00178
00179 ignoreMimicJoints(&qi_joints_);
00180 ROS_INFO_STREAM("Naoqi controlled joints are : " << print(qi_joints_));
00181 qi_commands_.reserve(qi_joints_.size());
00182 qi_commands_.resize(qi_joints_.size(), 0.0);
00183
00184
00185 memory_->init(qi_joints_);
00186 motion_->init(qi_joints_);
00187 if (use_dcm_)
00188 dcm_->init(qi_joints_);
00189
00190 hw_enabled_ = checkJoints();
00191
00192
00193 joint_states_topic_.header.frame_id = "base_link";
00194 joint_states_topic_.name = motion_->getBodyNames("Body");
00195 joint_states_topic_.position.resize(joint_states_topic_.name.size());
00196
00197
00198 std::vector<std::string> joints_all_names = motion_->getBodyNames("JointActuators");
00199 diagnostics_ = boost::shared_ptr<Diagnostics>(
00200 new Diagnostics(_session, &diag_pub_, joints_all_names, robot));
00201
00202 is_connected_ = true;
00203
00204
00205 subscribe();
00206
00207
00208 if (!setStiffness(stiffness_value_))
00209 return false;
00210
00211
00212 try
00213 {
00214 manager_ = new controller_manager::ControllerManager( this, *nhPtr_);
00215 }
00216 catch(const ros::Exception& e)
00217 {
00218 ROS_ERROR("Could not initialize controller manager!\n\tTrace: %s", e.what());
00219 return false;
00220 }
00221
00222 if(!initializeControllers(hw_joints_))
00223 return false;
00224
00225 ROS_INFO_STREAM(session_name_ << " module initialized!");
00226 return true;
00227 }
00228
00229 void Robot::subscribe()
00230 {
00231
00232 cmd_moveto_sub_ = nhPtr_->subscribe(prefix_+"cmd_moveto", 1, &Robot::commandVelocity, this);
00233
00234 diag_pub_ = nhPtr_->advertise<diagnostic_msgs::DiagnosticArray>(prefix_+"diagnostics", topic_queue_);
00235
00236 stiffness_pub_ = nhPtr_->advertise<std_msgs::Float32>(prefix_+"stiffnesses", topic_queue_);
00237 stiffness_.data = 1.0f;
00238
00239 joint_states_pub_ = nhPtr_->advertise<sensor_msgs::JointState>("/joint_states", topic_queue_);
00240 }
00241
00242 bool Robot::loadParams()
00243 {
00244 ros::NodeHandle nh("~");
00245
00246 nh.getParam("BodyType", body_type_);
00247 nh.getParam("TopicQueue", topic_queue_);
00248 nh.getParam("HighCommunicationFrequency", high_freq_);
00249 nh.getParam("ControllerFrequency", controller_freq_);
00250 nh.getParam("JointPrecision", joint_precision_);
00251 nh.getParam("OdomFrame", odom_frame_);
00252 nh.getParam("use_dcm", use_dcm_);
00253
00254 if (nh.hasParam("max_stiffness"))
00255 nh.getParam("max_stiffness", stiffness_value_);
00256
00257 if (use_dcm_)
00258 ROS_WARN_STREAM("Please, be carefull! "
00259 << "You have chosen to control the robot based on DCM. "
00260 << "It leads to concurrence between DCM and ALMotion, and "
00261 << "it can cause shaking the robot. "
00262 << "If the robot starts shaking, stop the node (Ctrl+C). "
00263 << "Use either ALMotion or stop ALMotion and use DCM only.");
00264
00265
00266 nh.getParam("Prefix", prefix_);
00267 if (prefix_.length() > 0)
00268 if (prefix_.at(prefix_.length()-1) != '/')
00269 prefix_ += "/";
00270
00271
00272 XmlRpc::XmlRpcValue params_pepper_dcm;
00273 nh.getParam("pepper_dcm", params_pepper_dcm);
00274 if (params_pepper_dcm.getType() != XmlRpc::XmlRpcValue::TypeStruct)
00275 ROS_ERROR("Please ensure that the list of controllers is TypeStruct");
00276
00277 XmlRpc::XmlRpcValue::ValueStruct::const_iterator it=params_pepper_dcm.begin();
00278 for (; it != params_pepper_dcm.end(); ++it)
00279 {
00280 XmlRpc::XmlRpcValue::ValueStruct::const_iterator it2 = params_pepper_dcm[it->first].begin();
00281 for (; it2 != params_pepper_dcm[it->first].end(); ++it2)
00282 {
00283 std::string param = (std::string)(it2->first);
00284 if (param.compare("joints") == 0)
00285 {
00286 XmlRpc::XmlRpcValue params_joints = params_pepper_dcm[it->first][it2->first];
00287 if (params_joints.getType() == XmlRpc::XmlRpcValue::TypeArray)
00288 {
00289 xmlToVector(params_joints, &hw_joints_);
00290 continue;
00291 }
00292 }
00293 }
00294 }
00295
00296
00297 std::string motor_groups_temp = "";
00298 nh.getParam("motor_groups", motor_groups_temp);
00299 motor_groups_ = toVector(motor_groups_temp);
00300 if (motor_groups_.empty())
00301 {
00302 motor_groups_.push_back("LArm");
00303 motor_groups_.push_back("RArm");
00304 }
00305 return true;
00306 }
00307
00308 void Robot::run()
00309 {
00310 controllerLoop();
00311 }
00312
00313 void Robot::controllerLoop()
00314 {
00315 static ros::Rate rate(controller_freq_);
00316 while(ros::ok())
00317 {
00318 ros::Time time = ros::Time::now();
00319
00320 if(!is_connected_)
00321 break;
00322
00323
00324
00325 stiffness_pub_.publish(stiffness_);
00326
00327 if (!diagnostics_->publish())
00328 stopService();
00329
00330 readJoints();
00331
00332
00333
00334 try
00335 {
00336 manager_->update(time, ros::Duration(1.0f/controller_freq_));
00337 }
00338 catch(ros::Exception& e)
00339 {
00340 ROS_ERROR("%s", e.what());
00341 return;
00342 }
00343
00344 writeJoints();
00345
00346
00347
00348
00349 rate.sleep();
00350 }
00351 ROS_INFO_STREAM("Shutting down the main loop");
00352 }
00353
00354 bool Robot::isConnected()
00355 {
00356 return is_connected_;
00357 }
00358
00359 void Robot::commandVelocity(const geometry_msgs::TwistConstPtr &msg)
00360 {
00361
00362 if(use_dcm_)
00363 motion_->setStiffnessArms(0.0f, 1.0f);
00364
00365 motion_->moveTo(msg->linear.x, msg->linear.y, msg->angular.z);
00366 sleep(1.0);
00367
00368
00369 if(use_dcm_)
00370 motion_->setStiffnessArms(1.0f, 1.0f);
00371 }
00372
00373 void Robot::publishBaseFootprint(const ros::Time &ts)
00374 {
00375 std::string odom_frame, base_link_frame;
00376 try
00377 {
00378 odom_frame = base_footprint_listener_.resolve(odom_frame_);
00379 base_link_frame = base_footprint_listener_.resolve("base_link");
00380 }
00381 catch(ros::Exception& e)
00382 {
00383 ROS_ERROR("%s", e.what());
00384 return;
00385 }
00386
00387 tf::StampedTransform tf_odom_to_base, tf_odom_to_left_foot, tf_odom_to_right_foot;
00388 double temp_freq = 1.0f/(10.0*high_freq_);
00389 if(!base_footprint_listener_.waitForTransform(odom_frame, base_link_frame, ros::Time(0), ros::Duration(temp_freq)))
00390 return;
00391 try
00392 {
00393 base_footprint_listener_.lookupTransform(odom_frame, base_link_frame, ros::Time(0), tf_odom_to_base);
00394 }
00395 catch (const tf::TransformException& ex)
00396 {
00397 ROS_ERROR("%s",ex.what());
00398 return ;
00399 }
00400
00401 tf::Vector3 new_origin = (tf_odom_to_right_foot.getOrigin() + tf_odom_to_left_foot.getOrigin())/2.0;
00402 double height = std::min(tf_odom_to_left_foot.getOrigin().getZ(), tf_odom_to_right_foot.getOrigin().getZ());
00403 new_origin.setZ(height);
00404
00405 double roll, pitch, yaw;
00406 tf_odom_to_base.getBasis().getRPY(roll, pitch, yaw);
00407
00408 tf::Transform tf_odom_to_footprint(tf::createQuaternionFromYaw(yaw), new_origin);
00409 tf::Transform tf_base_to_footprint = tf_odom_to_base.inverse() * tf_odom_to_footprint;
00410
00411 base_footprint_broadcaster_.sendTransform(tf::StampedTransform(tf_base_to_footprint, ts,
00412 base_link_frame, "base_footprint"));
00413 }
00414
00415 std::vector <bool> Robot::checkJoints()
00416 {
00417 std::vector <bool> hw_enabled;
00418 hw_enabled.reserve(hw_joints_.size());
00419 hw_enabled.resize(hw_joints_.size(), false);
00420
00421
00422 std::vector<std::string>::iterator hw_j = hw_joints_.begin();
00423 std::vector<std::string>::iterator qi_j = qi_joints_.begin();
00424 std::vector<bool>::iterator hw_enabled_j = hw_enabled.begin();
00425
00426 for(; hw_j != hw_joints_.end(); ++hw_j, ++hw_enabled_j)
00427 {
00428 if (*hw_j == *qi_j)
00429 {
00430 *hw_enabled_j = true;
00431 ++qi_j;
00432 }
00433 }
00434 return hw_enabled;
00435 }
00436
00437 void Robot::readJoints()
00438 {
00439
00440 std::vector<float> qi_joints_positions = memory_->getListData();
00441
00442
00443 std::vector<double>::iterator hw_command_j = hw_commands_.begin();
00444 std::vector<double>::iterator hw_angle_j = hw_angles_.begin();
00445 std::vector<float>::iterator qi_position_j = qi_joints_positions.begin();
00446 std::vector<bool>::iterator hw_enabled_j = hw_enabled_.begin();
00447
00448 for(; hw_command_j != hw_commands_.end(); ++hw_command_j, ++hw_angle_j, ++hw_enabled_j)
00449 {
00450 if (!*hw_enabled_j)
00451 continue;
00452
00453 *hw_angle_j = *qi_position_j;
00454
00455 *hw_command_j = *qi_position_j;
00456
00457
00458 ++qi_position_j;
00459 }
00460 }
00461
00462 void Robot::publishJointStateFromAlMotion(){
00463 joint_states_topic_.header.stamp = ros::Time::now();
00464
00465 std::vector<double> position_data = motion_->getAngles("Body");
00466 for(int i = 0; i<position_data.size(); ++i)
00467 joint_states_topic_.position[i] = position_data[i];
00468
00469 joint_states_pub_.publish(joint_states_topic_);
00470 }
00471
00472 void Robot::writeJoints()
00473 {
00474
00475 bool changed(false);
00476 std::vector<double>::iterator hw_angle_j = hw_angles_.begin();
00477 std::vector<double>::iterator hw_command_j = hw_commands_.begin();
00478 std::vector<double>::iterator qi_command_j = qi_commands_.begin();
00479 std::vector<bool>::iterator hw_enabled_j = hw_enabled_.begin();
00480 for(int i=0; hw_command_j != hw_commands_.end(); ++i, ++hw_command_j, ++hw_angle_j, ++hw_enabled_j)
00481 {
00482 if (!*hw_enabled_j)
00483 continue;
00484
00485 *qi_command_j = *hw_command_j;
00486 ++qi_command_j;
00487
00488 double diff = std::fabs(*hw_command_j - *hw_angle_j);
00489 if(diff > joint_precision_)
00490 {
00491
00492 changed = true;
00493 break;
00494 }
00495 }
00496
00497
00498 if(!changed)
00499 return;
00500
00501 if (use_dcm_)
00502 dcm_->writeJoints(qi_commands_);
00503 else
00504 motion_->writeJoints(qi_commands_);
00505 }
00506
00507 void Robot::ignoreMimicJoints(std::vector <std::string> *joints)
00508 {
00509
00510 for(std::vector<std::string>::iterator it=joints->begin(); it!=joints->end(); ++it)
00511 {
00512 if( (it->find("Wheel") != std::string::npos)
00513 || (*it=="RHand" || *it=="LHand" || *it == "RWristYaw" || *it == "LWristYaw") && (body_type_ == "H21"))
00514 {
00515 joints->erase(it);
00516 it--;
00517 }
00518 }
00519 }
00520
00521
00522 bool Robot::setStiffness(const float &stiffness)
00523 {
00524 stiffness_.data = stiffness;
00525
00526 if (!motion_->stiffnessInterpolation(motor_groups_, stiffness, 2.0f))
00527 return false;
00528
00529 return true;
00530 }