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:
Jacquin Antoine
2026-07-13 23:00:30 +02:00
parent 8daa9b4d58
commit d319ef6b4a
12 changed files with 522 additions and 143 deletions

View File

@ -70,6 +70,22 @@ func decodeResponse(pkt *pb.WsPacket, msg proto.Message) error {
return proto.Unmarshal(pkt.GetData(), msg)
}
// SendRaw sends a raw command with pre-serialized data (no inner proto).
// Useful for testing with custom payloads.
func (t *Telescope) SendRaw(cmd uint32, data []byte) (*pb.WsPacket, error) {
return t.t.Send(ModuleIDForCmd(cmd), cmd, data, 10*time.Second)
}
// --- Task Center commands ---
// SwitchShootingMode switches the telescope shooting mode.
// Mode 1 = photo, 2 = video/preview. Required to activate RTSP streaming on
// some firmwares — the camera won't stream until a shooting mode is active.
func (t *Telescope) SwitchShootingMode(mode int32) error {
_, err := t.send(CmdTaskSwitchMode, &pb.ReqSwitchShootingMode{Mode: mode})
return err
}
// --- Camera commands ---
// Camera identifies which camera to address.
@ -87,15 +103,19 @@ func cameraCmd(tele, wide uint32, cam Camera) uint32 {
return tele
}
// OpenCamera opens the specified camera.
// Some firmwares don't send a type=3 reply; fire-and-forget is safe.
// OpenCamera opens the specified camera and starts RTSP streaming.
// The rtsp_encode_type=1 field is REQUIRED for the RTSP server to activate
// (confirmed from WsOpenCameraReq.java in the APK).
func (t *Telescope) OpenCamera(cam Camera) error {
return t.sendNotify(cameraCmd(CmdTeleOpenCamera, CmdWideOpenCamera, cam), &pb.ReqMotorServiceJoystickStop{})
return t.sendNotify(cameraCmd(CmdTeleOpenCamera, CmdWideOpenCamera, cam), &pb.ReqOpenCamera{
Binning: false,
RtspEncodeType: 1,
})
}
// CloseCamera closes the specified camera.
func (t *Telescope) CloseCamera(cam Camera) error {
return t.sendNotify(cameraCmd(CmdTeleCloseCamera, CmdWideCloseCamera, cam), &pb.ReqMotorServiceJoystickStop{})
return t.sendNotify(cameraCmd(CmdTeleCloseCamera, CmdWideCloseCamera, cam), &pb.ReqOpenCamera{})
}
// TakePhoto captures a single photograph.
@ -410,12 +430,6 @@ func (t *Telescope) GetDeviceState() (*pb.ResGetDeviceStateInfo, error) {
return resp, decodeResponse(pkt, resp)
}
// SwitchShootingMode switches the active shooting mode.
func (t *Telescope) SwitchShootingMode(modeID int32) error {
_, err := t.send(CmdTaskSwitchMode, &pb.ReqSwitchShootingMode{Mode: modeID})
return err
}
// --- Panorama commands ---
// StartPanoramaGrid starts a panorama grid scan (triggers motor home/reset).