//------------------------------------------------------------------------------ // conicalScanController() -- controls the conical scans //------------------------------------------------------------------------------ void ScanGimbal::conicalScanController(const double dt) { double degPerDT = (getRevPerSec() * 360.0) * dt; static Basic::Integer iBar(1); switch(getScanState()) { // reset state: move to ref position case 0: { setServoMode(POSITION_SERVO); setFastSlewMode(true); setScanState(1); setConAngle(0); } break; case 1: { // wait state if (isPositioned() || isAtLimits()) { setScanState(2); // out of state 1 } break;// fall into state 2 } case 2: { // start scan setFastSlewMode(false); setConAngle( Basic::Angle::aepcdDeg(degPerDT + getConAngle()) ); // Trigger the SCAN_START event handler onStartScanEvent(&iBar); setScanState(3); } break; case 3: { // turn revolutions per second into degrees per sec per frame // now we get this to each time step double conAngleN1 = getConAngle(); setConAngle( Basic::Angle::aepcdDeg(degPerDT + getConAngle()) ); // end scan - finished with one rotation, check if our reference has moved bool onceAround = false; // clockwise rotation if (getRevPerSec() >= 0.0) { if (conAngleN1 < 0.0 && getConAngle() >= 0.0) { onceAround = true; } } // counter-clockwise rotation else { if (conAngleN1 < 0.0 && getConAngle() >= 0.0) { setConAngle(0); onceAround = true; } } // after one revolution if (onceAround) { // Trigger the SCAN_END event handler onEndScanEvent(&iBar); setScanState(2); } } break; } // azimuth double newX = getScanRadius() * sin(getConAngle() * Basic::Angle::D2RCC); // elevation double newY = getScanRadius() * cos(getConAngle() * Basic::Angle::D2RCC); setScanPos(newX, newY); // command our new position setCmdPos(getRefPosition() + getScanPos()); }
//------------------------------------------------------------------------------ // spiralScanController() -- controls the spiral scan //------------------------------------------------------------------------------ void ScanGimbal::spiralScanController(const double dt) { double degPerDT = (getRevPerSec() * 360.0) * dt; static Basic::Integer iBar(1); switch(getScanState()) { // reset state: move to ref position case 0: { setServoMode(POSITION_SERVO); setFastSlewMode(true); setScanState(1); setConAngle(0); setNumRevs(0.0); } break; case 1: { // wait state if (isPositioned() || isAtLimits()) { setScanState(2); // out of state 1 } break;// fall into state 2 } case 2: { // start scan setFastSlewMode(false); setConAngle(getConAngle() + degPerDT); if (fabs(getConAngle()) > 360.0) { setNumRevs(getNumRevs()+1); if (getConAngle() >= 0.0) { setConAngle(getConAngle() - 360.0); } else { setConAngle(getConAngle() + 360.0); } } // Trigger the SCAN_START event handler onStartScanEvent(&iBar); setScanState(3); } break; case 3: { // turn revolutions per second into degrees per sec per frame // now we get this to each time step setConAngle(getConAngle() + degPerDT); if (fabs(getConAngle()) > 360.0) { setNumRevs(getNumRevs()+1); if (getConAngle() >= 0.0) { setConAngle(getConAngle() - 360.0); } else { setConAngle(getConAngle() + 360.0); } } // end scan - finished with one rotation, check if our reference has moved bool onceAround = false; if (getNumRevs() >= getMaxNumRevs()) { onceAround = true; } // after one revolution if (onceAround) { // Trigger the SCAN_END event handler onEndScanEvent(&iBar); setConAngle(0.0); setNumRevs(0.0); setScanState(2); } } break; } double fullAngleRadians = getNumRevs() * 360.0; if (getRevPerSec() < 0.0) { fullAngleRadians = -fullAngleRadians; } fullAngleRadians = (fullAngleRadians + getConAngle()) * Basic::Angle::D2RCC; // azimuth double newX = getScanRadius() * (fullAngleRadians / (2.0 * PI)) * sin(fullAngleRadians); // elevation double newY = getScanRadius() * (fullAngleRadians / (2.0 * PI)) * cos(fullAngleRadians); setScanPos(newX, newY); // command our new position setCmdPos(getRefPosition() + getScanPos()); }
//------------------------------------------------------------------------------ // serialize //------------------------------------------------------------------------------ std::ostream& ScanGimbal::serialize(std::ostream& sout, const int i, const bool slotsOnly) const { int j = 0; if ( !slotsOnly ) { indent(sout,i); sout << "( " << getFactoryName() << std::endl; j = 4; } // scanMode: Sets the type of scan we desire (manual, horizontal, vertical, conical, circular, pseudorandom) indent(sout,i+j); if (scanMode == MANUAL_SCAN) sout << "scanMode: manual // scan type (manual, horizontal, vertical, conical, circular, pseudorandom)" << std::endl; else if (scanMode == HORIZONTAL_BAR_SCAN) sout << "scanMode: horizontal // scan type (manual, horizontal, vertical, conical, circular, pseudorandom)" << std::endl; else if (scanMode == VERTICAL_BAR_SCAN) sout << "scanMode: vertical // scan type (manual, horizontal, vertical, conical, circular, pseudorandom)" << std::endl; else if (scanMode == CONICAL_SCAN) sout << "scanMode: conical // scan type (manual, horizontal, vertical, conical, circular, pseudorandom)" << std::endl; else if (scanMode == CIRCULAR_SCAN) sout << "scanMode: circular // scan type (manual, horizontal, vertical, conical, circular, pseudorandom)" << std::endl; else if (scanMode == PSEUDO_RANDOM_SCAN) sout << "scanMode: pseudorandom // scan type (manual, horizontal, vertical, conical, circular, pseudorandom)" << std::endl; else if (scanMode == SPIRAL_SCAN) sout << "scanMode: spiral // scan type (manual, horizontal, vertical, conical, circular, pseudorandom)" << std::endl; // leftToRightScan: True to scan from left to right (else right to left) (Default: true) (up to down or down to up) indent(sout,i+j); if (leftToRightScan) { sout << "leftToRightScan: true // Right to left or left to right; up to down or down to up" << std::endl; } else { sout << "leftToRightScan: false // Right to left or left to right; up to down or down to up" << std::endl; } // scanWidth: Width of the scan (for search volume, or if specified manually) indent(sout,i+j); sout << "scanWidth: " << scanWidth << std::endl; // searchVolume: Scan width & height; sets HORIZONTAL_BAR_SCAN mode (radians) indent(sout,i+j); sout << "searchVolume: [ "; sout << scanWidth << " " << scanHeight; sout << " ]" << std::endl; // reference: Reference angles (center of the search volume) indent(sout,i+j); sout << "reference: [ "; sout << getRefAzimuth() << " " << getRefElevation(); sout << " ]" << std::endl; // barSpacing: Scan bar width spacing (radians) indent(sout,i+j); sout << "barSpacing: " << barSpacing << std::endl; // numBars: Sets the number of bars indent(sout,i+j); sout << "numBars: " << numBars << std::endl; // revolutionsPerSec: Revolutions per second for conical and circular scans (spiral scan too) indent(sout,i+j); sout << "revolutionsPerSec: " << getRevPerSec() << std::endl; // scanRadius: Radius of the circle we are using for conical scans (radians or Basic::Angle} (spiral scan too) indent(sout,i+j); sout << "scanRadius: " << scanRadius << " \t\t // WARNING or INFO:This is really a beam width or half beam width, not a radius!" << std::endl; // pseudoRandomPattern: Pseudo Random pattern vertices (2D - az and el) if (nprv > 0) { indent(sout,i+j); sout << "pseudoRandomPattern: { "; for (unsigned int ii = 0; ii < nprv; ii++) { sout << " [ " << prScanVertices[ii].x() << " " << prScanVertices[ii].y() << " ]" << std::endl; } sout << "} " << std::endl; } // maxRevolutions: Spiral Scan - Maximum number of revolutions indent(sout,i+j); sout << "maxRevolutions: " << maxNumRevs << std::endl; BaseClass::serialize(sout,i+j,true); if ( !slotsOnly ) { indent(sout,i); sout << ")" << std::endl; } return sout; }