/** * \brief Perform a measurement at a certain focus position */ FocusValue MeasureFocusWork::measureat(unsigned short pos) { debug(LOG_DEBUG, DEBUG_LOG, 0, "measurement at pos = %hu", pos); // move to the position focusingstatus(Focusing::MOVING); moveto(pos); // get an image focusingstatus(Focusing::MEASURING); ccd()->startExposure(exposure()); ccd()->wait(); ImagePtr image = ccd()->getImage(); // evaluate the image MeasureEvaluator evaluator; double value = evaluator(image); debug(LOG_DEBUG, DEBUG_LOG, 0, "pos = %hu, value = %g(%f)", pos, value, log10(value)); // call the callback callback(evaluator.evaluated_image(), pos, value); // return the focus information return FocusValue(pos, value); }
/** * \brief default main function for focusing */ void FocusWork::main(astro::thread::Thread<FocusWork>& thread) { if (!complete()) { debug(LOG_ERR, DEBUG_LOG, 0, "FocusWork is not completely configured"); focusingstatus(Focusing::FAILED); return; } debug(LOG_DEBUG, DEBUG_LOG, 0, "starting focus process in [%d,%d]", min(), max()); // prepare the set of focus items to base the focus computation on FocusItems focusitems; // prepare for (int step = 0; step < steps(); step++) { // find position unsigned short position = min() + (step * (max() - min())) / (steps() - 1); debug(LOG_DEBUG, DEBUG_LOG, 0, "next position: %hu", position); // move to this position moveto(position); // get an image focusingstatus(Focusing::MEASURING); ccd()->startExposure(exposure()); usleep(1000000 * exposure().exposuretime()); ccd()->wait(); ImagePtr image = ccd()->getImage(); debug(LOG_DEBUG, DEBUG_LOG, 0, "got an image of size %s", image->size().toString().c_str()); // evaluate the image double value = (*evaluator())(image); debug(LOG_DEBUG, DEBUG_LOG, 0, "evaluated to %f", value); // callback with the evaluated image callback(evaluator()->evaluated_image(), position, value); // add the information to a set focusitems.insert(FocusItem(position, value)); } // now solve we need a suitable solver for the method int targetposition = solver()->position(focusitems); if ((targetposition < min()) || (targetposition > max())) { std::string msg = stringprintf( "could not find a focus position: %d", targetposition); debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str()); focusingstatus(Focusing::FAILED); return; } // move to the final focus position focusingstatus(Focusing::MOVING); moveto(targetposition); focusingstatus(Focusing::FOCUSED); }
/** * \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 Main function of the Focusing process */ void MeasureFocusWork::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"); } counter = 0; // move to the minimum debug(LOG_DEBUG, DEBUG_LOG, 0, "measure left end of interval: %hu", min()); FocusValue left = measureat(min()); FocusValue right = measureat(max()); // perform measurements at both ends of the interval FocusInterval interval(left, right); // perform subdivisions double resolution = (max() - min()) / pow(2, steps()); debug(LOG_DEBUG, DEBUG_LOG, 0, "target resolution: %f", resolution); std::list<FocusInterval> intervals; intervals.push_back(interval); try { while (interval.length() > resolution) { try { interval = subdivide(interval); intervals.push_back(interval); } catch (wronginterval) { debug(LOG_DEBUG, DEBUG_LOG, 0, "retrying other interval"); intervals.pop_back(); interval = *intervals.rbegin() - interval; intervals.push_back(interval); } debug(LOG_DEBUG, DEBUG_LOG, 0, "new interval: %s", interval.toString().c_str()); } focusingstatus(Focusing::FOCUSED); } catch (std::exception& x) { debug(LOG_DEBUG, DEBUG_LOG, 0, "focus failed: %s", x.what()); focusingstatus(Focusing::FAILED); } catch (...) { debug(LOG_DEBUG, DEBUG_LOG, 0, "unknown exception during focus"); focusingstatus(Focusing::FAILED); } }
/** * \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"); }