Cesium Dual-Frustum Gimbal Preview Replaces Guesswork with Visual Aiming for Drone Routes
Any team building a drone ground station or 3D map tool that needs to preview a camera's view will hit the same frustum-orientation mismatch, event-capture conflict, and async flicker bugs documented here. The single-state, single-render-loop architecture is directly portable to other Cesium projects that synchronize multiple views.
Configuring a drone gimbal at a waypoint means answering three questions: altitude, pointing direction, and zoom. Three numeric inputs give no feedback on what the camera actually sees, so operators fly, check the photo, and iterate. A Cesium-based tool replaces that loop with a visual editor: a green frustum shows the current zoomed field of view, a yellow frustum shows the wide-angle reference, and a hawk-eye preview window lets users drag to aim. Changing the hawk-eye view updates a central state object, which redraws both frustums and a height pole on the main map in the same animation frame.
The implementation runs as a single HTML file with two Cesium Viewers. A unidirectional data flow — user input mutates state, a batched requestAnimationFrame redraws everything — prevents the drift and mismatch that plagued earlier attempts. Key fixes include forcing synchronous geometry creation to stop frustum flicker during drag, swapping HeadingPitchRoll parameters and applying a -90° X-axis rotation so the frustum points at the ground instead of the sky, and overlaying a transparent div to capture pointer events that Cesium's ScreenSpaceEventHandler would otherwise swallow.
Zoom uses multiplication rather than addition to match perceptual scaling, and the hawk-eye camera's aspectRatio is deliberately left untouched to avoid stretching on the non-16:9 preview panel. Ground distance from a ray-ellipsoid intersection is clamped at 20 km so near-horizontal views don't display absurd 30 km readings. The tool omits full route editing, persistence, and per-drone gimbal limits, keeping it a focused starting point for integrating visual gimbal aiming into a larger ground-station application.
The core insight is not the 3D math but the interaction design: replacing three numeric inputs with a draggable preview and dual frustums shifts the user's task from mental trigonometry to direct manipulation, which is what DJI's ground station already proved works.
Unidirectional data flow — a single state object mutated by user input and read by all render functions — is the architectural fix that eliminates view-synchronization bugs, and it's a pattern that applies to any multi-view Cesium application.
Many of the documented bugs (frustum pointing skyward, async flicker, event hijacking) stem from Cesium's internal conventions diverging from developer intuition, making this a useful reference for anyone building custom Cesium primitives beyond the standard entity API.