cart2_main.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  *  Author: Antonio Vasilijevic
00035  *  Created: 01.02.2013.
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 //#include <cart2/ImuInfo.h>
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 // Ulazi u funkciju su struktura Tauc (Tau.Frw i Tau.Yaw), Limit thrustera iz strukture TauT, 
00066 //i stanja digitalnih izlaza: int polje StateDO[4]
00067 //
00068 // Izlazi su Supply_Voltage, Motor_Current[2], Vehicle_Current i Temperature i moze biti ScaleThrust iz strukture TauT
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 //time_t cur_time;
00112 //clock_t start_time;
00113 int DigOutNumber=1; //From 1
00114 
00115 
00116 using namespace boost::asio;
00117 streambuf inputBuffer, outputBuffer;
00118 std::ostream os(&outputBuffer);
00119 //char a[] = {0x00};
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);//, GPS2port(io,"/dev/ttyS1"), modem(io,"/dev/ttyS0");
00126 
00127 char AxisONID1[] = {0x04, 0x00, 0x10,0x01, 0x02, 0x17}; //turn Axis1 ON
00128 char AxisONID2[] = {0x04, 0x00, 0x20,0x01, 0x02, 0x27}; //turn Axis2 ON
00129 char AxisOFFID1[] = {0x04, 0x00, 0x10,0x00, 0x02, 0x16}; //turn Axis1 OFF
00130 char AxisOFFID2[] = {0x04, 0x00, 0x20,0x00, 0x02, 0x26}; //turn Axis2 OFF
00131 char ResetID1[] = {0x04, 0x00, 0x10, 0x04, 0x02, 0x1A}; //Reset Axis 1
00132 char ResetID2[] = {0x04, 0x00, 0x20, 0x04, 0x02, 0x2A}; //Reset Axis 2
00133 char GetVoltage[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x40, 0x1F}; //get voltage from Axis1
00134 char GetTemperature[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x41, 0x20}; //get temperature from Axis2
00135 char GetVehicleCurrent[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x3E, 0x1D}; //get value from AI feedback, address 02 3E
00136 char GetCurrent1[] = {0x08, 0x00, 0x10, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x3C, 0x1B}; //get current from Axis1
00137 char GetCurrent2[] = {0x08, 0x00, 0x20, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x3C, 0x2B}; //get current from Axis2
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}; //get current from Axis1
00141 char GetPosition2[] = {0x08, 0x00, 0x20, 0xB0, 0x04, 0x00, 0x11, 0x02, 0x28, 0x17}; //get current from Axis2
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         //Motor_Current[ID-1] = (value-32736) * 2.5 * 4 / 65472;
00157         if (!(ChSum[0]==DriveReply[11]))// && (DriveReplyLong[1]==GetCurrent[5]) && (DriveReplyLong[2]==GetCurrent[6]) && (DriveReplyLong[5]==GetCurrent[1]) && (DriveReplyLong[6]==GetCurrent[2])) 
00158         {CommsOkFlag = false;}
00159         return value;
00160 }
00161 
00162 void SetDigiOut() // only for general purpose dig.out 0 & 1.
00163 {
00164         char DigOutSet[] = {0x08, 0x00, 0x10, 0xEC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05}; //Axis1, DO0, set to 0
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; //set axis
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];} //create checksum
00201         os.write(DigOutSet,sizeof(DigOutSet));
00202         write(port,outputBuffer);
00203         DigOutNumber++;
00204 }
00205 
00206 void SetReference(int ID, float REF) //REF from 0 to 1. 1 represents full thrust
00207 {
00208         char SetRefID1[] = {0x06, 0x00, 0x10, 0x20, 0xA9, 0x00, 0x00, 0xDF}; //Set Reference 0 for Axis1
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         // Motors are 3,4A max. Value of ext. reference (3272) corresponds to 1A. Full thrust (3.4A) is then ext. reference of 11138
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 //void ReadHandler(std::size_t size)
00233 {
00234         //std::cout<<"Mode:"<<Mode<<std::endl;
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)//is sync
00249                         {CommsOkFlag= true;}
00250                         MessageLength=1;
00251                         break;
00252                 }
00253 
00254                 if (Mode=="Data_V")// && (strncmp(DriveReply,"\r",1)==0)) //is sync
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")// && (strncmp(DriveReply,"\r",1)==0)) //is sync
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")// && (strncmp(DriveReply,"\r",1)==0)) //is sync
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                         //os.write(GetCurrent1,sizeof(GetCurrent1));
00292                         os.write(GetPosition1,sizeof(GetPosition1));
00293                         write(port,outputBuffer);
00294                         break;
00295                 }
00296 
00297                 if (Mode=="Data_C1")// && (strncmp(DriveReply,"\r",1)==0)) //is sync
00298                 {
00299                         MessageLength = 1;
00300                         CommsOkFlag= true;
00301 
00302                         //Motor_Current[0] = (parsData()-32736) * 2.5 * 4 / 65472;
00303                         Load_Position[0] = parsData();
00304 
00305                         Mode = "OK";
00306                         Mode1 = "Data_C2";
00307                         //os.write(GetCurrent2,sizeof(GetCurrent2));
00308                         os.write(GetPosition2,sizeof(GetPosition2));
00309                         write(port,outputBuffer);
00310                         break;
00311                 }
00312 
00313                 if (Mode=="Data_C2")// && (strncmp(DriveReply,"\r",1)==0)) //is sync
00314                 {
00315                         MessageLength = 1;
00316                         CommsOkFlag= true;
00317                         // IF current
00318                         //Motor_Current[1] = (parsData()-32736) * 2.5 * 4 / 65472;
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) //is sync
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), //boost::asio::transfer_at_least(1),
00356                         boost::bind(&ReadHandler, placeholders::error, placeholders::bytes_transferred));
00357         //ReadFlag = true;
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}; //Update Axis1
00371         char UpdID2[] = {0x04, 0x00, 0x20, 0x01, 0x08, 0x2D}; //Update Axis2
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         // Disable encoder wire break, (encoder does not exist)
00403         Mode = "OK";
00404         Mode1 = "";
00405         counter=0;
00406         do
00407         {
00408                 os.write(DisableEncoderWire,sizeof(DisableEncoderWire));
00409                 write(port,outputBuffer);
00410                 //read(port,boost::asio::buffer(&a,1));
00411                 counter++;
00412                 usleep(1000*delay);
00413         }
00414         while (!CommsOkFlag && (counter<2));
00415         if (counter>1)
00416         {b1 = false;}
00417 
00418         // Set torque Mode of operation
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         // Set external reference serial - RS 232
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         // Update Axis
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         //std::cout<<"Poziv"<<std::endl;
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         //TechnoSoft port configuration
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                 //read(port,boost::asio::buffer(&a,1));
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                 //read(port,boost::asio::buffer(&a,1));
00534 
00535                 if (CommsOkFlag)
00536                 {
00537                         //std::cout<<"promjenio na 115200 - OK"<<std::endl;
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                                 //std::cout<<"IPOS Port 115200"<<std::endl;
00546                                 //return true;
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         //labust::tools::watchdog WD(watch, tSum, tLoop);
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         //std::cout<<"Please enter path to config file"<<std::endl;
00721         //std::cin>>path;ΕΎ
00722 
00723 
00724         /*path="c:/config.xml";
00725         LABUST::XML::Reader reader(path, true);
00726         std::string configQuery;
00727         configQuery = "/configurations/config[@type='program']";
00728         _xmlNode* configNode = NULL;
00729 
00730         if (reader.try_value(configQuery, &configNode))
00731         {
00732         reader.useNode(configNode);
00733         }
00734 
00735         std::string joystickConfig("LogitechWireless");
00736         reader.useNode(configNode);
00737         joystick = new LABUST::JoystickReader(reader,joystickConfig);*/
00738 
00740         //Init node
00741         ros::init(argc,argv,"cart2_node");
00742         //Get handles
00743         ros::NodeHandle nh,ph("~");
00744         //Setup subscribers
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         //Setup publishers
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         //Get port name from configuration and open.
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         //WD.start();
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                 //return true;
00791         }
00792 
00793         // read port for the first time
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         //This we change with ros::ok
00798         //while (1)
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                         //return true;
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                                         //Set reference torque zero
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                         //LABUST::JoystickData joystickData;
00894                         //joystickData = joystick->ReadJoystickData();
00895 
00896                         /*if (abs(joystickData.axes[1])>2000)
00897                                 {TauControl.Frw = float(-joystickData.axes[1])/intMax;}
00898                         else
00899                                 {TauControl.Frw = 0;}
00900                         if (abs(joystickData.axes[5])>2000)
00901                                 {TauControl.Yaw = float(joystickData.axes[5])/intMax;}
00902                         else
00903                                 {TauControl.Yaw = 0;}
00904 
00905                         //if ((TauControl.Frw!=TauControlOld.Frw) || (TauControl.Yaw!=TauControlOld.Yaw))
00906                         //{
00907                                 TauControlOld = TauControl;*/
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                         // (TauC TauControl, float Limit)*/
00951                         //thrust.Port = 0;
00952                         //thrust.Stb = 0;
00953                         AverCount++;
00954                         //if (AverCount < 20)
00955                         //{thrust.Port = 0;
00956                         //thrust.Stb = 0.15;}
00957                         double an=0.045315881, wn= 0.0002496019;
00958                         double ann=0.0419426925, wnn= 0.0002506513;
00959 
00960                         //double rpm_port = (thrust.Port>=0)?log(thrust.Port/an)/wn:-log(-thrust.Port/ann)/wnn;
00961                         //double rpm_stbd = (thrust.Stb>=0)?log(thrust.Stb/an)/wn:-log(-thrust.Stb/ann)/wnn;
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                                 //rpm_port = int(rpm_port);
00987                                 //rpm_stbd = int(rpm_stbd);
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                                 //curr_port=labust::math::coerce(-Kp*error[0] + integralRPM[0],-max_current,max_current);
00995                                 curr_port=cport.step(rpm_port, rpm_port_meas);
00996                                 //curr_stbd=labust::math::coerce(Kp*error[1] + integralRPM[1],-max_current,max_current);
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                         //for(int i=0; i<2; ++i) currentAvg[i] = (currentAvg[i] + 0.01*Motor_Current[i])/1.01;
01047                         Supply_Voltage_Previous = Supply_Voltage;
01048                         //Motor_Current_Previous[0] = Motor_Current[0];
01049                         //Motor_Current_Previous[1] = Motor_Current[1];
01050                         Load_Position_Previous[0] = Load_Position[0];
01051                         Load_Position_Previous[1] = Load_Position[1];
01052                         ReadData();
01053                         //GetMotorCurrent(2);
01054                         /*if (!CommsOkFlag)
01055                                 {CommsOkFlag = true;
01056                                 CommsAll++;
01057                         }*/
01058                         /*GetSupplyVoltage();
01059                         if (!CommsOkFlag)
01060                                 {CommsOkFlag = true;
01061                                 CommsAll++;}*/  
01062 
01063                         if ((AverCount == 5) || (AverCount == 15))
01064                                 //{printf("%f\n",Motor_Current[0]);
01065                                 //printf("%f\n",abs(Motor_Current[1])*100);
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                         //WD.reset();}
01077                         sendDiagnostics(diagnostic, CommsOkFlag);
01078                         //This we exchange with ros rate
01079                         //rate.sleep();
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                         //stbdTest = portTest = false;
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                 //t.join();
01116                 //WD.reset();
01117         }
01118 
01119         //io.run();
01120 
01121         //imu.closePort();
01122         io.stop();
01123         t.join();
01124         std::cout<<"Exited."<<std::endl;
01125         return 0;
01126 }
01127 
01128 
01129 
01130 
01131 


cart2
Author(s): Gyula Nagy
autogenerated on Fri Feb 7 2014 11:37:19