bool REIXSSpectrometer::stop() { if(!canStop()) return false; if(moveInProgress()) { moveAction_->cancel(); /// \todo Actually, have to flag that a stop has started, and also catch when the stop is finished... Motors will take a while to actually receive and decelerate. moveAction_->deleteLater(); moveAction_ = 0; emit moveFailed(AMControl::WasStoppedFailure); AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, AMControl::WasStoppedFailure, "Spectrometer Move Stopped.")); } // just in case anything was moving from outside our instructions (ie: commanded from somewhere else in the building) spectrometerRotationDrive_->stop(); detectorTranslation_->stop(); detectorTiltDrive_->stop(); endstationTranslation_->stop(); // hexapod: cannot stop without wrecking init. Don't worry for now... just let it stop over time. Not necessary for it to be not-moving before we re-send it somewhere new. /// \todo Actually, have to flag that a stop has started, and also catch when the stop is finished... Motors will take a while to actually receive and decelerate. return true; }
void BioXASZebraTimeSeconds::updateValue() { if (canMeasure() && !moveInProgress()) { double newValue = convertTimeValue(timeValue_->value(), timeUnits_->value(), Seconds); setValue(newValue); } }
// Start a move to the value setpoint: AMControl::FailureExplanation CLSMDriveMotorControl::move(double Setpoint) { if(isMoving()) { if(!allowsMovesWhileMoving()) { AMErrorMon::debug(this, AMPVCONTROL_COULD_NOT_MOVE_WHILE_MOVING, QString("AMPVControl: Could not move %1 (%2) to %3, because the control is already moving.").arg(name()).arg(writePV_->pvName()).arg(setpoint_)); return AlreadyMovingFailure; } if(!moveInProgress()) { // the control is already moving, but it's not one of our moves. In this situation, there is no way that we can start a move and be assured that we'll be notified when OUR move finishes. AMErrorMon::debug(this, AMPVCONTROL_COULD_NOT_MOVE_WHILE_MOVING_EXTERNAL, QString("AMPVControl: Could not move %1 (%2) to %3, because the control is already moving.").arg(name()).arg(writePV_->pvName()).arg(setpoint_)); return AlreadyMovingFailure; } // Otherwise: This control supports mid-move updates, and we're already moving. We just need to update the setpoint and send it. setpoint_ = writeUnitConverter()->convertToRaw(Setpoint); writePV_->setValue(setpoint_); // since the settling phase is considered part of a move, it's OK to be here while settling... But for Acquaman purposes, this will be considered a single re-targetted move, even though the hardware will see two. If we're settling, disable the settling timer, because we only want to respond to the end of the second move. if(settlingInProgress_) { settlingInProgress_ = false; settlingTimer_.stop(); } emit moveReTargetted(); // re-targetted moves will emit moveReTargetted(), although no moveSucceeded()/moveFailed() will be issued for the initial move. } else { settlingInProgress_ = false; stopInProgress_ = false; moveInProgress_ = false; // Flag that "our" move started: startInProgress_ = true; // This is our new target: setpoint_ = writeUnitConverter()->convertToRaw(Setpoint); // Special case: "null move" should complete immediately. Use only if moveStartTolerance() is non-zero, and the move distance is within moveStartTolerance(). if(moveStartTolerance() != 0 && fabs(setpoint()-value()) < moveStartTolerance()) { startInProgress_ = false; moveInProgress_ = true; emit moveStarted(); moveInProgress_ = false; emit moveSucceeded(); } // Normal move: else { // Issue the move command: writePV_->setValue(setpoint_); // start the timer to check if our move failed to start: moveStartTimer_.start(int(moveStartTimeout_*1000.0)); } } return NoFailure; }
AMControl::FailureExplanation REIXSSpectrometer::move(double setpoint) { if(!isConnected()) { AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, 2, "Can't move the spectrometer: some motor controls are not connected. Check that the IOCs are running and the network connections are good.")); return NotConnectedFailure; } // can't start a move while moving if(moveInProgress() || isMoving()) { AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, 2, "Can't move the spectrometer, because it's already moving. Stop the spectrometer first before attempting another move.")); return AlreadyMovingFailure; } specifiedEV_ = setpoint; currentFocusOffset_ = specifiedFocusOffset_; currentDetectorTiltOffset_ = specifiedDetectorTiltOffset_; if(currentGrating_ != specifiedGrating_) { emit gratingChanged(currentGrating_ = specifiedGrating_); } /// \todo limits? out of range? moveSetpoint_ = calibration_.computeSpectrometerPosition(specifiedGrating_, specifiedEV_, currentFocusOffset_, currentDetectorTiltOffset_); // build the move action (With sub-actions to run in parallel) moveAction_ = new AMListAction3(new AMListActionInfo3("spectrometer eV move", "spectrometer eV move"), AMListAction3::Parallel, this); // if we need to move the grating into position, add actions for that: if(!gratingInPosition()) { // make a sequential action for the grating moves AMListAction3* gratingAction = new AMListAction3(new AMListActionInfo3("grating move", "grating move")); // sequential by default. // first, move Z to 0 gratingAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->z(), 0)); // then move U,V,W to 0 AMListAction3* uvw0Action = new AMListAction3(new AMListActionInfo3("grating UVW move to 0"), AMListAction3::Parallel); uvw0Action->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->u(), 0)); uvw0Action->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->v(), 0)); uvw0Action->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->w(), 0)); gratingAction->addSubAction(uvw0Action); // then move R,S,T into position (Can do simultaneously with parallel action) AMListAction3* rstAction = new AMListAction3(new AMListActionInfo3("grating RST move"), AMListAction3::Parallel); rstAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->r(), moveSetpoint_.controlNamed("hexapodR").value())); rstAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->s(), moveSetpoint_.controlNamed("hexapodS").value())); rstAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->t(), moveSetpoint_.controlNamed("hexapodT").value())); gratingAction->addSubAction(rstAction); // move U,V,W to actual position AMListAction3* uvwAction = new AMListAction3(new AMListActionInfo3("grating UVW move"), AMListAction3::Parallel); uvwAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->u(), moveSetpoint_.controlNamed("hexapodU").value())); uvwAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->v(), moveSetpoint_.controlNamed("hexapodV").value())); uvwAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->w(), moveSetpoint_.controlNamed("hexapodW").value())); gratingAction->addSubAction(uvwAction); // then move X,Y,Z into position (can do simultaneously with parallel action) AMListAction3* xyzAction = new AMListAction3(new AMListActionInfo3("grating XYZ move"), AMListAction3::Parallel); xyzAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->x(), moveSetpoint_.controlNamed("hexapodX").value())); xyzAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->y(), moveSetpoint_.controlNamed("hexapodY").value())); xyzAction->addSubAction(AMActionSupport::buildControlMoveAction(hexapod_->z(), moveSetpoint_.controlNamed("hexapodZ").value())); gratingAction->addSubAction(xyzAction); moveAction_->addSubAction(gratingAction); } // add Lift, Tilt, and Translation moveAction_->addSubAction(AMActionSupport::buildControlMoveAction(spectrometerRotationDrive_, moveSetpoint_.controlNamed("spectrometerRotationDrive").value())); moveAction_->addSubAction(AMActionSupport::buildControlMoveAction(detectorTiltDrive_, moveSetpoint_.controlNamed("detectorTiltDrive").value())); moveAction_->addSubAction(AMActionSupport::buildControlMoveAction(detectorTranslation_, moveSetpoint_.controlNamed("detectorTranslation").value())); // Disabled for now: moveAction_->addSubAction(new AMInternalControlMoveAction(endstationTranslation_, moveSetpoint_.controlNamed("endstationTranslation").value())) // Watch the move action: succeeded or failed (or cancelled) connect(moveAction_, SIGNAL(stateChanged(int,int)), this, SLOT(onMoveActionStateChanged(int,int))); emit moveStarted(); moveAction_->start(); return NoFailure; }