/** * \brief Move Focuser to a given position * * This method ensures that the movement always comes from the same side. * If the current position below the new position, nothing needs to be * done. If however the current position is above the new position then * the focuser is first moved to the target position minus the backlash * amount before being moved to the target position. */ void FocusWork::moveto(unsigned short position) { // ensure we are inside the interval if (position < min()) { throw std::runtime_error("internal error: Focuser move below min"); } if (position > max()) { throw std::runtime_error("interval error: focuser move above max()"); } // switch state to moving focusingstatus(Focusing::MOVING); // check whether backlash compensation is needed if ((backlash() > 0) && (focuser()->current() > position)) { unsigned short compensated = position - backlash(); if (position < backlash()) { debug(LOG_WARNING, DEBUG_LOG, 0, "not enough room for backlash: current = %hu, " "position = %hu, backlash = %hu", focuser()->current(), position, backlash()); compensated = 0; } debug(LOG_DEBUG, DEBUG_LOG, 0, "moving to compensated position: %hu", compensated); focuser()->moveto(compensated); } // now move to the final position debug(LOG_DEBUG, DEBUG_LOG, 0, "move to final position: %hu", position); focuser()->moveto(position); }
/** * \brief Find backlash amount from Focuser */ unsigned short FocusWork::backlash() { return (focuser()) ? focuser()->backlash() : 0; }
/** * \brief Main function of the Focusing process */ void VCurveFocusWork::main(astro::thread::Thread<FocusWork>& /* thread */) { debug(LOG_DEBUG, DEBUG_LOG, 0, "start focusing work"); if (!complete()) { focusingstatus(Focusing::FAILED); throw std::runtime_error("focuser not completely specified"); } FocusCompute fc; // determine how many intermediate steps we want to access if (min() < focuser()->min()) { throw std::runtime_error("minimum too small"); } // based on the exposure specification, build an evaluator ImageSize size = exposure().size(); int radius = std::min(size.width(), size.height()) / 2; FWHM2Evaluator evaluator(size.center(), radius); unsigned long delta = max() - min(); for (int i = 0; i < steps(); i++) { // compute new position unsigned short position = min() + (i * delta) / (steps() - 1); debug(LOG_DEBUG, DEBUG_LOG, 0, "measuring position %hu", position); // move to new position moveto(position); // get an image from the Ccd focusingstatus(Focusing::MEASURING); ccd()->startExposure(exposure()); usleep(1000000 * exposure().exposuretime()); ccd()->wait(); ImagePtr image = ccd()->getImage(); // turn the image into a value FWHMInfo fwhminfo = focusFWHM2_extended(image, size.center(), radius); double value = fwhminfo.radius; // add the new value fc.insert(std::pair<unsigned short, double>(position, value)); // send the callback data callback(combine(image, fwhminfo), position, value); } // compute the best focus position double focusposition = 0; try { focusposition = fc.focus(); } catch (std::exception& x) { debug(LOG_DEBUG, DEBUG_LOG, 0, "no optimal focus position: %s", x.what()); focusingstatus(Focusing::FAILED); return; } debug(LOG_DEBUG, DEBUG_LOG, 0, "optimal focus position: %f", focusposition); // plausibility check for the position if (!((focusposition >= min()) && (focusposition <= max()))) { focusingstatus(Focusing::FAILED); debug(LOG_DEBUG, DEBUG_LOG, 0, "focusing failed"); return; } // move to the focus position unsigned short targetposition = focusposition; moveto(targetposition); focusingstatus(Focusing::FOCUSED); debug(LOG_DEBUG, DEBUG_LOG, 0, "target position reached"); }