Improve odometry with rotation estimation, daemon stability, and RTSP fixes
- Add rotation estimation via log-polar phase correlation (EstimateRotation,
rotateGray) — de-rotate before translation to avoid aliasing
- Track cumulative field rotation in Tracker, reject low-confidence frames
- Extract RTSP grabber into internal/rtspgrab module
- Daemon: pause odometry during slew (motion blur), auto-resume after settle
delay, add /pause and /resume HTTP endpoints, switch shooting mode before
opening camera, use ReqOpenCamera with rtsp_encode_type=1
- WebSocket heartbeat (ping/pong every 10s) to prevent idle disconnects
- FFmpeg low-latency flags (-fflags nobuffer, -probesize, -analyzeduration)
- Add SendRaw API for custom payloads, increase daemon HTTP timeout to 60s
💘 Generated with Crush
Assisted-by: Crush:/models/Qwen3.6-27B-uncensored-heretic-v2-Native-MTP-Preserved-Q4_K_M.gguf
This commit is contained in:
@ -19,20 +19,19 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Result holds the rotation estimated between two frames.
|
||||
// Result holds the motion estimated between two frames.
|
||||
type Result struct {
|
||||
// PanPx / TiltPx are the image-plane shift (in resized pixels) of the scene
|
||||
// from frame 1 to frame 2. Positive PanPx = scene moved right; positive
|
||||
// TiltPx = scene moved down. To point back at the original target, slew the
|
||||
// motors in the opposite direction.
|
||||
// PanPx / TiltPx are the image-plane translation (in resized pixels).
|
||||
PanPx float64
|
||||
TiltPx float64
|
||||
// PanDeg / TiltDeg convert the pixel shift to degrees using the supplied FoV.
|
||||
PanDeg float64
|
||||
TiltDeg float64
|
||||
// Confidence in [0,1]: the normalized phase-correlation peak height. Higher
|
||||
// is better; below ~0.05 the frames are likely too flat or the motion too
|
||||
// large to be trusted.
|
||||
// RotDeg is the estimated field rotation (degrees). Positive = scene rotated
|
||||
// counter-clockwise. Dominant when the telescope points near zenith on an
|
||||
// alt-az mount (azimuth rotation → field rotation, not translation).
|
||||
RotDeg float64
|
||||
// Confidence in [0,1].
|
||||
Confidence float64
|
||||
// Size is the FFT grid dimension actually used.
|
||||
Size int
|
||||
@ -78,13 +77,31 @@ func Estimate(img1, img2 image.Image, fovXDeg, fovYDeg float64, size int) (Resul
|
||||
g1 := toGrayDownscaled(img1, size, size)
|
||||
g2 := toGrayDownscaled(img2, size, size)
|
||||
|
||||
dx, dy, conf := phaseCorrelation(g1, g2, size, size)
|
||||
// Pass 1: estimate rotation (log-polar phase correlation).
|
||||
rotDeg, confRot := EstimateRotation(g1, g2, size, size)
|
||||
|
||||
// Pass 2: de-rotate g2, then estimate translation on de-rotated images.
|
||||
// This removes the rotation-induced aliasing that corrupts translation.
|
||||
var dx, dy, confTrans float64
|
||||
if absf(rotDeg) > 0.3 {
|
||||
g2Derot := rotateGray(g2, size, rotDeg)
|
||||
dx, dy, confTrans = phaseCorrelation(g1, g2Derot, size, size)
|
||||
} else {
|
||||
dx, dy, confTrans = phaseCorrelation(g1, g2, size, size)
|
||||
}
|
||||
|
||||
// Use the higher-confidence metric as the overall confidence.
|
||||
conf := confTrans
|
||||
if confRot > conf {
|
||||
conf = confRot
|
||||
}
|
||||
|
||||
r := Result{
|
||||
PanPx: dx,
|
||||
TiltPx: dy,
|
||||
PanDeg: dx * fovXDeg / float64(size),
|
||||
TiltDeg: dy * fovYDeg / float64(size),
|
||||
RotDeg: rotDeg,
|
||||
Confidence: conf,
|
||||
Size: size,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user