00001
00002
00003
00004
00005
00006
00007 #include "ros/ros.h"
00008 #include <stdio.h>
00009 #include "corobot_srvs/SetOdom.h"
00010 #include "corobot_msgs/PosMsg.h"
00011 #include "corobot_msgs/PowerMsg.h"
00012 #include "corobot_msgs/IrMsg.h"
00013 #include "corobot_msgs/BumperMsg.h"
00014 #include "corobot_msgs/GripperMsg.h"
00015 #include "corobot_msgs/phidget_info.h"
00016 #include "corobot_msgs/spatial.h"
00017 #include "corobot_msgs/RangeSensor.h"
00018 #include "sensor_msgs/Imu.h"
00019 #include <phidget21.h>
00020 #include <tf/transform_datatypes.h>
00021 #include <diagnostic_updater/diagnostic_updater.h>
00022 #include <diagnostic_updater/publisher.h>
00023
00024 #define GRAVITY 9.81
00025
00026 CPhidgetEncoderHandle m_rightEncoder;
00027 CPhidgetEncoderHandle m_leftEncoder;
00028 CPhidgetInterfaceKitHandle ifKit = 0;
00029 CPhidgetSpatialHandle spatial = 0;
00030
00031 int analog_inputs_value [8] = {0,0,0,0,0,0,0,0};
00032 char digital_inputs_value = 0;
00033 float acc [3] = {0,0,0};
00034 float ang [3] = {0,0,0};
00035 float mag [3] = {0,0,0};
00036
00037 bool m_encoder1Seen=false, m_encoder2Seen=false,m_encodersGood = false;
00038 bool m_validAnalogs = false,m_validDigitals=false;
00039 int m_leftEncoderNumber,m_rightEncoderNumber;
00040
00041 bool m_rearBumperPresent = false;
00042 bool sonarsPresent = false;
00043
00044 bool phidget888_connected, phidget_encoder_connected;
00045
00046 bool spatial_good = false;
00047
00048 ros::Publisher posdata_pub,powerdata_pub,irData_pub,bumper_pub,gripper_pub,spatial_pub, imu_pub, sonar_pub;
00049
00050 int bwOutput = -1;
00051 int strobeOutput = -1;
00052 int lastSonarInput = -1;
00053 int firstSonarInput = -1;
00054 int batteryPort = 0;
00055 int irFrontPort = 1;
00056 int irBackPort = 2;
00057 int gripperPort = 3;
00058
00059 bool motors_inverted;
00060 bool encoders_inverted;
00061
00062 int interfaceKitError = 0, spatialError = 0, encoderError = 0;
00063
00064 int RightEncoderAttach(CPhidgetHandle phid, void *userPtr);
00065 int LeftEncoderAttach(CPhidgetHandle phid, void *userPtr);
00066
00067 double dCMMatrix[3][3];
00068 int timestampPreviousCall;
00069 double pitchOffset;
00070 double rollOffset;
00071 double gravity[3];
00072 double proportionalVector[3];
00073 double integratorVector[3];
00074 double gyroscopeVectorCorrected[3];
00075 double kpRollpitch = 0.015;
00076 double kiRollpitch = 0.000010;
00077 double gravityEpsilon = 0.07;
00078 int validGravityCounter = 0;
00079 int validAccelerationVectorsNecessaryToDetectGravity = 10;
00080 double lastGravityVectorDetected[3] = {0,0,0};
00081
00082
00084 bool SetOdom(corobot_srvs::SetOdom::Request &req,corobot_srvs::SetOdom::Response &res )
00085 {
00086 int err=0;
00087 err = CPhidgetEncoder_setPosition(m_leftEncoder, m_leftEncoderNumber,req.px);
00088 err += CPhidgetEncoder_setPosition(m_rightEncoder, m_rightEncoderNumber,req.py);
00089
00090 if(err)
00091 res.err = 1;
00092 else
00093 res.err = 0;
00094
00095 return true;
00096
00097 }
00098
00099 int AttachHandler(CPhidgetHandle IFK, void *userptr)
00100 {
00101 int serialNo;
00102 const char *name;
00103
00104 CPhidget_getDeviceName(IFK, &name);
00105 CPhidget_getSerialNumber(IFK, &serialNo);
00106
00107 printf("%s %10d attached!\n", name, serialNo);
00108
00109 return 0;
00110 }
00111
00112 int DetachHandler(CPhidgetHandle IFK, void *userptr)
00113 {
00114 int serialNo;
00115 const char *name;
00116
00117 CPhidget_getDeviceName (IFK, &name);
00118 CPhidget_getSerialNumber(IFK, &serialNo);
00119
00120 printf("%s %10d detached!\n", name, serialNo);
00121
00122 return 0;
00123 }
00124
00125 int ErrorHandler(CPhidgetHandle IFK, void *userptr, int ErrorCode, const char *unknown)
00126 {
00127
00128 printf("Error handled. %d - %s \n", ErrorCode, unknown);
00129 return 0;
00130 }
00131
00132 void encoderAttach(const int which)
00137 {
00138 if (which == 1)
00139 {
00140 m_encoder1Seen = true;
00141
00142
00143 int count;
00144 CPhidgetEncoder_getEncoderCount(m_leftEncoder, &count);
00145 if (count > 1)
00146 {
00147
00148 m_leftEncoderNumber = 0;
00149 m_rightEncoderNumber = 1;
00150
00151 if(motors_inverted || encoders_inverted){
00152 m_leftEncoderNumber = 1;
00153 m_rightEncoderNumber = 0;
00154 }
00155
00156 m_rightEncoder = m_leftEncoder;
00157 m_encoder2Seen = true;
00158 m_encodersGood = true;
00159 }
00160 else
00161 {
00162 m_leftEncoderNumber = 0;
00163 m_rightEncoderNumber = 0;
00164
00165 CPhidgetEncoder_create(&m_rightEncoder);
00166 CPhidget_set_OnAttach_Handler((CPhidgetHandle) m_rightEncoder,
00167 RightEncoderAttach, NULL);
00168 CPhidget_open((CPhidgetHandle) m_rightEncoder, -1);
00169 }
00170 }
00171 else
00172 {
00173 m_encoder2Seen = true;
00174 }
00175
00176 if (m_encoder1Seen && m_encoder2Seen)
00177 {
00178
00179 int leftSerial;
00180 int rightSerial;
00181
00182 CPhidget_getSerialNumber((CPhidgetHandle) m_leftEncoder, &leftSerial);
00183 CPhidget_getSerialNumber((CPhidgetHandle) m_rightEncoder, &rightSerial);
00184
00185 if (leftSerial > rightSerial)
00186 {
00187
00188 CPhidgetEncoderHandle tempEncoder = m_leftEncoder;
00189 m_leftEncoder = m_rightEncoder;
00190 m_rightEncoder = tempEncoder;
00191
00192 int tempNumber = m_leftEncoderNumber;
00193 m_leftEncoderNumber = m_rightEncoderNumber;
00194 m_rightEncoderNumber = tempNumber;
00195 }
00196 CPhidgetEncoder_setEnabled(m_leftEncoder, m_leftEncoderNumber, PTRUE);
00197 CPhidgetEncoder_setEnabled(m_rightEncoder, m_rightEncoderNumber, PTRUE);
00198 m_encodersGood = true;
00199
00200 }
00201 }
00206 int RightEncoderAttach(CPhidgetHandle phid, void *userPtr)
00207
00208 {
00209 encoderAttach(2);
00210 return 0;
00211 }
00215 int LeftEncoderAttach(CPhidgetHandle phid, void *userPtr)
00216
00217 {
00218 encoderAttach(1);
00219 return 0;
00220 }
00221
00227 static float irVoltageToDistance(float volts)
00228 {
00229 int sensorValue=int(volts*200.0+0.5);
00230 float distanceInCm;
00231 if (sensorValue>=80 && sensorValue <= 530)
00232 {
00233 distanceInCm= 2076/(sensorValue-11);
00234 }
00235 else
00236 {
00237 distanceInCm = 2540;
00238 }
00239 return distanceInCm/100.0;
00240 }
00241
00246 static double sonarVoltageToMeters(int value)
00247 {
00248
00249
00250 const double vcc = 5.0;
00251 double voltage = value * vcc / 1000.0;
00252 double range_inches = voltage * 512 / vcc;
00253
00254 return range_inches * 2.54 / 100;
00255 }
00256
00260 int publish_data(){
00261
00262 if(spatial_good)
00263 {
00264 corobot_msgs::spatial spatial;
00265 sensor_msgs::Imu imu;
00266
00267 spatial.acc1 = acc[0];
00268 spatial.acc2 = acc[1];
00269 spatial.acc3 = acc[2];
00270 spatial.ang1 = ang[0];
00271 spatial.ang2 = ang[1];
00272 spatial.ang3 = ang[2];
00273 spatial.mag1 = mag[0];
00274 spatial.mag2 = mag[1];
00275 spatial.mag3 = mag[2];
00276
00277 imu.header.frame_id = "base_link";
00278 imu.header.stamp = ros::Time::now();
00279 imu.orientation = tf::createQuaternionMsgFromRollPitchYaw((atan2(dCMMatrix[2][1],dCMMatrix[2][2]) + rollOffset),(-asin(dCMMatrix[2][0]) + pitchOffset), (atan2(dCMMatrix[1][0],dCMMatrix[0][0])));
00280 imu.angular_velocity.x = ang[0];
00281 imu.angular_velocity.y = ang[1];
00282 imu.angular_velocity.z = ang[2];
00283 imu.linear_acceleration.x = acc[0];
00284 imu.linear_acceleration.y = acc[1];
00285 imu.linear_acceleration.z = acc[2];
00286
00287 spatial_pub.publish(spatial);
00288 imu_pub.publish(imu);
00289
00290 spatialError = 0;
00291 }
00292
00293 if(m_encodersGood)
00294 {
00295 corobot_msgs::PosMsg posdata;
00296
00297
00298 int phidgetEncoderStatus = 0;
00299
00300 CPhidget_getDeviceStatus((CPhidgetHandle) m_leftEncoder,
00301 &phidgetEncoderStatus);
00302 if (phidgetEncoderStatus != 0)
00303 {
00304 int value;
00305
00306 CPhidgetEncoder_getPosition(m_leftEncoder, m_leftEncoderNumber, &value);
00307 posdata.px = -value;
00308 printf("Left encoder value = %d", value);
00309
00310 }
00311 else
00312 {
00313 encoderError = 2;
00314 }
00315 phidgetEncoderStatus = 0;
00316 CPhidget_getDeviceStatus((CPhidgetHandle) m_rightEncoder,
00317 &phidgetEncoderStatus);
00318 if (phidgetEncoderStatus != 0)
00319 {
00320 int value;
00321
00322 CPhidgetEncoder_getPosition(m_rightEncoder, m_rightEncoderNumber, &value);
00323
00324
00325 posdata.py = value;
00326 }
00327 else
00328 {
00329 encoderError = 2;
00330 }
00331
00332 posdata.header.stamp = ros::Time::now();
00333 posdata_pub.publish(posdata);
00334 encoderError = 0;
00335 }
00336 else
00337 {
00338 encoderError = 1;
00339 }
00340 if (m_validAnalogs){
00342
00343 if(batteryPort != -1)
00344 {
00345 corobot_msgs::PowerMsg powerdata;
00346 powerdata.volts = (float) (analog_inputs_value[batteryPort] - 500) * 0.0734;
00347
00348 powerdata.min_volt = 10.0;
00349 powerdata.max_volt = 14.2;
00350 powerdata_pub.publish(powerdata);
00351 }
00352
00354
00355 if(irFrontPort != -1 || irBackPort != -1)
00356 {
00357 corobot_msgs::IrMsg irData;
00358 if(irFrontPort != -1)
00359 irData.voltage1=(float) analog_inputs_value[irFrontPort] / 200.0;
00360 else
00361 irData.voltage1=0;
00362 if(irBackPort != -1)
00363 irData.voltage2=(float) analog_inputs_value[irBackPort] / 200.0;
00364 else
00365 irData.voltage2=0;
00366 irData.range1=irVoltageToDistance(irData.voltage1);
00367 irData.range2=irVoltageToDistance(irData.voltage2);
00368 irData_pub.publish(irData);
00369 }
00370
00371 if(gripperPort != -1)
00372 {
00373 corobot_msgs::GripperMsg gripperData;
00374 gripperData.state=analog_inputs_value[gripperPort];
00375 gripper_pub.publish(gripperData);
00376 }
00377 interfaceKitError = 0;
00378 }
00379
00380 if (m_validDigitals)
00381 {
00383
00384 corobot_msgs::BumperMsg bumper_data;
00385
00386 if (m_rearBumperPresent)
00387 {
00388 bumper_data.bumpers_count=4;
00389 bumper_data.value0=(digital_inputs_value) & (0x01<<0);
00390 bumper_data.value1=(digital_inputs_value) & (0x01<<1);
00391 bumper_data.value2=(digital_inputs_value) & (0x01<<2);
00392 bumper_data.value3=(digital_inputs_value) & (0x01<<3);
00393 }
00394 else {
00395 bumper_data.bumpers_count=2;
00396 bumper_data.value0=(digital_inputs_value) & (0x01<<0);
00397 bumper_data.value1=(digital_inputs_value) & (0x01<<1);
00398 }
00399
00400 bumper_pub.publish(bumper_data);
00401 interfaceKitError = 0;
00402
00403 }
00404
00405 return 0;
00406 }
00407
00411 int sendSonarResult()
00412 {
00413 corobot_msgs::RangeSensor data;
00414 data.type = data.ULTRASOUND;
00415 data.numberSensors = lastSonarInput + 1 - firstSonarInput;
00416
00417 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 1);
00418 ros::Duration(0.002).sleep();
00419 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 0);
00420
00421
00422 for(int i = firstSonarInput; i<= lastSonarInput;i++)
00423 {
00424 data.range.push_back(sonarVoltageToMeters(analog_inputs_value[i]));
00425 }
00426 sonar_pub.publish(data);
00427 return 0;
00428 }
00429
00430
00434 int InputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int State)
00435 {
00436 printf("Digital Input: %d > State: %d\n", Index, State);
00437
00438 if(State==PTRUE)
00439 digital_inputs_value = digital_inputs_value|(0x01<<Index);
00440 else if(State == PFALSE)
00441 digital_inputs_value = digital_inputs_value&(~(0x01<<Index));
00442 m_validDigitals = true;
00443
00444 return 0;
00445 }
00446
00447
00448
00449 int OutputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int State)
00450 {
00451 printf("Digital Output: %d > State: %d\n", Index, State);
00452 return 0;
00453 }
00454
00455
00456
00457 int SensorChangeHandler(CPhidgetInterfaceKitHandle IFK, void *usrptr, int Index, int Value)
00458 {
00459 printf("Sensor: %d > Value: %d\n", Index, Value);
00460
00461
00462
00463 analog_inputs_value[Index]=Value;
00464
00465 m_validAnalogs = true;
00466
00467 return 0;
00468 }
00469
00470 void vectorScale(double vectorOut[3],double vectorIn[3], double scale2)
00471 {
00472 for(int c=0; c<3; c++)
00473 {
00474 vectorOut[c]=vectorIn[c]*scale2;
00475 }
00476 }
00477
00478
00479
00480 void vectorCrossProduct(double vectorOut[3], double vectorIn1[3],double vectorIn2[3])
00481 {
00482 vectorOut[0]= (vectorIn1[1]*vectorIn2[2]) - (vectorIn1[2]*vectorIn2[1]);
00483 vectorOut[1]= (vectorIn1[2]*vectorIn2[0]) - (vectorIn1[0]*vectorIn2[2]);
00484 vectorOut[2]= (vectorIn1[0]*vectorIn2[1]) - (vectorIn1[1]*vectorIn2[0]);
00485 }
00486
00487 void vectorAddition(double vectorOut[3],double vectorIn1[3], double vectorIn2[3])
00488 {
00489 for(int c=0; c<3; c++)
00490 {
00491 vectorOut[c]=vectorIn1[c]+vectorIn2[c];
00492 }
00493 }
00494
00495 void matrixMultiply(double MatrixOut[3][3],double MatrixIn1[3][3], double MatrixIn2[3][3])
00496 {
00497 double op[3];
00498 for(int x=0; x<3; x++)
00499 {
00500 for(int y=0; y<3; y++)
00501 {
00502 for(int w=0; w<3; w++)
00503 {
00504 op[w]=MatrixIn1[x][w]*MatrixIn2[w][y];
00505 }
00506 MatrixOut[x][y]=0;
00507 MatrixOut[x][y]=op[0]+op[1]+op[2];
00508
00509 }
00510 }
00511 }
00512
00513 double ToRad(double value)
00514 {
00515 return value*0.01745329252;
00516 }
00517
00518 double vectorDotProduct(double vector1[3],double vector2[3])
00519 {
00520 double op=0;
00521
00522 for(int c=0; c<3; c++)
00523 {
00524 op+=vector1[c]*vector2[c];
00525 }
00526
00527 return op;
00528 }
00529
00530 double constrain(double value, double min, double max)
00531 {
00532 if((value>=min) && (value<= max))
00533 return value;
00534 else if(value<min)
00535 return min;
00536 else
00537 return max;
00538 }
00539
00540 bool isEqual(double vector1[3], double vector2[3])
00541 {
00542 if(abs(vector1[0] - (vector2[0]/GRAVITY) + vector1[1] - (vector2[1]/GRAVITY) + vector1[2] - (vector2[2]/GRAVITY))>0.0001)
00543 return false;
00544 else
00545 return true;
00546 }
00547
00548
00549 void AnglesMatrixUpdate(float gyroscopeVector[3], int gyroscopeTimestamp)
00550 {
00551
00552
00553 double period;
00554 if(timestampPreviousCall==0)
00555 period = 0;
00556 else
00557 period = (gyroscopeTimestamp - timestampPreviousCall);
00558
00559 double temporaryVector[3]= {0,0,0};
00560 double updateMatrix[3][3];
00561 double temporaryMatrix[3][3];
00562 double gyroscopeVectorInvertedSystem[3];
00563
00564
00565
00566 gyroscopeVectorInvertedSystem[0] = gyroscopeVector[1];
00567 gyroscopeVectorInvertedSystem[1] = gyroscopeVector[0];
00568 gyroscopeVectorInvertedSystem[2] = gyroscopeVector[2];
00569
00570
00571
00572
00573 vectorAddition(temporaryVector, gyroscopeVectorInvertedSystem, integratorVector);
00574 vectorAddition(gyroscopeVectorCorrected, temporaryVector, proportionalVector);
00575
00576
00577
00578 updateMatrix[0][0]=0;
00579 updateMatrix[0][1]=-period*gyroscopeVectorCorrected[2];
00580 updateMatrix[0][2]=period*gyroscopeVectorCorrected[1];
00581 updateMatrix[1][0]=period*gyroscopeVectorCorrected[2];
00582 updateMatrix[1][1]=0;
00583 updateMatrix[1][2]=-period*gyroscopeVectorCorrected[0];
00584 updateMatrix[2][0]=-period*gyroscopeVectorCorrected[1];
00585 updateMatrix[2][1]=period*gyroscopeVectorCorrected[0];
00586 updateMatrix[2][2]=0;
00587
00588
00589
00590
00591 matrixMultiply(temporaryMatrix,dCMMatrix, updateMatrix);
00592
00593 for(int x=0; x<3; x++)
00594 {
00595 for(int y=0; y<3; y++)
00596 {
00597 dCMMatrix[x][y]+=temporaryMatrix[x][y];
00598 }
00599 }
00600
00601 timestampPreviousCall = gyroscopeTimestamp;
00602
00603 }
00604
00605
00606 void AnglesNormalize()
00607 {
00608 double error=0;
00609 double temporaryMatrix[3][3];
00610 double vectorNorm=0;
00611 bool problem=false;
00612
00613
00614
00615 error= -vectorDotProduct(dCMMatrix[0],dCMMatrix[1])*.5f;
00616
00617 vectorScale(temporaryMatrix[0], dCMMatrix[1], error);
00618 vectorScale(temporaryMatrix[1], dCMMatrix[0], error);
00619
00620 vectorAddition(temporaryMatrix[0], temporaryMatrix[0], dCMMatrix[0]);
00621 vectorAddition(temporaryMatrix[1], temporaryMatrix[1], dCMMatrix[1]);
00622
00623 vectorCrossProduct(temporaryMatrix[2],temporaryMatrix[0],temporaryMatrix[1]);
00624
00625
00626
00627
00628 vectorNorm= vectorDotProduct(temporaryMatrix[0],temporaryMatrix[0]);
00629 if (vectorNorm < 1.5625f && vectorNorm > 0.64f) {
00630 vectorNorm= .5f * (3-vectorNorm);
00631 } else if (vectorNorm < 100.0f && vectorNorm > 0.01f) {
00632 vectorNorm= 1. / sqrt(vectorNorm);
00633 } else {
00634 problem = true;
00635 }
00636 vectorScale(dCMMatrix[0], temporaryMatrix[0], vectorNorm);
00637
00638 vectorNorm= vectorDotProduct(temporaryMatrix[1],temporaryMatrix[1]);
00639 if (vectorNorm < 1.5625f && vectorNorm > 0.64f) {
00640 vectorNorm= .5f * (3-vectorNorm);
00641 } else if (vectorNorm < 100.0f && vectorNorm > 0.01f) {
00642 vectorNorm= 1. / sqrt(vectorNorm);
00643 } else {
00644 problem = true;
00645 }
00646 vectorScale(dCMMatrix[1], temporaryMatrix[1], vectorNorm);
00647
00648 vectorNorm= vectorDotProduct(temporaryMatrix[2],temporaryMatrix[2]);
00649 if (vectorNorm < 1.5625f && vectorNorm > 0.64f) {
00650 vectorNorm= .5f * (3-vectorNorm);
00651 } else if (vectorNorm < 100.0f && vectorNorm > 0.01f) {
00652 vectorNorm= 1. / sqrt(vectorNorm);
00653 } else {
00654 problem = true;
00655 }
00656 vectorScale(dCMMatrix[2], temporaryMatrix[2], vectorNorm);
00657
00658
00659
00660 if (problem) {
00661 dCMMatrix[0][0]= 1.0f;
00662 dCMMatrix[0][1]= 0.0f;
00663 dCMMatrix[0][2]= 0.0f;
00664 dCMMatrix[1][0]= 0.0f;
00665 dCMMatrix[1][1]= 1.0f;
00666 dCMMatrix[1][2]= 0.0f;
00667 dCMMatrix[2][0]= 0.0f;
00668 dCMMatrix[2][1]= 0.0f;
00669 dCMMatrix[2][2]= 1.0f;
00670 problem = false;
00671 }
00672
00673 }
00674
00675
00676 void AnglesDriftCorrection(float AccelerationVector[3])
00677 {
00678
00679 double scaledIntegratorVector[3];
00680 double accelerationMagnitude;
00681 double accelerationWeight;
00682 double integratorMagnitude;
00683 double AccelerationVectorInvertedDystem[3];
00684 double errorRollPitch[3];
00685
00686
00687
00688
00689
00690
00691 accelerationMagnitude = sqrt(AccelerationVector[0]*AccelerationVector[0] + AccelerationVector[1]*AccelerationVector[1] + AccelerationVector[2]*AccelerationVector[2]);
00692 accelerationMagnitude = accelerationMagnitude / GRAVITY;
00693
00694
00695
00696 accelerationWeight = constrain(1 - 2*abs(1 - accelerationMagnitude),0,1);
00697
00698
00699
00700 AccelerationVectorInvertedDystem[0] = AccelerationVector[1];
00701 AccelerationVectorInvertedDystem[1] = AccelerationVector[0];
00702 AccelerationVectorInvertedDystem[2] = AccelerationVector[2];
00703
00704
00705
00706 vectorScale(AccelerationVectorInvertedDystem,AccelerationVectorInvertedDystem,101/9.81);
00707
00708
00709 vectorCrossProduct(errorRollPitch,AccelerationVectorInvertedDystem,dCMMatrix[2]);
00710 vectorScale(proportionalVector,errorRollPitch,kpRollpitch*accelerationWeight);
00711
00712 vectorScale(scaledIntegratorVector,errorRollPitch,kiRollpitch*accelerationWeight);
00713 vectorAddition(integratorVector,integratorVector,scaledIntegratorVector);
00714
00715
00716
00717
00718 integratorMagnitude = sqrt(vectorDotProduct(integratorVector,integratorVector));
00719 if (integratorMagnitude > ToRad(300)) {
00720 vectorScale(integratorVector,integratorVector,0.5f*ToRad(300)/integratorMagnitude);
00721 }
00722
00723
00724 }
00725
00726 void detectGravity(double gravity[3], float acceleration[3])
00727 {
00728 double norm = sqrt(acceleration[0] * acceleration[0] + acceleration[1] * acceleration[1] + acceleration[2] * acceleration[2]);
00729
00730
00731 if(norm >= (GRAVITY*(1-gravityEpsilon)) && norm<= (GRAVITY*(1+gravityEpsilon)))
00732 {
00733 validGravityCounter++;
00734
00735
00736 if(validGravityCounter == validAccelerationVectorsNecessaryToDetectGravity)
00737 {
00738 lastGravityVectorDetected[0] = acceleration[0];
00739 lastGravityVectorDetected[1] = acceleration[1];
00740 lastGravityVectorDetected[2] = acceleration[2];
00741
00742 validGravityCounter = 0;
00743 }
00744 }
00745 else
00746 validGravityCounter =0;
00747
00748 gravity[0] = lastGravityVectorDetected[0];
00749 gravity[1] = lastGravityVectorDetected[1];
00750 gravity[2] = lastGravityVectorDetected[2];
00751
00752 }
00753
00754
00755 int SpatialDataHandler(CPhidgetSpatialHandle spatial, void *userptr, CPhidgetSpatial_SpatialEventDataHandle *data, int count)
00756 {
00757 int i;
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769 for(i = 0; i< count; i++)
00770 {
00771 acc[0] = data[i]->acceleration[0];
00772 acc[1] = data[i]->acceleration[1];
00773 acc[2] = data[i]->acceleration[2];
00774 ang[0] = data[i]->angularRate[0];
00775 ang[1] = data[i]->angularRate[1];
00776 ang[2] = data[i]->angularRate[2];
00777 mag[0] = data[i]->magneticField[0];
00778 mag[1] = data[i]->magneticField[1];
00779 mag[2] = data[i]->magneticField[2];
00780
00781 if (ang[0] != 0 || ang[1] != 0 || ang[2] != 0)
00782 AnglesMatrixUpdate(ang, data[i]->timestamp.seconds + ((float)data[i]->timestamp.microseconds)/1000000);
00783 AnglesNormalize();
00784 AnglesDriftCorrection(acc);
00785
00786 double gravity_[3];
00787 detectGravity(gravity_, acc);
00788
00789 if(!isEqual(gravity, gravity_))
00790 {
00791
00792
00793
00794 gravity[0] = gravity_[0]/GRAVITY;
00795 gravity[1] = gravity_[1]/GRAVITY;
00796 gravity[2] = gravity_[2]/GRAVITY;
00797
00798
00799
00800 pitchOffset = gravity[1];
00801 if(pitchOffset>1.0f)
00802 pitchOffset = 1.0f;
00803 if(pitchOffset<-1.0f)
00804 pitchOffset = -1.0f;
00805
00806 pitchOffset = asin(-pitchOffset);
00807
00808 rollOffset = gravity[2]/cos(pitchOffset);
00809 if(rollOffset>1.0f)
00810 rollOffset = 1.0f;
00811 if(rollOffset<-1.0f)
00812 rollOffset = -1.0f;
00813
00814 pitchOffset -= (-asin(dCMMatrix[2][0]));
00815 rollOffset = acos(rollOffset) - (atan2(dCMMatrix[2][1],dCMMatrix[2][2]));
00816 }
00817
00818 }
00819
00820 ROS_INFO("publishing IMU data in ROS!");
00821
00822 spatial_good = true;
00823
00824 return 0;
00825 }
00826
00827
00828
00829
00830 int interfacekit_simple()
00831 {
00832 int result, num_analog_inputs, num_digital_inputs;
00833 const char *err;
00834
00835
00836 CPhidgetInterfaceKit_create(&ifKit);
00837
00838
00839
00840 CPhidget_set_OnDetach_Handler((CPhidgetHandle)ifKit, DetachHandler, NULL);
00841 CPhidget_set_OnError_Handler((CPhidgetHandle)ifKit, ErrorHandler, NULL);
00842
00843 CPhidgetInterfaceKit_set_OnInputChange_Handler (ifKit, InputChangeHandler, NULL);
00844
00845 CPhidgetInterfaceKit_set_OnSensorChange_Handler (ifKit, SensorChangeHandler, NULL);
00846
00847 CPhidgetInterfaceKit_set_OnOutputChange_Handler (ifKit, OutputChangeHandler, NULL);
00848
00849
00850
00851 CPhidgetSpatial_create(&spatial);
00852 CPhidget_set_OnAttach_Handler((CPhidgetHandle)spatial, AttachHandler, NULL);
00853 CPhidget_set_OnDetach_Handler((CPhidgetHandle)spatial, DetachHandler, NULL);
00854 CPhidget_set_OnError_Handler((CPhidgetHandle)spatial, ErrorHandler, NULL);
00855 CPhidgetSpatial_set_OnSpatialData_Handler(spatial, SpatialDataHandler, NULL);
00856
00857
00858
00859 CPhidget_open((CPhidgetHandle)ifKit, -1);
00860
00861
00862 CPhidget_open((CPhidgetHandle)spatial, -1);
00863
00864
00865 CPhidgetInterfaceKit_getInputCount(ifKit, &num_digital_inputs);
00866 CPhidgetInterfaceKit_getSensorCount(ifKit, &num_analog_inputs);
00867
00868
00869 printf("Waiting for spatial to be attached.... \n");
00870 if((result = CPhidget_waitForAttachment((CPhidgetHandle)spatial, 1000)))
00871 {
00872 CPhidget_getErrorDescription(result, &err);
00873 ROS_ERROR("Phidget Spatial: Problem waiting for attachment: %s\n", err);
00874 spatialError = 1;
00875 }
00876
00877 printf("Waiting for interface kit to be attached....");
00878 if((result = CPhidget_waitForAttachment((CPhidgetHandle)ifKit, 1000)))
00879 {
00880 CPhidget_getErrorDescription(result, &err);
00881 ROS_ERROR("Phidget IK: Problem waiting for attachment: %s\n", err);
00882 phidget888_connected = false;
00883 interfaceKitError = 1;
00884 }
00885
00886 phidget888_connected = true;
00887
00888 CPhidgetInterfaceKit_setRatiometric(ifKit, 0);
00889
00890 CPhidgetSpatial_setDataRate(spatial, 16);
00891
00892 CPhidgetEncoder_create(&m_leftEncoder);
00893 CPhidget_set_OnAttach_Handler((CPhidgetHandle) m_leftEncoder,LeftEncoderAttach, NULL);
00894 CPhidget_open((CPhidgetHandle) m_leftEncoder, -1);
00895
00896 if (m_encoder1Seen && m_encoder2Seen)
00897 phidget_encoder_connected = true;
00898 else phidget_encoder_connected = false;
00899
00900
00901 if(sonarsPresent)
00902 {
00903 CPhidgetInterfaceKit_setOutputState(ifKit, bwOutput, 1);
00904 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 0);
00905 ros::Duration(0.250).sleep();
00906 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 1);
00907 ros::Duration(0.002).sleep();
00908 CPhidgetInterfaceKit_setOutputState(ifKit, strobeOutput, 0);
00909 ros::Duration(0.150).sleep();
00910 }
00911 return 0;
00912 }
00913
00914 void phidget_ik_diagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
00918 {
00919 if (!interfaceKitError)
00920 stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "initialized");
00921 else
00922 {
00923 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "cannot be attached");
00924 stat.addf("Recommendation", "Please unplug and replug the Phidget Interface Kit Board USB cable from the Motherboard.");
00925 }
00926 }
00927
00928 void phidget_spatial_diagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
00932 {
00933 if (!spatialError)
00934 stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "initialized");
00935 else
00936 {
00937 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "cannot be attached");
00938 stat.addf("Recommendation", "Please verify that the robot has a Phidget Spatial board. If present, please unplug and replug the Phidget Spatial Board USB cable from the Motherboard.");
00939 }
00940 }
00941
00942 void phidget_encoder_diagnostic(diagnostic_updater::DiagnosticStatusWrapper &stat)
00946 {
00947 if (!encoderError)
00948 stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "intialized");
00949 else if(encoderError == 1)
00950 {
00951 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "cannot be attached");
00952 stat.addf("Recommendation", "Please verify that the robot has a Phidget Encoder board. If present, please unplug and replug the Phidget Spatial Board USB cable from the Motherboard.");
00953 }
00954 else if(encoderError == 2)
00955 {
00956 stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "cannot read");
00957 stat.addf("Recommendation", "Please verify that the two encoders are connected to the Phidget Encoder Board.");
00958 }
00959
00960 }
00961
00962 int main(int argc, char* argv[])
00963 {
00964 ros::init(argc, argv, "phidget_component");
00965 ros::NodeHandle n;
00966 ros::NodeHandle nh("~");
00967 nh.param("rearBumper", m_rearBumperPresent, false);
00968 nh.param("bwOutput", bwOutput, -1);
00969 nh.param("strobeOutput", strobeOutput, -1);
00970 nh.param("lastSonarInput", lastSonarInput, -1);
00971 nh.param("firstSonarInput", firstSonarInput, -1);
00972 nh.param("battery", batteryPort, 0);
00973 nh.param("irFront", irFrontPort, 1);
00974 nh.param("irBack", irBackPort, 2);
00975 nh.param("gripper", gripperPort, 3);
00976 nh.param("motors_inverted", motors_inverted, false);
00977 nh.param("encoders_inverted", encoders_inverted, false);
00978
00979 dCMMatrix[0][0]=1;
00980 dCMMatrix[0][1]=0;
00981 dCMMatrix[0][2]=0;
00982 dCMMatrix[1][0]=0;
00983 dCMMatrix[1][1]=1;
00984 dCMMatrix[1][2]=0;
00985 dCMMatrix[2][0]=0;
00986 dCMMatrix[2][1]=0;
00987 dCMMatrix[2][2]=1;
00988
00989 timestampPreviousCall = 0;
00990 pitchOffset = 0;
00991 rollOffset = 0;
00992 proportionalVector[0] = 0;
00993 proportionalVector[1] = 0;
00994 proportionalVector[2] = 0;
00995
00996 integratorVector[0] = 0;
00997 integratorVector[1] = 0;
00998 integratorVector[2] = 0;
00999 gyroscopeVectorCorrected[0] = 0;
01000 gyroscopeVectorCorrected[1] = 0;
01001 gyroscopeVectorCorrected[2] = 0;
01002
01003
01004 diagnostic_updater::Updater updater;
01005 updater.setHardwareIDf("Phidget");
01006 updater.add("Interface Kit", phidget_ik_diagnostic);
01007 updater.add("Spatial", phidget_spatial_diagnostic);
01008 updater.add("Encoders", phidget_encoder_diagnostic);
01009 interfacekit_simple();
01010
01011 ros::ServiceServer odom = n.advertiseService("phidgetnode_set_odom", SetOdom);
01012
01013 posdata_pub = n.advertise<corobot_msgs::PosMsg>("position_data", 100);
01014 irData_pub = n.advertise<corobot_msgs::IrMsg>("infrared_data", 100);
01015 powerdata_pub = n.advertise<corobot_msgs::PowerMsg>("power_data", 100);
01016 bumper_pub = n.advertise<corobot_msgs::BumperMsg>("bumper_data", 100);
01017 gripper_pub = n.advertise<corobot_msgs::GripperMsg>("gripper_data",100);
01018 sonar_pub = n.advertise<corobot_msgs::RangeSensor>("sonar_data", 100);
01019 spatial_pub = n.advertise<corobot_msgs::spatial>("spatial_data",100);
01020 imu_pub = n.advertise<sensor_msgs::Imu>("imu_data",100);
01021
01022 ros::Publisher phidget_info_pub = n.advertise<corobot_msgs::phidget_info>("phidget_info", 1000);
01023
01024 corobot_msgs::phidget_info info;
01025 if(phidget888_connected)
01026 info.phidget888_connected = 1;
01027 else info.phidget888_connected = 0;
01028 if(phidget_encoder_connected)
01029 info.phidget_encoder_connected = 1;
01030 else info.phidget_encoder_connected = 0;
01031 phidget_info_pub.publish(info);
01032
01033 ros::Rate loop_rate(20);
01034
01035 while (ros::ok())
01036 {
01037 ros::spinOnce();
01038 if(sonarsPresent)
01039 sendSonarResult();
01040 publish_data();
01041 loop_rate.sleep();
01042 updater.update();
01043 }
01044 printf("Out of ros spin");
01045
01046 CPhidget_close((CPhidgetHandle)ifKit);
01047 CPhidget_delete((CPhidgetHandle)ifKit);
01048 if (m_rightEncoder != m_leftEncoder)
01049 {
01050 CPhidget_close((CPhidgetHandle)m_leftEncoder);
01051 CPhidget_delete((CPhidgetHandle)m_leftEncoder);
01052 }
01053 CPhidget_close((CPhidgetHandle)m_rightEncoder);
01054 CPhidget_delete((CPhidgetHandle)m_rightEncoder);
01055 CPhidget_close((CPhidgetHandle)spatial);
01056 CPhidget_delete((CPhidgetHandle)spatial);
01057
01058
01059 return 0;
01060 }