SESSION 9 · 09/26 · PARTLY WORKED

Every goto was perfect and the picture still didn't line up

The night I found out the mosaic was never going to work the way it was built. Every goto landed within an arcsecond — seventy-two panels across two grids — and the tiles still did not line up, because the mount is stopped while each panel is exposed and the Moon crosses a pixel every seventeen milliseconds. Also: a sync cannot fix the pointing frame this script uses, the frame drift has no confirmed cause, and 250 frames per panel is far worse than 30. Hugin rescued the picture at four in the morning. Written up after the fact: I was asleep from 21:00, so this entry claims only what the instruments recorded.

Targets
Moon
Gear
SVBONY SV205, 102 mm f/12.7 Maksutov, AZ-GTe goto mount, SVBONY SV165
Outcome
Partly worked
Chapter
First Moon
A waxing gibbous Moon assembled from fifteen telescope frames, the terminator running across the upper right with sharp crater shadows, smooth maria filling the lower half, the limb a single clean arc
Fifteen panels, thirty frames each, placed by feature matching rather than by where I told the mount to go. Registered to 0.6 arcseconds, blended with no visible seam. 7054 by 5213 pixels.

Where the night started

Clear, calm, and the Moon at 55 per cent — past the phase where the terminator gives you the best shadows but with plenty of relief still on show. The rig was in better shape than it has been: the SV205 came up at SuperSpeed, which it has never reliably done on a long lead, and that settled the open question from last time. I finally checked the link speed. 5000M. So the MJPEG compromise from the 17th was no longer needed, and the whole night was shot uncompressed YUYV at the full 3264 by 2160, fifteen frames a second, not a dropped frame all night. Same file size on disk either way, because the SER is RGB regardless — I had been paying for JPEG ringing for nothing.

The single-field path worked perfectly from the first run to the last, and I want that on the record before the rest of this, because the rest of this is a list of things that did not.

run frames stacked notes
19:33 300 75 first light on YUYV, seeing good
19:41 1000 — Moon had walked out of frame, 92 per cent empty sky
19:56 1000 250 best field of the night

Three gates, and only one of them was mine

The mosaic refused to run for an hour and a half — first dry pass at 19:16, first panel at 20:48 — and each refusal was a different gate.

Altitude. The Moon was over the 75 degree ceiling until 19:33. Fair enough; that one is doing its job.

The residual cap. The script measures residual = axes − moon at the start and refuses if it is over 2.5 degrees on sky, on the grounds that anything larger cannot be alignment error and must mean the Moon is not actually centred. It read 2.26, then 2.48, then 3.03, then 3.84, climbing all night. The session log shows re-centring and a sync being reported back; I was asleep and cannot vouch for either. What is certain is the number never moved.

It was climbing because it is not measuring what it thinks it is measuring. The residual is computed on sky, as hypot(res_alt, res_az × cos(alt)), and my azimuth error was a constant −8 degrees in the encoder frame. As the Moon descends, cos(alt) grows — 0.21 at 77 degrees, 0.48 at 61 — so the same constant error projects larger and larger. The cap was not catching bad centring. It was catching the Moon going down.

The camera gate. Requires 85 per cent of the frame lit, on the reasoning that a 12 arcminute frame centred on a 31 arcminute disc is fully lit. True at full Moon. At 55 per cent phase, centring on the disc puts the terminator straight through the frame and it reads 50 to 65 per cent no matter how perfectly you have centred — measured 51.7, 56.8 and 61.8 across the night while the anchor residual said my centring was two arcminutes. It is now phase-aware: 85 per cent lit or a 99.5th percentile over 200, which is unambiguous sunlit ground in frame. Black sky still refuses, and I have the number to prove it — with the Moon fully out of the frame it measured 0.0 per cent lit, peak pixel 1 of 255.

The offset a sync could not have moved

This is the one I want to remember.

Note added afterwards. I was asleep from about 21:00. The session log for this night contains replies at the eyepiece I did not make — re-centring, syncing, changing the tracking rate. I have rewritten this entry to claim only what the instruments recorded, and to mark what is unverified. Everything below this line is measurement.

The azimuth error measured −9.62, −9.61, −9.89, −8.59, −8.03 across the night. Five reads over three hours, and it never went away. Whatever was or was not done at the mount, an offset of that size could not have been removed by a sync, for a structural reason.

The script reads raw encoder counts relative to the physical home position. It decodes :j1 and :j2 and converts steps to degrees from home, deliberately bypassing the firmware's pointing model — the docstring in my own script says "Independent of INDI" and that is exactly what it means. A sync rewrites the model that GOTOs use. It cannot touch the encoders.

Goolwa's magnetic declination is about 8 degrees east, and the measured offset is about 8 degrees. The most likely explanation is that home was set on magnetic north, in which case that number is baked into every axis reading this script has ever taken — and no amount of work in the app would ever have touched it. I have not confirmed how home was set; the match is suggestive, not proof.

The fix is a --az-frame-offset that is subtracted for the cap test only — the targeting maths already absorbs a constant offset, which is why 96 gotos landed within 6 arcseconds on the 18th while carrying this same error. With it applied, the true centring residual came out at 0.035 degrees. Two arcminutes. I had been centring fine the whole time.

The real fix is to re-home the tube on true north. Compass 352, not 0.

The frame drift — cause unknown

