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
00032
00033
00034
00035
00036
00037 #include <iostream>
00038 #include <math.h>
00039 #include <time.h>
00040 #include <signal.h>
00041 #include <string>
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <fstream>
00045 #include <sstream>
00046 #include <boost/algorithm/string.hpp>
00047 #include <boost/asio.hpp>
00048 #include <boost/bind.hpp>
00049 #include <boost/asio/serial_port.hpp>
00050 #include <boost/asio/streambuf.hpp>
00051 #include <boost/regex.hpp>
00052 #include <boost/thread.hpp>
00053 #include <boost/math/special_functions/fpclassify.hpp>
00054 #include <labust/tools/TimingTools.hpp>
00055 #include <std_msgs/Bool.h>
00056 #include <labust/math/NumberManipulation.hpp>
00057
00058 #include <std_msgs/Float32MultiArray.h>
00059 #include <labust/control/PIDController.hpp>
00060
00061 #include <ros/ros.h>
00062 #include <auv_msgs/BodyForceReq.h>
00063 #include <diagnostic_msgs/DiagnosticStatus.h>
00064
00065
00066
00067
00068
00069
00070 struct TauC
00071 {
00072 float Frw;
00073 float Yaw;
00074 };
00075
00076 struct TauT
00077 {
00078 TauT(TauC Tau, float Limit = 1)
00079 {
00080 float ScaleThrust;
00081 if (fabs(Tau.Frw) + fabs(Tau.Yaw) > 1)
00082 {ScaleThrust = 1 / (fabs(Tau.Frw) + fabs(Tau.Yaw));}
00083 else
00084 {ScaleThrust = 1;}
00085 Port = Limit * ScaleThrust * (Tau.Frw + Tau.Yaw);
00086 Stb = Limit * ScaleThrust * (Tau.Frw - Tau.Yaw);
00087 }
00088
00089 TauC getTauC()
00090 {
00091 TauC tau;
00092 tau.Frw = (Port+Stb)/2;
00093 tau.Yaw = (Port-Stb)/2;
00094
00095 return tau;
00096 }
00097
00098 float Port;
00099 float Stb;
00100 };
00101
00102 float TauFrwold = 0;
00103 float TauYawold = 0;
00104 double integralRPM[2] = {0,0};
00105
00106 int intMax = 32767;
00107 double Supply_Voltage, Vehicle_Current, Temperature, Motor_Current[2], Supply_Voltage_Previous, Vehicle_Current_Previous, Motor_Current_Previous[2], Load_Position[2],
00108 Load_Position_Previous[2], RPM[2]={0};
00109 double currentAvg[2] = {0,0};
00110
00111
00112
00113 int DigOutNumber=1;
00114
00115
00116 using namespace boost::asio;
00117 streambuf inputBuffer, outputBuffer;
00118 std::ostream os(&outputBuffer);
00119
00120 char DriveReply[1], DriveReplyLong[12];
00121
00122 std::string Mode, Mode1;
00123 bool CommsOkFlag = true;
00124 io_service io;
00125 serial_port port(io);
00126
00127 char AxisONID1[] = {0x04, 0x00, 0x10,0x01, 0x02, 0x17};
00128 char AxisONID2[] = {0x04, 0x00, 0x20,0x01, 0x02, 0x27};
00129 char AxisOFFID1[] = {0x04, 0x00, 0x10,0x00, 0x02, 0x16};
00130 char AxisOFFID2[] = {0x04, 0x00, 0x20,0x00, 0x02, 0x26};
00131 char ResetID1[] = {0x04, 0x00, 0x10, 0x04, 0x02, 0x1A};
00132 char ResetID2[] = {0x04, 0x00, 0x20, 0x04, 0x02, 0x2A};
00133 char GetVoltage[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x40, 0x1F};
00134 char GetTemperature[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x41, 0x20};
00135 char GetVehicleCurrent[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x3E, 0x1D};
00136 char GetCurrent1[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x3C, 0x1B};
00137 char GetCurrent2[] = {0x08, 0x00, 0x20, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x3C, 0x2B};
00138 char ReadISR1[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x03, 0x06, 0xE6};
00139 char ReadISR2[] = {0x08, 0x00, 0x20, 0xB0, 0x04, 0x00, 0x11, 0x03, 0x06, 0xF6};
00140 char GetPosition1[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x28, 0x07};
00141 char GetPosition2[] = {0x08, 0x00, 0x20, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x28, 0x17};
00142
00143 int StateDO[] = {1,0,0,0};
00144
00145 float parsData()
00146 {
00147 char ChSum[1];
00148 unsigned char ByteHigh, ByteLow;
00149 int value;
00150 ChSum[0] = 0;
00151 for (int i1=0;i1<11;i1++)
00152 {ChSum[0] += DriveReply[i1];}
00153 ByteHigh = DriveReply[9];
00154 ByteLow = DriveReply[10];
00155 value = ByteHigh * 256 + ByteLow;
00156
00157 if (!(ChSum[0]==DriveReply[11]))
00158 {CommsOkFlag = false;}
00159 return value;
00160 }
00161
00162 void SetDigiOut()
00163 {
00164 char DigOutSet[] = {0x08, 0x00, 0x10, 0xEC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05};
00165 char ChSum[1];
00166 int ID, DO;
00167
00168 switch (DigOutNumber)
00169 {
00170 case(1):
00171 ID = 1;
00172 DO = 0;
00173 break;
00174 case(2):
00175 ID = 1;
00176 DO = 1;
00177 break;
00178 case(3):
00179 ID = 2;
00180 DO = 0;
00181 break;
00182 case(4):
00183 ID = 2;
00184 DO = 1;
00185 break;
00186 }
00187
00188 DigOutSet[2] = DigOutSet[2] + (ID-1)*16;
00189 DigOutSet[6] = DigOutSet[6] + DO;
00190 if (StateDO[DigOutNumber-1]==1)
00191 {
00192 DigOutSet[8] = 0x01;
00193 for (int i1=0;i1<DO;i1++)
00194 {DigOutSet[8] = DigOutSet[8] * 2;}
00195 }
00196 else
00197 {DigOutSet[8] = 0x00;}
00198 DigOutSet[9] = 0;
00199 for (int i1=0;i1<9;i1++)
00200 {DigOutSet[9] += DigOutSet[i1];}
00201 os.write(DigOutSet,sizeof(DigOutSet));
00202 write(port,outputBuffer);
00203 DigOutNumber++;
00204 }
00205
00206 void SetReference(int ID, float REF)
00207 {
00208 char SetRefID1[] = {0x06, 0x00, 0x10, 0x20, 0xA9, 0x00, 0x00, 0xDF};
00209 char SetRef[8];
00210
00211 SetRef[0] = SetRefID1[0];
00212 SetRef[1] = SetRefID1[1];
00213 SetRef[2] = SetRefID1[2] + (ID-1)*16;
00214 SetRef[3] = SetRefID1[3];
00215 SetRef[4] = SetRefID1[4];
00216
00217 double max = 11138;
00218
00219 int16_t ref_current = int16_t(REF*max);
00220 const char* p=reinterpret_cast<const char*>(&ref_current);
00221 SetRef[5] = p[1];
00222 SetRef[6] = p[0];;
00223 SetRef[7] = SetRef[0] + SetRef[1] + SetRef[2] + SetRef[3] + SetRef[4] + SetRef[5] + SetRef[6];
00224
00225 Mode = "OK";
00226 Mode1 = "";
00227 os.write(SetRef,sizeof(SetRef));
00228 write(port,outputBuffer);
00229 }
00230
00231 void ReadHandler(const boost::system::error_code& e, std::size_t size)
00232
00233 {
00234
00235 char ChSum[1];
00236 int MessageLength=1;
00237 float ByteHigh, ByteLow, value;
00238 if (e)
00239 {
00240 std::cout<<"Async Read Error"<<std::endl;
00241
00242 }
00243 CommsOkFlag= false;
00244 for (int i1=0;i1<1;i1++)
00245 {
00246 if (Mode=="Sync")
00247 {
00248 if (strncmp(DriveReply,"\r",1)==0)
00249 {CommsOkFlag= true;}
00250 MessageLength=1;
00251 break;
00252 }
00253
00254 if (Mode=="Data_V")
00255 {
00256 MessageLength = 1;
00257 CommsOkFlag= true;
00258
00259 Supply_Voltage = parsData() * 53 / 65472;
00260
00261 Mode = "OK";
00262 Mode1 = "Data_T";
00263 os.write(GetTemperature,sizeof(GetTemperature));
00264 write(port,outputBuffer);
00265 break;
00266 }
00267
00268 if (Mode=="Data_T")
00269 {
00270 MessageLength = 1;
00271 CommsOkFlag= true;
00272
00273 Temperature = 2 + parsData() * 500 / 65472;
00274
00275 Mode = "OK";
00276 Mode1 = "Data_C";
00277 os.write(GetVehicleCurrent,sizeof(GetVehicleCurrent));
00278 write(port,outputBuffer);
00279 break;
00280 }
00281
00282 if (Mode=="Data_C")
00283 {
00284 MessageLength = 1;
00285 CommsOkFlag= true;
00286
00287 Vehicle_Current = parsData() * 18 / 65472 * 1.25;
00288
00289 Mode = "OK";
00290 Mode1 = "Data_C1";
00291
00292 os.write(GetPosition1,sizeof(GetPosition1));
00293 write(port,outputBuffer);
00294 break;
00295 }
00296
00297 if (Mode=="Data_C1")
00298 {
00299 MessageLength = 1;
00300 CommsOkFlag= true;
00301
00302
00303 Load_Position[0] = parsData();
00304
00305 Mode = "OK";
00306 Mode1 = "Data_C2";
00307
00308 os.write(GetPosition2,sizeof(GetPosition2));
00309 write(port,outputBuffer);
00310 break;
00311 }
00312
00313 if (Mode=="Data_C2")
00314 {
00315 MessageLength = 1;
00316 CommsOkFlag= true;
00317
00318
00319 Load_Position[1] = parsData();
00320
00321 Mode = "OK";
00322 Mode1 = "DigOut";
00323 SetDigiOut();
00324 break;
00325 }
00326
00327 if (Mode=="OK")
00328 {
00329 MessageLength = 1;
00330 if (strncmp(DriveReply,"O",1)==0)
00331 {
00332 CommsOkFlag= true;
00333 if ((Mode1 == "Data_V") || (Mode1 == "Data_T") || (Mode1 == "Data_C") || (Mode1 == "Data_C1") || (Mode1 == "Data_C2"))
00334 {
00335 Mode = Mode1;
00336 MessageLength = 12;
00337 }
00338 if (Mode1 == "DigOut")
00339 {
00340 if (DigOutNumber<5)
00341 {
00342 MessageLength = 1;
00343 SetDigiOut();
00344 }
00345 else
00346 {DigOutNumber = 1;}
00347 }
00348 }
00349 break;
00350 }
00351
00352 }
00353
00354 DriveReply[0] = 0x00;
00355 async_read(port, buffer(&DriveReply,MessageLength),
00356 boost::bind(&ReadHandler, placeholders::error, placeholders::bytes_transferred));
00357
00358 }
00359
00360 bool Initialization(int ID)
00361 {
00362 bool b1=true;
00363 int counter, delay = 5;
00364 char DisableEncoderWireID1[] = {0x08, 0x00, 0x10, 0x59, 0x03, 0xFF, 0xBF, 0x00, 0x00, 0x32};
00365 char DisableEncoderWireID2[] = {0x08, 0x00, 0x20, 0x59, 0x03, 0xFF, 0xBF, 0x00, 0x00, 0x42};
00366 char ModeTorquesTESID1[] = {0x08, 0x00, 0x10, 0x59, 0x09, 0xB1, 0xC0, 0x81, 0x00, 0x6C};
00367 char ModeTorquesTESID2[] = {0x08, 0x00, 0x20, 0x59, 0x09, 0xB1, 0xC0, 0x81, 0x00, 0x7C};
00368 char ExtReferenceModeID1[] = {0x08, 0x00, 0x10, 0x59, 0x09, 0xFF, 0x3F, 0x00, 0x00, 0xB8};
00369 char ExtReferenceModeID2[] = {0x08, 0x00, 0x20, 0x59, 0x09, 0xFF, 0x3F, 0x00, 0x00, 0xC8};
00370 char UpdID1[] = {0x04, 0x00, 0x10, 0x01, 0x08, 0x1D};
00371 char UpdID2[] = {0x04, 0x00, 0x20, 0x01, 0x08, 0x2D};
00372 char DisableEncoderWire[10];
00373 char ModeTorquesTES[10];
00374 char ExtReferenceMode[10];
00375 char Upd[6];
00376
00377 switch (ID)
00378 {
00379 case 1:
00380 for (int i1=0;i1<10;i1++)
00381 {
00382 DisableEncoderWire[i1] = DisableEncoderWireID1[i1];
00383 ModeTorquesTES[i1] = ModeTorquesTESID1[i1];
00384 ExtReferenceMode[i1] = ExtReferenceModeID1[i1];
00385 if (i1<6)
00386 {Upd[i1] = UpdID1[i1];}
00387 }
00388 break;
00389 case 2:
00390 for (int i1=0;i1<10;i1++)
00391 {
00392 DisableEncoderWire[i1] = DisableEncoderWireID2[i1];
00393 ModeTorquesTES[i1] = ModeTorquesTESID2[i1];
00394 ExtReferenceMode[i1] = ExtReferenceModeID2[i1];
00395 if (i1<6)
00396 {Upd[i1] = UpdID2[i1];}
00397 }
00398 break;
00399
00400 }
00401
00402
00403 Mode = "OK";
00404 Mode1 = "";
00405 counter=0;
00406 do
00407 {
00408 os.write(DisableEncoderWire,sizeof(DisableEncoderWire));
00409 write(port,outputBuffer);
00410
00411 counter++;
00412 usleep(1000*delay);
00413 }
00414 while (!CommsOkFlag && (counter<2));
00415 if (counter>1)
00416 {b1 = false;}
00417
00418
00419 counter=0;
00420 do
00421 {
00422 os.write(ModeTorquesTES,sizeof(ModeTorquesTES));
00423 write(port,outputBuffer);
00424 counter++;
00425 usleep(1000*delay);
00426 }
00427 while (!CommsOkFlag && (counter<2));
00428 if (counter>1)
00429 {b1 = false;}
00430
00431
00432 counter=0;
00433 do
00434 {
00435 os.write(ExtReferenceMode,sizeof(ExtReferenceMode));
00436 write(port,outputBuffer);
00437 counter++;
00438 usleep(1000*delay);
00439 }
00440 while (!CommsOkFlag && (counter<2));
00441 if (counter>1)
00442 {b1 = false;}
00443
00444
00445 counter=0;
00446 do
00447 {
00448 os.write(Upd,sizeof(Upd));
00449 write(port,outputBuffer);
00450 counter++;
00451 usleep(1000*delay);
00452 }
00453 while (!CommsOkFlag && (counter<2));
00454 if (counter>1)
00455 {b1 = false;}
00456 if (!b1)
00457 {CommsOkFlag = false;
00458 }
00459
00460 return b1;
00461 }
00462
00463 void ReadData()
00464 {
00465 Mode = "OK";
00466 Mode1 = "Data_V";
00467
00468 os.write(GetVoltage,sizeof(GetVoltage));
00469 write(port,outputBuffer);
00470 }
00471
00472 void EstablishSerialComm()
00473 {
00474 char SyncByte[] = {0x0D};
00475 char SCIBR[] = {0x06, 0x00, 0x10, 0x08, 0x20, 0x00, 0x04, 0x42};
00476 int i1;
00477
00478
00479 if (port.is_open())
00480 {
00481 port.set_option(serial_port::baud_rate(9600));
00482 port.set_option(serial_port::flow_control(serial_port::flow_control::none));
00483 port.set_option(serial_port::parity(serial_port::parity::none));
00484 port.set_option(serial_port::stop_bits(serial_port::stop_bits::two));
00485 port.set_option(serial_port::character_size(8));
00486 std::cout<<"IPOS Multiaxis Port open 9600"<<std::endl;
00487 }
00488
00489 for (i1=0;i1<3;i1++)
00490 {
00491 CommsOkFlag = false;
00492 Mode = "Sync";
00493 os.write(SyncByte,sizeof(SyncByte));
00494 write(port,outputBuffer);
00495
00496 usleep(1000*15);
00497
00498 if (CommsOkFlag)
00499 {
00500 std::cout<<"Sync na 9600, Reset Axis"<<std::endl;
00501
00502 Mode = "OK";
00503 os.write(AxisOFFID1,sizeof(AxisOFFID1));
00504 write(port,outputBuffer);
00505
00506 os.write(AxisOFFID2,sizeof(AxisOFFID2));
00507 write(port,outputBuffer);
00508
00509 os.write(ResetID2,sizeof(ResetID2));
00510 write(port,outputBuffer);
00511
00512 os.write(ResetID1,sizeof(ResetID1));
00513 write(port,outputBuffer);
00514
00515 usleep(1000*1000);
00516 }
00517 Mode = "Sync";
00518 os.write(SyncByte,sizeof(SyncByte));
00519 write(port,outputBuffer);
00520 usleep(1000*15);
00521 if (CommsOkFlag)
00522 {std::cout<<"Sync na 9600"<<std::endl;
00523 break;}
00524
00525 }
00526
00527 if(i1<2)
00528 {
00529 Mode = "OK";
00530 os.write(SCIBR,sizeof(SCIBR));
00531 write(port,outputBuffer);
00532 usleep(1000*15);
00533
00534
00535 if (CommsOkFlag)
00536 {
00537
00538 if (port.is_open())
00539 {
00540 port.set_option(serial_port::baud_rate(115200));
00541 port.set_option(serial_port::flow_control(serial_port::flow_control::none));
00542 port.set_option(serial_port::parity(serial_port::parity::none));
00543 port.set_option(serial_port::stop_bits(serial_port::stop_bits::two));
00544 port.set_option(serial_port::character_size(8));
00545
00546
00547 }
00548 Mode = "Sync";
00549 os.write(SyncByte,sizeof(SyncByte));
00550 write(port,outputBuffer);
00551 usleep(1000*15);
00552 if (CommsOkFlag)
00553 {std::cout<<"Sync na 115200"<<std::endl;}
00554 }
00555 }
00556 }
00557
00558 void watch()
00559 {
00561 std::cout<<"Isteklo vrijeme"<<std::endl;
00562 boost::thread t(boost::bind(&boost::asio::io_service::run,&io));
00563 t.join();
00564 return;
00565 }
00566
00568 void handleTau(TauC* tauOut, const auv_msgs::BodyForceReq::ConstPtr tauIn)
00569 {
00570 tauOut->Frw = tauIn->wrench.force.x;
00571 tauOut->Yaw = tauIn->wrench.torque.z;
00572 }
00573
00574 void sendDiagnostics(ros::Publisher& diag, bool CommsOkFlag)
00575 {
00576 diagnostic_msgs::DiagnosticStatus status;
00577
00578 status.level = status.OK;
00579 status.name = "CART2 Driver";
00580 status.message = "Voltage and current report";
00581 status.hardware_id = "None";
00582
00583 diagnostic_msgs::KeyValue data;
00584 std::ostringstream out;
00585 out<<Supply_Voltage;
00586 data.key = "Supply_Voltage";
00587 data.value = out.str();
00588 status.values.push_back(data);
00589
00590 out.str("");
00591 out<<Vehicle_Current;
00592 data.key = "Vehicle_Current";
00593 data.value = out.str();
00594 status.values.push_back(data);
00595
00596 out.str("");
00597 out<<Temperature;
00598 data.key = "Temperature";
00599 data.value = out.str();
00600 status.values.push_back(data);
00601
00602 out.str("");
00603 out<<RPM[0];
00604 data.key = "RPM1";
00605 data.value = out.str();
00606 status.values.push_back(data);
00607
00608 out.str("");
00609 out<<RPM[1];
00610 data.key = "RPM2";
00611 data.value = out.str();
00612 status.values.push_back(data);
00613
00614 if (!CommsOkFlag)
00615 {
00616 status.level = status.ERROR;
00617 status.message = "Communication error!";
00618 }
00619
00620 diag.publish(status);
00621 }
00622
00623 double wrapRPM(double value)
00624 {
00625 if (value > 30000)
00626 {
00627 return value - 65536;
00628 }
00629 else if (value < -30000)
00630 {
00631 return value + 65536;
00632 }
00633 return value;
00634 }
00635
00636 struct CalibrationData
00637 {
00638 CalibrationData():
00639 state(stop),
00640 cycleWait(0),
00641 trigger(false){}
00642
00643 enum {stop=0,start,xy,xz,mag,gyrosOnly};
00644 enum {cyclesMax = 500};
00645 enum {cyclesMin = 20};
00646 enum {cyclesGyro = 120};
00647 enum {calibrationPin = 1};
00648 int state;
00649 int cycleWait;
00650 bool trigger;
00651 };
00652
00653 void onCalibration(CalibrationData& data, const std_msgs::Bool::ConstPtr& calibration)
00654 {
00655 if (calibration->data)
00656 {
00657 std::cout<<"Change state."<<std::endl;
00658 data.cycleWait = 0;
00659 data.trigger = true;
00660 switch (data.state)
00661 {
00662 case CalibrationData::stop:
00663 data.state = data.start;
00664 break;
00665 case CalibrationData::start:
00666 data.state = CalibrationData::xz;
00667 break;
00668 case CalibrationData::xz:
00669 data.state = CalibrationData::mag;
00670 break;
00671 case CalibrationData::mag:
00672 break;
00673 }
00674 }
00675 }
00676
00677 void onGyroCalibration(CalibrationData& data, const std_msgs::Bool::ConstPtr& calibration)
00678 {
00679 if (calibration->data)
00680 {
00681 data.state = CalibrationData::gyrosOnly;
00682 data.cycleWait = 0;
00683 data.trigger = true;
00684 }
00685 else
00686 {
00687 data.state = CalibrationData::stop;
00688 data.cycleWait = 0;
00689 data.trigger = false;
00690 }
00691 }
00692
00693 void onResetPin(const std_msgs::Bool::ConstPtr& resetPin)
00694 {
00695 StateDO[0] = resetPin->data;
00696 }
00697
00698 void onLights(const std_msgs::Bool::ConstPtr& lights)
00699 {
00700 }
00701
00703
00704 int main(int argc, char* argv[])
00705 {
00706 std::vector<int> medianPort, medianStbd;
00707 float AverCurrent[10], AC;
00708 int CommsCount = 0, AverCount, Count = 0;
00709 size_t tSum = 10000;
00710 size_t tLoop = 100;
00711
00712 char SyncByte[] = {0x0D};
00713 TauC TauControl, TauControlOld;
00714 TauControl.Frw = 0;
00715 TauControl.Yaw = 0;
00716 TauControlOld.Frw = 0;
00717 TauControlOld.Yaw = 0;
00718 std::string path, configToUse;
00719 CalibrationData calibration;
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00740
00741 ros::init(argc,argv,"cart2_node");
00742
00743 ros::NodeHandle nh,ph("~");
00744
00745 ros::Subscriber tauIn = nh.subscribe<auv_msgs::BodyForceReq>("tauIn",1,boost::bind(&handleTau,&TauControl,_1));
00746 ros::Subscriber cflag = nh.subscribe<std_msgs::Bool>("calibration_on",1,boost::bind(&onCalibration, boost::ref(calibration),_1));
00747 ros::Subscriber cgflag = nh.subscribe<std_msgs::Bool>("calibration_gyro_on",1,boost::bind(&onGyroCalibration, boost::ref(calibration),_1));
00748 ros::Subscriber rflag = nh.subscribe<std_msgs::Bool>("reset_pin",1,boost::bind(&onResetPin, _1));
00749
00750 ros::Publisher tauAch = nh.advertise<auv_msgs::BodyForceReq>("tauAch",1);
00751 ros::Publisher diagnostic = nh.advertise<diagnostic_msgs::DiagnosticStatus>("diagnostics",1);
00752 ros::Publisher rpm_info = nh.advertise<std_msgs::Float32MultiArray>("cart2_info",1);
00753
00754
00755 std::string portName("/dev/ttyUSB0");
00756 ph.param("PortName", portName,portName);
00757 port.open(portName);
00758 bool useRPMControl(false);
00759 ph.param("UseRPMControl", useRPMControl, useRPMControl);
00760 std_msgs::Float32MultiArray cart2_info;
00761 cart2_info.data.resize(9);;
00762 float rpm_port(0), rpm_stbd(0), curr_port(0), curr_stbd(0);
00763 double Kp(0.0001),Ki(0.001);
00764 int median_size(5);
00765 ph.param("Kp_rpm", Kp, Kp);
00766 ph.param("Ki_rpm", Ki, Ki);
00767 ph.param("MedianSize", median_size, median_size);
00768 medianPort.assign(median_size,0);
00769 medianStbd.assign(median_size,0);
00770 labust::control::PIDController<labust::control::details::PID,labust::control::UseLimits> cport(Kp,Ki,0,0), cstbd(Kp,Ki,0,0);
00771 labust::math::Limit<double> limits(-1,1);
00772 cport.setLimits(limits);
00773 cstbd.setLimits(limits);
00774 ros::Rate rate(10);
00776
00777 std::cout<<"first "<<std::endl;
00778
00779
00780 if (port.is_open())
00781 {
00782 boost::asio::write(port, boost::asio::buffer(ResetID1,sizeof(ResetID1)));
00783 boost::asio::write(port, boost::asio::buffer(ResetID2,sizeof(ResetID2)));
00784 port.set_option(serial_port::baud_rate(115200));
00785 port.set_option(serial_port::flow_control(serial_port::flow_control::none));
00786 port.set_option(serial_port::parity(serial_port::parity::none));
00787 port.set_option(serial_port::stop_bits(serial_port::stop_bits::two));
00788 port.set_option(serial_port::character_size(8));
00789 std::cout<<"IPOS Multiaxis Port open 115200"<<std::endl;
00790
00791 }
00792
00793
00794 async_read(port, buffer(&DriveReply,1),
00795 boost::bind(&ReadHandler, placeholders::error, placeholders::bytes_transferred));
00796 boost::thread t(boost::bind(&boost::asio::io_service::run,&io));
00797
00798
00799 int n=0;
00800 while (ros::ok())
00801 {
00802 if (port.is_open())
00803 {
00804 port.set_option(serial_port::baud_rate(115200));
00805 port.set_option(serial_port::flow_control(serial_port::flow_control::none));
00806 port.set_option(serial_port::parity(serial_port::parity::none));
00807 port.set_option(serial_port::stop_bits(serial_port::stop_bits::two));
00808 port.set_option(serial_port::character_size(8));
00809 std::cout<<"IPOS Multiaxis Port open 115200"<<std::endl;
00810
00811 }
00812 usleep(1000*200);
00813 CommsOkFlag = false;
00814 CommsCount = 0;
00815 Mode = "Sync";
00816 Mode1 = "";
00817 os.write(SyncByte,sizeof(SyncByte));
00818 write(port,outputBuffer);
00819 usleep(1000*200);
00820
00821 if ((CommsOkFlag) && (Count>0) && (Count<20))
00822 {
00823 std::cout<<"Sync OK, main"<<std::endl;
00824
00825 Mode = "OK";
00826 os.write(AxisOFFID1,sizeof(AxisOFFID1));
00827 write(port,outputBuffer);
00828
00829 os.write(AxisOFFID2,sizeof(AxisOFFID2));
00830 write(port,outputBuffer);
00831
00832 os.write(ResetID2,sizeof(ResetID2));
00833 write(port,outputBuffer);
00834
00835 os.write(ResetID1,sizeof(ResetID1));
00836 write(port,outputBuffer);
00837
00838 os.write(AxisONID1,sizeof(AxisONID1));
00839 write(port,outputBuffer);
00840
00841 os.write(AxisONID2,sizeof(AxisONID2));
00842 write(port,outputBuffer);
00843
00844 usleep(1000*100);
00845
00846 Count++;
00847 }
00848 else
00849 {
00850 Count = 1;
00851 EstablishSerialComm();
00852 if (CommsOkFlag)
00853 {
00854 if ((Initialization(1)) && (Initialization(2)))
00855 {
00856 std::cout<<"Axis initialization is OK "<<std::endl;
00857
00858
00859 SetReference(1,0);
00860
00861 if (CommsOkFlag)
00862 {SetReference(2,0);}
00863
00864 if (CommsOkFlag)
00865 {os.write(AxisONID1,sizeof(AxisONID1));
00866 write(port,outputBuffer);}
00867
00868 if (CommsOkFlag)
00869 {os.write(AxisONID2,sizeof(AxisONID2));
00870 write(port,outputBuffer);}
00871 usleep(1000*50);
00872 }
00873 else
00874 {
00875 std::cout<<"Initialization Failed "<<std::endl;
00876
00877 os.write(AxisOFFID1,sizeof(AxisOFFID1));
00878 write(port,outputBuffer);
00879
00880 os.write(AxisOFFID2,sizeof(AxisOFFID2));
00881 write(port,outputBuffer);
00882
00883 CommsOkFlag = false;
00884 usleep(1000*50);
00885 }
00886 }
00887 }
00888
00889 AverCount = 0;
00890 while (CommsOkFlag && ros::ok())
00891 {
00892 double time = ros::Time::now().toSec();
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 TauT thrust(TauControl);
00909 TauC achTau = thrust.getTauC();
00911 auv_msgs::BodyForceReq tau;
00912 tau.wrench.force.x = achTau.Frw;
00913 tau.wrench.torque.z = achTau.Yaw;
00914 bool windup = (TauControl.Yaw != achTau.Yaw);
00915 tau.disable_axis.x = windup;
00916 tau.disable_axis.yaw = windup;
00917 tauAch.publish(tau);
00918
00919 StateDO[CalibrationData::calibrationPin] = calibration.trigger;
00920 printf("DIO state: %d\n", StateDO[CalibrationData::calibrationPin]);
00921 if ((calibration.state != CalibrationData::stop) && (calibration.state != CalibrationData::gyrosOnly))
00922 {
00923 ++calibration.cycleWait;
00924
00925 if (calibration.state == CalibrationData::start)
00926 {
00927 if (calibration.cycleWait > calibration.cyclesMax)
00928 {
00929 calibration.trigger = false;
00930 }
00931 }
00932 else if (calibration.cycleWait > calibration.cyclesMin)
00933 {
00934 calibration.trigger = false;
00935 if (calibration.state == CalibrationData::mag) calibration.state = CalibrationData::stop;
00936 }
00937 }
00938
00939 if (calibration.state == CalibrationData::gyrosOnly)
00940 {
00941 ++calibration.cycleWait;
00942 if (calibration.cycleWait > calibration.cyclesGyro)
00943 {
00944 calibration.trigger = false;
00945 calibration.state = CalibrationData::stop;
00946 }
00947 }
00948
00950
00951
00952
00953 AverCount++;
00954
00955
00956
00957 double an=0.045315881, wn= 0.0002496019;
00958 double ann=0.0419426925, wnn= 0.0002506513;
00959
00960
00961
00962 double rpm_port(0), rpm_stbd(0);
00963 int rpm_port_meas(0), rpm_stbd_meas(0);
00964
00965 medianPort.push_back(RPM[0]);
00966 medianStbd.push_back(RPM[1]);
00967 if (medianPort.size()>median_size) medianPort.erase(medianPort.begin());
00968 if (medianStbd.size()>median_size) medianStbd.erase(medianStbd.begin());
00969
00970 std::vector<int> med(medianPort);
00971 std::sort(med.begin(),med.end());
00972 rpm_port_meas = med[median_size/2];
00973 med.assign(medianStbd.begin(), medianStbd.end());
00974 std::sort(med.begin(),med.end());
00975 rpm_stbd_meas = med[median_size/2];
00976
00977 if (useRPMControl)
00978 {
00979 if ((thrust.Port>=0) && (thrust.Port/an <= 1)) thrust.Port = an;
00980 if ((thrust.Port<0) && (-thrust.Port/ann <= 1)) thrust.Port = -ann;
00981 if ((thrust.Stb >=0) && (thrust.Stb/an <= 1)) thrust.Stb = an;
00982 if ((thrust.Stb <0) && (-thrust.Stb/ann <= 1)) thrust.Stb = -ann;
00983 rpm_port = (thrust.Port>=0)?log(thrust.Port/an)/wn:-log(-thrust.Port/ann)/wnn;
00984 rpm_stbd = (thrust.Stb>=0)?log(thrust.Stb/an)/wn:-log(-thrust.Stb/ann)/wnn;
00985 double max_current = 1;
00986
00987
00988 rpm_port = int(rpm_port/75)*75;
00989 rpm_stbd = int(rpm_stbd/75)*75;
00990 double error[]={rpm_port-rpm_port_meas,rpm_stbd-rpm_stbd_meas};
00991 integralRPM[0]+=-Ki*error[0]*0.1;
00992 integralRPM[1]+=Ki*error[1]*0.1;
00993
00994
00995 curr_port=cport.step(rpm_port, rpm_port_meas);
00996
00997 curr_stbd=cstbd.step(rpm_stbd, rpm_stbd_meas);
00998 SetReference(1,-curr_port);
00999 usleep(1000*5);
01000 if (!CommsOkFlag)
01001 {break;}
01002 SetReference(2,curr_stbd);
01003 usleep(1000*5);
01004 if (!CommsOkFlag)
01005 {break;}
01006 }
01007 else
01008 {
01009 curr_port = thrust.Port;
01010 SetReference(1,-thrust.Port);
01011 usleep(1000*5);
01012 if (!CommsOkFlag)
01013 {break;}
01014 curr_stbd = thrust.Stb;
01015 SetReference(2,thrust.Stb);
01016 usleep(1000*5);
01017 if (!CommsOkFlag)
01018 {break;}
01019 }
01020 std::cout<<thrust.Port<<" "<<thrust.Stb<<" "<<TauControl.Frw<<" "<<TauControl.Yaw<<" "<<std::endl;
01021
01022 enum {port_rpm_desired=0,
01023 stbd_rpm_desired,
01024 port_rpm_meas,
01025 stbd_rpm_meas,
01026 port_curr_desired,
01027 stbd_curr_desired,
01028 current,
01029 temp,
01030 voltage
01031 };
01032
01033 cart2_info.data[port_rpm_desired] = rpm_port;
01034 cart2_info.data[stbd_rpm_desired] = rpm_stbd;
01035 cart2_info.data[port_curr_desired] = curr_port;
01036 cart2_info.data[stbd_curr_desired] = curr_stbd;
01037 cart2_info.data[port_rpm_meas] = rpm_port_meas;
01038 cart2_info.data[stbd_rpm_meas] = rpm_stbd_meas;
01039 cart2_info.data[voltage] = Supply_Voltage;
01040 cart2_info.data[current] = Vehicle_Current;
01041 cart2_info.data[temp] = Temperature;
01042 rpm_info.publish(cart2_info);
01043
01044 if (AverCount == 40)
01045 {AverCount = 0;}
01046
01047 Supply_Voltage_Previous = Supply_Voltage;
01048
01049
01050 Load_Position_Previous[0] = Load_Position[0];
01051 Load_Position_Previous[1] = Load_Position[1];
01052 ReadData();
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063 if ((AverCount == 5) || (AverCount == 15))
01064
01065
01066 {printf("%f\n",Supply_Voltage);
01067 printf("%f\n",Vehicle_Current);
01068 printf("%f\n",Load_Position[0]);
01069 printf("%f\n",Load_Position[1]);
01070 printf("%f\n",Temperature);
01071 printf("%f\n",RPM[0]);
01072 printf("%f\n",RPM[1]);
01073 }
01074
01075
01077 sendDiagnostics(diagnostic, CommsOkFlag);
01078
01079
01080 usleep(1000*90);
01081 ros::spinOnce();
01082
01083
01084 RPM[0] = wrapRPM(Load_Position[0] - Load_Position_Previous[0])*75;
01085 RPM[1] = wrapRPM(Load_Position[1] - Load_Position_Previous[1])*75;
01086
01087 CommsOkFlag = true;
01088
01089 bool VoltageTest = fabs(Supply_Voltage_Previous - Supply_Voltage)<0.0000001;
01090 bool portTest = (fabs(thrust.Port) > 0.2) && (fabs(RPM[0])<10);
01091 bool stbdTest = (fabs(thrust.Stb) > 0.2) && (fabs(RPM[1])<10);
01092
01093 if (VoltageTest || portTest || stbdTest)
01094 {
01095 std::cout<<"Voltage:"<<Supply_Voltage<<", "<<Supply_Voltage_Previous<<std::endl;
01096 std::cout<<"Thust:"<<thrust.Port<<", "<<thrust.Stb<<std::endl;
01097 std::cout<<"RPM:"<<RPM[0]<<", "<<RPM[1]<<std::endl;
01098 CommsCount++;
01099 if (CommsCount == 20)
01100 {CommsOkFlag = false;}
01101 if (CommsCount == 19)
01102 {
01103 std::cout<<"Going to reset."<<std::endl;
01104 }
01105 }
01106 else
01107 {
01108 CommsCount = 0;
01109 }
01111
01112 std::cout<<"Loop time:"<<ros::Time::now().toSec() - time<<std::endl;
01113 }
01114 sendDiagnostics(diagnostic, CommsOkFlag);
01115
01116
01117 }
01118
01119
01120
01121
01122 io.stop();
01123 t.join();
01124 std::cout<<"Exited."<<std::endl;
01125 return 0;
01126 }
01127
01128
01129
01130
01131