00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "ros/ros.h"
00032 #include "orientation.h"
00033 #include <stdio.h>
00034 #include "corobot_msgs/PosMsg.h"
00035 #include "corobot_msgs/PowerMsg.h"
00036 #include "corobot_msgs/SensorMsg.h"
00037 #include "sensor_msgs/MagneticField.h"
00038 #include "sensor_msgs/Imu.h"
00039 #include "std_msgs/Int16.h"
00040 #include <phidget21.h>
00041 #include <tf/transform_datatypes.h>
00042 #include <diagnostic_updater/diagnostic_updater.h>
00043 #include <diagnostic_updater/publisher.h>
00044 #include <corobot_diagnostics/diagnostics.h>
00045 #include <std_srvs/Empty.h>
00046
00047 CPhidgetInterfaceKitHandle ifKit = 0;
00048 CPhidgetSpatialHandle spatial = 0;
00049
00050 Orientation orientation_calculation;
00051
00052
00053 bool m_rearBumperPresent = false;
00054
00055
00056 bool sonarsPresent = false;
00057
00058
00059 bool imu = true;
00060
00061
00062 ros::Publisher powerdata_pub,irData_pub,bumper_pub, imu_pub, mag_pub, sonar_pub, other_pub;
00063
00064
00065
00066 ros::ServiceServer calibrate_gyroscope_service;
00067
00068
00069 int bwOutput = -1;
00070
00071
00072 int strobeOutput = -1;
00073
00074
00075 int lastSonarInput = -1;
00076
00077
00078 int firstSonarInput = -1;
00079 int batteryPort = 0;
00080 int irFrontPort = 1;
00081 int irBackPort = 2;
00082
00083
00084 int interfaceKitError = 0, spatialError = 0;
00085
00086
00087
00088
00089 int ErrorHandler(CPhidgetHandle IFK, void *userptr, int ErrorCode, const char *unknown)
00090 {
00091 ROS_ERROR("Error handled. %d - %s \n", ErrorCode, unknown);
00092 return 0;
00093 }
00094
00095
00096
00102 static float irVoltageToDistance(float volts)
00103 {
00104 int sensorValue=int(volts*200.0+0.5);
00105 float distanceInCm;
00106
00107 if (sensorValue>=80 && sensorValue <= 530)
00108 {
00109 distanceInCm= 2076/(sensorValue-11);
00110 }
00111
00112 else
00113 {
00114
00115 distanceInCm = 2540;
00116 }
00117 return distanceInCm/100.0;
00118 }
00119
00120
00125 static double sonarVoltageToMeters(int value)
00126 {
00127
00128
00129 const double vcc = 5.0;
00130 double voltage = value * vcc / 1000.0;
00131 double range_inches = voltage * 512 / vcc;
00132
00133 return range_inches * 2.54 / 100;
00134 }
00135
00138 int sendSonarResult()
00139 {
00140
00141 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 1);
00142
00143 ros::Duration(0.002).sleep();
00144 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 0);
00145 }
00146
00147
00151 int DigitalInputHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int State)
00152 {
00153 corobot_msgs::SensorMsg msg;
00154 msg.value = ((State == PTRUE)?1:0);
00155 msg.index = Index;
00156
00157
00158 if (Index <= 3 && m_rearBumperPresent == true && bumper_pub)
00159 {
00160 msg.type = msg.BUMPER;
00161 bumper_pub.publish(msg);
00162 }
00163
00164 else if (Index <= 1 && bumper_pub)
00165 {
00166 msg.type = msg.BUMPER;
00167 bumper_pub.publish(msg);
00168 }
00169
00170 else if(other_pub)
00171 {
00172 msg.type = msg.OTHER;
00173 other_pub.publish(msg);
00174 }
00175
00176
00177 interfaceKitError = 0;
00178 return 0;
00179 }
00180
00181
00182
00183 int AnalogInputHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int Value)
00184 {
00185
00186
00187
00188
00189 if(batteryPort == Index && powerdata_pub)
00190 {
00191 corobot_msgs::PowerMsg powerdata;
00192 powerdata.volts = (float) (Value - 500) * 0.0734;
00193
00194 powerdata.min_volt = 10.0;
00195 powerdata.max_volt = 14.2;
00196 powerdata_pub.publish(powerdata);
00197 }
00198
00199 else if(irFrontPort == Index && irData_pub)
00200 {
00201 corobot_msgs::SensorMsg data;
00202 data.type = data.INFRARED_FRONT;
00203 data.index = Index;
00204
00205 data.value = irVoltageToDistance((float) Value / 200.0);
00206 irData_pub.publish(data);
00207 }
00208
00209 else if(irBackPort == Index && irData_pub)
00210 {
00211 corobot_msgs::SensorMsg data;
00212 data.type = data.INFRARED_REAR;
00213 data.index = Index;
00214
00215 data.value = irVoltageToDistance((float) Value / 200.0);
00216 irData_pub.publish(data);
00217 }
00218
00219 else if(Index >= firstSonarInput && Index <= lastSonarInput && sonar_pub)
00220 {
00221 corobot_msgs::SensorMsg data;
00222 data.type = data.ULTRASOUND;
00223 data.index = Index;
00224
00225 data.value = sonarVoltageToMeters((float) Value / 200.0);
00226 sonar_pub.publish(data);
00227 }
00228
00229 else if(other_pub)
00230 {
00231 corobot_msgs::SensorMsg data;
00232 data.type = data.OTHER;
00233 data.value = Value;
00234 data.index = Index;
00235 other_pub.publish(data);
00236 }
00237
00238
00239 interfaceKitError = 0;
00240 return 0;
00241 }
00242
00243
00247 int SpatialDataHandler(CPhidgetSpatialHandle spatial, void *userptr, CPhidgetSpatial_SpatialEventDataHandle *data, int count)
00248 {
00249 sensor_msgs::Imu imu;
00250 sensor_msgs::MagneticField mag;
00251
00252 imu.header.frame_id = "base_link";
00253 imu.header.stamp = ros::Time::now();
00254
00255 mag.header.frame_id = "base_link";
00256 mag.header.stamp = ros::Time::now();
00257
00258 for(int i = 0; i< count; i++)
00259 {
00260 if (data[i]->angularRate[0] != 0 || data[i]->angularRate[1] != 0 || data[i]->angularRate[2] != 0)
00261 orientation_calculation.updateAngles((float*)&(data[i]->angularRate[0]), (float*)&(data[i]->acceleration), data[i]->timestamp.seconds + ((float)data[i]->timestamp.microseconds)/1000000);
00262
00263
00264 imu.orientation = tf::createQuaternionMsgFromRollPitchYaw(orientation_calculation.get_roll(),orientation_calculation.get_pitch(), orientation_calculation.get_yaw());
00265
00266
00267 imu.angular_velocity.x = data[i]->angularRate[0] * (3.14 / 180);
00268 imu.angular_velocity.y = data[i]->angularRate[1] * (3.14 / 180);
00269 imu.angular_velocity.z = data[i]->angularRate[2] * (3.14 / 180);
00270
00271 imu.linear_acceleration.x = data[i]->acceleration[0] * 9.81;
00272 imu.linear_acceleration.y = data[i]->acceleration[1] * 9.81;
00273 imu.linear_acceleration.z = data[i]->acceleration[2] * 9.81;
00274
00275 mag.magnetic_field.x = data[i]->magneticField[0] * 0.0001;
00276 mag.magnetic_field.y = data[i]->magneticField[1] * 0.0001;
00277 mag.magnetic_field.z = data[i]->magneticField[2] * 0.0001;
00278
00279 if(imu_pub)
00280 imu_pub.publish(imu);
00281 if(mag_pub)
00282 mag_pub.publish(mag);
00283 }
00284
00285 spatialError = 0;
00286 return 0;
00287 }
00288
00289
00290
00291 bool calibrate_gyroscope(std_srvs::Empty::Request& request, std_srvs::Empty::Response& response)
00292 {
00293 CPhidgetSpatial_zeroGyro(spatial);
00294 }
00295
00296
00297 int interfacekit_simple()
00298
00299 {
00300 int result, num_analog_inputs, num_digital_inputs;
00301 const char *err;
00302 ros::NodeHandle n;
00303
00304
00305 CPhidgetInterfaceKit_create(&ifKit);
00306
00307
00308 CPhidget_set_OnError_Handler((CPhidgetHandle)ifKit, ErrorHandler, NULL);
00309 CPhidgetInterfaceKit_set_OnInputChange_Handler (ifKit, DigitalInputHandler, NULL);
00310 CPhidgetInterfaceKit_set_OnSensorChange_Handler (ifKit, AnalogInputHandler, NULL);
00311
00312
00313
00314 CPhidget_open((CPhidgetHandle)ifKit, -1);
00315
00316
00317 CPhidgetInterfaceKit_getInputCount(ifKit, &num_digital_inputs);
00318 CPhidgetInterfaceKit_getSensorCount(ifKit, &num_analog_inputs);
00319
00320
00321 printf("Waiting for interface kit to be attached....");
00322 if((result = CPhidget_waitForAttachment((CPhidgetHandle)ifKit, 1000)))
00323 {
00324 CPhidget_getErrorDescription(result, &err);
00325 ROS_ERROR("Phidget IK: Problem waiting for attachment: %s\n", err);
00326 interfaceKitError = 1;
00327 }
00328 else
00329 {
00330 irData_pub = n.advertise<corobot_msgs::SensorMsg>("infrared_data", 100);
00331 powerdata_pub = n.advertise<corobot_msgs::PowerMsg>("power_data", 100);
00332 bumper_pub = n.advertise<corobot_msgs::SensorMsg>("bumper_data", 100);
00333
00334 other_pub = n.advertise<corobot_msgs::SensorMsg>("sensor_data", 100);
00335 }
00336
00337
00338
00339 if (imu)
00340 {
00341 CPhidgetSpatial_create(&spatial);
00342 CPhidget_set_OnError_Handler((CPhidgetHandle)spatial, ErrorHandler, NULL);
00343 CPhidgetSpatial_set_OnSpatialData_Handler(spatial, SpatialDataHandler, NULL);
00344 CPhidget_open((CPhidgetHandle)spatial, -1);
00345
00346
00347 printf("Waiting for spatial to be attached.... \n");
00348 if((result = CPhidget_waitForAttachment((CPhidgetHandle)spatial, 1000)))
00349 {
00350 CPhidget_getErrorDescription(result, &err);
00351 ROS_ERROR("Phidget Spatial: Problem waiting for attachment: %s\n", err);
00352 spatialError = 1;
00353 }
00354 else
00355 {
00356 imu_pub = n.advertise<sensor_msgs::Imu>("imu_data",100);
00357 mag_pub = n.advertise<sensor_msgs::MagneticField>("magnetic_data",100);
00358 calibrate_gyroscope_service = n.advertiseService("calibrate_gyroscope",calibrate_gyroscope);
00359 }
00360
00361 CPhidgetSpatial_setDataRate(spatial, 4);
00362 }
00363
00364 CPhidgetInterfaceKit_setRatiometric(ifKit, 0);
00365
00366
00367 if(sonarsPresent)
00368 {
00369 CPhidgetInterfaceKit_setOutputState(ifKit, bwOutput, 1);
00370 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 0);
00371
00372 ros::Duration(0.250).sleep();
00373 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 1);
00374
00375 ros::Duration(0.002).sleep();
00376 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 0);
00377
00378 ros::Duration(0.150).sleep();
00379
00380 sonar_pub = n.advertise<corobot_msgs::SensorMsg>("sonar_data", 100);
00381 }
00382 return 0;
00383 }
00384
00385 void phidget_ik_diagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
00389 {
00390 if (!interfaceKitError)
00391 stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "initialized");
00392 else
00393 {
00394 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "Phidget 8/8/8 cannot be initialized");
00395 stat.addf("Recommendation", PhidgetIK_INIT_ERROR);
00396 }
00397 }
00398
00399 void phidget_spatial_diagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
00403 {
00404 if (!spatialError)
00405 stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "initialized");
00406 else
00407 {
00408 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "IMU cannot be initialized");
00409 stat.addf("Recommendation", PhidgetIMU_INIT_ERROR);
00410 }
00411 }
00412
00413 int main(int argc, char* argv[])
00414 {
00415 ros::init(argc, argv, "phidget_component");
00416 ros::NodeHandle n;
00417 ros::NodeHandle nh("~");
00418 nh.param("rearBumper", m_rearBumperPresent, false);
00419 nh.param("bwOutput", bwOutput, -1);
00420 nh.param("strobeOutput", strobeOutput, -1);
00421 nh.param("lastSonarInput", lastSonarInput, -1);
00422 nh.param("firstSonarInput", firstSonarInput, -1);
00423
00424 nh.param("battery", batteryPort, 0);
00425
00426 nh.param("irFront", irFrontPort, 1);
00427
00428 nh.param("irBack", irBackPort, 2);
00429 nh.param("imu", imu, true);
00430
00431
00432 diagnostic_updater::Updater updater;
00433 updater.setHardwareIDf("Phidget");
00434
00435 updater.add("Interface Kit", phidget_ik_diagnostic);
00436
00437 updater.add("Spatial", phidget_spatial_diagnostic);
00438
00439 interfacekit_simple();
00440 ros::Rate rate(70);
00441 while (ros::ok())
00442 {
00443
00444 ros::spinOnce();
00445
00446
00447 if(sonarsPresent)
00448 sendSonarResult();
00449
00450 updater.update();
00451 rate.sleep();
00452 }
00453
00454
00455
00456 CPhidget_close((CPhidgetHandle)ifKit);
00457 CPhidget_delete((CPhidgetHandle)ifKit);
00458
00459 if (imu)
00460 {
00461 CPhidget_close((CPhidgetHandle)spatial);
00462 CPhidget_delete((CPhidgetHandle)spatial);
00463 }
00464
00465 return 0;
00466 }