#include "MCosy.h" #include "MCosy.h" #include #include #include #include #include #include #include #include #include #include #include #include "MGCosy.h" #include "SlaStars.h" #include "slalib/slalib.h" // FIXME: REMOVE #include "macs.h" #include "base/timer.h" #include "shaftencoder.h" //#include // PRIO_PROCESS ClassImp(MCosy); typedef struct tm tm_t; /* #define GEAR_RATIO_ALT 2475.6 // [U_mot/U_tel(360deg)] #define GEAR_RATIO_AZ 5891.7 // [U_mot/U_tel(360deg)] #define RES_RE 500 // [re/U_mot] #define RES_SE 16384 // [se/U_tel(360deg)] */ /* #define GEAR_RATIO_ALT (75.55*16384/1500) // 75.25 VERY IMPORTANT! unit=U_mot/U_tel #define GEAR_RATIO_AZ (179.8*16384/1500) // VERY IMPORTANT! unit=U_mot/U_tel */ //const XY kGearRatio (GEAR_RATIO_ALT*RES_RE/RES_SE, GEAR_RATIO_AZ*RES_RE/RES_SE); //[re/se] //const XY kGearRatio2(GEAR_RATIO_ALT*RES_RE/360.0, GEAR_RATIO_AZ*RES_RE/360.0); //[re/deg] /* +===================================+ FIXME: What if fMac3 (Sync) died? +===================================+ */ double MCosy::Rad2SE(double rad) const { return 16384.0/k2Pi*rad; } double MCosy::Rad2ZdRE(double rad) const { return 16384.0/k2Pi*rad*kGearRatio.X(); } double MCosy::Rad2AzRE(double rad) const { return 16384.0/k2Pi*rad*kGearRatio.Y(); } double MCosy::Deg2ZdRE(double rad) const { return rad*kGearRatio2.X(); } double MCosy::Deg2AzRE(double rad) const { return rad*kGearRatio2.Y(); } ZdAz MCosy::CorrectTarget(const ZdAz &src, const ZdAz &dst) { // CorrectTarget [se] // src [se] // dst [rad] // fAltMax = 70 // fAltMin = -105/110 // fAzMin = -355 // fAzMax = 355 ZdAz source = src * 360.0/16384.0; ZdAz dest = dst * kRad2Deg; if (dest.Zd()>-3 && dest.Zd()<3) dest.Zd(dest.Zd()<0?-3:3); if (dest.Zd()>-1e-6 && dest.Zd()<1e-6) return dst*(16384.0/k2Pi); const float fZdMin = -67; const float fZdMax = 67; const float fAzMin = -29; const float fAzMax = 423; // // This corrects to target for the shortest distance, not for the fastest move! // ZdAz s = source-dest; float min = s.Sqr(); // // Is it enought to search inside one revolution? // ZdAz ret = dest; for (int i=-5; i<5+1; i++) { const ZdAz p(i%2 ? -dest.Zd() : dest.Zd(), dest.Az() - i*180); // // Range Check // if (p.Zd()fZdMax) continue; if (p.Az()fAzMax) continue; // // Calculate distance // s = source-p; const float dist = s.Sqr(); if (dist > min) continue; // // New shortest distance // ret = p; min = dist; } return ret*(16384.0/360.0); } // -------------------------------------------------------------------------- // // GetSePos, reads the Shaftencoder positions from the Can-drivers // for the shaftencoders. The two shaft encoders at the elevation axis // are avaraged. The values are returned as a ZdAz object. // // If one of the two shaftencoders on the elevation axis is missing // the other one's position is returned. // // The positions are alway up-to-date because the shaftencoders are // sending all changes immediatly. // ZdAz MCosy::GetSePos() { const int pa = fAz->GetPos(); if (fZd1->IsZombieNode() && fZd2->IsZombieNode()) return ZdAz(0, pa); // // Get the values // int p1 = (fZd1->GetPos()+8192)%16384; int p2 = -(fZd2->GetPos()+8192)%16384; if (fZd1->IsZombieNode()) return ZdAz(p2, pa); if (fZd2->IsZombieNode()) return ZdAz(p1, pa); // // interpolate shaft encoder positions // float p = (float)(p1+p2)/2; return ZdAz(p, pa); } // -------------------------------------------------------------------------- // // request the current positions from the rotary encoders. // use GetRePos to get the psotions. If the request fails the function // returns kFALSE, otherwise kTRUE // Bool_t MCosy::RequestRePos() { // // Send request // fMac2->RequestSDO(0x6004); fMac1->RequestSDO(0x6004); // // Wait until the objects are received. // fMac2->WaitForSdo(0x6004); fMac1->WaitForSdo(0x6004); // FIXME, what when waiting times out (Zombie) // WaitForSdos(); // // If waiting was not interrupted everything is ok. return. // if (!(Break() || HasError()) && !HasZombie()) return kTRUE; // // If the waiting was interrupted due to a network error, // print some logging message. // if (HasError()) lout << "Error while requesting re pos from Macs (SDO #6004)" << endl; return kFALSE; } // -------------------------------------------------------------------------- // // reads the Rotary encoder positions from the last request of the Macs. // // The positions are returned as a ZdAz object. Use RequestRePos to request // the current positions first. // ZdAz MCosy::GetRePos() { return ZdAz(fMac2->GetPos(), fMac1->GetPos()); } // -------------------------------------------------------------------------- // // reads the Rotary encoder positions from the Macs. // // The positions are returned as a ZdAz object. The positions are the ones // which are send as PDOs to the computer. This is done at a given // frequency. Which means, that this positions are not ought to be // up-to-date. // ZdAz MCosy::GetRePosPdo() { return ZdAz(fMac2->GetPdoPos(), fMac1->GetPdoPos()); } // -------------------------------------------------------------------------- // // set the velocity and accelerations for position maneuvers. // // The acceleratin is set as given (in percent of maximum). // The velocity is given in percent, depending on the ratio (<1 or >1) // one of the axis becomes a slower velocity. This is used for maneuvers // in which both axis are moved synchromously and should reach their // target position at the same time. // void MCosy::SetPosVelocity(const Float_t ratio, Float_t vel) { // // Set velocities // const int vr = fMac1->GetVelRes(); vel *= vr; if (ratio <1) { fMac1->SetVelocity(vel); fMac2->SetVelocity(vel*ratio); } else { fMac1->SetVelocity(vel/ratio); fMac2->SetVelocity(vel); } } // -------------------------------------------------------------------------- // // Does a relative positioning. // // The steps to move are given in a ZdAz object relative to the current // position. The coordinates are given in Roteryencoder steps. // Axis 1 is moved only if axe1==kTRUE, Axis 2 is moved only // if Axis 2==kTRUE. The function waits for the movement to be finished. // void MCosy::DoRelPos(const ZdAz &rd, const Bool_t axe1, const Bool_t axe2) { if (HasZombie()) return; SetStatus(MCosy::kMoving); if (axe1) fMac2->StartRelPos(rd.Zd()); if (axe2) fMac1->StartRelPos(rd.Az()); cout << "Waiting for positioning..." << flush; if (axe1) fMac2->WaitForSdo(0x6004, 1); if (axe2) fMac1->WaitForSdo(0x6004, 1); WaitForEndMovement(); cout << "done." << endl; } // -------------------------------------------------------------------------- // // check for a break-signal (from the msgqueue) and errors. // int MCosy::StopWaitingForSDO() const { return 0/*Break() || HasError()*/; } // -------------------------------------------------------------------------- // // Waits for a movement to become finished. // // First waits for all peding Sdos, then waits until both motors are stopped // or waiting for SDOs was stopped (either by an error or by Break) // void MCosy::WaitForEndMovement() { // FIXME, what when waiting times out (Zombie) while ((fMac1->IsPositioning() || fMac2->IsPositioning()) && !(Break() || HasError()) && !HasZombie()) usleep(1); if (Break() || HasError() || HasZombie()) lout << "WaitForEndMovement aborted..." << endl; } // -------------------------------------------------------------------------- // // Check for an error... // // This is ment for usage after the Action: All Motors Stop. // void MCosy::CheckForError() { // // Check all Can-Nodes for an Error. If there is no error the motor // status is set to stopped. // if (!HasError()) { SetStatus(MCosy::kStopped); return; } // // If there is an error, the error status is set to Error. // SetStatus(MCosy::kError); /* FIXME: HANDLINGE ERROR // // Now try to handle the error. // fMac1->HandleError(); fMac2->HandleError(); // // If the error couldn't get solved return // if (HasError()) return; // // Set motor status to stopped // SetStatus(MCosy::kStopped); */ } // -------------------------------------------------------------------------- // // Move the telescope to the given position. The position must be given in // a ZdAz object in rad. // // The first positioning is done absolutely. If we didn't reach the // correct psotion we try to correct for this by 10 relative position // maneuvers. If this doesn't help positioning failed. // // As a reference the shaftencoder values are used. // int MCosy::SetPosition(const ZdAz &dst, Bool_t track) // [rad] { // FIXME: Correct by fOffset ? /* ZdAz if (dst.Az()<-TMath::Pi()/2) dst.Az(dst.Az() + TMath::Pi()*2); if (dst.Az()>3*TMath::Pi()/2) dst.Az(dst.Az() -TMath::Pi()*2); */ // track=kFALSE; // const ZdAz d1 = track ? CorrectTarget(src, dst) : dst*16384/TMath::Pi()/2; // [se] const ZdAz d = dst*kRad2Deg; lout << "Target Position: " << d.Zd() << "deg, " << d.Az() << "deg (Zd/Az)" << endl; if (d.Zd()fMax.Zd()) { lout << "ERROR: Requested Zenith Angle (" << d.Zd() << "deg) not "; lout << "inside allowed range." << endl; return kFALSE; } if (d.Az()fMax.Az()) { lout << "ERROR: Requested Azimuth Angle (" << d.Az() << "deg) not "; lout << "inside allowed range." << endl; return kFALSE; } // // Calculate new target position (shortest distance to go) // const ZdAz src = GetSePos(); // [se] /* if (fMac1->IsZombieNode() || fMac2->IsZombieNode()) { cout << "SetPosition: No connection to at least one of the MACS!" << endl; return TRUE; } */ // // Make sure that the motors are in sync mode (necessary if the // MACS has been rebooted from a Zombie state. // //InitSync(); //if (fMac3->IsZombieNode()) // return false; // ==================================== RequestRePos(); ZdAz before = GetRePos(); // ==================================== // // Because we agreed on I don't search for the shortest move // anymore // // const ZdAz dest = CorrectTarget(src, dst); // const ZdAz dest = fBending(dst)*16384/2/TMath::Pi(); // [se] fZdAzSoll = dst; cout << "Source Zd: " << src.Zd() << "se Az:" << src.Az() << "se" << endl; cout << "Destination Zd: " << Rad2SE(dst.Zd()) << "se Az:" << Rad2SE(dst.Az()) << "se" << endl; cout << "Bend'd Dest Zd: " << Rad2SE(fZdAzSoll.Zd()) << "se Az:" << Rad2SE(fZdAzSoll.Az()) << "se" << endl; cout << "Shortest Dest Zd: " << dest.Zd() << "se Az:" << dest.Az() << "se" << endl; /* * re(se) = -28.1*cos(x*360/16384/se - 14.4) + 443.2*re/se * * int(re) = -1278.86*sin(0.021972656 *x/se - 14.4 )re + 443.2re x/se * int(re) = -73273.4*sin(0.000383495197*x/se - .2513274)re + 443.2re x/se * * int (-75deg..95deg) = 3.28343e7 re * */ // // Set velocities // const int vr = fMac1->GetVelRes(); int i; for (i=0; i<10 && !(Break() || HasError()) && !HasZombie(); i++) { lout << "Step #" << i << endl; // // Get Shaft Encoder Positions // const ZdAz p=GetSePos(); // // calculate control deviation and rounded cd // ZdAz rd = dest-p; // [se] /* if (rd.Az()>0 && rd.Az()<0.5) rd.Az(1); if (rd.Az()<0 && rd.Az()>-0.5) rd.Az(-1); */ cout << "Deviation: " << rd.Zd() << "se Az:" << rd.Az() << "se" << endl; // =========================================== Float_t k1 = dest.Zd()*360/16384 - 14.3979; //[deg] Float_t k0 = p.Zd()*360/16384 - 14.3979; //[deg] // // -28re/se*cos((x/deg-14.4)*pi/180) + 443.2re/se x // 28re/se*2*pi/360*sin((x/deg-14.4)*pi/180)*deg + 443.2re/se*x/deg // Float_t dk = 443.152*(dest.Zd()-p.Zd()); Float_t dx = 28.0148/2/TMath::Pi()*(sin(k1/kRad2Deg)-sin(k0/kRad2Deg)); cout << "Using: " << rd.Zd()*kGearRatio.X() << endl; // [re] cout << "Estimated1: " << 16384*dx + dk << endl; cout << "Estimated2: " << (16384*dx + dk)/1.085949688 << endl; // =========================================== ZdAz cd = rd; // [se] cd.Round(); /* if (rd.Az()>0 && rd.Az()<0.5) rd.Az(0.5); if (rd.Az()<0 && rd.Az()>-0.5) rd.Az(-0.5); */ // // Check if there is a control deviation on the axis // const Bool_t cdzd = (int)cd.Zd() ? kTRUE : kFALSE; const Bool_t cdaz = (int)cd.Az() ? kTRUE : kFALSE; // // check if we reached the correct position already // if (!cdzd && !cdaz) { lout << "Positioning done in " << i << (i==1?" step.":" steps.") << endl; SetStatus(MCosy::kStopped); // ==================================== RequestRePos(); ZdAz after = GetRePos(); // ==================================== after -= before; cout << "Drove: " << after.Zd() << " " << after.Az() << endl; return TRUE; } // // change units from se to re // rd *= kGearRatio; // [re] // // Initialize Velocities so that we reach both positions // at the same time // if (i) { fMac1->SetAcceleration(0.1*vr); fMac2->SetAcceleration(0.1*vr); fMac1->SetDeceleration(0.1*vr); fMac2->SetDeceleration(0.1*vr); SetPosVelocity(1.0, 0.05); } else { if (rd.Az()>-15*kGearRatio.Y() && rd.Az()<15*kGearRatio.Y()) { cout << " -------------- LO ---------------- " << endl; fMac1->SetAcceleration(0.05*vr); fMac1->SetDeceleration(0.05*vr); } else { cout << " -------------- HI ---------------- " << endl; fMac1->SetAcceleration(0.2*vr); fMac1->SetDeceleration(0.1*vr); } fMac2->SetAcceleration(0.2*vr); fMac2->SetDeceleration(0.1*vr); // vel(0.6) acc(0.5) SetPosVelocity(fabs(rd.Ratio()), 0.175); // SetPosVelocity(fabs(rd.Ratio()), 0.1, 0.3); } rd.Round(); // FIXME? Check for Error or Zombie? /* cout << " + " << (int)cdzd << " " << (int)cdaz << endl; cout << " + APOS: Zd=" << setw(6) << p.Zd() << "se Az=" << setw(6) << p.Az() << "se" << endl; cout << " + dZd=" << setw(6) << cd.Zd() << "se dAz=" << setw(6) << cd.Az() << "se" << endl; cout << " + dZd=" << setw(6) << rd.Zd() << "re dAz=" << setw(6) << rd.Az() << "re" << endl; cout << " + Ratio: Zd=" << setw(6) << kGearRatio.X() << "se Az=" << setw(6) << kGearRatio.Y() << "se" << endl; */ // // repositioning (relative) // lout << "Do Relative Positioning Done" << endl; DoRelPos(rd, cdzd, cdaz); lout << "Relative Positioning Done" << endl; } if (i<10) StopMovement(); lout << "Warning: Requested position not reached (i=" << i << ")" << endl; return FALSE; } // -------------------------------------------------------------------------- // // Sets the tracking velocity // // The velocities are given in a ZdAz object in re/min. Return kTRUE // in case of success, kFALSE in case of failure. // Bool_t MCosy::SetVelocity(const ZdAz &v) { // // Send the new velocities for both axes. // fMac2->SendSDO(0x3006, 1, (LWORD_t)v.Zd()); // SetRpmVelocity [re/min] fMac1->SendSDO(0x3006, 1, (LWORD_t)v.Az()); // SetRpmVelocity [re/min] // // Wait for the objects to be OKed. // fMac2->WaitForSdo(0x3006, 1); fMac1->WaitForSdo(0x3006, 1); // FIXME, what when waiting times out (Zombie) // WaitForSdos(); // // If the waiting for the objects wasn't interrupted return kTRUE // if (!(Break() || HasError()) && !HasZombie()) return kTRUE; // // print a message if the interruption was due to a Can-node Error // if (HasError()) lout << "Error while setting velocity (SDO #3006)" << endl; return kFALSE; } // -------------------------------------------------------------------------- // // Initializes Tracking mode // // Initializes the accelerations of both axes with 90% of the maximum // acceleration. Set the status for moving and tracking and starts thr // revolution mode. // bool MCosy::InitTracking() { // FIXME? Handling of Zombie OK? if (fMac1->IsZombieNode() || fMac2->IsZombieNode()) return false; // // Start revolution mode // fMac2->SetAcceleration(0.2*fMac2->GetVelRes()); fMac2->SetDeceleration(0.2*fMac2->GetVelRes()); if (fMac2->IsZombieNode()) return false; fMac1->SetAcceleration(0.2*fMac1->GetVelRes()); fMac1->SetDeceleration(0.2*fMac1->GetVelRes()); if (fMac1->IsZombieNode()) return false; SetStatus(MCosy::kMoving | MCosy::kTracking); fMac2->SetRpmMode(TRUE); if (fMac2->IsZombieNode()) return false; fMac1->SetRpmMode(TRUE); if (fMac1->IsZombieNode()) return false; return true; } // -------------------------------------------------------------------------- // // Limits the speed. // // This function should work as a limiter. If a tracking error is too large // to be corrected fast enough we would get enormous velocities. These // velocities are limited to the maximum velocity. // void MCosy::LimitSpeed(ZdAz *vt, const ZdAz &vcalc) const { // // How to limit the speed. If the wind comes and blowes // we cannot forbid changing of the sign. But on the other hand // we don't want fast changes! // ULong_t vrzd = fMac1->GetVelRes(); ULong_t vraz = fMac2->GetVelRes(); #define sgn(x) (x<0?-1:1) const Float_t limit = 0.25; /* if (sgn(vt->Az()) != sgn(vcalc.Az())) vt->Az(0); // else { if (fabs(vt->Az()) < fabs(vcalc.Az()) *0.5) vt->Az(0.5*vcalc.Az()); if (fabs(vt->Az()) > fabs(vcalc.Az()) *1.5) vt->Az(1.5*vcalc.Az()); } if (sgn(vt->Zd()) != sgn(vcalc.Zd())) vt->Zd(0); // else { if (fabs(vt->Zd()) > fabs(vcalc.Az()) *1.5) vt->Zd(1.5*vcalc.Zd()); if (fabs(vt->Zd()) < fabs(vcalc.Az()) *0.5) vt->Zd(0.5*vcalc.Zd()); } */ if (sgn(vt->Az()) != sgn(vcalc.Az()) && fabs(vt->Az()) < limit*fabs(vcalc.Az()) ) vt->Az(0); else if (fabs(vt->Az()) > 0.9*vraz) { lout << "Warning: Azimuth speed limit exceeded. Limiting speed to 90% max." << endl; vt->Az(0.9*vraz*sgn(vt->Az())); } if (sgn(vt->Zd()) != sgn(vcalc.Zd()) && fabs(vt->Zd()) < limit*fabs(vcalc.Zd()) ) vt->Zd(0); else if (fabs(vt->Zd()) > 0.9*vrzd) { lout << "Warning: Altitude speed limit exceeded. Limiting speed to 90% max." << endl; vt->Zd(0.9*vrzd*sgn(vt->Zd())); } } void MCosy::TrackPosition(const RaDec &dst) // ra, dec [rad] { lout << "Track Position: " << dst.Ra()*kRad2Deg/15 << "h, " << dst.Dec()*kRad2Deg << "deg (Ra/Dec)" << endl; SlaStars sla(fObservatory); // // Position to actual position // sla.Now(); ZdAz dest = sla.CalcZdAz(dst); if (dest.Az()<-TMath::Pi()/2) dest.Az(dest.Az() + TMath::Pi()*2); if (dest.Az()>3*TMath::Pi()/2) dest.Az(dest.Az() -TMath::Pi()*2); if (!SetPosition(dest, kTRUE)) { lout << "Error: Cannot start tracking, positioning failed." << endl; return; } // // calculate offset from present se position // const ZdAz sepos = GetSePos()*kGearRatio; if (!RequestRePos()) return; // // Estimate Offset before starting to track // fOffset = sepos-GetRePos(); /* cout << "Sepos: " << sepos.Zd() << "re, " << sepos.Az() << "re" << endl; cout << "Repos: " << repos.Zd() << "re, " << repos.Az() << "re" << endl; cout << "Offset: " << fOffset.Zd() << "re, " << fOffset.Az() << "re" << endl; */ // // Init accelerations and Rpm Mode // if (!InitTracking()) return; XY xy(Rad2Deg(dst.Ra())*24/360, Rad2Deg(dst.Dec())); lout << "Start tracking:"; lout << " Ra: " << xy.X() << "h " << "Dec: " << xy.Y() << "\xb0" << endl; ofstream fout("coordinates.txt"); fout << xy; fout.close(); // // Initialize Tracker (slalib or starguider) // fRaDec = dst; fBackground = kBgdTracking; //--- ofstream fout("log/cosy.pos"); //--- fout << "Tracking:"; //--- fout << " Ra: " << Rad2Deg(dst.Ra()) << "\x9c "; //--- fout << "Dec: " << Rad2Deg(dst.Dec()) << "\x9c" << endl << endl; //--- fout << " Mjd/10ms V/re/min/4" << endl; // // We want to reach the theoretical position exactly in about 0.5s // // *OLD*const float dt = 1; // 1 second const float dt = 3; // 2 second while (!(Break() || HasError()) && !HasZombie()) { // // Request Target position for this moment // sla.Now(); // // Request theoretical Position for a time in the future (To+dt) from CPU // sla.SetMjd(sla.GetMjd()+dt/(60*60*24)); ZdAz dummy1 = sla.CalcZdAz(fRaDec); if (dummy1.Az()<-TMath::Pi()/2) dummy1.Az(dummy1.Az() + TMath::Pi()*2); if (dummy1.Az()>3*TMath::Pi()/2) dummy1.Az(dummy1.Az() -TMath::Pi()*2); ZdAz dummy = fBending(dummy1); dest = CorrectTarget(GetSePos(), dummy); // [se] const ZdAz d = dest*360./16384; // [deg] dest *= kGearRatio; // [re] ZdAz min = fBending(fMin/kRad2Deg)*kRad2Deg; ZdAz max = fBending(fMax/kRad2Deg)*kRad2Deg; /* if (d.Zd()max.Zd() || d.Az()>max.Az()) { lout << "ERROR: Calculated position for T+dt not inside allowed range." << endl; lout << "> " << d.Zd() << " " << max.Zd() << " " << d.Az() << " " << max.Az() << endl; break; } */ ZdAz vcalc = sla.GetApproxVel(fRaDec) * kGearRatio2*4./60.; // [re/min] // // Request absolute position of rotary encoder from Macs // if (!RequestRePos()) break; // // distance between (To+dt) and To [re] // position time difference < 5usec // fOffset does the synchronization between the // Shaft- and the rotary encoders // dest -= GetRePos() + fOffset; // // Velocity to go [re/min] to reach the right position at time t+dt // correct for the duration of RaDec2AltAz // const ZdAz v = dest*60.0/(dt/*-(fMac2->GetTime()-sla)*/); // // calculate real velocity of future [re/min] // believing the Macs manual '/4' shouldn't be necessary, but it is. // ZdAz vt = v/4; LimitSpeed(&vt, vcalc); vt.Round(); // // check if the drive is fast enough to follow the star // if (vt.Zd()>.9*fMac1->GetVelRes() || vt.Az()>.9*fMac2->GetVelRes()) { lout << "Error: Tracking speed faster than 90% of possible maximum velocity." << endl; break; } // // Set theoretical velocity (as early after calculation as possible) // Maybe we should attenuate the changes // if (!SetVelocity(vt)) break; // // Now do 'unnecessary' things // fVelocity = vt/kGearRatio2*4; //--- const double mjd = fMac2->GetMjd(); //--- fout << setprecision(15) << setw(17) << mjd*60.*60.*24. << " "; //--- fout << setw(4) << vt.Zd() << " "; //--- fout << setw(4) << vt.Az() << endl; // // FIXME? Calculate an accuracy for the tracking system? // How good do we reach the calculated position in 'real' // re valus? // // // Update speed as often as possible. // make sure, that dt is around 10 times larger than the // update time // // // The loop should not be executed faster than the ramp of // a change in the velocity can be followed. // (This is important on fast machines >500MHz) // usleep(50000); // 0.25s //usleep(50000); // 0.05s } fBackground = kBgdNone; StopMovement(); lout << "Tracking stopped." << endl; } // -------------------------------------------------------------------------- // // Stops the movement of both motors. // // Sets the status to stopping. Sets the deceleration to 50% of the maximum. // stops. Quits the revolution mode and wait for the end of the movement. // void MCosy::StopMovement() { // // Set status to Stopping // SetStatus(MCosy::kStopping); // // set deceleration to 50% // cout << "Stopping movement (dec=20%)..." << endl; fMac1->SetDeceleration(0.3*fMac1->GetVelRes()); fMac2->SetDeceleration(0.3*fMac2->GetVelRes()); fMac1->SetRpmMode(FALSE); fMac2->SetRpmMode(FALSE); /* fMac1->SetDeceleration(0.3*fMac1->GetVelRes()); fMac2->SetDeceleration(0.3*fMac2->GetVelRes()); fMac2->SendSDO(0x3000, Macs::string('s','t','o','p')); fMac1->SendSDO(0x3000, Macs::string('s','t','o','p')); fMac2->WaitForSdo(0x3000, 0); fMac1->WaitForSdo(0x3000, 0); fMac1->SetRpmMode(FALSE); fMac2->SetRpmMode(FALSE); */ // // Wait for the movement to really be finished. // cout << "Waiting for end of movement..." << endl; WaitForEndMovement(); // // Check whether everything works fine. // CheckForError(); cout << "Movement stopped." << endl; } void MCosy::StopTracking() { // // Set status to Stopping // SetStatus(MCosy::kStopping); // // set deceleration to 50% // cout << "Stopping tracking (dec=20%)..." << endl; fMac1->SetDeceleration(0.2*fMac1->GetVelRes()); fMac2->SetDeceleration(0.2*fMac2->GetVelRes()); fMac2->SendSDO(0x3006, 1, (LWORD_t)0); // SetRpmVelocity [re/min] fMac1->SendSDO(0x3006, 1, (LWORD_t)0); // SetRpmVelocity [re/min] fMac2->WaitForSdo(0x3006, 1); fMac1->WaitForSdo(0x3006, 1); cout << "Waiting for end of movement..." << endl; WaitForEndMovement(); // // Wait for the objects to be OKed. // fMac1->SetRpmMode(FALSE); fMac2->SetRpmMode(FALSE); // // Wait for the movement to really be finished. // //cout << "Waiting for end of movement..." << endl; //WaitForEndMovement(); // // Check whether everything works fine. // CheckForError(); cout << "Movement stopped." << endl; } bool MCosy::CheckNetwork() { //return kTRUE; //CheckConnections(); if (HasZombie()) { lout << "- Found Zombies in Network..." << endl; if (!RebootZombies()) return false; } /* FIXME HANDLING ERROR */ if (HasError()) { fMac1->HandleError(); fMac2->HandleError(); fMac3->HandleError(); if (HasError() || HasZombie()) return false; } return true; } void *MCosy::Proc(int msg, void *mp) { switch (msg) { case WM_WAIT: cout << "Wait for execution of Proc(WM_*, ): done." << endl; return NULL; case WM_STOP: cout << "MCosy::Proc: Stop." << endl; if (!CheckNetwork()) return (void*)0xebb0; StopMovement(); return NULL; case WM_PRESET: cout << "WM_Preset: start." << endl; if (!CheckNetwork()) return (void*)0xebb0; fZd1->SetPreset(); fZd2->SetPreset(); fAz->SetPreset(); cout << "WM_Preset: done. (return 0xaffe)" << endl; return (void*)0xaffe; case WM_CALIB: { cout << "WM_Calib: start." << endl; if (!CheckNetwork()) return (void*)0xebb0; SlaStars sla(fObservatory); sla.Now(); RaDec rd = *((RaDec*)mp); //RaDec rd(37.94, 89.2644); // POLARIS //RaDec rd(213.915417, 19.1825); // ACTURUS cout << "Calibrating to: " << rd.Ra()*24/360 << "h " << rd.Dec() << "°" << endl; ZdAz za=sla.CalcZdAz(rd*kDeg2Rad)*16384.0/k2Pi; cout << "Calc Zd: " << za.Zd() << " Az: " << za.Az() << endl; ZdAz sepos = GetSePos(); cout << "Got Zd: " << sepos.Zd() << " Az: " << sepos.Az() << endl; fZd1->SetPreset(za.Zd()); fZd2->SetPreset(-za.Zd()); fAz->SetPreset(za.Az()); cout << "WM_Calib: done. (return 0xaffe)" << endl; } return (void*)0xaffe; case WM_TPOINT: { cout << "WM_TPoint: start." << endl; SlaStars sla(fObservatory); sla.Now(); RaDec rd = *((RaDec*)mp); cout << "TPoint Star: " << rd.Ra()/15 << "h " << rd.Dec() << "°" << endl; AltAz za=sla.CalcAltAz(rd*kDeg2Rad)*kRad2Deg; cout << " Alt/Az: " << za.Alt() << "° " << za.Az() << "°" << endl; *tpout << setprecision(7) << za.Az() << " " << za.Alt() << " "; ZdAz sepos = GetSePos()*TMath::Pi()*2/16384;; za.Set(TMath::Pi()/2-sepos.Zd(), sepos.Az()); za *= kRad2Deg; cout << " SE-Pos: " << za.Alt() << "° " << za.Az() << "°" << endl; *tpout << fmod(za.Az()+360, 360) << " " << za.Alt() << " "; *tpout << rd.Ra()/15 << " " << rd.Dec() << " " << setprecision(11) << sla.GetMjd() << endl; cout << "WM_TPoint: done. (return 0xaffe)" << endl; } return (void*)0xca1b; case WM_POSITION: cout << "WM_Position: start." << endl; { if (!CheckNetwork()) return (void*)0xebb0; ZdAz dest = *((ZdAz*)mp); SetPosition(dest*kDeg2Rad); } cout << "WM_Position: done. (return 0x7777)" << endl; return (void*)0x7777; case WM_TESTSE: cout << "WM_TestSe: start." << endl; fBackground = mp ? kBgdSeTest : kBgdNone; cout << "WM_TestSe: done. (return 0x1e51)" << endl; return (void*)0x1e51; case WM_GEAR: cout << "WM_Gear: start." << endl; fBackground = mp ? kBgdGear : kBgdNone; cout << "WM_Gear: done. (return 0xfeaf)" << endl; return (void*)0xfeaf; case WM_DISPLAY: cout << "WM_Display: start." << endl; fTriggerDisplay = kTRUE; cout << "WM_Disply: done. (return 0xd1e1)" << endl; return (void*)0xd1e1; case WM_TRACK: cout << "WM_Track: START" << endl; { if (!CheckNetwork()) return (void*)0xebb0; RaDec dest = *((RaDec*)mp); TrackPosition(dest*kDeg2Rad); } cout << "WM_Track: done. (return 0x8888)" << endl; return (void*)0x8888; case WM_NEWTRACK: cout << "WM_NewTrack: START" << endl; fRaDec = *((RaDec*)mp); cout << "WM_NewTrack: done. (return 0x9999)" << endl; return (void*)0x9999; case WM_LOADBENDING: cout << "WM_LoadBending: START" << endl; fBending.Load("bending.txt"); cout << "WM_LoadBending: done. (return 0xbe0d)" << endl; return (void*)0xbe0d; case WM_RESETBENDING: cout << "WM_ResetBending: START" << endl; fBending.Reset(); cout << "WM_ResetBending: done. (return 0xbe0e)" << endl; return (void*)0xbe0e; case WM_HOME: cout << "WM_Home: START" << endl; if (!CheckNetwork()) return (void*)0xebb0; else { cout << "HOME NOT ALLOWED... for Magic." << endl; /* cout << "Going Home..." << endl; TEnv env(".cosyrc"); SetStatus(MCosy::kMoving); fMac1->SetHome(250000, env.GetValue("Az_MaxTime2ReachHome[s]", 100)); fMac2->SetHome(250000, env.GetValue("Zd_MaxTime2ReachHome[s]", 100)); lout << "SETHOME DONE" << endl; SetStatus(HasError() ? MCosy::kError : MCosy::kStopped); fAz->SetPreset(); fZd1->SetPreset(); fZd2->SetPreset(); fMac1->ReqPos(); fMac2->ReqPos(); fMac3->StopMotor(); */ } cout << "WM_Home: done. (return 0x403e)" << endl; return (void*)0x403e; case WM_CALCALTAZ: { cout << endl; SlaStars sla(fObservatory); sla.Now(); XY xy = *((XY*)mp); RaDec rd(xy.X()*15., xy.Y()); // [deg] ZdAz a0 = sla.CalcZdAz(rd*kDeg2Rad); ZdAz a1 = fBending(a0); ZdAz se = CorrectTarget(GetSePos(), a1); a0 *= kRad2Deg; a1 *= kRad2Deg; ZdAz a2 = a1*16384/360; cout << "Ra/Dec source: " << xy.X() << "h " << xy.Y() << "°" << endl; cout << "Zd/Az source: " << a0.Zd() << "° " << a0.Az() << "°" << endl; cout << "Zd/Az bended: " << a1.Zd() << "° " << a1.Az() << "°" << endl; cout << "SE bended: " << a2.Zd() << " " << a2.Az() << endl; cout << "SE target: " << se.Zd() << " " << se.Az() << endl; } return (void*)0xa17a; case WM_QUIT: cout << "WM_Quit: now." << endl; if (!CheckNetwork()) { lout << "ERROR: Cannot shutdown CANbus network." << endl; return (void*)0xebb0; } TerminateApp(); cout << "WM_Quit: done." << endl; return (void*)0xaaaa; } cout << "MCosy::Proc: Unknown message 0x" << msg << endl; return (void*)0xffffffff; } void *MTTalk::Thread() { fCosy->TalkThread(); return NULL; } void MCosy::ReadConfig() { cout << "Reading configuration file..." << flush; TEnv env(".cosyrc"); cout << "done." << endl; cout << "Reading telescope range..." << flush; const Double_t amin = env.GetValue("Az_Min[deg]", -90.0); const Double_t zmin = env.GetValue("Zd_Min[deg]", -74.5); fMin.Set(zmin, amin); cout << " Min: " << zmin << "deg " << amin << "deg" << endl; const Double_t amax = env.GetValue("Az_Max[deg]", 318.0); const Double_t zmax = env.GetValue("Zd_Max[deg]", 100.5); fMax.Set(zmax, amax); cout << " Max: " << zmax << "deg " << amax << "deg" << endl; cout << "Reading gear ratios..." << flush; const Double_t gaz = env.GetValue("Az_GearRatio[U_mot/U_tel]", 1000.0); const Double_t gzd = env.GetValue("Zd_GearRatio[U_mot/U_tel]", 1000.0); Double_t resreaz = 0; if (fMac1 && !fMac1->IsZombieNode()) resreaz = fMac1->GetRes(); else if (fMac3 && !fMac3->IsZombieNode()) resreaz = fMac3->GetRes(); else resreaz = env.GetValue("Az_ResRE[re/U_mot]", 1500); Double_t resrezd = 0; if (fMac2 && !fMac2->IsZombieNode()) resrezd = fMac2->GetRes(); else resrezd = env.GetValue("Zd_ResRE[re/U_mot]", 1500); Double_t ressezd = 0; if (fZd1 && !fZd1->IsZombieNode()) ressezd = fZd1->GetPhysRes(); else if (fZd2 && !fZd2->IsZombieNode()) ressezd = fZd2->GetPhysRes(); else ressezd = env.GetValue("Zd_ResSE[se/U_mot]", 16384); Double_t resseaz = 0; if (fAz && !fAz->IsZombieNode()) resseaz = fAz->GetPhysRes(); else resseaz = env.GetValue("Az_ResSE[se/U_mot]", 16384); kGearRatio.Set (gzd*resrezd*4/ressezd, gaz*resreaz*4/resseaz); //[re/se] kGearRatio2.Set(gzd*resrezd*4/360.0, gaz*resreaz*4/360.0); //[re/deg] cout << "done." << endl; cout << " * Setting Gear Ratios:" << endl; cout << " --------------------" << endl; cout << " * X: " << gzd << "*" << resrezd << "/" << ressezd << "=" << kGearRatio.X() << endl; cout << " * Y: " << gaz << "*" << resreaz << "/" << resseaz << "=" << kGearRatio.Y() << endl; } void MCosy::InitSync() { if (!fMac3) { lout << "Unable to Init Sync! Mac3 not available." << endl; return; } const int res = fMac3->GetVelRes(); fMac3->SetVelocity(0.3*res); fMac3->SetAcceleration(0.2*res); fMac3->SetDeceleration(0.2*res); fMac3->StartPosSync(); } void MCosy::TalkThreadTracking() { if (fZd1->IsZombieNode() && fZd2->IsZombieNode()) return; if (fAz->IsZombieNode()) return; if (!fMac1 || !fMac2) return; lout << "Tracking Thread started..." << endl; SlaStars sla(fObservatory); ZdAz old; ZdAz ist; ZdAz sollzd; ZdAz sollaz; ZdAz istre = -fOffset; // [re] ZdAz time; // // only update fTrackingError while tracking // bool phca1=false; bool phca2=false; bool phcaz=false; while (fBackground==kBgdTracking) { // // Make changes (eg wind) smoother - attenuation of control function // const float weight = 1.; //0.3; // // This is the time constant which defines how fast // you correct for external influences (like wind) // fZd1->ResetPosHasChanged(); fZd2->ResetPosHasChanged(); fAz->ResetPosHasChanged(); do { phca1 = fZd1->PosHasChanged(); phca2 = fZd2->PosHasChanged(); phcaz = fAz->PosHasChanged(); usleep(1); } while (!phca1 && !phca2 && !phcaz && fBackground==kBgdTracking); //---usleep(100000); // 0.1s // // get position, where we are // old = ist; ist = GetSePos(); // [se] // // if the position didn't change continue // /*--- if ((int)ist.Zd() == (int)old.Zd() && (int)ist.Az() == (int)old.Az()) continue; */ istre = GetRePosPdo(); // // Get time from last shaftencoder position change (position: ist) // FIXME: I cannot take the avarage // // FIXME //time.Zd(fZd1->GetMjd()); /* OLD* */ if (fZd1->GetMjd()>fZd2->GetMjd()) time.Zd(fZd1->GetMjd()); else time.Zd(fZd2->GetMjd()); //time.Zd((fZd1->GetMjd()+fZd2->GetMjd())/2.0); time.Az(fAz->GetMjd()); // // if Shaftencoder changed position // calculate were we should be // if (phca1 || phca2 /*(int)ist.Zd() != (int)old.Zd()*/) { sla.SetMjd(time.Zd()); ZdAz dummy = fBending(sla.CalcZdAz(fRaDec)); sollzd = CorrectTarget(ist, dummy); // [se] fOffset.Zd(fOffset.Zd()*(1.-weight)+(ist.Zd()*kGearRatio.X()-istre.Zd())*weight); } if (phcaz /*(int)ist.Az() != (int)old.Az()*/) { sla.SetMjd(time.Az()); ZdAz dummy = fBending(sla.CalcZdAz(fRaDec)); sollaz = CorrectTarget(ist, dummy); // [se] fOffset.Az(fOffset.Az()*(1.-weight)+(ist.Az()*kGearRatio.Y()-istre.Az())*weight); } ZdAz soll(sollzd.Zd(), sollaz.Az()); // [se] fZdAzSoll = fBending.CorrectBack(soll*2*TMath::Pi()/16384); fTrackingError.Set((ist.Zd()-sollzd.Zd())*kGearRatio.X(), (ist.Az()-sollaz.Az())*kGearRatio.Y()); //--- fout << setprecision(15) << setw(17) << time.Zd()*60.*60.*24. << " "; //--- fout << setprecision(5) << setw(7) << fTrackingError.Zd() << " "; //--- fout << setprecision(15) << setw(17) << time.Az()*60.*60.*24. << " "; //--- fout << setprecision(5) << setw(7) << fTrackingError.Az() << endl; } lout << "Tracking Thread done." << endl; //--- fout << endl << endl; } void MCosy::TalkThreadSeTest() { // if (fZd1->IsZombieNode() || fZd2->IsZombieNode()) // return; if (fHist) { lout << "You are much too fast... try again." << endl; return; } fHist = new TH2F("Diff", "Difference of SE values", 201, fMin.Zd(), fMax.Zd(), 41, -10.5, 10.5); fHist->SetXTitle("ZA [\\circ]"); fHist->SetYTitle("\\Delta SE"); Double_t offset = 0; int cnt = 0; lout << "Starting Shaftencoder Test..." << endl; while (fBackground==kBgdSeTest) { fZd1->ResetPosHasChanged(); fZd2->ResetPosHasChanged(); while (!fZd1->PosHasChanged() && !fZd2->PosHasChanged() && fBackground==kBgdSeTest) usleep(1); const Double_t pos[3] = { (fZd1->GetPos()+8192)%16384, (fZd2->GetPos()+8192)%16384, fAz->GetPos() }; // // Estimate Offset from the first ten positions // if (cnt++<10) { offset += pos[0]+pos[1]; continue; } if (cnt==11) { offset /= 10; cnt++; } Double_t apos = (pos[0]-pos[1])/2 * TMath::Pi()*2 / 16384; ZdAz bend = fBending.CorrectBack(ZdAz(apos, pos[2]))*kRad2Deg; fHist->Fill(bend.Zd(), pos[0]+pos[1]-offset); } lout << "Shaftencoder Test Stopped... displaying Histogram." << endl; fBackground=kBgdSeTestDispl; } void MCosy::TalkThreadGear() { // if (fZd1->IsZombieNode() || fZd2->IsZombieNode()) // return; if (fHist) { lout << "You are much too fast... try again." << endl; return; } // fHist = new TH2F("Gear", "Gear Ratio Re/Se", // 201, fMin.Zd(), fMax.Zd(), 61, 349.5, 500.5); fHist = new TH2F("Gear", "Gear Ratio Re/Se", 201, fMin.Az(), fMax.Az(), 61, 419.5, 570.5); fHist->SetXTitle("ZA [\\circ]"); fHist->SetYTitle("Re/Se"); lout << "Starting Gear determination..." << endl; ZdAz se0 = GetSePos(); ZdAz re0 = GetRePosPdo(); while (fBackground==kBgdGear) { fZd1->ResetPosHasChanged(); fZd2->ResetPosHasChanged(); fAz->ResetPosHasChanged(); while (!fZd1->PosHasChanged() && !fZd2->PosHasChanged() && !fAz->PosHasChanged() && fBackground==kBgdGear) usleep(1); ZdAz se = GetSePos(); ZdAz re = GetRePosPdo(); ZdAz dse = se-se0; ZdAz dre = re-re0; if (fabs(dse.Zd())*144>16384) // Each 2.5deg { se0.Zd(se.Zd()); re0.Zd(re.Zd()); ZdAz bend = fBending.CorrectBack(se*2*TMath::Pi()/16384)*kRad2Deg; fHist->Fill(bend.Zd(), dre.Zd()/dse.Zd()); } if (fabs(dse.Az())*144>16384) // Each 2.5deg { se0.Az(se.Az()); re0.Az(re.Az()); ZdAz bend = fBending.CorrectBack(se*2*TMath::Pi()/16384)*kRad2Deg; fHist->Fill(bend.Az(), dre.Az()/dse.Az()); cout << bend.Az() << ": " << dre.Az()/dse.Az() << endl; } /* const Double_t pos[3] = { (fZd1->GetPos()+8192)%16384, (fZd2->GetPos()+8192)%16384, fAz->GetPos() }; // // Estimate Offset from the first ten positions // if (cnt++<10) { offset += pos[0]+pos[1]; continue; } if (cnt==11) { offset /= 10; cnt++; } Double_t apos = (pos[0]-pos[1])/2 * TMath::Pi()*2 / 16384; ZdAz bend = fBending.CorrectBack(ZdAz(apos, pos[2]))*kRad2Deg; fHistTestSe->Fill(bend.Zd(), pos[0]+pos[1]-offset); */ } lout << "Gear Test Stopped... displaying Histogram." << endl; fBackground=kBgdGearDispl; } void MCosy::TalkThread() { /* ========== FIXME? ============= if (fMac1->IsZombieNode() || fMac2->IsZombieNode()) return; */ if (fMac1 && fMac2) { fMac1->ReqPos(); fMac2->ReqPos(); } InitSync(); /*** FOR DEMO MODE ***/ if (!fZd1 || !fZd2 || !fAz) return; /*** FOR DEMO MODE ***/ // // Start the Network // while (1) { // // wait until a tracking session is started // while (fBackground==kBgdNone) usleep(1); switch (fBackground) { case kBgdNone: continue; case kBgdTracking: TalkThreadTracking(); continue; case kBgdSeTest: TalkThreadSeTest(); continue; case kBgdGear: TalkThreadGear(); continue; default: continue; } } } Bool_t MCosy::HandleTimer(TTimer *t) { // // Update Gui, foremer MTGui. // if (fZd1) fZd1->DisplayVal(); if (fZd2) fZd2->DisplayVal(); if (fAz) fAz->DisplayVal(); ZdAz seist = GetSePos()*2*TMath::Pi()/16384; // [se] ZdAz bendist = fBending.CorrectBack(seist); Byte_t avail = 0; avail |= (fMac1 && !fMac1->IsZombieNode()) ? 0x01 : 0; avail |= (fMac2 && !fMac2->IsZombieNode()) ? 0x02 : 0; avail |= (fMac3 && !fMac3->IsZombieNode()) ? 0x04 : 0; avail |= (fZd1 && !fZd1->IsZombieNode()) ? 0x08 : 0; avail |= (fZd2 && !fZd2->IsZombieNode()) ? 0x10 : 0; avail |= (fAz && !fAz->IsZombieNode()) ? 0x20 : 0; if (HasError()) SetStatus(MCosy::kError); lout.UpdateGui(); fWin->Update(bendist*(360.0/2/TMath::Pi()), fTrackingError/kGearRatio2, fVelocity, fOffset, fRaDec, fZdAzSoll, fStatus, avail); /* cout << (int)(fMac1->GetStatus()&Macs::kOutOfControl) << " "; cout << (int)(fMac2->GetStatus()&Macs::kOutOfControl) << " "; cout << (int)(fMac3->GetStatus()&Macs::kOutOfControl) << endl; */ const Bool_t trigger = fTriggerDisplay; fTriggerDisplay = kFALSE; if (fBackground==kBgdSeTestDispl || (trigger&&fBackground==kBgdSeTest)) DisplayHistTestSe(!trigger); if (fBackground==kBgdGearDispl || (trigger&&fBackground==kBgdGear)) DisplayHistGear(!trigger); return kTRUE; } void MCosy::DisplayHistTestSe(Bool_t del) { lout << "Displaying histogram..." << endl; TH2F &hist = *fHist; if (del) { fHist = NULL; fBackground = kBgdNone; } TCanvas *c=new TCanvas("c1", "", 1000, 1000); c->Divide(1,2); c->cd(1); TH2 *h=(TH2*)hist.DrawCopy(); TProfile *p = h->ProfileX("_pfx", -1, 9999, "s"); p->SetLineColor(kBlue); p->Draw("same"); p->SetBit(kCanDelete); c->cd(2); TH1F p2("spread", "Spread of the differences", hist.GetNbinsX(), hist.GetBinLowEdge(1), hist.GetBinLowEdge(hist.GetNbinsX()+1)); p2.SetXTitle("ZA [\\circ]"); for (int i=0; iGetBinError(i)); p2.SetLineColor(kRed); p2.SetStats(0); p2.DrawCopy(); if (del) delete &hist; } void MCosy::DisplayHistGear(Bool_t del) { lout << "Displaying histogram..." << endl; TH2F &hist = *fHist; if (del) { fHist = NULL; fBackground = kBgdNone; } TCanvas *c=new TCanvas("c1", "", 1000, 1000); c->Divide(1,2); c->cd(1); TH2 *h=(TH2*)hist.DrawCopy(); TProfile *p = h->ProfileX("_pfx", -1, 9999, "s"); p->SetLineColor(kBlue); p->Draw("same"); p->SetBit(kCanDelete); c->cd(2); TH1F p2("spread", "Spread of the gear [16384/1500/4*U/U]", hist.GetNbinsX(), hist.GetBinLowEdge(1), hist.GetBinLowEdge(hist.GetNbinsX()+1)); p2.SetXTitle("ZA [\\circ]"); for (int i=0; iGetBinError(i)); p2.SetLineColor(kRed); p2.SetStats(0); p2.DrawCopy(); if (del) delete &hist; } // -------------------------------------------------------------------------- // // Start the work of the application: // // Start the Can-Network. // Start the MCosy::TalkThread thread. // turn on the gui update // void MCosy::Start() { // Don't call this function twice! Network::Start(); ReadConfig(); lout << "- Starting TX Thread." << endl; fTTalk = new MTTalk(this); lout << "- Starting GUI update." << endl; fUpdateGui->TurnOn(); } // -------------------------------------------------------------------------- // // Start the work of the application: // // Turn of the gui update // stop the MCosy::TalkThread thread. // Stop the network // void MCosy::Stop() { lout << "- Stopping GUI update." << endl; fUpdateGui->TurnOff(); lout << "- GUI Update stopped." << endl; delete fTTalk; lout << "- TX Thread stopped." << endl; Network::Stop(); } // -------------------------------------------------------------------------- // // Disable the synchronization by using a negative CAN Id for id2. // void MCosy::Constructor(Int_t id1, Int_t id2, Int_t id3, Int_t id4, Int_t id5, Int_t id6) { // // Create Nodes // lout << "- Setting up network." << endl; fMac1=new Macs(id1, "Mac/Az", lout); fMac2=new Macs(id3, "Mac/Zd", lout); if (id2>=0) fMac3=new Macs(id2, "Mac/Az-Sync", lout); fZd1=new ShaftEncoder(id4, "SE/Zd1", lout); fZd2=new ShaftEncoder(id5, "SE/Zd2", lout); fAz =new ShaftEncoder(id6, "SE/Az", lout); lout << "- Connecting devices to network." << endl; // // Connect the devices to the network // SetNode(fMac1); SetNode(fMac2); if (id2>=0) SetNode(fMac3); SetNode(fZd1); SetNode(fZd2); SetNode(fAz); // // Create Gui Event timer and Gui // lout << "- Initializing GUI Timer." << endl; fUpdateGui = new TTimer(this, 100); // 100ms lout << "- Starting GUI." << endl; fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1); } void MCosy::ConstructorSE(Int_t id4, Int_t id5, Int_t id6) { // // Create Nodes // lout << "- Setting up network." << endl; fZd1=new ShaftEncoder(id4, "SE/Zd1", lout); fZd2=new ShaftEncoder(id5, "SE/Zd2", lout); fAz =new ShaftEncoder(id6, "SE/Az", lout); lout << "- Connecting devices to network." << endl; // // Connect the devices to the network // SetNode(fZd1); SetNode(fZd2); SetNode(fAz); // // Create Gui Event timer and Gui // lout << "- Initializing GUI Timer." << endl; fUpdateGui = new TTimer(this, 100); // 100ms lout << "- Starting GUI." << endl; fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1); } void MCosy::ConstructorDemo() { // // Create Nodes // lout << "- Setting up network." << endl; // // Create Gui Event timer and Gui // lout << "- Initializing GUI Timer." << endl; fUpdateGui = new TTimer(this, 100); // 100ms lout << "- Starting GUI." << endl; fWin=new MGCosy(fObservatory, this, gClient->GetRoot(), 1, 1); } MCosy::MCosy(int mode, const char *dev, const int baud, MLog &out) : Network(dev, baud, out), fObservatory(MObservatory::kMagic1), fZd1(0), fZd2(0), fAz(0), fMac1(0), fMac2(0), fMac3(0), fBackground(kBgdNone) { TEnv env(".cosyrc"); const Int_t id1 = env.GetValue("Az_Id-MAC1", 1); //1 const Int_t id2 = env.GetValue("Az_Id-MAC2", 2); //2 const Int_t id3 = env.GetValue("Zd_Id-MAC", 3); //3 const Int_t id4 = env.GetValue("Zd_Id-SE1", 4); //4 const Int_t id5 = env.GetValue("Zd_Id-SE2", 5); //5 const Int_t id6 = env.GetValue("Az_Id-SE", 6); //6 lout << "- Program in "; switch (mode) { case 0: lout << "<>" << endl; fBending.Load("bending.txt"); Constructor(id1, id2, id3, id4, id5, id6); break; case 1: lout << "<>" << endl; fBending.Load("bending.txt"); ConstructorSE(id4, id5, id6); break; default: lout << "<>" << endl; ConstructorDemo(); } lout.SetOutputGui(fWin->GetLog(), kTRUE); fZd1->SetDisplay(fWin->GetLabel2()); fZd2->SetDisplay(fWin->GetLabel3()); fAz->SetDisplay(fWin->GetLabel1()); int i=0; char name[100]; while (1) { sprintf(name, "tpoint/tpoint%03d.txt", i++); if (gSystem->AccessPathName(name, kFileExists)) break; } Timer time; time.Now(); cout << "TPoint File ********* " << name << " ********** " << endl; tpout = new ofstream(name); *tpout << "Magic Model TPOINT data file" << endl; *tpout << ": ALTAZ" << endl; *tpout << "49 48 0 "; *tpout << time.Year() << " " << time.Month() << " " << time.Day() << " "; *tpout << /*"20 1013.25 300 0.5 0.55 0.0065" <<*/ endl; // temp(°C) pressure(mB) height(m) humidity(1) wavelength(microm) troplapserate(K/m) } void MCosy::TerminateApp() { cout << "MCosy::TerminateApp()" << endl; /* Int_t rc; TGMessageBox msg(this, gClient->GetRoot(), "Information", "Cosy is shutting down the system - this may take wa while!", kMBIconExclamation, kMBOK, //kMBClose &rc, 0); */ lout.DisableOutputDevice(MLog::eGui); // FIXME: WHY DOES THIS CRASH THE APPLICATIOn WHILE TRAKING? // lout.SetOutputGui(NULL, kFALSE); gApplication->Terminate(0); } MCosy::~MCosy() { *tpout << "END" << endl; delete tpout; cout << "Deleting GUI timer." << endl; delete fUpdateGui; cout << "Deleting Nodes." << endl; delete fAz; delete fZd1; delete fZd2; delete fMac1; delete fMac2; if (fMac3) delete fMac3; cout << "Deleting MGCosy." << endl; lout.DisableOutputDevice(MLog::eGui); delete fWin; cout << "MGCosy destructed." << endl; }