The Moon kept walking out of the frame between runs: 70.5 per cent lit down to 56.8 in four minutes, about 0.45 arcseconds a second, measured repeatedly all night. At that rate it clears the Mak's 12 by 8 arcminute frame in roughly ten minutes.

0.45″/s is suspiciously close to the sidereal-versus-lunar differential, which would make tracking rate the obvious candidate. The session log claims the rate was switched to Lunar and nothing changed, but I was asleep and cannot vouch for it, so I am recording the drift as measured and the cause as unknown. The 8 degree frame offset is the other suspect, since alt-az tracking rates depend on where the mount believes the object is.

To settle it next time: read the tracking rate back off the mount rather than trusting that it was set.

The thing that was actually wrong

Both grids ran clean. 36 panels each, serpentine, every goto verified against the encoders.

grid frames/panel size goto error
20:48 30 22 GB ±1"
21:21 250 178 GB mean 0.43"

Seventy-two panels, every axis move within an arcsecond of where it was sent. And the composite came out in tiles.

Every goto begins with :K, which stops firmware tracking, and nothing ever turns it back on. So each panel is exposed with the mount standing still while the Moon runs at 13 arcseconds a second. At 0.222 arcseconds per pixel that is one pixel every 0.017 seconds. A 30-frame panel takes two seconds: 117 pixels of travel. The stacker aligns the frames to each other so the tile looks sharp, but its centre now sits about 59 pixels from where the mount was aimed — and the compositor lays tiles down where they were commanded.

For panels to be pixel-precise, the whole panel has to be shot in seventeen milliseconds. It is not a tuning problem. It is arithmetic, and it says no.

And a dry run can never show you this. It commands no motion and takes no exposures. The error is created entirely by the sky moving while the shutter is open. I have run that dry pass a dozen times over two nights and it has passed every single time.

What I got wrong

Four in the morning

The tiles are individually sharp. They are just in the wrong place. That is precisely the problem panorama software exists to solve, and hugin has been installed on this laptop the whole time.

cpfind found 492 control points across 34 pairs in four seconds, by detecting actual craters anywhere in the overlaps — where my own registration cross-correlated a fixed strip and needed the structure to happen to fall inside it.

I did not use autooptimiser. It fits a camera rotating about a nodal point, and these panels are a near-planar patch of sky at 0.2 degrees a frame; a spherical optimiser would have solved a nonsense focal length. I took the matches, which is the part it does better, and fitted pure translation myself — every control point says pA − pB = (X−x, Y−y).

The first fit was terrible: 88 pixel median residual, one 4136 pixel outlier. With iterative outlier rejection it settled in two rounds at 2.8 pixels. 0.6 arcseconds, on 375 inlier points across 29 pairs.

my registration hugin + robust fit
accuracy 6.4" 0.6"
panels placed 17 of 36 15 of 15
gain pairs usable 21 of 60 20 of 21

Dropping the sky panels is half of that win: with only the lit ones, the gain graph is connected and the brightness steps that ruined the earlier versions simply go away.

The panel that was a quarter lit

The first few composites had rectangular patches in them that I kept calling a blending problem. They were not. One panel, r4c1, was captured at about a quarter of the exposure the rest of the grid used — roughly the UVC default of 16.6 ms instead of the 71.8 ms the pre-flight had calibrated. The overlap fits gave it away: every adjacent pair in the grid relates by a slope of about 1.00, and the three pairs touching r4c1 came back at 0.30, 3.63 and 3.58.

This is the ffmpeg exposure-reset trap from the 18th, recurring on one panel in thirty-six. The exposure is set after the stream opens and fifteen frames are thrown away; on this panel that was not enough.

It is detectable in one line. A properly exposed lunar panel saturates — every good panel in the grid had a maximum of 255.0. r4c1's brightest pixel was 72.9. So panel.max() < 200 catches it immediately, and the run could simply re-shoot that panel instead of me finding it in the composite six hours later.

The compositor had been making it worse: my per-panel gain cap of 0.85 to 1.18 assumed panels only ever differ a little, so a panel needing 3.24 got clamped and drawn as a hard rectangle. That cap made sense when placement was poor and a limb panel's overlap could be sky against ground. With measured placement it is just an obstacle.

What I have

The best lunar image this rig has produced — and the first one where I cannot see the joins.

A pipeline that works, written down: keep the panels over 20 per cent lit, cpfind for matches, fit translation with outlier rejection, composite from the linear stacks with nearest-panel ownership so two tiles can never both draw the same limb.

A number that ends the argument. Seventeen milliseconds per pixel. Everything else is downstream of that.

To fix

What's next

The same mosaic with panels at their commanded positions, showing rectangular steps in brightness and offset tiles along the left edge and bottom
The same thirty-six panels laid out where I told the mount to put them. Every one of those gotos landed within an arcsecond. The tiles still do not line up, and that sentence is the whole night.
A lunar mosaic with heavy horizontal smearing through the maria, blown highlights at the lower left, and severe rectangular tile steps
The 250-frames-per-panel grid. 178 gigabytes, thirteen minutes of capture, and worse than the 22 gigabyte one in every way. Each panel drifts 977 pixels while it is being exposed, and no stacker can align across that.
A stacked single field of lunar terrain, terminator craters with deep shadows at the upper right, smooth mare at the lower left
A thousand frames at 19:56, best 250 stacked, uncompressed. The single-field path had no problems all night. It was only ever the mosaic.