void AMCompositeControl::onChildControlMovingChanged()
{
	bool nowMoving = isMoving();

	if(wasMoving_ && !nowMoving)
		emit movingChanged(wasMoving_ = nowMoving);

	if(!wasMoving_ && nowMoving)
		emit movingChanged(wasMoving_ = nowMoving);
}
示例#2
0
void AMPVwStatusControl::onSettlingTimeFinished()
{
	settlingTimer_.stop();

	if(!settlingInProgress_) {
		// temporary, for settling state testing:
		qWarning() << "AMPVwStatusControl:" << name() << ": Settling timeout while settlingInProgress is not true.  This should never happen; please report this bug.";
		return;
	}

	settlingInProgress_ = false;

	if(moveInProgress_) {
		moveInProgress_ = false;
		// Check if we succeeded...
		if(inPosition()) {
			emit moveSucceeded();
		}
		else {
			emit moveFailed(AMControl::ToleranceFailure);
		}
	}
	else {
		// temporary, for settling state testing:
		qWarning() << "AMPVwStatusControl: " << name() << ": Settling time reached while moveInProgress_  == false. This should never happen; please report this bug.";
	}

	// possible that a change in settlingInProgress_ caused isMoving() to change. Emit signal if necessary:
	bool nowMoving = isMoving();
	if(nowMoving != wasMoving_)
		emit movingChanged(wasMoving_ = nowMoving);
}
示例#3
0
// This is called whenever there is an update from the move status PV
// In it we simply do change detection of the moving status, and emit signals if it has changed.
void AMReadOnlyPVwStatusControl::onMovingChanged(int movingValue) {

	bool nowMoving = (*statusChecker_)(movingValue);

	if(wasMoving_ != nowMoving)
		emit movingChanged(wasMoving_ = nowMoving);
}
示例#4
0
// This is used to check every new value, to see if we entered tolerance:
void AMPVControl::onNewFeedbackValue(double) {

	// If we're not in the middle of a move, don't really care about changing values.
	if(!moveInProgress_)
		return;

	// Did we make it?
	if( inPosition() ) {
		// move is now done:
		emit movingChanged(moveInProgress_ = false);
		// disable the timer, so it doesn't trigger an error later
		completionTimer_.stop();
		// let everyone know we succeeded:
		emit moveSucceeded();

	}
}
示例#5
0
// This is used to handle the timeout of a move:
void AMPVControl::onCompletionTimeout() {

	// if we weren't moving, this shouldn't have happened. someone forgot to shutoff the timer?
	// todo: this is only included for state testing debugging... can remove if never happens
	if(!moveInProgress_) {
		return;
	}

	// No matter what, this move is over:
	emit movingChanged(moveInProgress_ = false);
	completionTimer_.stop();

	// Did we make it?
	if( inPosition() ) {
		emit moveSucceeded();
	}
	// Didn't make it into position:
	else {
		emit moveFailed(AMControl::TimeoutFailure);
	}
}
示例#6
0
// Re-implemented from AMReadOnlyPVwStatusControl:
void AMPVwStatusControl::onMovingChanged(int isMovingValue) {

	bool nowMoving = (*statusChecker_)(isMovingValue);	// according to the hardware.  For checking moveSucceeded/moveStarted/moveFailed, use the value delivered in the signal argument, instead of re-checking the PV, in case we respond late and the hardware has already changed again.

	// In case the hardware is being silly and sending multiple MOVE ACTIVE, MOVE ACTIVE, MOVE ACTIVE states in a row, or MOVE DONE, MOVE DONE, MOVE DONE states in a row: only act on changes. [Edge detection]
	if(nowMoving == hardwareWasMoving_)
		return;

	hardwareWasMoving_ = nowMoving;

	// moveStarted, moveFailed, moveSucceeded, or transition to settling:
	///////////////////////////////////////////////////////////////////////

	// if we requested one of our moves, and moving just started:
	if(startInProgress_ && nowMoving) {
		moveInProgress_ = true;
		startInProgress_ = false;
		// This is great... the device started moving within the timeout:

		// disable the moveStartTimer, we don't need it anymore
		moveStartTimer_.stop();

		emit moveStarted();
	}

	// If one of our moves was running, and we stopped moving:
	if(moveInProgress_ && !nowMoving) {

		// Mode 1: No settling:
		if( settlingTime_ == 0.0) {
			// That's the end of our move
			moveInProgress_ = false;

			// Check if we succeeded...
			if(inPosition()) {
				emit moveSucceeded();

			} else {
				emit moveFailed(AMControl::ToleranceFailure);

			}
		}
		// Mode 2: allow settling
		else {
			if(!settlingInProgress_) {
				settlingInProgress_ = true;
				settlingTimer_.start(int(settlingTime_*1000)); // QTimer uses millisecond time intervals.
			}
		}
	}

	// "sucessfully" stopped due to a stop() command.
	if(stopInProgress_ && !nowMoving) {
		stopInProgress_ = false;
		// but the move itself has failed, due to a stop() intervention.
		emit moveFailed(AMControl::WasStoppedFailure);
	}



	// Emitting movingChanged().
	/////////////////////////////////////

	// For external purposes, isMoving() depends on whether the hardware says we're moving, or we're in the settling phase.
	nowMoving = isMoving();

	if(nowMoving != wasMoving_)
		emit movingChanged(wasMoving_ = nowMoving);
}
示例#7
0
// Start a move to the value setpoint:
AMControl::FailureExplanation AMPVControl::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;
		}

		// assuming this control can accept mid-move updates. We just need to update our setpoint and send it.

		if(!canMove()) {	// this would be rare: a past move worked, but now we're no longer connected?
			AMErrorMon::debug(this, AMPVCONTROL_COULD_NOT_MOVE_BASED_ON_CANMOVE, QString("AMPVControl: Could not move %1 (%2) to %3.").arg(name()).arg(writePV_->pvName()).arg(setpoint_));
			return NotConnectedFailure;
		}
		setpoint_ = setpoint;
		writePV_->setValue(setpoint_);
		completionTimer_.start(int(completionTimeout_*1000.0)); // restart the completion timer... Since this might be another move, give it some more time.
		// re-targetted moves will emit moveReTargetted(), although no moveSucceeded()/moveFailed() will be issued for the first move.
		emit moveReTargetted();

		// check for done:
		if(inPosition()) {
			completionTimer_.stop();
			emit movingChanged(moveInProgress_ = false);
			emit moveSucceeded();
		}
	}

	// Regular case: start of a new move.
	else {
		// kill any old countdowns:
		completionTimer_.stop();

		if(!canMove()) {
			AMErrorMon::debug(this, AMPVCONTROL_COULD_NOT_MOVE_BASED_ON_CANMOVE, QString("AMPVControl: Could not move %1 (%2) to %3.").arg(name()).arg(writePV_->pvName()).arg(setpoint_));
			return NotConnectedFailure;
		}

		// new move target:
		setpoint_ = setpoint;
		// Issue the move, check on attemptMoveWhenWithinTolerance
		if(!attemptMoveWhenWithinTolerance_ && inPosition()){
			emit moveSucceeded();
		}
		else{
			writePV_->setValue(setpoint_);

			// We're now moving! Let's hope this control makes it... (No way to actually check.)
			emit movingChanged(moveInProgress_ = true);
			// emit the signal that we started:
			emit moveStarted();

			// Are we in-position? [With the default tolerance of AMCONTROL_TOLERANCE_DONT_CARE, we will always be in-position, and moves will complete right away, that's the intended behaviour, because we have no other way of knowing when they'll finish.]
			if(inPosition()) {
				emit movingChanged(moveInProgress_ = false);
				emit moveSucceeded();
			}
			else {
				// start the countdown to see if we get there in time or stall out: (completionTimeout_ is in seconds)
				completionTimer_.start(int(completionTimeout_*1000.0));
			}
		}
	}
	return NoFailure;
}