Skip to content

Commit 809f1bd

Browse files
authored
Merge pull request #24 from akrobotics/imu-diag
Add IMU diagnostics (related to #20)
2 parents bed0816 + ce5d419 commit 809f1bd

File tree

5 files changed

+121
-12
lines changed

5 files changed

+121
-12
lines changed

phidgets_api/include/phidgets_api/phidget.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Phidget
4949
~Phidget();
5050

5151
/**@brief Open a connection to a Phidget
52-
* @param serial_number THe serial number of the phidget to which to attach (-1 will connect to any)*/
52+
* @param serial_number The serial number of the phidget to which to attach (-1 will connect to any)*/
5353
int open(int serial_number);
5454

5555
/**@brief Close the connection to the phidget */

phidgets_imu/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
cmake_minimum_required(VERSION 2.8.3)
22
project(phidgets_imu)
33

4-
find_package(catkin REQUIRED COMPONENTS geometry_msgs nodelet pluginlib phidgets_api roscpp sensor_msgs std_msgs std_srvs tf)
4+
find_package(catkin REQUIRED COMPONENTS diagnostic_msgs diagnostic_updater geometry_msgs nodelet pluginlib phidgets_api roscpp sensor_msgs std_msgs std_srvs tf)
55

66
find_package(Boost REQUIRED COMPONENTS thread)
77

88
catkin_package(
99
INCLUDE_DIRS include
1010
LIBRARIES phidgets_imu
1111
DEPENDS Boost
12-
CATKIN_DEPENDS geometry_msgs nodelet pluginlib phidgets_api roscpp sensor_msgs std_msgs std_srvs tf
12+
CATKIN_DEPENDS diagnostic_msgs diagnostic_updater geometry_msgs nodelet pluginlib phidgets_api roscpp sensor_msgs std_msgs std_srvs tf
1313
)
1414

1515
include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})

phidgets_imu/include/phidgets_imu/imu_ros_i.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@
44
#include <ros/ros.h>
55
#include <ros/service_server.h>
66
#include <boost/thread/mutex.hpp>
7+
#include <boost/shared_ptr.hpp>
78
#include <tf/transform_datatypes.h>
89
#include <sensor_msgs/Imu.h>
910
#include <std_srvs/Empty.h>
1011
#include <std_msgs/Bool.h>
1112
#include <geometry_msgs/Vector3Stamped.h>
13+
#include <diagnostic_updater/diagnostic_updater.h>
14+
#include <diagnostic_updater/publisher.h>
1215
#include <phidgets_api/imu.h>
1316

17+
using namespace std;
18+
1419
namespace phidgets {
1520

1621
const float G = 9.81;
@@ -36,6 +41,16 @@ class ImuRosI : public Imu
3641
ros::Publisher cal_publisher_;
3742
ros::ServiceServer cal_srv_;
3843

44+
/**@brief updater object of class Update. Used to add diagnostic tasks, set ID etc. refer package API.
45+
* Added for diagnostics */
46+
diagnostic_updater::Updater diag_updater_;
47+
boost::shared_ptr<diagnostic_updater::TopicDiagnostic> imu_publisher_diag_ptr_;
48+
49+
// diagnostics
50+
bool is_connected_;
51+
int error_number_;
52+
double target_publish_freq_;
53+
3954
bool initialized_;
4055
boost::mutex mutex_;
4156
ros::Time last_imu_time_;
@@ -70,7 +85,16 @@ class ImuRosI : public Imu
7085
void calibrate();
7186
void initDevice();
7287
void dataHandler(CPhidgetSpatial_SpatialEventDataHandle* data, int count);
88+
void attachHandler();
89+
void detachHandler();
90+
void errorHandler(int error);
7391
void processImuData(CPhidgetSpatial_SpatialEventDataHandle* data, int i);
92+
93+
/**@brief Main diagnostic method that takes care of collecting diagnostic data.
94+
* @param stat The stat param is what is the diagnostic tasks are added two. Internally published by the
95+
* diagnostic_updater package.
96+
* Added for diagnostics */
97+
void phidgetsDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat);
7498
};
7599

76100
} //namespace phidgets

