diagnostics.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2016 SoftBank Robotics Europe
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  *
00016 */
00017 
00018 #include <diagnostic_msgs/DiagnosticArray.h>
00019 
00020 #include "naoqi_dcm_driver/diagnostics.hpp"
00021 #include "naoqi_dcm_driver/tools.hpp"
00022 
00023 Diagnostics::Diagnostics(const qi::SessionPtr& session,
00024                          ros::Publisher *pub,
00025                          const std::vector<std::string> &joints_all_names,
00026                          const std::string &robot):
00027     pub_(pub),
00028     joints_all_names_(joints_all_names),
00029     temperature_warn_level_(68.0f),
00030     temperature_error_level_(73.0f)
00031 {
00032   //resize the joint current vector
00033   joints_current_.reserve(joints_all_names_.size());
00034   joints_current_.resize(joints_all_names_.size());
00035 
00036   //set the default status
00037   status_.name = std::string("naoqi_dcm_driver:Status");
00038   status_.hardware_id = "robot";
00039   status_.level = diagnostic_msgs::DiagnosticStatus::OK;
00040   status_.message = "OK";
00041 
00042   //connect to Memmory proxy
00043   try
00044   {
00045     memory_proxy_ = session->service("ALMemory");
00046   }
00047   catch (const std::exception& e)
00048   {
00049     ROS_ERROR("DIAGNOSTICS: Failed to connect to Memory Proxy!\n\tTrace: %s", e.what());
00050   }
00051 
00052   //set the keys to check
00053   keys_tocheck_.push_back("Device/SubDeviceList/Battery/Charge/Sensor/Value");
00054 
00055   std::vector<std::string>::const_iterator it = joints_all_names_.begin();
00056   for(; it != joints_all_names_.end(); ++it) {
00057     keys_tocheck_.push_back("Device/SubDeviceList/" + *it + "/Temperature/Sensor/Value");
00058     keys_tocheck_.push_back("Device/SubDeviceList/" + *it + "/Hardness/Actuator/Value");
00059     keys_tocheck_.push_back("Device/SubDeviceList/" + *it + "/ElectricCurrent/Sensor/Value");
00060   }
00061 
00062   std::vector<std::string>::const_iterator it_cntrl = joints_all_names_.begin();
00063   for(; it_cntrl != joints_all_names_.end(); ++it_cntrl)
00064     keys_tocheck_.push_back("Device/SubDeviceList/" + *it_cntrl + "/ElectricCurrent/Sensor/Value");
00065 
00066   //allow the temperature reporting (for CPU)
00067   try
00068   {
00069     if ((robot == "pepper") || (robot == "juliette") || (robot == "nao")) {
00070       qi::AnyObject body_temperature_ = session->service("ALBodyTemperature");
00071       body_temperature_.call<void>("setEnableNotifications", true);
00072     }
00073   }
00074   catch (const std::exception& e)
00075   {
00076     ROS_WARN("DIAGNOSTICS: Failed to connect to ALBodyTemperature!\n\tTrace: %s", e.what());
00077   }
00078 }
00079 
00080 void Diagnostics::setMessageFromStatus(diagnostic_updater::DiagnosticStatusWrapper &status)
00081 {
00082   if (status.level == diagnostic_msgs::DiagnosticStatus::OK) {
00083     status.message = "OK";
00084   } else if (status.level == diagnostic_msgs::DiagnosticStatus::WARN) {
00085     status.message = "WARN";
00086   } else {
00087     status.message = "ERROR";
00088    }
00089  }
00090 
00091 void Diagnostics::setAggregatedMessage(diagnostic_updater::DiagnosticStatusWrapper &status)
00092 {
00093   if(status.level > status_.level) {
00094     status_.level = status.level;
00095     status_.message = status.message;
00096   }
00097 }
00098 
00099 bool Diagnostics::publish()
00100 {
00101   diagnostic_msgs::DiagnosticArray msg;
00102   msg.header.stamp = ros::Time::now();
00103 
00104   //set the default status
00105   status_.level = diagnostic_msgs::DiagnosticStatus::OK;
00106   status_.message = "OK";
00107 
00108   // Fill the temperature / stiffness message for the joints
00109   float maxTemperature = 0.0f;
00110   float maxStiffness = 0.0f;
00111   float minStiffness = 1.0f;
00112   float minStiffnessWoHands = 1.0f;
00113   float maxCurrent = 0.0f;
00114   float minCurrent = 10.0f;
00115   std::stringstream hotJointsSS;
00116   diagnostic_msgs::DiagnosticStatus::_level_type max_level = diagnostic_msgs::DiagnosticStatus::OK;
00117 
00118   std::vector<float> values;
00119   try
00120   {
00121     qi::AnyValue keys_tocheck_qi = memory_proxy_.call<qi::AnyValue>("getListData", keys_tocheck_);
00122     values = fromAnyValueToFloatVector(keys_tocheck_qi);
00123   }
00124   catch(const std::exception& e)
00125   {
00126     ROS_ERROR("DIAGNOSTICS: Could not get joint data from the robot \n\tTrace: %s", e.what());
00127     return false;
00128   }
00129 
00130   //check the battery charge level
00131   size_t val = 0;
00132   float batteryCharge = static_cast<float>(values[val++]);
00133 
00134   diagnostic_updater::DiagnosticStatusWrapper status_battery;
00135   status_battery.name = std::string("naoqi_dcm_driver:Battery");
00136   status_battery.hardware_id = "battery";
00137   status_battery.add("BatteryCharge", batteryCharge);
00138 
00139   //TODO check if it is charging
00140   if (batteryCharge > 5.0f)
00141   {
00142     status_battery.level = diagnostic_msgs::DiagnosticStatus::OK;
00143     status_battery.message = "OK";
00144   }
00145   else
00146   {
00147     status_battery.level = diagnostic_msgs::DiagnosticStatus::ERROR;
00148     status_battery.message = "LOW Battery Charge";
00149   }
00150   msg.status.push_back(status_battery);
00151 
00152   std::vector<std::string>::iterator it_name = joints_all_names_.begin();
00153   std::vector<float>::iterator it_current = joints_current_.begin();
00154   for(; it_name != joints_all_names_.end(); ++it_name, ++it_current)
00155   {
00156     diagnostic_updater::DiagnosticStatusWrapper status;
00157     status.name = std::string("naoqi_dcm_driver:") + *it_name;
00158 
00159     float temperature = static_cast<float>(values[val++]);
00160     float stiffness = static_cast<float>(values[val++]);
00161     *it_current = static_cast<float>(values[val++]);
00162 
00163     // Fill the status data
00164     status.hardware_id = *it_name;
00165     status.add("Temperature", temperature);
00166     status.add("Stiffness", stiffness);
00167     status.add("ElectricCurrent", *it_current);
00168 
00169     // Define the level
00170     if (temperature < temperature_warn_level_)
00171     {
00172       status.level = diagnostic_msgs::DiagnosticStatus::OK;
00173       status.message = "OK";
00174     }
00175     else if (temperature < temperature_error_level_)
00176     {
00177       status.level = diagnostic_msgs::DiagnosticStatus::WARN;
00178       status.message = "Hot";
00179     }
00180     else
00181     {
00182       status.level = diagnostic_msgs::DiagnosticStatus::ERROR;
00183       status.message = "HIGH JOINT TEMPERATURE : " + *it_name;
00184     }
00185 
00186     msg.status.push_back(status);
00187     setAggregatedMessage(status);
00188 
00189     // Fill the joint data for later processing
00190     max_level = std::max(max_level, status.level);
00191     maxTemperature = std::max(maxTemperature, temperature);
00192     maxStiffness = std::max(maxStiffness, stiffness);
00193     minStiffness = std::min(minStiffness, stiffness);
00194     if((*it_name).find("Hand") == std::string::npos)
00195       minStiffnessWoHands = std::min(minStiffnessWoHands, stiffness);
00196     maxCurrent = std::max(maxCurrent, *it_current);
00197     minCurrent = std::min(minCurrent, *it_current);
00198     if(status.level >= (int) diagnostic_msgs::DiagnosticStatus::WARN) {
00199       hotJointsSS << std::endl << *it_name << ": " << temperature << "°C";
00200     }
00201   }
00202 
00203   // Get the aggregated joints status
00204   diagnostic_updater::DiagnosticStatusWrapper status;
00205   status.name = std::string("naoqi_dcm_driver:Status");
00206   status.hardware_id = "joints";
00207   status.level = max_level;
00208   setMessageFromStatus(status);
00209 
00210   status.add("Highest Temperature", maxTemperature);
00211   status.add("Highest Stiffness", maxStiffness);
00212   status.add("Lowest Stiffness", minStiffness);
00213   status.add("Lowest Stiffness without Hands", minStiffnessWoHands);
00214   status.add("Highest Electric Current", maxCurrent);
00215   status.add("Lowest Electric current", minCurrent);
00216   status.add("Hot Joints", hotJointsSS.str());
00217 
00218   msg.status.push_back(status);
00219 
00220   pub_->publish(msg);
00221 
00222   if(status_.level >= (int) diagnostic_msgs::DiagnosticStatus::ERROR)
00223   {
00224     ROS_ERROR_STREAM("DIAGNOSTICS: ERROR DETECTED: " << getStatusMsg());
00225     return false;
00226   }
00227   else
00228     return true;
00229 }
00230 
00231 std::string Diagnostics::getStatusMsg()
00232 {
00233   return status_.message;
00234 }


naoqi_dcm_driver
Author(s): Konstantinos Chatzilygeroudis , Mikael Arguedas , Karsten Knese , Natalia Lyubova
autogenerated on Thu Jun 6 2019 20:50:49