Cancel homing and shut down cleanly when the program is stopped during homing
This commit is contained in:
parent
9f02b70dae
commit
eb91f470dd
|
|
@ -722,7 +722,8 @@ It is modular (`test gimbal`, `test imu drift`, `test host`, …) and driven by
|
|||
**profiles** configured under `[Test]` / `[TestProfile.<name>]` in `config.ini`
|
||||
(repetition counts, sampling windows, pass thresholds; default `standard`). While a
|
||||
test (or calibration, or homing) runs, interfering commands are ignored and **Esc**
|
||||
cancels. Full reference: [test-command.md](test-command.md). Replaces the former
|
||||
cancels. A stop is not ignored: `exit`, Ctrl-C or SIGTERM (`scripts/fgc stop`) during homing
|
||||
cancels the homing, as Esc does, and shuts the program down. Full reference: [test-command.md](test-command.md). Replaces the former
|
||||
`gimbal diag` (now folded into `test gimbal encoder`).
|
||||
|
||||
## Terminal dashboard (TUI)
|
||||
|
|
|
|||
|
|
@ -146,8 +146,11 @@ it is shown dimmed.
|
|||
|
||||
`scripts/fgc stop` sends SIGTERM and waits up to 120 s; the program handles it
|
||||
with the same shutdown path as the `exit` command (stop capture, close the
|
||||
camera, flush the image queue). Do **not** `kill -9` - an unclean exit leaves the
|
||||
camera wedged for the next run. If it will not stop, attach and look at why.
|
||||
camera, flush the image queue). A stop while the gimbal is homing cancels the
|
||||
homing rather than waiting for it - a full home takes minutes on some towers,
|
||||
longer than this wait - so the gimbal is left un-homed, and the next start homes
|
||||
it again. Do **not** `kill -9` - an unclean exit leaves the camera wedged for the
|
||||
next run. If it will not stop, attach and look at why.
|
||||
|
||||
`scripts/fgc start` refuses if a run is already up, and prints the previous
|
||||
run's last output if it died rather than silently discarding it.
|
||||
|
|
|
|||
|
|
@ -84,8 +84,18 @@ constexpr long kEncoderQuantumCounts = 13;
|
|||
// (StopContinuousImageAcquisition + Close). Without this, a Ctrl-C / kill / systemd
|
||||
// stop skips teardown and leaves the camera acquiring - which wedges it so the NEXT
|
||||
// run gets no frames. Only an atomic flag is set here (async-signal-safe).
|
||||
//
|
||||
// Installed as the very first thing run() does, so a stop that arrives while the
|
||||
// camera opens or the gimbal homes is not the default action - which kills the
|
||||
// process on the spot and wedges the camera. A second signal of the same kind
|
||||
// goes back to that default: Ctrl-C twice still gets out of a start that hangs.
|
||||
std::atomic<bool> g_shutdown_requested{false};
|
||||
void handleShutdownSignal(int) { g_shutdown_requested.store(true); }
|
||||
void handleShutdownSignal(int sig) {
|
||||
if (g_shutdown_requested.exchange(true)) {
|
||||
std::signal(sig, SIG_DFL);
|
||||
std::raise(sig);
|
||||
}
|
||||
}
|
||||
|
||||
long long nowEpochMs() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
|
|
@ -1195,6 +1205,12 @@ struct Application::Impl {
|
|||
}
|
||||
}
|
||||
|
||||
// A stop that came in while the program was starting up: do not begin a
|
||||
// home that would only be cancelled.
|
||||
if (shutdownRequested()) {
|
||||
LOG_INFO << "stop requested: not homing";
|
||||
return;
|
||||
}
|
||||
motor->sendCommand("HOME"); // homes all axes; firmware runs it non-blocking
|
||||
|
||||
auto allReady = [](const MotorTelemetry& t) {
|
||||
|
|
@ -2494,11 +2510,27 @@ struct Application::Impl {
|
|||
Command c = parseCommand(line);
|
||||
if (c.verb == "cancel" || (c.verb == "mode" && c.device == "manual"))
|
||||
cancel_procedure_ = true;
|
||||
else if (c.verb == "exit")
|
||||
running = false; // not an interfering command: a stop
|
||||
else if (!c.empty())
|
||||
LOG_WARN << "ignored '" << c.verb << "': homing in progress (Esc to cancel)";
|
||||
local.pop();
|
||||
}
|
||||
// A stop cancels homing, as Esc does, rather than waiting for it to finish:
|
||||
// a full home takes minutes on some towers - longer than `fgc stop` (120 s)
|
||||
// and systemd (150 s) wait before giving up or killing the program outright,
|
||||
// which wedges the camera. Dropping the stop instead, as this once did, left
|
||||
// the program running with its dashboard already closed.
|
||||
if (shutdownRequested() && !cancel_procedure_) {
|
||||
LOG_INFO << "stop requested: cancelling homing to shut down";
|
||||
cancel_procedure_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
// A stop asked for in any of the ways there are: the `exit` command - which is
|
||||
// also what the dashboard sends when it closes, on Ctrl-C and SIGTERM too - or
|
||||
// SIGINT/SIGTERM caught by handleShutdownSignal() when there is no dashboard.
|
||||
bool shutdownRequested() const { return !running || g_shutdown_requested.load(); }
|
||||
|
||||
// ---- `test` command ----
|
||||
static std::string lowerStr(std::string s) {
|
||||
|
|
@ -2977,6 +3009,14 @@ struct Application::Impl {
|
|||
int run() {
|
||||
start_time = std::chrono::steady_clock::now();
|
||||
|
||||
// Clean up on Ctrl-C / kill / systemd stop, not just on "exit"/Ctrl-D - so the
|
||||
// camera is always stopped and closed (an unclean exit wedges it for next time).
|
||||
// First, before anything slow: homing alone takes minutes on some towers.
|
||||
// The TUI's own handler takes over while the dashboard runs (it turns the
|
||||
// signal into "exit") and puts this one back when the dashboard closes.
|
||||
std::signal(SIGINT, handleShutdownSignal);
|
||||
std::signal(SIGTERM, handleShutdownSignal);
|
||||
|
||||
// Log level: config first, CLI overrides.
|
||||
if (!cfg.logging.level.empty() && !Logger::setLevelFromString(cfg.logging.level))
|
||||
LOG_WARN << "unknown Logging.level '" << cfg.logging.level << "', keeping default";
|
||||
|
|
@ -3162,12 +3202,8 @@ struct Application::Impl {
|
|||
sendAnchorConfig();
|
||||
applyHomedTravel();
|
||||
}
|
||||
if (start_in != Mode::Manual) setMode(start_in);
|
||||
|
||||
// Clean up on Ctrl-C / kill / systemd stop, not just on "exit"/Ctrl-D - so the
|
||||
// camera is always stopped and closed (an unclean exit wedges it for next time).
|
||||
std::signal(SIGINT, handleShutdownSignal);
|
||||
std::signal(SIGTERM, handleShutdownSignal);
|
||||
// A stop that came in during homing: do not start sweeping on the way out.
|
||||
if (start_in != Mode::Manual && !shutdownRequested()) setMode(start_in);
|
||||
|
||||
LOG_INFO << "Entering control loop (type 'exit' to quit, or Ctrl-C)";
|
||||
oneshot_since_ = std::chrono::steady_clock::now();
|
||||
|
|
|
|||
Loading…
Reference in New Issue