phidgets_imu/package.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
<build_depend>std_msgs</build_depend>
2424
<build_depend>std_srvs</build_depend>
2525
<build_depend>tf</build_depend>
26+
<build_depend>diagnostic_updater</build_depend>
27+
<build_depend>diagnostic_msgs</build_depend>
28+
2629
<run_depend>geometry_msgs</run_depend>
2730
<run_depend>nodelet</run_depend>
2831
<run_depend>pluginlib</run_depend>
@@ -32,6 +35,8 @@
3235
<run_depend>std_msgs</run_depend>
3336
<run_depend>std_srvs</run_depend>
3437
<run_depend>tf</run_depend>
38+
<run_depend>diagnostic_updater</run_depend>
39+
<run_depend>diagnostic_msgs</run_depend>
3540

3641
<export>
3742
<nodelet plugin="${prefix}/phidgets_imu_nodelet.xml" />

phidgets_imu/src/imu_ros_i.cpp

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
#include <boost/make_shared.hpp>
12
#include "phidgets_imu/imu_ros_i.h"
23

34
namespace phidgets {
45

56
ImuRosI::ImuRosI(ros::NodeHandle nh, ros::NodeHandle nh_private):
67
Imu(),
7-
nh_(nh),
8+
nh_(nh),
89
nh_private_(nh_private),
10+
is_connected_(false),
11+
error_number_(0),
12+
target_publish_freq_(0.0),
913
initialized_(false)
1014
{
1115
ROS_INFO ("Starting Phidgets IMU");
@@ -45,13 +49,27 @@ ImuRosI::ImuRosI(ros::NodeHandle nh, ros::NodeHandle nh_private):
4549
cal_publisher_ = nh_.advertise<std_msgs::Bool>(
4650
"imu/is_calibrated", 5);
4751

52+
// Set up the topic publisher diagnostics monitor for imu/data_raw
53+
// 1. The frequency status component monitors if imu data is published
54+
// within 10% tolerance of the desired frequency of 1.0 / period
55+
// 2. The timstamp status component monitors the delay between
56+
// the header.stamp of the imu message and the real (ros) time
57+
// the maximum tolerable drift is +- 100ms
58+
target_publish_freq_ = 1000.0 / static_cast<double>(period_);
59+
imu_publisher_diag_ptr_ = boost::make_shared<diagnostic_updater::TopicDiagnostic>(
60+
"imu/data_raw",
61+
boost::ref(diag_updater_),
62+
diagnostic_updater::FrequencyStatusParam(&target_publish_freq_, &target_publish_freq_, 0.1, 5),
63+
diagnostic_updater::TimeStampStatusParam(-0.1, 0.1)
64+
);
65+
4866
// **** advertise services
4967

5068
cal_srv_ = nh_.advertiseService(
5169
"imu/calibrate", &ImuRosI::calibrateService, this);
5270

5371
// **** initialize variables and device
54-
72+
5573
imu_msg_.header.frame_id = frame_id_;
5674

5775
// build covariance matrices
@@ -79,6 +97,10 @@ ImuRosI::ImuRosI(ros::NodeHandle nh, ros::NodeHandle nh_private):
7997
// signal that we have no orientation estimate (see Imu.msg)
8098
imu_msg_.orientation_covariance[0] = -1;
8199

100+
// init diagnostics, we set the hardware id properly when the device is connected
101+
diag_updater_.setHardwareID("none");
102+
diag_updater_.add("IMU Driver Status", this, &phidgets::ImuRosI::phidgetsDiagnostics);
103+
82104
initDevice();
83105

84106
if (has_compass_params)
@@ -108,7 +130,10 @@ void ImuRosI::initDevice()
108130
int result = waitForAttachment(10000);
109131
if(result)
110132
{
111-
const char *err;
133+
is_connected_ = false;
134+
error_number_ = result;
135+
diag_updater_.force_update();
136+
const char *err;
112137
CPhidget_getErrorDescription(result, &err);
113138
ROS_FATAL("Problem waiting for IMU attachment: %s Make sure the USB cable is connected and you have executed the phidgets_api/share/setup-udev.sh script.", err);
114139
}
@@ -118,6 +143,11 @@ void ImuRosI::initDevice()
118143

119144
// calibrate on startup
120145
calibrate();
146+
147+
// set the hardware id for diagnostics
148+
diag_updater_.setHardwareIDf("%s-%d",
149+
getDeviceName().c_str(),
150+
getDeviceSerialNumber());
121151
}
122152

123153
bool ImuRosI::calibrateService(std_srvs::Empty::Request &req,
@@ -144,7 +174,7 @@ void ImuRosI::calibrate()
144174
void ImuRosI::processImuData(CPhidgetSpatial_SpatialEventDataHandle* data, int i)
145175
{
146176
// **** calculate time from timestamp
147-
ros::Duration time_imu(data[i]->timestamp.seconds +
177+
ros::Duration time_imu(data[i]->timestamp.seconds +
148178
data[i]->timestamp.microseconds * 1e-6);
149179

150180
ros::Time time_now = time_zero_ + time_imu;
@@ -159,14 +189,14 @@ void ImuRosI::processImuData(CPhidgetSpatial_SpatialEventDataHandle* data, int i
159189
// **** initialize if needed
160190

161191
if (!initialized_)
162-
{
192+
{
163193
last_imu_time_ = time_now;
164194
initialized_ = true;
165195
}
166196

167197
// **** create and publish imu message
168198

169-
boost::shared_ptr<ImuMsg> imu_msg =
199+
boost::shared_ptr<ImuMsg> imu_msg =
170200
boost::make_shared<ImuMsg>(imu_msg_);
171201

172202
imu_msg->header.stamp = time_now;
@@ -182,12 +212,13 @@ void ImuRosI::processImuData(CPhidgetSpatial_SpatialEventDataHandle* data, int i
182212
imu_msg->angular_velocity.z = data[i]->angularRate[2] * (M_PI / 180.0);
183213

184214
imu_publisher_.publish(imu_msg);
215+
imu_publisher_diag_ptr_->tick(time_now);
185216

186217
// **** create and publish magnetic field message
187218

188-
boost::shared_ptr<MagMsg> mag_msg =
219+
boost::shared_ptr<MagMsg> mag_msg =
189220
boost::make_shared<MagMsg>();
190-
221+
191222
mag_msg->header.frame_id = frame_id_;
192223
mag_msg->header.stamp = time_now;
193224

@@ -205,8 +236,11 @@ void ImuRosI::processImuData(CPhidgetSpatial_SpatialEventDataHandle* data, int i
205236
mag_msg->vector.y = nan;
206237
mag_msg->vector.z = nan;
207238
}
208-
239+
209240
mag_publisher_.publish(mag_msg);
241+
242+
// diagnostics
243+
diag_updater_.update();
210244
}
211245

212246
void ImuRosI::dataHandler(CPhidgetSpatial_SpatialEventDataHandle *data, int count)
@@ -215,5 +249,51 @@ void ImuRosI::dataHandler(CPhidgetSpatial_SpatialEventDataHandle *data, int coun
215249
processImuData(data, i);
216250
}
217251

252+
// Added for diagnostics
253+
void ImuRosI::attachHandler()
254+
{
255+
Imu::attachHandler();
256+
is_connected_ = true;
257+
// Reset error number to no error if the prev error was disconnect
258+
if (error_number_ == 13) error_number_ = 0;
259+
diag_updater_.force_update();
260+
}
261+
262+
void ImuRosI::detachHandler()
263+
{
264+
Imu::detachHandler();
265+
is_connected_ = false;
266+
diag_updater_.force_update();
267+
}
268+
269+
void ImuRosI::errorHandler(int error)
270+
{
271+
Imu::errorHandler(error);
272+
error_number_ = error;
273+
diag_updater_.force_update();
274+
}
275+
276+
void ImuRosI::phidgetsDiagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
277+
{
278+
if (is_connected_)
279+
{
280+
stat.summary(diagnostic_msgs::DiagnosticStatus::OK, "The Phidget is connected.");
281+
stat.add("Device Serial Number", getDeviceSerialNumber());
282+
stat.add("Device Name", getDeviceName());
283+
stat.add("Device Type", getDeviceType());
284+
}
285+
else
286+
{
287+
stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "The Phidget is not connected. Check the USB.");
288+
}
289+
290+
if (error_number_ != 0)
291+
{
292+
stat.summary(diagnostic_msgs::DiagnosticStatus::ERROR, "The Phidget reports error.");
293+
stat.add("Error Number", error_number_);
294+
stat.add("Error message", getErrorDescription(error_number_));
295+
}
296+
}
297+
218298
} // namespace phidgets
219299

0 commit comments

Comments
 (0)