Install the server on your computer
The server is the program that receives the photos and drives the processing. Install it once, on the computer that will do the work. Pick your platform.
- Open Photo3DServer.dmg.
- Drag Photo3D Server onto the Applications folder shown next to it.
- Open it from Launchpad and press Start.
On first launch it prepares its own environment (a few seconds). The window shows the status light, the save folder and a QR code the app will use.
- Unzip Photo3DServer-Windows.zip wherever you like.
- Double-click Photo3D Server.exe — it has buttons for everything. Prefer the terminal? Run
photo3d-server.exe, or right-clickavvia-server.ps1→ Run with PowerShell. - Windows will ask about network access: choose Allow on private networks. The window speaks Italian or English following the system language.
From 1.9.46 the window shows its state in colour: at the top Server running in green or Server off in red; next to each installation (free engine, object recognition) Installed in green, Not installed in orange, Installing · 45% with a bar while it works, and Problem: … in red if something goes wrong, with a Details button that opens that installation's log. In the diary and in the Log tab the lines are coloured the same way: red for errors, orange for what is missing, green for what went well.
With the .deb package (Debian, Ubuntu and derivatives):
$ sudo apt install ./photo3d-server_1.2.0_amd64.deb
$ sudo systemctl enable --now photo3d
The server then starts at every boot. To check on it:
$ systemctl status photo3d # is it running?
$ journalctl -u photo3d -f # what is it doing
The package also installs the window: look for Photo3D Server among your applications.
Where the photos go. The server uses the first external disk it finds, otherwise your Pictures folder. You can change it from the window on the Mac, or per session from the app.
Drone flight. The window also has a Plan a flight… button: it opens in the browser the drone flight planner (grids, orbits, legs per battery, KMZ and KML files), which runs inside the server; the phone downloads its plans with “Plan from the server”. See chapter 5b, Planning on the computer.
Choose a processing engine
The server doesn't compute on its own: it relies on a photogrammetry engine. You need at least one.
| Engine | Cost | When it fits |
|---|---|---|
| Agisoft Metashape Pro | Paid licence | Objects and finds: tap-to-scale, merging two passes, and the best results on difficult surfaces. |
| WebODM (NodeODM) | Free | Drone surveys and topography, or computers without a licence. On Linux with an NVIDIA card it is very fast. |
| Open engine (COLMAP + OpenMVS) | Free | Objects and finds without a licence: installs itself from the app, with masks and tap-to-scale. Slower than Metashape on a Mac (see the dedicated section below). |
| PyArchInit Photogrammetry | Free | Excavations, objects and flights without a licence, georeferenced with ArUco targets or GCPs: model, point cloud, DEM and orthophoto, plus a project to open in the PyArchInit Photogrammetry app (see below). |
Metashape
Install it in the default location and the server finds it on its own (/Applications on Mac, C:\Program Files\Agisoft on Windows, /opt/metashape-pro on Linux).
WebODM
Install Docker Desktop (free), then paste this command once:
$ docker run -d -p 3000:3000 --name nodeodm \
--restart unless-stopped opendronemap/nodeodm
From then on the engine restarts by itself. With an NVIDIA card add --gpus all.
Free engine for objects (COLMAP + OpenMVS)
A free alternative to Metashape. It installs itself: in the Mac app, Free engine panel, Install button. From the terminal:
$ photo3d-server --installa-motore open
It takes roughly 220 MB on Mac, 145 on Windows, 670 on Linux.
Before you head to the field, with a good internet connection:
$ photo3d-server --installa-motore open --solo-scarica
fills the cache, so the real install works even offline.
What to know:
- on Mac it is three to five times slower than Metashape, because OpenMVS only runs on CPU there; the automatic install is CPU-only on every platform, Windows included: speeds only become comparable once you manually install OpenMVS's CUDA build, not with the installer;
- to do that: install the engine the normal way first (
--installa-motore open), then downloadOpenMVS_Windows_x64_CUDA.7zfrom the OpenMVS v2.4.0 GitHub release and extract it over…\Photo3D\engines\open\openmvs\, replacing the binaries; then openmanifest.json(sameopenfolder) and set"cuda": trueby hand. Don't rerun the install after swapping the binaries: it would wipe that folder again and refill it with the CPU build, losing the swap; - Intel Macs are not supported (pycolmap only publishes the Apple Silicon version);
- scale works with tap and scale bar; coded markers don't, those stay Metashape only;
- merging two sides is not yet available on this engine;
- during the depth maps phase the progress bar restarts from zero several times: those are OpenMVS's internal sub-phases (estimate, filter, fuse), not a hang;
- a first full run on Apple Silicon (64 photos, preview preset) took roughly ten minutes.
PyArchInit Photogrammetry engine (from 1.9.51)
The free engine of pyarchinit-photogrammetry, made for excavations: it aligns the photos, georeferences them with ArUco/AprilTag targets or hand-placed GCPs, and builds point cloud, textured model, DEM and orthophoto. Install it with the Install button in the PyArchInit Photogrammetry engine panel (Mac app and the Windows and Linux window), or from the phone at the first upload of a session that uses it. From the terminal:
$ photo3d-server --installa-motore ppg
What it downloads depends on the computer:
- Apple Silicon Mac and Linux (x86_64): the PyPI package in a separate folder, about 400 MB. If the PyArchInit Photogrammetry app is already in Applications (from its DMG), the server uses it and installs nothing;
- Windows, ARM included: the app's zip from the latest GitHub release, checked against the sha256 GitHub publishes (250 MB for ARM, 480 for x64);
- Intel Mac and Linux ARM: not available.
What to know:
- the targets it recognises are ArUco/AprilTag (the ones the engine prints with
ppg markers sheet), not Metashape's circular targets; hand-placed GCPs from the GCP page, tap-to-scale and the scale bar work too; - it does not use masks: choosing it, the phone turns them off;
- DEM and orthophoto come out only when the session is georeferenced (at least three points) or scaled;
- the session's
metashapefolder also holdsppg_project.ppg: open it in the PyArchInit Photogrammetry app for sections, stratigraphic units, cleaning and publishing to the PyArchInit database; - test on a Mac (Apple Silicon): 28 photos with 8 targets, all aligned, 0.7 mm error on the targets, ten seconds with the preview preset.
Install the app on your phone
- iPhone and iPad: accept the invitation you receive by email, install TestFlight from the App Store and get Photo3D from there.
- Android: copy Photo3D.apk onto the phone and open it; Android will ask once to allow installing from this source.
On first launch grant Camera and Local Network: without local network permission the app cannot see your computer.
Connect the app to the server
Phone and computer must be on the same Wi‑Fi network. Normally you do nothing: the app finds the server and shows it at the top of the screen.
If it doesn't (common on hotel and office networks, which block automatic discovery):
- Open Settings in the app (the gear) and choose Manual.
- Scan the QR code shown by the window on the computer — it carries address, port and, if set, the password. Or type the address the server prints at startup (for example
172.16.13.84) and port8765.
Take the photos
Press +, name the session, choose quality and engine, then Take photos. You can also import from the gallery (HEIC files are converted for you).
- Walk around the object with one shot every 10–15 degrees: roughly 30 photos per lap.
- Each photo must overlap the previous one by at least 60%.
- Do two or three laps at different heights: from above, three-quarters, from the side.
- Even light, no hard shadows, no flash. The object must stay still.
- Put a scale bar in the frame: you'll need it for real measurements.
Zoom stays at 1× for the whole session, and that is not a limitation: photogrammetry needs the same focal length in every shot. To fill the frame, step closer.
Fly the drone (Android app)
With an Android phone, Photo3D can fly the DJI drones supported by Mobile SDK v5: Mini 3, Mini 3 Pro, Mini 4 Pro, Mavic 3 Enterprise / 3T / 3M, Matrice 30, 4E/4T, 300 and 350, and the Parrot Anafi, Anafi USA and Anafi Ai (those from the iPhone too, see below). The newer consumer models (Mini 5 Pro, Air 3 and 3S, Mavic 3 and 4 Pro) cannot be flown by the app, but they fly the same plan from DJI Fly: see "With the screen controller".
Which drones
Photo3D uses DJI's Mobile SDK v5, the only way a third-party app can fly a drone. These are the models that support it:
| Model | Line | Notes for surveying |
|---|---|---|
| DJI Mini 3 | Consumer | Light, under 250 g |
| DJI Mini 3 Pro | Consumer | 1/1.3" sensor, good detail |
| DJI Mini 4 Pro | Consumer | Best value for excavation work: 1/1.3", under 250 g |
| DJI Mavic 3 Enterprise (3E) | Enterprise | 4/3 sensor, mechanical shutter, optional RTK: the best for mapping |
| DJI Mavic 3 Thermal (3T) | Enterprise | Thermal plus wide camera |
| DJI Mavic 3 Multispectral (3M) | Enterprise | Multispectral, for soil and vegetation analysis |
| DJI Matrice 30 / 30T | Enterprise | Rugged, handles wind and rain |
| DJI Matrice 4E / 4T | Enterprise | Recent mapping generation |
| DJI Matrice 4D / 4TD | Enterprise / Dock | Automated flights from a dock |
| DJI Matrice 300 RTK / 350 RTK | Enterprise | Interchangeable cameras (P1, H20): centimetre accuracy |
| DJI Matrice 400 | Enterprise | The largest of the line |
| Parrot Anafi, Anafi USA, Anafi Ai | Parrot | With GroundSDK, from Android and from the iPhone: phone on the drone's Wi‑Fi or on the SkyController |
Not every recent DJI can be flown by an external app. DJI leaves out Air 3 and Air 3S, Mavic 3 (Classic, Pro), Mavic 4 Pro, Mini 5 Pro, Neo, Flip and Avata 2, and the controllers with a built-in screen (RC 2, RC Pro), which don't accept third-party apps. The ones that have waypoints in DJI Fly still fly the Photo3D plan, though: Mini 4 Pro, Mini 5 Pro, Air 3, Air 3S, Mavic 3 / Classic / Pro and Mavic 4 Pro. Export the KMZ and copy it to the controller (see With the screen controller); the planner and the app have a camera profile for each. Without waypoints remain Mini 3 and Mini 3 Pro (flown only by the app), Neo, Flip and Avata 2: with those you fly by hand and import the photos from the card.
Connecting the phone to the controller
The phone does not talk to the drone: it talks to the controller, which relays everything. So you need the cable, not Wi‑Fi.
- Put the phone in the controller's clamp (RC-N2 or RC-N3 for the Mini 4 Pro; controllers with a built-in screen, like the RC 2, cannot run third-party apps).
- Connect the USB‑C to USB‑C data cable from DJI, controller to phone. It must be a data cable: charge-only cables do not work and give no error message.
- Switch on the controller first, then the drone, and wait for them to link.
- Close DJI Fly: two apps cannot use the controller at once. If Android offers "Open DJI Fly?", say no.
- When you plug in the cable (or switch on the controller) Android asks "Open Photo3D to handle…?", or lists the apps that can use the controller: pick Photo3D and tick Always. Then open a session → Drone. If the prompt does not appear, unplug and replug the cable with Photo3D open; if still nothing, the cable is charge-only.
The status at the top reads Registering with DJI… while the app authenticates (the first time the phone needs internet, Wi‑Fi or mobile data), then shows the drone model and battery once connected. If it reads “Controller connected, but the drone is not responding”, the drone is off or the controller is not linked: a new controller, such as the RC-N3, must be linked the first time in DJI Fly (“…” → Control → Re-pair to Aircraft, then hold the drone's power button for 4 seconds until it beeps twice).
In the Drone screen the display turns landscape by itself, the way the phone sits in the controller's clamp, even if auto-rotate is off: map and video on the left, controls on the right. Leaving the screen gives rotation back to the phone.
Drawing the survey area
- Move it: drag the map until your site is centred (the "Move the grid with the map centre" tick keeps the grid attached; untick it to lock the grid and look around).
- Resize it: the Area slider, from 20 to 300 m across. Pinching only zooms the map, it does not change the area.
- Rotate it: the Strip direction slider (0–90°). Align the strips with the long side of the trench: fewer turns, less battery, more even coverage.
- Satellite or map: the button at the top right. Satellite to read the ground, map to orient yourself by roads and buildings.
Drawing the area by hand
When the site isn't a square — a narrow trench, an irregular sounding, a beach — tap Draw the area and then the corners on the map: the grid fills only what you outlined, without wasting battery on the rest. Undo point removes the last tap, Done closes the polygon (three corners minimum), Clear the area returns to the square with the slider.
The drawn area and the rotation work together. Rotating the strip direction leaves your outlined area exactly where it is: only the passes inside it turn, and shots, minutes and path are recomputed accordingly. On a narrow trench try both ways: aligning the strips with the long side means fewer turns, aligning them with the short side often covers an irregular shape better.
Rings, paths and terrain, drawn on the phone
From 1.9.43 the Drone screen also draws what used to need the computer. A plan is made of blocks (the row of chips above the map, with Add block), each with its own settings, flown one at a time like the blocks that come from the server.
- Grid: the usual one, on the square around the centre or on the area you drew.
- Ring: a 36-vertex circle around a centre, camera looking at the centre (Radius with the slider or the field). The centre follows the map until you fix it with Set the centre on the map.
- Path: tap the points in order (Draw the path, then Done); Closed returns to the first point, Towards the centre points the camera inwards instead of ahead. For a wall, a road, the edge of a tell.
- Follow the terrain: the checkbox fetches the ground elevations (the same open tiles the computer uses: internet is needed at that moment, not the Mac) and from then on every point of the block flies at the same height above the ground. The elevation grid stays with the plan; if you move the plan outside it, the line below says so and Fetch the terrain redoes it. Without internet the block flies at a fixed height, and it says so.
Plans stay with the project. Each project remembers its own: the drawn one (blocks, camera, terrain) and the imported or downloaded file. Reopen the project and they are back; Remove this block and Remove the plan from the phone take them away. With Save to the computer the drawn plan goes to the server in the planner's format: you find it in the web page, edit it there (special points, targets, legs per battery) and fetch it from any phone with Plan from the server. If a block follows the terrain but the phone had no internet, the computer computes the elevations when saving.
Without internet and with the computer off (from 1.9.44). You still work in the field, and sync later:
- Save to the computer with the computer off does not fail: the plan stays on the phone marked “to send” (the line The plan is waiting for the computer) and goes by itself as soon as the app sees the server: when the app or the Drone screen opens, or when the Mac appears on the network.
- Follow the terrain without internet: the checkbox stays on, the block flies at a fixed height and says so, and the elevations download by themselves every half minute once the connection is back. When saving to the computer, the Mac computes the missing elevations.
- Prepare the area to work without internet (below the map), to do at home or where there is a connection: it keeps on the phone the satellite map up to zoom 18 for 1.5 km around the centre and the terrain elevations for 5 km. From then on drawing, terrain and flight work with nothing at all.
Importing or exporting the plan (KML, KMZ, GeoJSON)
The plan can be prepared outside the app, in a GIS or in Google Earth, and brought in with Import plan. The app reads:
- KML and GeoJSON: every track becomes a route to fly (its turns are the waypoints),
every polygon becomes the grid area. Altitude, camera pitch and speed are read from the file
when present (
quota 110 m, camera -45gradiin the description, or the GeoJSON attributesquota_m,camera_gradi,velocita_ms). A closed track is an orbit: it is flown with the nose toward the centre. - DJI KMZ, that is the waypoint file of DJI Fly or another flight app: points, altitude, speed and pitch are rebuilt from it.
With several tracks in the file the blocks appear as buttons above the map: you fly one
block at a time, and the altitude, speed and pitch fields take the block's values (you can
correct them). Export KMZ writes one KMZ per leg (see below) plus a KML with all the routes,
and shares them. The KMZ is written the way DJI Fly writes it for the Mini 4 Pro: you can copy it
into DJI Fly's waypoint folder
(Android/data/dji.go.v5/files/waypoint/<folder>/<folder>.kmz, replacing a
mission saved for the purpose) and fly it from there if the phone cannot pilot, or open it in
Google Earth and QGIS.
Planning on the computer
The big screen is where planning is comfortable: the server app has a Plan a flight…
button (on the Mac in the “Drone flight” section, on Windows and Linux in the window) that
opens the planner in the browser at http://127.0.0.1:8765/piano. On the satellite
map you add blocks: a grid (click the corners of the area, then Done; points can
be dragged, right-click removes them), an orbit (centre and radius, camera toward the
centre), a route by hand (points clicked in flight order: a road, or the outline of the tell
closed into a loop, with the camera toward the centre or toward an aim point chosen on the
map) or a route imported from KML, KMZ or GeoJSON, even just an area polygon drawn in QGIS.
For each block you set altitude, camera, overlaps, strip direction, speed and shooting mode, and
read at once shots, minutes, batteries, legs, GSD and camera cadence; the plan total is at the
bottom. Each block has a switch: off, it stays in the plan but is left out of the totals,
the files and what the phone downloads, so “if time allows” blocks stay ready. The arithmetic is
the same as in the Android app.
Where am I moves the map to where the computer is (the browser asks for permission; it
works on the 127.0.0.1 address, not on the plain network one), “Go to” accepts typed
coordinates. New starts again from an empty plan (otherwise the page reopens the last one left on
screen); Save on the server stores the plan in the piani folder inside the photo
folder, with KML, GeoJSON and the zip of KMZ files (one per leg). On the phone, in the Drone
screen, Plan from the server downloads it and opens it like an imported file: the blocks
appear as buttons and you fly one at a time. The loaded plan, from a file or the server, stays on
the phone: reopen the app and it is there as it was, until you tap Forget the plan next to the
blocks. Export downloads the same files for Google
Earth, QGIS or DJI Fly's waypoint folder, and the legs report: Legs spreadsheet is a sheet with one row per leg
(altitude, camera, speed, overlaps, direction, shooting, waypoints, shots, minutes, batteries, GSD, take-off), the
totals per block and per plan, every waypoint, and one sheet per leg with the map of its route alone on the
satellite image (take-off H, first and last point, shots, scale and figures). HTML report is the same report
as a single page with the maps inside, which opens anywhere and prints; Leg maps is the zip of the images
alone, one per leg, to show whoever flies. The maps use the planner's satellite imagery, so they need the network
and a few seconds.
Design the flight: from the goal to the plan (with AI, if you want it)
In the planner, above “Copy into DJI Fly”, there is the Design the flight panel: instead of choosing altitude and overlaps by hand, you say what you want to obtain and the program works out the rest, explaining every choice. Draw the area, pick the objective from the menu — orthophoto (centimetres per pixel), terrain model (DEM) (cell size in centimetres: the GSD comes out finer, because a clean cell wants two or three pixels per side), full 3D model (nadir plus two crossed oblique passes at 45°, which see the vertical walls), close inspection, quick survey or GSD by hand — type the value and press Design the flight. Out come the blocks, ready, and the list of reasons: the GSD needed, the altitude that gives it with that camera, how the strips are oriented, how many shots, minutes and batteries. If the detail you ask for would mean flying above 120 m, the altitude stops there and says so, with the GSD you really get.
Terrain elevations fetches the elevations of the drawn area and reports minimum, maximum, relief, slope and hectares. They come from the AWS open tiles (Terrain Tiles, Copernicus/SRTM, about 30 m): free, no key needed, the same on Mac, Windows and Linux; where the data has a hole it retries by itself at another zoom level.
Seeing the elevations on the map. Terrain elevations draws the coloured relief (green at the bottom, white on top, clipped to the area) with contour lines: hover one to read its height, every fifth line is heavier, and the legend gives the lowest and highest elevation and the contour interval. It is there so you can check the elevations are real before trusting them to fly.
Where elevations come from. The “Elevations from” menu picks the source: the open tiles cover the world at ~30 m, but as soon as you have processed a flight of the site your own DEM appears too, at survey resolution — centimetres instead of tens of metres. Outside your DEM the open tiles are used again, shifted by the offset measured where the two overlap. Elevation detail chooses how finely to sample them (~15, ~8 or ~4 m).
Follow the terrain gives each waypoint its own height: the drone keeps the same distance from the ground, so detail does not change where the ground rises — on a mound that is the difference between an even orthophoto and one that goes soft at the top. Heights are relative to the take-off point, as DJI’s file requires, and stay between 10 and 120 m. They are written into the KMZ, the KML and the GeoJSON, and the Android app reads them back: even when the flight is split into legs, or resumed after a battery change, every point flies at its own height.
With AI. Tick with AI and write in your own words what you need (“a 4 cm DEM
and a high-resolution orthophoto of the mound, the ground is uneven”): Claude reads the area,
the elevations and the camera and proposes objective, resolution, overlaps and whether to
follow the terrain, with its reasoning and warnings. The numbers are recomputed here
anyway, and its choices are kept within sensible limits: the plan is flyable even if the
AI gets it wrong, and without AI the designer works just the same. The Anthropic key is
saved once and stays on the computer, in ~/.photo3d/anthropic_key (on Windows
C:\Users\<name>\.photo3d\anthropic_key), outside the repository: the page
never shows it again, only its last four characters, and Forget the key deletes it. The
environment variable ANTHROPIC_API_KEY works too.
Voice and sounds. With voice and sounds ticked (on by default) the phone says what matters while you watch the drone: “Taking off. Home point recorded” — or the warning that there is no home point yet, without which return-to-home has nowhere to go —, “Returning to the take-off point”, “Landed”, “Leg finished”, the battery at each threshold (50, 30, 25, 20…), too few satellites, the position no longer arriving, and the reason a flight was interrupted. Every shot plays the shutter sound.
Simulating the flight, on screen and with the drone on the ground
In the planner, below the blocks, there is the Flight simulation: Take-off on the map places the starting point (H, draggable; if missing, the first point of the plan is used), Simulate flies the drone in accelerated time (1× to 300×), leg by leg: take-off, transit to the first point, the route at the effective speed with the pause at each turn, the shots lighting up on the map, the return, the battery swap. The line below tells leg, phase, clock, shots taken and how much battery that leg is expected to use, transit included: above 100%, shorten the minutes per battery or move the take-off closer.
The simulation video. With the record the video tick next to Simulate, the simulation is recorded: the map with its tiles, the routes, the shots lighting up, the take-off points, the drone and the status line at the bottom. At the end of the flight (or with Stop) Download the video appears: MP4 where the browser can write it (Chrome, Safari), otherwise WebM, and if the server has ffmpeg the MP4 button converts it there. It is the file to send to whoever wants to see the flight before it happens. The video has the size of the map on screen: widen the window before recording, and at 30× a one-hour flight lasts two minutes.
Moving between batteries. Each leg is a flight of its own: the file carries no take-off point, the drone starts from where you are, flies straight to the leg's first waypoint and at the end returns to where it took off that time. Starting from the south and then moving north for the northern legs shortens outbound and return and improves the signal. One caution: altitudes are relative to the take-off point. If you take off from a spot higher or lower than the previous one, the whole leg shifts by that much: from the top of a tell the drone flies higher over the plain (more overlap, a bit less detail), from the plain after starting on the top it flies lower over the tell, and on 40-50 m obliques that can get dangerous. All take-offs of a block from the same ground level. Below the simulation, Take-off per leg gives each leg its own point (one click on the map, the H1, H2… marker can be dragged): the simulation and the battery estimate start there, and the exported KML marks the take-off points, so in the field you know where to stand. Optimise take-offs works them out by itself: for each leg the point halfway between first and last waypoint, where outbound plus return is shortest, and legs whose points fall close (within 150 m) share the take-off, so you move rarely, and the points stay outside the orbits, which circle the mound: a take-off on the tell would throw the altitudes off; the message says how many points came out and how many kilometres you save. It is a proposal on distance alone: check they are places you can stand, at the same ground level, and drag them if needed; Remove all goes back to the main H.
DJI's simulator does not exist for the Mini 4 Pro. DJI Assistant 2 (Consumer Drones Series), on the Mac too, only does firmware updates, Flysafe data and log export for the Mini 4 Pro: in the release notes the Simulator appears only for Mavic 2, Air 2, Air 2S and the first Mini. So the KMZ is tested like this:
- On the ground, propellers off. Drone and controller on, phone connected, Photo3D → Drone, Prepare leg 1: if the drone accepts the file the message says “Plan uploaded”. A refusal here means the file needs fixing. Do not press Take off on the ground. DJI has reports of files accepted at upload and refused at start, so this check is not enough.
- In the field, a short leg. A 60 m grid over a meadow, 40 m altitude, timed shooting, one leg. Check in order: take-off and transit to the first point; the strips; the message “Camera: shooting every N s” and the shutter light on the drone; Stop halfway, the return, Resume where it left off and that it restarts on the right strip; at the end the offer of leg 2.
- The photos. Fetch the photos from the drone and check there are as many as the estimate said and that the geotags draw the strips.
If step 2 fails at start, the fallback is ready: Export KMZ, copy the file into DJI Fly's waypoint folder and fly from there, with timed shooting set by hand in the camera.
Special points: a close-up photo, a panorama, a video
Every block in the planner (step 4) has + Special point: click on the map where the drone must do something other than the survey.
- Detail photo: descend, shoot, climb back. It is what a target, a trench or an inscription needs: from 12 m a 20 cm target reads perfectly, from 60 m it is a blur.
- Panorama (photos to stitch): a turn of photos with the nose pointing outwards, 8 by default (4 to 16), to be merged later in a stitching program. The Mini 4 Pro has no "panorama mode" in a mission: the turn is a small ring of waypoints, 1.5 m in radius.
- Video panorama: a slow turn (5 m radius, 1 m/s) with recording that starts and stops by itself.
- Start video / Stop video: on two route waypoints, to film a stretch.
Snapped or free. Clicking near a waypoint (within a dozen metres) snaps the point to the route: the drone does it when passing. Elsewhere it stays free: free points are all visited at the end of the block, nearest first, so the survey is flown whole and without detours. The "on the waypoint" tick switches between the two.
The descent can be given in two ways: metres above ground ("go to 12 m above the ground": it uses the terrain heights, which the page measures by itself the first time even if the block flies at a fixed height; on the phone this height follows the place you really take off from) or metres above take-off, the height you read on the controller.
Either way the descent is vertical: the drone arrives above the point at flight height, descends, does its job, climbs back and only then moves on. It never goes below five metres above ground (when the terrain is known) nor below five metres above take-off; if the height you asked for would take it lower it is raised, and you read that in red under the point. Under each point you read what will really happen: "on waypoint 12 · descends to 23 m above take-off (12 m above ground)".
Batteries and resuming. A special point is never split between two batteries, and after a Stop the flight never resumes from its low waypoint: it goes back to its first waypoint, at flight height, and does it again.
Photos, by interval or per point. Shooting per point, the special photo is an action in the file like all the others. Shooting by interval, the interval timer itself takes it: the drone hovers on the point for a generous interval, and at least one shot falls there (a shoot command with the camera in "interval" mode would start a burst).
Video stops the photos. From the Android app the camera switches to video when arriving at the point and goes back to survey shooting by itself when recording ends. With the screen controller (DJI Fly) the interval timer must be restarted by hand after the video: better to put videos in a block of their own, or at the end.
Try it first. The actions are written the way DJI Fly writes them, but panorama and video in a mission on the Mini 4 Pro should be seen flying once, over an open field and with a cautious descent (30 m), before trusting them on site. Litchi, QGroundControl and Parrot receive the survey only.
Ground targets: from the GNSS file to GCPs, without clicking photos
A GCP is a point whose coordinates you know because you measured them. So you know where the targets are before flying: the drone does not have to find them, it has to go there.
- Print Metashape's coded targets (Tools → Markers → Print Markers, 12-bit circular), as large as you can. As a rule of thumb, from the Mini 4 Pro's pixels: an A4 from 10 m, an A3 from 15. Try it before leaving: photograph a target from that distance and see whether Metashape detects it (Tools → Markers → Detect Markers). Lay them out and measure them with GNSS, noting the target number for each.
- In the planner, step 4, Import the target file: a CSV with name, coordinates and
height. Degrees or UTM (WGS84), with or without a header, comma or point decimals, east
before north or the other way round: the order is worked out from the numbers and the site,
and you are told when a doubt remains. The target number is read from the name
(
T12,target 3,GCP_07). - Each target gets a special point: at the end of the block the drone visits them one by one and descends in steps — from 60 m it shoots at 36, 22, 13 and 10 m above ground. A single photo from ten metres, six times finer than the survey, would struggle to tie in with the others, and a target seen in one photo only has no position.
- Processing with Metashape needs nothing from you: if the photos were taken over the targets of a saved plan, the server uses them by itself. After alignment it detects the coded targets, matches them to the coordinates by number, switches the project to your system (UTM), sets the drone GPS aside, optimises the alignment and logs the error on each target. At least three are needed.
Five targets cost a couple of minutes of flight. WebODM does not detect coded targets: there GCPs are given by hand, from the GCP page (step 7).
Altitude, overlap, shooting and flight time
The altitude decides everything: double it and each photo covers twice the ground, so the number of shots drops quickly — but so does detail. The overlaps (80% front, 65% side; 70% for a topographic survey) are the recommended values. Below the fields the app tells you shots, minutes, batteries, GSD and how the camera will shoot.
How it shoots. Two ways:
- Timed shooting (recommended): the waypoints are only the turns and the camera shoots by itself on a timer; the app starts it at the first waypoint and stops it at the end of the leg. DJI cameras accept fixed intervals (2, 3, 5, 7, 10 s…): the app picks the shortest one that keeps the photo spacing and, if needed, lowers the speed. Example: at 110 m with 80% the spacing is 23.6 m; at 5 m/s you would need 4.7 s, the camera offers 5 s, so you fly at 4.7 m/s. At 48 MP the minimum interval rises to 5 s.
- One shot per point: one waypoint per photo, with the shoot action inside the file. DJI Fly understands it without touching the camera, but it is heavy: about a hundred waypoints per mission, hence more legs.
| Area | Altitude | Footprint | Shots | Flight | Shooting | Detail (12 MP) |
|---|---|---|---|---|---|---|
| 50×50 m | 30 m | 43 m | 24 | ~2 min | 2 s at 3.2 m/s | ~1.1 cm/px |
| 100×100 m | 30 m | 43 m | 112 | ~5 min | 2 s at 3.2 m/s | ~1.1 cm/px |
| 100×100 m | 50 m | 72 m | 36 | ~3 min | 3 s at 3.6 m/s | ~1.8 cm/px |
| 150×150 m | 30 m | 43 m | 230 | ~10 min | 2 s at 3.2 m/s | ~1.1 cm/px |
| 150×150 m | 50 m | 72 m | 84 | ~6 min | 3 s at 3.6 m/s | ~1.8 cm/px |
| 200×200 m | 30 m | 43 m | 403 | ~16 min | 2 s at 3.2 m/s | ~1.1 cm/px |
| 200×200 m | 50 m | 72 m | 152 | ~9 min | 3 s at 3.6 m/s | ~1.8 cm/px |
| 300×300 m | 60 m | 86 m | 230 | ~14 min | 3 s at 4.3 m/s | ~2.1 cm/px |
| 600×600 m | 110 m | 158 m | 275 | ~26 min | 5 s at 4.7 m/s | ~3.9 cm/px |
Figures for the Mini 4 Pro at 12 MP with the recommended overlaps and 5 m/s requested; at 48 MP detail doubles (0.5 cm/px at 30 m, 1.95 at 110 m) and the minimum interval rises to 5 s. For an excavation area 30–40 m is enough; for a tell you go up to 90–110 m, always under 120 m above ground, and the app warns you if you exceed it.
Flying, one battery at a time
A long flight does not fit one battery. With Minutes per battery (18 for the Mini 4 Pro: 34 nominal, but you need margin for the way out, the return and wind) the app splits the route into legs at the end of a strip, each under 100 waypoints. Above the buttons you read "Leg 2 of 4 · points 9–17 · 14 min", with arrows to choose which one to upload.
- Prepare leg N: the leg's KMZ is generated, goes through DJI's formal check and is uploaded to the drone (you see the upload percentage).
- Take off: the drone goes to the first point, flies the leg shooting and at the end returns home by itself. The app moves on to the next leg: swap the battery, Prepare, Take off.
- Stop interrupts at any moment; the controller's sticks always take priority. At take-off the Flight view opens by itself: the camera video full screen, the figures on top (battery, altitude and distance from the take-off point, speed, satellites, flight time), and the controls always in reach below: Stop, Return to home (same as the controller's button) and Map, which shows the drone on the route with the points already flown. Close goes back to the screen, the Flight view button reopens it, and the screen stays on while it is open. In flight “Point X of N” advances by itself, worked out from the drone's position along the route, because the index the drone sends does not always arrive; the map follows the drone while “Follow the drone” is ticked; the flight view's commands report their outcome right there, so if the drone refuses to return home you read why. After a Stop, Resume where it left off always appears: if the point reached is unknown, it restarts from the beginning of the leg.
- Resume where it left off: if the drone comes back before the end (low battery, wind, your Stop), the app remembers the last point reached and where the drone was. On tap it builds the KMZ of what is left, stepping back 20 m so no gap is left, uploads it and starts again. Progress survives closing the app: reopening the session you find "Flight interrupted at point 12 of leg 2: you can resume from there".
On the map the chosen leg is drawn bold, the part already flown turns green, the orange dot is the centre the camera looks at in orbits, the green one is the drone.
Test everything before leaving, with a short leg over your house: that the drone accepts the KMZ, that the camera shoots on its timer, that at the end of a leg the app offers the next one and that "Resume" restarts from the right point. If the drone rejects the app's file, export the KMZ and fly it from DJI Fly, where after a battery swap you pick by hand the waypoint to restart from (the app tells you which).
The Parrots: Anafi, Anafi USA, Anafi Ai
With the Parrots the app really flies, on Android and on the iPhone, because Parrot has an open SDK (GroundSDK). Put the phone on the drone's Wi‑Fi (Anafi) or connect it to the SkyController with the cable; the app finds the drone by itself and model and battery appear at the top of the screen. Then everything goes as with the DJIs: Prepare the leg writes the flight plan in Parrot's format (take-off, speed, camera pitch, a photo every N metres in GPS-lapse or one per point, the waypoints with the nose along the route or toward the target point, return) and uploads it to the drone; Take off starts it; Stop interrupts and brings the drone back; Resume from where it left redoes what remains of the leg after the battery swap. The drone takes the photos by itself, by distance, so there is no Timed Shot to set, and they stay on its card: import them with Add from Files or SD card. On the iPhone the Parrot section of the Drone screen does the same things, leg by leg, with the plan taken from the server. No camera image in the app and no photo download over the radio: those remain DJI features.
First time here too with a short leg over a meadow: the plan upload, the take-off, the photo every N metres (the camera light), Stop halfway with the return, Resume.
With the screen controller: the KMZ in DJI Fly
With the DJI RC 2 (or RC Pro) Photo3D cannot pilot, because those controllers accept no third-party apps. The KMZ, though, is written the way DJI Fly writes it, so you load it there and fly from there. This also works with the RC‑N3 if you prefer DJI Fly.
Which drones. Every one that has waypoints in DJI Fly: Mini 4 Pro, Mini 5 Pro, Air 3, Air 3S, Mavic 3 / Classic / Pro and Mavic 4 Pro (not Mini 3 and Mini 3 Pro, Neo, Flip, Avata 2, which have no waypoints). In the planner and in the app pick your drone's profile (the "only with DJI Fly" group): photo spacing, speed, shooting cadence and GSD are its own, the file is the same for all. Inside is the Mini 4 Pro's code 68: tested on the Mini 4 Pro, reported working on the Mini 5 Pro and Mavic 3 Pro, assumed for the others; if DJI Fly does not show the mission, that code is what needs changing. On multi-camera drones (Air 3 and 3S, Mavic 3 Pro, Mavic 4 Pro) the file does not pick the lens: before take-off select the wide (main) camera and, with timed shooting, start the Timed Shot by hand. Here too, first time with a short leg over a meadow.
With a screenless controller (RC‑N2, RC‑N3). Only the folder's location changes,
because DJI Fly on the phone does the flying either way. On Android the folder is the
same as on the RC 2, Android/data/dji.go.v5/files/waypoint/<folder>/<folder>.kmz:
reach it from the computer over the cable, as with the controller; on the phone itself, from
Android 11 on, only with a file manager that goes through Shizuku (FV File Explorer, for
instance), because apps cannot enter other apps' data. On iPhone and iPad use the Files
app: On My iPhone → DJI Fly → wayline_mission → folder; put the KMZ in iCloud Drive or in
Files, paste it into the placeholder mission's folder, copy the original file's name, delete
it and rename the new one to that name. From DJI Fly 1.17 missions can also be uploaded to the
DJI cloud and show up on the other device.
- Export the plan. Pick the shooting mode that suits DJI Fly: one shot per point (the shot is inside the file and DJI Fly runs it by itself; each leg stays under 100 waypoints, hence more files), or timed shooting (light files with only the turns, but you set the timer yourself in DJI Fly's camera, Timed Shot, with the interval the plan shows). Then Export KMZ: a zip with one KMZ per leg.
- Create the containers in DJI Fly. On the controller open waypoint flight, draw any
mission with two points and save it: DJI Fly creates a folder named like
550E8400-E29B-…with a.kmzfile of the same name inside. You need one dummy mission per leg: DJI Fly lists only the missions it created itself, one per folder with a single file inside, and it does not look for new folders. A folder added by hand with a made-up name does not show up in the library: tested on the RC 2 with a folder named at random and a valid KMZ inside, DJI Fly ignored it (and FlyPath and Litchi Utilities, indeed, can only replace existing missions). For a twelve-leg plan, twelve dummy missions; make them all beforehand, at home, each takes a minute. With fewer missions you can reuse the same folder, but between legs you have to plug the controller into the computer again. - Replace the files. Connect the controller (or the phone) to the computer over
USB‑C. In the planner the Copy into DJI Fly panel does the work: Find the
device locates the waypoint folder (on Windows the controller or phone connected over
USB, on Linux the mounted device, anywhere an SD card or a path you paste), lists the
placeholder missions with date and number of points, assigns one leg to each, and Copy to
the device writes every KMZ over the mission's file, with the right name. If the device
is not visible as a folder (on a Mac the RC 2 and Android phones do not mount: you need
iDroid, OpenMTP or Android File Transfer), paste the names of the folders DJI Fly
created into the Folder names box, one per line: each leg takes the first free one, each leg's
dropdown offers only the names not yet assigned to the others, and a name used twice is marked in
red. Then
Download the ready folders: a zip with
<folder>/<folder>.kmz, to drag intowaypoint/replacing the folders with the same names. Beware: thewaypointfolder iDroid opens in the Finder lives inLibrary/Containers/com.leonboettger.idroid/Data/tmp/and is a temporary copy on the Mac: pasting that path into “Copy to the device” writes nothing to the controller, and the planner refuses it; on a Mac it refuses any path outside/Volumes, because awaypointfolder downloaded to the disk is a copy too, and writing into it scrambles the files. The zip also holds amap_previewfolder with one preview per leg (map_preview/<folder>/<folder>.jpg, 1920×1080 like DJI Fly's own): the leg's map with its number and name in large type. Drag those too, intowaypoint/map_preview/, replacing the ones with the same names: the mission keeps the name DJI Fly gave it (it lives in its database and cannot be written from outside), but in the library you recognise it by the picture. Copy to the device writes them by itself. Missions in DJI Fly cannot be renamed: the name is the time you created them. The panel reads it from each placeholder mission's file and shows it next to the leg (“in DJI Fly: 08/09/2026 08:01:35”); the pairing stays in the plan and goes into the Excel and HTML report (“DJI Fly mission” and “DJI Fly folder” columns) and onto the leg maps, so in the field you know which mission to launch. The KMZ written over the placeholder keeps its creation time, so the name in DJI Fly does not change. On a Mac, iDroid's temporary copy is listed by itself, marked “names only”: that is what it is for, not copying. By hand, the path isAndroid/data/dji.go.v5/files/waypoint/<folder>/: replace the.kmzwith the leg's one, renamed to the folder's name. - Fly. Reopen DJI Fly: the mission library shows the imported routes. Check altitude and speed and go; at the end of a leg the drone returns, you swap the battery and launch the next. If a leg stops halfway, DJI Fly lets you pick the waypoint to restart from: note the last one reached, because landing resets the count. The mission can also be tweaked and re-saved in DJI Fly, or synced to the cloud: the file carries the points in the template too, which DJI Fly re-reads in those cases.
- The photos come from the card: in Photo3D use Add from Files or SD card.
DJI Fly may draw the routes a bit crooked in the preview, but flies them fine. Here too, before leaving, a short leg over a meadow.
The other drones: QGroundControl, Parrot, Litchi
The planner also writes plans for those that do not speak DJI's KMZ, always one file per leg, with altitudes above take-off and distance triggering (a photo every N metres, independent of speed). The drone menu has an "Other drones" group with the camera profiles of Autel EVO II Pro and Lite+, Parrot Anafi and Anafi Ai, Skydio 2, DJI Mavic 2 Enterprise Advanced and Phantom 4 Multispectral: altitude, photo spacing and GSD come out right even when you then fly with the maker's app.
- QGroundControl (.plan): ArduPilot and PX4 drones, that is the open survey
drones and the home-built ones. Open it in QGroundControl or Mission Planner, check altitude
and camera, upload to the drone. The autopilot triggers the shots
(
DO_SET_CAM_TRIGG_DIST): the camera must be wired to it. - Parrot (.mavlink): Anafi, Anafi USA and Anafi Ai, in GroundSDK's dialect, for those who prefer flying from FreeFlight 7 (share the single leg's file, which opens in Flight Plan) or from QGroundControl. With Photo3D on Android or iPhone the file is not needed: the app flies them directly, see "The Parrots".
- Litchi (.csv): the DJI models without waypoints in DJI Fly (Mini 2 and SE, Air 2 and 2S, Mavic 2, Phantom 4), which Litchi flies on iOS and Android. Import the CSV in the Mission Hub (flylitchi.com/hub), save, and the mission shows up in the app. Camera interpolated at the chosen pitch or aimed at the target point, a photo every N metres.
- Autel (EVO II V3, Enterprise): Autel Explorer imports a KML, which the planner already writes; altitudes and actions are refined in the app. Skydio: no import, only the camera profile to do the sums and fly with its own app.
- DJI Mavic 2 Enterprise Advanced and Phantom 4 Multispectral: the Android app cannot fly them (Mobile SDK v5 does not know them) and DJI Fly does not fly them. The profile sets altitude, overlap and GSD; the flight is done with DJI Pilot (M2EA) or DJI GS Pro on iPad (P4M), as a mapping mission over the area exported with the "Area for DJI Pilot / GS Pro (experimental)" button: one KML per active grid, outline only. The DJI app computes the lines, so altitude, overlaps and camera must be set again by hand: the plan values are in the area description. Experimental: not flight-tested with the two apps yet. The P4M has a 2 MP RGB camera: fine for vegetation indices, weak for a detailed 3D model.
From the iPhone: the Drone screen
The iOS app does not fly (DJI's Mobile SDK is Android only), but from the airplane button at the top it does everything else, and with the Parrots it flies (Parrot section: Prepare, Take off, Stop, Resume, leg by leg). Plan from the server takes the plan drawn in the planner and shows its legs; Files for the flight app hands the share sheet the KMZ, the QGroundControl plan, Parrot's MAVLink or Litchi's CSV, all legs in a zip or a single leg from the button on its row (FreeFlight 7 wants the single leg). Copy into DJI Fly is the iPhone version of the planner's command: pick once the folder On My iPhone → DJI Fly → wayline_mission in the Files app, the app lists the missions saved there with their date, assigns one leg to each and writes the KMZs in their place, with the right name. Then reopen DJI Fly.
Or fly however you like
The plan is optional: fly by hand with DJI Fly and shoot as you see fit (useful for section faces, standing structures, details). Then close DJI Fly, open Photo3D and use Fetch the photos from the drone: the card is downloaded straight into the session — no card reader, no camera roll.
Flying is not possible on iPhone and iPad: DJI publishes Mobile SDK v5 for Android only (the iOS branch stopped at version 4 in 2022, before the recent drones). On iPad you fly with DJI Fly and import from the card with Add from Files or SD card.
Isolate the object (optional)
Use this when you want only the find, without table and background. In the session, tap a photo and then tap the object: the computer recognises it in all the other photos and outlines in yellow what it will keep.
On excavation or drone surveys, skip it. There the object is the ground itself: with no tap no mask is made, and that is exactly right.
On Windows and Linux the recognition is installed separately. The executable does not carry it
(torch weighs hundreds of MB): in the server window, Object recognition (SAM2) box, press
Download and install (about 500 MB) with the server running. The server downloads uv, a
Python of its own, torch (the CUDA-free build: it runs on any PC) and the SAM2 weights into a folder of their
own (%LOCALAPPDATA%\Photo3D\engines\sam2 on Windows, ~/.photo3d/engines/sam2 on
Linux), as it does for the free engine; the percentage and the bar sit next to the button, the line-by-line detail
in the Log tab (entry Installation · object recognition), and a problem shows in red with a
Details button. One installation at a time. Internet is needed once; from then on
masks work as on the Mac. Headless: photo3d-server --installa-motore sam2. On the Mac nothing to
do: the app downloads them by itself on first launch.
Give it real scale
A model without references has no dimensions. Three ways, in the Metric scale section (with Metashape):
- Tap the scale bar on a photo — pick the photo where the bar shows best, zoom up to 16×, tap both ends and type the millimetres. The most precise way.
- Find the scale bar automatically — turn on the switch and state the bar's length.
- Coded targets — if you print them from Metashape, just give the distance between two targets.
Surveying: ground control points (GCP)
For a survey in real coordinates use Ground control points (GCP): pick the photo, zoom in, tap the point on the ground and type East, North and Elevation. It works with both engines. With drone photos, georeferencing already happens through GPS.
From the computer or from Android: the GCP page. For drone flights it is the most
convenient way: Ground control points (GCP)… in the server window (or
http://<your-server>:8765/gcp), and the Ground control points (GCP)
button inside the session in the Android app, as soon as the photos have reached the server.
From the computer the page first asks which session to work on (the list is the sessions
on the computer, newest first; change it at the top right); from Android it opens straight on
the one you were looking at. The photos stay on the computer, so it also works on a project
that has already been processed.
It is the same page, in three steps:
- The measured points: import the GNSS CSV (the same as for targets: degrees or UTM, any column order), press Use the plan targets if the saved plan already has them, or type them in.
- Mark them on the photos: pick a point, then a photo. Photos are sorted by distance from the point (from the GPS written inside them), in green those that almost certainly show it. Zoom in — wheel or two fingers: beyond twice the real size you see the pixels — and tap the centre of the mark; the arrows move it one pixel at a time. Each point must be marked on at least two photos, better three or four; at least three points.
- Save, or Save and reprocess. Reopening the page brings everything back.
With GCPs the project switches to your coordinate system and, from three points up, the photo GPS is set aside: a drone without RTK is metres off, and tens of metres in height.
Send and process
Press Send to the Mac. The upload keeps going with the screen locked and resumes where it stopped. Once the upload ends, processing starts by itself and the same screen shows the stage and the percentage.
Rough timings: a find with 100 photos at medium quality takes 20 to 40 minutes; a drone flight with 180 photos can reach an hour. You can close the app: the work happens on the computer.
Sessions that live on the computer. A job made from another phone — or from this one, before replacing it or reinstalling the app — can be picked up from the computer: Sessions on the Mac on iPhone, From computer on Android, at the top of the list. Tap one and you have it there too: status, model, control points, sharing, and Reprocess on the computer to run it again (after marking GCPs, for instance). The photos stay on the computer: they do not come back to the phone, and are not needed.
View the model and take measurements
When the work is done View 3D model appears: the model turns with your fingers and the background changes with the colour picker. The first opening downloads the model (with a progress bar); after that it is instant.
Viewing the model on Android and in a browser
In the Android app, once processing is done, there is View the model: it opens full
screen, you rotate it with one finger and zoom with two, with Mesh, Point cloud,
Background and Recentre. The page is served by the computer
(http://<server>:8765/modello?sessione=<id>), so it also opens in any
browser on the same network — handy for showing the result to someone without installing
anything. The 3D libraries travel inside the server, so it works in the field with no
Internet. Sections and profiles are still iPhone only.
Terrain model and orthophoto (drone flights)
When the photos carry coordinates, processing also produces — with Metashape and with
WebODM alike — dem.tif (the terrain model) and orthophoto.tif (the
straightened, scaled view from above), next to the model in the session folder. They open in
QGIS, and can be fetched from the server at
/api/sessions/<id>/raster/dem.tif. For an object photographed close up they
are not created: a vase has no terrain model.
Sections and profiles
- Tap the scissors.
- Turn the model until you see it the way you want to draw it, then tap two points.
- Choose the cut: As I see it for the profile of a vessel or a sherd; Along the line for a terrain section.
The section reports width, height and the length of the line (the ruler button turns the dimensions on and off). With Add to the plate each section takes a letter — A–A1, B–B1 — which also appears on the model, where you cut; the plate can be reordered and shared as a single image.
Merge two passes of the same object
To capture the underside too, photograph the object in two positions (upright and upside down) as two separate sessions, process both, then in one of them tap Merge with another session….
- Align positions (recommended): works even on dark, featureless surfaces.
- Masks only: for objects rich in detail.
A new session is created with all the photos and a single model. If the two halves don't lock together, the app says so instead of handing you a wrong result: you need more linking photos framing the same areas in both positions.
Share the result
- Share the model (OBJ): a zip with geometry and texture, ready for Blender, MeshLab, CloudCompare.
- Sections and plates: images ready for the report.
- On the computer, in the session folder, you also get the point cloud (
.ply, or georeferenced.laz) for QGIS and CloudCompare.
Sessions made on other devices open from the disk with waves icon in the list: it shows every job on the computer and brings it onto your phone with one tap.
Working away from home
On a local network nothing else is needed. To use the app from another network or on mobile data, the computer opens a secure link (HTTPS) and the app uses a password, the token.
On the Mac: two switches
In the Photo3D Server window, section Access from outside:
- Turn on Ask for a password (token): it is created on the spot and shown next to it, with a copy button. Restart the server so it takes effect.
- Choose Cloudflare (instant) — no account, a new address at every start — or Tailscale (fixed address), and press Open to the public. On Windows and Linux
cloudflareddownloads by itself the first time (about 60 MB) and the link opens as soon as it is ready; Tailscale must be installed and signed in to your account. - When the
https://…address appears with the green padlock, you are online. Close shuts it down.
The QR code in the window updates itself: scanning it, the app receives the public address and the password together.
On Windows and Linux: one command
$ scripts/tunnel.sh # prints address and password
$ scripts/tailscale.sh # an address that never changes
An address that never changes, with Cloudflare too: if ~/.cloudflared/ holds a named-tunnel configuration (config-photo3d.yml), both the app button and scripts/tunnel.sh pick it up on their own and the address stays the same forever (for example https://photo3d.pyarchinit.com) instead of the random trycloudflare.com. One-time setup: cloudflared tunnel login, tunnel create photo3d, and the subdomain's DNS record.
Always-on tunnel, reboots included: on macOS a user LaunchAgent (~/Library/LaunchAgents/com.enzo.photo3d.tunnel.plist, with KeepAlive) starts the tunnel at login and restarts it if it drops — the fixed address depends neither on the app nor on an open terminal. Log in ~/Library/Logs/photo3d-tunnel.log; to stop it: launchctl bootout gui/$(id -u)/com.enzo.photo3d.tunnel. On Linux the equivalent ships ready-made in scripts/photo3d-tunnel.service (instructions in the file header); on Windows tunnel.ps1 picks up the named-tunnel config on its own.
Right-click tunnel.ps1 → Run with PowerShell: it downloads what it needs and prints address and password. For the password alone: genera-token.ps1.
In the app: Settings → Manual, paste the https://… address and the password in the Token field — or simply scan the QR code.
The password always applies. While it is on, the server refuses any request without it, even at home: put it on every device you use, or turn the switch off while working locally.
If something goes wrong
The cases that actually happen, with the fix in one line.
"No Mac found on the network"
Check in order: the phone is on Wi‑Fi and not mobile data; Local Network permission is on in the phone's settings; the server is running. If it persists, the network blocks automatic discovery: enter the address manually (Settings → Manual).
The app used to find the server, now it returns 401
The password is on. Scan the QR code again (it carries it), or copy it from the Access from outside section into Settings → Token. If the phone runs an older build without that field, update it or turn the switch off while working at home.
Uploading photos is painfully slow
Blame the shared Wi‑Fi. Use the phone's hotspot with the computer joined to it, or a cable. The upload continues with the screen locked: let it work.
Processing fails: "too few photos aligned"
The photos don't tie together. Reshoot closer together (every 10–15°), with constant light, no blur and no zoom changes. Shiny, black or featureless surfaces are the hardest: dull them down or add references around the object.
The yellow outline grabs background too
Tap the object on a brighter, closer photo: that tap is the reference for all the others. If you are surveying ground, turn masks off entirely.
Section measurements look wrong (0.99, 1.00…)
The model has no scale: those are arbitrary units. Set the metric scale and re-run with Apply the scale.
The vessel profile comes out as a ring
You are looking at the piece from above: the cut passes through the diameter. Turn the model to the side (rim up), tap the two ends of the silhouette and use As I see it.
"The two positions don't lock together"
The two passes share too little. Add linking photos framing the same parts of the object in both positions, then try again with Align positions.
The drone screen says "connect the phone to the controller"
Check the data cable (charge-only cables give no error), that DJI Fly is closed, and that controller and drone are linked. Then accept the USB access request.
Nothing happens with WebODM
The engine is off. Open Docker Desktop and check that the nodeodm container is running; if it is missing, run the command from step 02 again.
The model in the viewer looks like a still image
Drag with one finger to rotate and two fingers to zoom; with the scissors active the first tap places a point instead of turning. Tap the scissors again to leave.
"The take-off point is … km from the flight" (in red, in the planner)
The take-off was left over from another plan: you drew a new area without pressing New. For terrain-following heights the server ignores it by itself (it starts from the first waypoint), but remove it with Remove that take-off and place it again in step 6. Before this fix such a plan came out with every height at 500 m: reopen and save it again, it repairs itself.
Something is off in flight (counter stuck, altitude missing, shots not counted)
At every mission the app writes a black box: a CSV with what the drone sends and what the app decides, second by second. It reaches the computer with the photos (session folder, registri/), or use Share the last flight's log in the Drone screen. Send it along with a description of what you saw.
I change height or overlap on the phone and the result stays the same
From 1.9.39 they also apply to terrain-following plans: changing the height shifts every height by the same amount, changing the overlap rebuilds the points on the terrain the plan carries, and the line under the fields says what happened. Only when the block has special points do they stay as planned: change them in the planner.
Android: I cannot find how to delete
An object or a flight: long-press its row in the list, or Delete at the top inside the session (it leaves the phone; what is on the computer stays). The imported plan: Remove the plan from the phone; a drawn block: Remove this block. A plan on the server: Plan from server → the ✕ next to its name.
Android: “Save to the computer” says the plan is waiting for the computer
Normal when the computer is off or not on its network: the plan is on the phone and goes by itself as soon as the app sees the server (switch the Mac on, on the same network, or reopen the app). If the Mac is on and it still does not go: the password (error 401) or the phone not seeing it (the light on the first screen).
Android: “Follow the terrain” stays at a fixed height
The elevations are missing: internet is needed at that moment, or the area prepared beforehand with Prepare the area to work without internet. The app retries by itself every half minute; when saving to the computer, the Mac computes them.
macOS: I press Start and the server doesn't run
If you save onto an external disk, macOS must authorise the app: System Settings → Privacy & Security → Files and Folders (or Removable Volumes) → enable Photo3DServer. This comes back after every app update.
macOS: “The server exited with code 3”
The port still belongs to a previous server left hanging (it happened when changing folder). From 1.9.42 the app closes it by itself: press Start again. On an earlier version: in Terminal lsof -ti tcp:8765 | xargs kill, then Start.
Windows/Linux: “SAM2 not included” or masks do not run
From 1.9.45 it installs from the server window: Object recognition (SAM2) → Download and install, with the server running and internet (about 500 MB, once). If it fails, the reason is in the Log tab; retrying resumes from where it was (uv and the weights already downloaded stay).
Linux: the service won't start
Find out why with journalctl -u photo3d -f. Nearly always it is the port already taken by another running server.