nao.cpp
Go to the documentation of this file.
00001 
00023 #include <iostream>
00024 #include "nao_dcm_driver/nao.h"
00025 #include <alerror/alerror.h>
00026 #include <alcommon/albroker.h>
00027 #include <algorithm>
00028 
00029 Nao::Nao(boost::shared_ptr<AL::ALBroker> broker, const string &name)
00030     : AL::ALModule(broker,name),is_connected_(false)
00031 {
00032     setModuleDescription("Nao Robot Module");
00033 
00034     functionName("brokerDisconnected", getName(), "Callback when broker disconnects!");
00035     BIND_METHOD(Nao::brokerDisconnected);
00036 }
00037 
00038 Nao::~Nao()
00039 {
00040     if(is_connected_)
00041         disconnect();
00042 }
00043 
00044 bool Nao::initialize()
00045 {
00046       // Joints Initialization
00047     const char* joint[] = {"HeadYaw",
00048                             "HeadPitch",
00049                             "LShoulderPitch",
00050                             "LShoulderRoll",
00051                             "LElbowYaw",
00052                             "LElbowRoll",
00053                             "LWristYaw",
00054                             "LHand",
00055                             "RShoulderPitch",
00056                             "RShoulderRoll",
00057                             "RElbowYaw",
00058                             "RElbowRoll",
00059                             "RWristYaw",
00060                             "RHand",
00061                             "LHipYawPitch",
00062                             "RHipYawPitch",
00063                             "LHipRoll",
00064                             "LHipPitch",
00065                             "LKneePitch",
00066                             "LAnklePitch",
00067                             "LAnkleRoll",
00068                             "RHipRoll",
00069                             "RHipPitch",
00070                             "RKneePitch",
00071                             "RAnklePitch",
00072                             "RAnkleRoll"};
00073     joint_names_ = vector<string>(joint, end(joint));
00074     
00075     for(vector<string>::iterator it=joint_names_.begin();it!=joint_names_.end();it++)
00076     {
00077         if((*it=="RHand" || *it=="LHand" || *it == "RWristYaw" || *it == "LWristYaw") && (body_type_ == "H21"))
00078         {
00079             joint_names_.erase(it);
00080             it--;
00081             continue;
00082         }
00083         joints_names_.push_back("Device/SubDeviceList/"+(*it)+"/Position/Sensor/Value");
00084         if(*it!="RHipYawPitch")
00085         {
00086             joint_temperature_names_.push_back("Device/SubDeviceList/"+(*it)+"/Temperature/Sensor/Value");
00087         }
00088     }
00089     number_of_joints_ = joint_names_.size();
00090 
00091     // DCM Motion Commands Initialization
00092     try
00093     {
00094         // Create Motion Command
00095         commands_.arraySetSize(4);
00096         commands_[0] = string("Joints");
00097         commands_[1] = string("ClearAll");
00098         commands_[2] = string("time-mixed");
00099         commands_[3].arraySetSize(number_of_joints_);
00100 
00101         // Create Joints Actuators Alias
00102         AL::ALValue commandAlias;
00103         commandAlias.arraySetSize(2);
00104         commandAlias[0] = string("Joints");
00105         commandAlias[1].arraySetSize(number_of_joints_);
00106         for(int i=0;i<number_of_joints_;i++)
00107         {
00108             commandAlias[1][i] = string("Device/SubDeviceList/"+joint_names_[i]+"/Position/Actuator/Value");
00109             commands_[3][i].arraySetSize(1);
00110             commands_[3][i][0].arraySetSize(2);
00111         }
00112         dcm_proxy_.createAlias(commandAlias);
00113 
00114         // Create Joints Hardness Alias
00115         commandAlias[0] = string("JointsHardness");
00116         commandAlias[1].arraySetSize(number_of_joints_-1);
00117         int k = 0;
00118         for(int i=0;i<number_of_joints_;i++)
00119         {
00120             if(joint_names_[i] == "RHipYawPitch")
00121             {
00122                 k = -1;
00123                 i++;
00124             }
00125             commandAlias[1][i+k] = string("Device/SubDeviceList/"+joint_names_[i]+"/Hardness/Actuator/Value");
00126         }
00127         dcm_proxy_.createAlias(commandAlias);
00128 
00129     }
00130     catch(const AL::ALError& e)
00131     {
00132         ROS_ERROR("Could not initialize dcm aliases!\n\tTrace: %s",e.what());
00133         return false;
00134     }
00135 
00136     // Turn Stiffness On
00137     vector<float> stiff = vector<float>(number_of_joints_-1,1.0f);
00138     vector<int> times = vector<int>(number_of_joints_-1,0);
00139     DCMAliasTimedCommand("JointsHardness",stiff, times);
00140     stiffnesses_enabled_ = true;
00141 
00142     return true;
00143 }
00144 
00145 bool Nao::initializeControllers(controller_manager::ControllerManager& cm)
00146 {
00147     if(!initialize())
00148     {
00149         ROS_ERROR("Initialization method failed!");
00150         return false;
00151     }
00152 
00153     // Initialize Controllers' Interfaces
00154     joint_angles_.resize(number_of_joints_);
00155     joint_velocities_.resize(number_of_joints_);
00156     joint_efforts_.resize(number_of_joints_);
00157     joint_commands_.resize(number_of_joints_);
00158 
00159     try
00160     {
00161         for(int i=0;i<number_of_joints_;i++)
00162         {
00163             hardware_interface::JointStateHandle state_handle(joint_names_[i], &joint_angles_[i],
00164                                                               &joint_velocities_[i], &joint_efforts_[i]);
00165             jnt_state_interface_.registerHandle(state_handle);
00166 
00167             hardware_interface::JointHandle pos_handle(jnt_state_interface_.getHandle(joint_names_[i]),
00168                                                        &joint_commands_[i]);
00169             jnt_pos_interface_.registerHandle(pos_handle);
00170         }
00171 
00172         registerInterface(&jnt_state_interface_);
00173         registerInterface(&jnt_pos_interface_);
00174     }
00175     catch(const ros::Exception& e)
00176     {
00177         ROS_ERROR("Could not initialize hardware interfaces!\n\tTrace: %s",e.what());
00178         return false;
00179     }
00180     ROS_INFO("Nao Module initialized!");
00181     return true;
00182 }
00183 
00184 bool Nao::connect(const ros::NodeHandle nh)
00185 {
00186     // Initialize ROS nodes
00187     node_handle_ = nh;
00188 
00189     is_connected_ = false;
00190 
00191     // Load ROS Parameters
00192     loadParams();
00193 
00194     // Needed for Error Checking
00195     try
00196     {
00197         subscribeToMicroEvent("ClientDisconnected", "Nao", "brokerDisconnected");
00198     }
00199     catch (const AL::ALError& e)
00200     {
00201         ROS_ERROR("Could not subscribe to brokerDisconnected!\n\tTrace: %s",e.what());
00202     }
00203 
00204     // Initialize DCM Proxy
00205     try
00206     {
00207         dcm_proxy_ = AL::DCMProxy(getParentBroker());
00208     }
00209     catch (const AL::ALError& e)
00210     {
00211         ROS_ERROR("Failed to connect to DCM Proxy!\n\tTrace: %s",e.what());
00212         return false;
00213     }
00214 
00215     // Initialize Memory Proxy
00216     try
00217     {
00218         memory_proxy_ = AL::ALMemoryProxy(getParentBroker());
00219     }
00220     catch (const AL::ALError& e)
00221     {
00222         ROS_ERROR("Failed to connect to Memory Proxy!\n\tTrace: %s",e.what());
00223         return false;
00224     }
00225 
00226     is_connected_ = true;
00227 
00228     // Subscribe/Publish ROS Topics/Services
00229     subscribe();
00230 
00231     // Initialize Controller Manager and Controllers
00232     manager_ = new controller_manager::ControllerManager(this,node_handle_);
00233     if(!initializeControllers(*manager_))
00234     {
00235         ROS_ERROR("Could not load controllers!");
00236         return false;
00237     }
00238     ROS_INFO("Controllers successfully loaded!");
00239     return true;
00240 }
00241 
00242 void Nao::disconnect()
00243 {
00244     if(!is_connected_)
00245         return;
00246     try
00247     {
00248         unsubscribeFromMicroEvent("ClientDisconnected", "Nao");
00249     }
00250     catch (const AL::ALError& e)
00251     {
00252         ROS_ERROR("Failed to unsubscribe from subscribed events!\n\tTrace: %s",e.what());
00253     }
00254     is_connected_ = false;
00255 }
00256 
00257 void Nao::subscribe()
00258 {
00259     // Subscribe/Publish ROS Topics/Services
00260 
00261     stiffness_pub_ = node_handle_.advertise<std_msgs::Float32>(prefix_+"stiffnesses", topic_queue_);
00262     stiffness_.data = 1.0f;
00263 
00264     stiffness_switch_ = node_handle_.advertiseService<Nao, nao_dcm_msgs::BoolService::Request,
00265             nao_dcm_msgs::BoolService::Response>(prefix_+"Stiffnesses/Enable", &Nao::switchStiffnesses, this);
00266 }
00267 
00268 void Nao::loadParams()
00269 {
00270     ros::NodeHandle n_p("~");
00271     // Load Server Parameters
00272     n_p.param("Version", version_, string("V4"));
00273     n_p.param("BodyType", body_type_, string("H21"));
00274     n_p.param("TopicQueue", topic_queue_, 50);
00275 
00276     n_p.param("Prefix", prefix_, string("nao_dcm"));
00277     prefix_ = prefix_+"/";
00278 
00279     n_p.param("LowCommunicationFrequency", low_freq_, 10.0);
00280     n_p.param("HighCommunicationFrequency", high_freq_, 100.0);
00281     n_p.param("ControllerFrequency", controller_freq_, 15.0);
00282     n_p.param("JointPrecision", joint_precision_, 0.00174532925);
00283     n_p.param("OdomFrame", odom_frame_, string("odom"));
00284 }
00285 
00286 void Nao::brokerDisconnected(const string& event_name, const string &broker_name, const string& subscriber_identifier)
00287 {
00288     if(broker_name == "Nao Driver Broker")
00289         is_connected_ = false;
00290 }
00291 
00292 void Nao::DCMTimedCommand(const string &key, const AL::ALValue &value, const int &timeOffset, const string &type)
00293 {
00294     try
00295     {
00296         // Create timed-command
00297         AL::ALValue command;
00298         command.arraySetSize(3);
00299         command[0] = key;
00300         command[1] = type;
00301         command[2].arraySetSize(1);
00302         command[2][0].arraySetSize(2);
00303         command[2][0][0] = value;
00304         command[2][0][1] = dcm_proxy_.getTime(timeOffset);
00305 
00306         // Execute timed-command
00307         dcm_proxy_.set(command);
00308     }
00309     catch(const AL::ALError& e)
00310     {
00311         ROS_ERROR("Could not execute DCM timed-command!\n\t%s\n\n\tTrace: %s", key.c_str(), e.what());
00312     }
00313 }
00314 
00315 void Nao::DCMAliasTimedCommand(const string &alias, const vector<float> &values, const vector<int> &timeOffsets,
00316                                const string &type, const string &type2)
00317 {
00318     try
00319     {
00320         // Create Alias timed-command
00321         AL::ALValue command;
00322         command.arraySetSize(4);
00323         command[0] = alias;
00324         command[1] = type;
00325         command[2] = type2;
00326         command[3].arraySetSize(values.size());
00327         int T = dcm_proxy_.getTime(0);
00328         for(int i=0;i<values.size();i++)
00329         {
00330             command[3][i].arraySetSize(1);
00331             command[3][i][0].arraySetSize(2);
00332             command[3][i][0][0] = values[i];
00333             command[3][i][0][1] = T+timeOffsets[i];
00334         }
00335 
00336         // Execute Alias timed-command
00337         dcm_proxy_.setAlias(command);
00338     }
00339     catch(const AL::ALError& e)
00340     {
00341         ROS_ERROR("Could not execute DCM timed-command!\n\t%s\n\n\tTrace: %s", alias.c_str(), e.what());
00342     }
00343 }
00344 
00345 void Nao::insertDataToMemory(const string &key, const AL::ALValue &value)
00346 {
00347     memory_proxy_.insertData(key,value);
00348 }
00349 
00350 AL::ALValue Nao::getDataFromMemory(const string &key)
00351 {
00352     return memory_proxy_.getData(key);
00353 }
00354 
00355 void Nao::subscribeToEvent(const string &name, const string &callback_module, const string &callback_method)
00356 {
00357     try
00358     {
00359         memory_proxy_.subscribeToEvent(name,callback_module,"",callback_method);
00360     }
00361     catch(const AL::ALError& e)
00362     {
00363         ROS_ERROR("Could not subscribe to event '%s'.\n\tTrace: %s",name.c_str(),e.what());
00364     }
00365 }
00366 
00367 void Nao::subscribeToMicroEvent(const string &name, const string &callback_module,
00368                                 const string &callback_method, const string &callback_message)
00369 {
00370     try
00371     {
00372         memory_proxy_.subscribeToMicroEvent(name,callback_module,callback_message,callback_method);
00373     }
00374     catch(const AL::ALError& e)
00375     {
00376         ROS_ERROR("Could not subscribe to micro-event '%s'.\n\tTrace: %s",name.c_str(),e.what());
00377     }
00378 }
00379 
00380 void Nao::unsubscribeFromEvent(const string &name, const string &callback_module)
00381 {
00382     try
00383     {
00384         memory_proxy_.unsubscribeToEvent(name,callback_module);
00385     }
00386     catch(const AL::ALError& e)
00387     {
00388         ROS_ERROR("Could not unsubscribe from event '%s'.\n\tTrace: %s",name.c_str(),e.what());
00389     }
00390 }
00391 
00392 void Nao::unsubscribeFromMicroEvent(const string &name, const string &callback_module)
00393 {
00394     try
00395     {
00396         memory_proxy_.unsubscribeToMicroEvent(name,callback_module);
00397     }
00398     catch(const AL::ALError& e)
00399     {
00400         ROS_ERROR("Could not unsubscribe from micro-event '%s'.\n\tTrace: %s",name.c_str(),e.what());
00401     }
00402 }
00403 
00404 void Nao::raiseEvent(const string &name, const AL::ALValue &value)
00405 {
00406     try
00407     {
00408         memory_proxy_.raiseEvent(name,value);
00409     }
00410     catch(const AL::ALError& e)
00411     {
00412         ROS_ERROR("Could not raise event '%s'.\n\tTrace: %s",name.c_str(),e.what());
00413     }
00414 }
00415 
00416 void Nao::raiseMicroEvent(const string &name, const AL::ALValue &value)
00417 {
00418     try
00419     {
00420         memory_proxy_.raiseMicroEvent(name,value);
00421     }
00422     catch(const AL::ALError& e)
00423     {
00424         ROS_ERROR("Could not raise micro-event '%s'.\n\tTrace: %s",name.c_str(),e.what());
00425     }
00426 }
00427 
00428 void Nao::declareEvent(const string &name)
00429 {
00430     try
00431     {
00432         memory_proxy_.declareEvent(name);
00433     }
00434     catch(AL::ALError& e)
00435     {
00436         ROS_ERROR("Could not declare event '%s'.\n\tTrace: %s",name.c_str(),e.what());
00437     }
00438 }
00439 
00440 void Nao::run()
00441 {
00442 /*    boost::thread t1(&Nao::controllerLoop,this);
00443     boost::thread t2(&Nao::lowCommunicationLoop,this);
00444     boost::thread t3(&Nao::highCommunicationLoop,this);
00445     t1.join();
00446     t2.join();
00447     t3.join();  */
00448     controllerLoop();
00449 }
00450 /*
00451 void Nao::lowCommunicationLoop()
00452 {
00453     static ros::Rate rate(low_freq_);
00454     while(ros::ok())
00455     {
00456         ros::Time time = ros::Time::now();
00457 
00458         if(!is_connected_)
00459             break;
00460 
00461         publishBaseFootprint(time);
00462 
00463         if(stiffnesses_enabled_)
00464         {
00465             stiffness_.data = 1.0f;
00466         }
00467         else
00468         {
00469             stiffness_.data = 0.0f;
00470         }
00471         stiffness_pub_.publish(stiffness_);
00472 
00473         rate.sleep();
00474     }
00475 }
00476 
00477 void Nao::highCommunicationLoop()
00478 {
00479     static ros::Rate rate(high_freq_);
00480     while(ros::ok())
00481     {
00482         ros::Time time = ros::Time::now();
00483 
00484         if(!is_connected_)
00485             break;
00486 
00487         try
00488         {
00489             dcm_proxy_.ping();
00490         }
00491         catch(const AL::ALError& e)
00492         {
00493             ROS_ERROR("Could not ping DCM proxy.\n\tTrace: %s",e.what());
00494             is_connected_ = false;
00495         }
00496         rate.sleep();
00497     }
00498 }
00499 */
00500 void Nao::controllerLoop()
00501 {
00502     static ros::Rate rate(controller_freq_+10.0);
00503     while(ros::ok())
00504     {
00505         ros::Time time = ros::Time::now();
00506 
00507         if(!is_connected_)
00508             break;
00509         try
00510         {
00511             dcm_proxy_.ping();
00512         }
00513         catch(const AL::ALError& e)
00514         {
00515             ROS_ERROR("Could not ping DCM proxy.\n\tTrace: %s",e.what());
00516             is_connected_ = false;
00517         }
00518 
00519         publishBaseFootprint(time);
00520         if(stiffnesses_enabled_)
00521         {
00522             stiffness_.data = 1.0f;
00523         }
00524         else
00525         {
00526             stiffness_.data = 0.0f;
00527         }
00528 
00529         stiffness_pub_.publish(stiffness_);
00530 
00531         readJoints();
00532 
00533         manager_->update(time,ros::Duration(1.0f/controller_freq_));
00534 
00535         writeJoints();
00536 
00537         rate.sleep();
00538     }
00539 }
00540 
00541 bool Nao::connected()
00542 {
00543     return is_connected_;
00544 }
00545 
00546 void Nao::commandVelocity(const geometry_msgs::TwistConstPtr &msg)
00547 {
00548     ROS_WARN("This function does nothing at the moment..");
00549 }
00550 
00551 
00552 void Nao::publishBaseFootprint(const ros::Time &ts)
00553 {
00554     string odom_frame, l_sole_frame, r_sole_frame, base_link_frame;
00555     try {
00556         odom_frame = base_footprint_listener_.resolve(odom_frame_);
00557         l_sole_frame = base_footprint_listener_.resolve("l_sole");
00558         r_sole_frame = base_footprint_listener_.resolve("r_sole");
00559         base_link_frame = base_footprint_listener_.resolve("base_link");
00560     }
00561     catch(ros::Exception& e)
00562     {
00563         ROS_ERROR("%s",e.what());
00564         return;
00565     }
00566 
00567     tf::StampedTransform tf_odom_to_base, tf_odom_to_left_foot, tf_odom_to_right_foot;
00568     double temp_freq = 1.0f/(10.0*high_freq_);
00569     if(!base_footprint_listener_.waitForTransform(odom_frame, l_sole_frame, ros::Time(0), ros::Duration(temp_freq)))
00570         return;
00571     try {
00572         base_footprint_listener_.lookupTransform(odom_frame, l_sole_frame, ros::Time(0), tf_odom_to_left_foot);
00573         base_footprint_listener_.lookupTransform(odom_frame, r_sole_frame, ros::Time(0), tf_odom_to_right_foot);
00574         base_footprint_listener_.lookupTransform(odom_frame, base_link_frame,  ros::Time(0), tf_odom_to_base);
00575     }
00576     catch (const tf::TransformException& ex){
00577         ROS_ERROR("%s",ex.what());
00578         return ;
00579     }
00580 
00581     tf::Vector3 new_origin = (tf_odom_to_right_foot.getOrigin() + tf_odom_to_left_foot.getOrigin())/2.0;
00582     double height = std::min(tf_odom_to_left_foot.getOrigin().getZ(), tf_odom_to_right_foot.getOrigin().getZ());
00583     new_origin.setZ(height);
00584 
00585     double roll, pitch, yaw;
00586     tf_odom_to_base.getBasis().getRPY(roll, pitch, yaw);
00587 
00588     tf::Transform tf_odom_to_footprint(tf::createQuaternionFromYaw(yaw), new_origin);
00589     tf::Transform tf_base_to_footprint = tf_odom_to_base.inverse() * tf_odom_to_footprint;
00590 
00591     base_footprint_broadcaster_.sendTransform(tf::StampedTransform(tf_base_to_footprint, ts,
00592                                                                    base_link_frame, "base_footprint"));
00593 }
00594 
00595 void Nao::readJoints()
00596 {
00597     vector<float> jointData;
00598     try
00599     {
00600         jointData = memory_proxy_.getListData(joints_names_);
00601     }
00602     catch(const AL::ALError& e)
00603     {
00604         ROS_ERROR("Could not get joint data from Nao.\n\tTrace: %s",e.what());
00605         return;
00606     }
00607 
00608     for(short i = 0; i<jointData.size(); i++)
00609     {
00610         joint_angles_[i] = jointData[i];
00611         // Set commands to the read angles for when no command specified
00612         joint_commands_[i] = jointData[i];
00613     }
00614 }
00615 
00616 void Nao::writeJoints()
00617 {
00618     // Update joints only when actual command is issued
00619     bool changed = false;
00620     for(int i=0;i<number_of_joints_;i++)
00621     {
00622         if(fabs(joint_commands_[i]-joint_angles_[i])>joint_precision_)
00623         {
00624             changed = true;
00625             break;
00626         }
00627     }
00628     // Do not write joints if no change in joint values
00629     if(!changed)
00630     {
00631         return;
00632     }
00633 
00634     try
00635     {
00636         int T = dcm_proxy_.getTime(0);
00637         for(int i=0;i<number_of_joints_;i++)
00638         {
00639             commands_[3][i][0][0] = float(joint_commands_[i]);
00640             commands_[3][i][0][1] = T+(int)(800.0f/controller_freq_);
00641         }
00642         
00643         dcm_proxy_.setAlias(commands_);
00644     }
00645     catch(const AL::ALError& e)
00646     {
00647         ROS_ERROR("Could not send joint commands to Nao.\n\tTrace: %s",e.what());
00648         return;
00649     }
00650 }
00651 
00652 bool Nao::switchStiffnesses(nao_dcm_msgs::BoolService::Request &req, nao_dcm_msgs::BoolService::Response &res)
00653 {
00654     if(stiffnesses_enabled_!=req.enable && req.enable)
00655     {
00656         DCMAliasTimedCommand("JointsHardness",vector<float>(number_of_joints_,1.0f), vector<int>(number_of_joints_,0));
00657     }
00658     else if(stiffnesses_enabled_!=req.enable)
00659     {
00660         DCMAliasTimedCommand("JointsHardness",vector<float>(number_of_joints_,0.0f), vector<int>(number_of_joints_,0));
00661     }
00662     stiffnesses_enabled_ = req.enable;
00663 }
00664 


nao_dcm_driver
Author(s): Konstantinos Chatzilygeroudis
autogenerated on Wed Oct 19 2016 03:58:50