7 #include <boost/shared_ptr.hpp> 8 #include <boost/bind.hpp> 9 #include <boost/ref.hpp> 10 #include <boost/program_options.hpp> 11 #include <boost/thread/thread.hpp> 13 #include <log4cxx/logger.h> 17 #include "diagnostic_msgs/DiagnosticArray.h" 18 #include "diagnostic_msgs/DiagnosticStatus.h" 21 #include "pr2_msgs/BatteryServer.h" 26 namespace po = boost::program_options;
35 float result = tmp / 1000.0;
41 float fKelvin = (float) (iKelvin * 0.1);
42 return (fKelvin - (
float) 273.15);
49 server(
const int &majorID,
const std::string &dev,
const int debug_level = 0 ) :
50 majorID(majorID), debug_level(debug_level), serial_device(
"/dev/ttyUSB0"), stopRequest(false),
51 has_warned_temp_alarm_(false), has_warned_no_good_(false)
61 ss <<
"/dev/ttyUSB" << majorID;
62 serial_device = ss.str();
65 ss <<
"port" << majorID;
66 bool result = private_handle.
getParam( ss.str(), tmp_device );
69 ROS_INFO(
"Using %s from getParam.\n", ss.str().c_str());
70 serial_device = tmp_device;
73 ROS_INFO(
"Defaulting to: %s", serial_device.c_str());
78 ROS_INFO(
"Overriding device with argument: %s", dev.c_str() );
82 private_handle.
param(
"lag_timeout", lag_timeout_, 60);
83 private_handle.
param(
"stale_timeout", stale_timeout_, 120);
116 std::stringstream ss;
127 diagnostic_msgs::DiagnosticArray msg_out;
129 Time lastTime, currentTime, startTime;
131 ocean os( majorID, debug_level);
135 pr2_msgs::BatteryServer oldserver;
136 oldserver.battery.resize(4);
138 lastTime = Time::now();
139 startTime = Time::now();
141 while(handle.
ok() && (stopRequest ==
false))
145 currentTime = Time::now();
147 if((os.
run() > 0) && ((currentTime - lastTime) > MESSAGE_TIME))
154 oldserver.id = os.
server.id;
155 oldserver.lastTimeSystem = os.
server.last_system_update.sec;
156 oldserver.timeLeft = os.
server.time_left.toSec()/60;
157 oldserver.averageCharge = os.
server.average_charge;
158 oldserver.message = os.
server.message;
159 oldserver.lastTimeController = os.
server.last_controller_update.sec;
160 oldserver.present = os.
server.battery[0].present * 1 + os.
server.battery[1].present * 2 + os.
server.battery[2].present * 4 + os.
server.battery[3].present * 8;
161 oldserver.charging = os.
server.battery[0].charging * 1 + os.
server.battery[1].charging * 2 + os.
server.battery[2].charging * 4 + os.
server.battery[3].charging * 8;
162 oldserver.discharging = os.
server.battery[0].discharging * 1 + os.
server.battery[1].discharging * 2 + os.
server.battery[2].discharging * 4 + os.
server.battery[3].discharging * 8;
164 oldserver.powerPresent = os.
server.battery[0].power_present * 1 + os.
server.battery[1].power_present * 2 + os.
server.battery[2].power_present * 4 + os.
server.battery[3].power_present * 8;
165 oldserver.powerNG = os.
server.battery[0].power_no_good * 1 + os.
server.battery[1].power_no_good * 2 + os.
server.battery[2].power_no_good * 4 + os.
server.battery[3].power_no_good * 8;
166 oldserver.inhibited = os.
server.battery[0].inhibited * 1 + os.
server.battery[1].inhibited * 2 + os.
server.battery[2].inhibited * 4 + os.
server.battery[3].inhibited * 8;
168 for(
int xx = 0; xx < os.
server.MAX_BAT_COUNT; ++xx)
170 oldserver.battery[xx].lastTimeBattery = os.
server.battery[xx].last_battery_update.sec;
173 oldserver.battery[xx].batReg[yy] = os.
server.battery[xx].battery_register[yy];
174 oldserver.battery[xx].batRegFlag[yy] = os.
server.battery[xx].battery_update_flag[yy];
175 oldserver.battery[xx].batRegTime[yy] = os.
server.battery[xx].battery_register_update[yy].sec;
180 bs.publish(oldserver);
182 lastTime = currentTime;
187 ss <<
"IBPS " << majorID;
188 stat.name = ss.str();
189 stat.level = diagnostic_msgs::DiagnosticStatus::OK;
192 stat.
add(
"Time Remaining (min)", (os.
server.time_left.toSec()/60));
193 stat.
add(
"Average charge (percent)", os.
server.average_charge );
195 stat.
add(
"Time since update (s)", elapsed.
toSec());
198 msg_out.status.push_back(stat);
200 for(
int xx = 0; xx < os.
server.MAX_BAT_COUNT; ++xx)
205 ss <<
"Smart Battery " << majorID <<
"." << xx;
206 stat.name = ss.str();
207 stat.level = diagnostic_msgs::DiagnosticStatus::OK;
210 if(!os.
server.battery[xx].present)
212 stat.
add(
"Battery Present",
"False");
213 stat.level = diagnostic_msgs::DiagnosticStatus::ERROR;
214 stat.message =
"Not present";
218 stat.
add(
"Battery Present",
"True");
219 stat.
add(
"Charging", (os.
server.battery[xx].charging) ?
"True":
"False");
220 stat.
add(
"Discharging", (os.
server.battery[xx].discharging) ?
"True":
"False");
221 stat.
add(
"Power Present", (os.
server.battery[xx].power_present) ?
"True":
"False");
222 stat.
add(
"No Good", (os.
server.battery[xx].power_no_good) ?
"True":
"False");
223 stat.
add(
"Charge Inhibited", (os.
server.battery[xx].inhibited) ?
"True":
"False");
225 int16_t voltage = -1;
226 int16_t design_voltage = -1;
227 int16_t relative_charge = -1;
228 int16_t absolute_charge = -1;
233 if(os.
server.battery[xx].battery_update_flag[addr])
244 std::stringstream date;
247 unsigned int day = os.
server.battery[xx].battery_register[addr] & 0x1F;
248 unsigned int month = (os.
server.battery[xx].battery_register[addr] >> 5) & 0xF;
249 unsigned int year = (os.
server.battery[xx].battery_register[addr] >> 9) + 1980;
250 date << month <<
"/" << day <<
"/" << year;
252 stat.
add(
"Manufacture Date (MDY)", date.str());
262 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN, warn.str());
265 stat.
add(
"Temperature (C)", celsius);
270 stat.
add(
"Serial Number", os.
server.battery[xx].battery_register[addr]);
272 std::stringstream hw_id;
273 hw_id << os.
server.battery[xx].battery_register[addr];
275 stat.hardware_id = hw_id.str();
279 voltage = os.
server.battery[xx].battery_register[addr];
280 stat.
add( ss.str(), os.
server.battery[xx].battery_register[addr]);
283 design_voltage = os.
server.battery[xx].battery_register[addr];
284 stat.
add( ss.str(), os.
server.battery[xx].battery_register[addr]);
287 relative_charge = os.
server.battery[xx].battery_register[addr];
288 stat.
add( ss.str(), os.
server.battery[xx].battery_register[addr]);
291 absolute_charge = os.
server.battery[xx].battery_register[addr];
292 stat.
add( ss.str(), os.
server.battery[xx].battery_register[addr]);
295 stat.
add( ss.str(), os.
server.battery[xx].battery_register[addr]);
301 elapsed = currentTime - os.
server.battery[xx].last_battery_update;
302 if (os.
server.battery[xx].last_battery_update >=
Time(1))
303 stat.
add(
"Time since update (s)", elapsed.
toSec());
305 stat.
add(
"Time since update (s)",
"N/A");
307 if ( absolute_charge >= 0 && relative_charge >= 0 ) {
308 if( absolute_charge < relative_charge/2 ) {
309 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN,
"Battery capacity low, please replace.");
313 if ( voltage >= 0 && design_voltage >= 0 ) {
314 if( voltage < design_voltage/2 ) {
315 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN,
"Battery voltage too low, please replace.");
321 bool updateGracePeriod = (currentTime - startTime).toSec() < stale_timeout_;
322 if (os.
server.battery[xx].last_battery_update <=
Time(1) && updateGracePeriod)
323 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN,
"Waiting for battery update");
324 else if (stale_timeout_ > 0 && elapsed.
toSec() > stale_timeout_)
325 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::ERROR,
"No updates");
326 else if (lag_timeout_ > 0 && elapsed.
toSec() > lag_timeout_)
327 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN,
"Stale updates");
333 if (os.
server.battery[xx].power_present && !os.
server.battery[xx].charging
334 && os.
server.battery[xx].battery_register[0x0d] < 90
337 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN,
"Charge Inhibited, High Temperature");
338 if (!has_warned_temp_alarm_)
340 ROS_WARN(
"Over temperature alarm found on battery %d. Battery will not charge.", xx);
341 has_warned_temp_alarm_ =
true;
346 if (os.
server.battery[xx].battery_register[0x16] & 0x1000)
347 stat.
mergeSummary(diagnostic_msgs::DiagnosticStatus::WARN,
"Over Temp Alarm");
351 if (os.
server.battery[xx].power_no_good && !has_warned_no_good_)
353 ROS_WARN(
"Battery %d reports \"No Good\".", xx);
354 has_warned_no_good_ =
true;
357 msg_out.status.push_back(stat);
362 msg_out.status.clear();
370 int main(
int argc,
char** argv)
376 po::options_description desc(
"Allowed options");
378 (
"help",
"this help message")
379 (
"debug", po::value<int>(&debug_level)->default_value(0),
"debug level")
380 (
"count", po::value<int>(&max_ports)->default_value(4),
"number of ports to monitor")
381 (
"dev", po::value<string>(&tmp_device),
"serial device to open");
383 po::variables_map vm;
384 po::store(po::parse_command_line( argc, argv, desc), vm);
387 if( vm.count(
"help"))
389 cout << desc <<
"\n";
403 if( my_logger->getLevel() == 0 )
409 private_handle.
getParam(
"number_of_ports", max_ports );
410 ROS_INFO(
"number_of_ports=%d", max_ports);
411 private_handle.
getParam(
"debug_level", debug_level );
412 ROS_DEBUG(
"debug_level=%d", debug_level);
414 vector<server> server_list;
416 for(
int xx = 0; xx < max_ports; ++xx)
417 server_list.push_back(
server( xx, tmp_device, debug_level));
419 for(
int xx = 0; xx < max_ports; ++xx)
420 server_list[xx].
start();
425 for(
int xx = 0; xx < max_ports; ++xx)
426 server_list[xx].stop();
static const unsigned regListLength
void publish(const boost::shared_ptr< M > &message) const
int main(int argc, char **argv)
pr2_msgs::BatteryServer2 server
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
volatile bool stopRequest
float tempToCelcius(const int &iKelvin)
server(const int &majorID, const std::string &dev, const int debug_level=0)
#define ROSCONSOLE_AUTOINIT
float toFloat(const int &value)
void initialize(const std::string &input_dev)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
std::string serial_device
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
static const float BATTERY_TEMP_WARN
void mergeSummary(unsigned char lvl, const std::string s)
bool getParam(const std::string &key, std::string &s) const
bool has_warned_temp_alarm_
boost::shared_ptr< boost::thread > myThread
void add(const std::string &key, const T &val)
#define ROSCONSOLE_DEFAULT_NAME
static const struct regPair regList[]