Multiuser Virtual Field Trips & Training
The Virtual Field Trip (VFT) system lets several people share a single VRGS scene in real time — walking the same outcrop, looking at the same models, and collaborating through pointers, annotations, chat, and shared waypoints. It is designed for teaching, guided field trips, and training, where one instructor (the leader) drives a session that students or trainees join.
A live session is called a trip. One person hosts it; everyone else joins with an invite code and is admitted through a waiting room. While the trip runs, participants see each other's avatars and viewpoints, the leader can recall everyone to a location, presenters can drop annotations and waypoints, and the whole session can be recorded for later replay and debrief.
System at a glance
The system has three parts:
| Component | What it is | Who uses it |
|---|---|---|
| VRGS client | The desktop / VR application. The VFT panel (a dockable side panel) is the control surface for hosting and joining. | Instructors, students, trainees |
| geotour-server | A standalone networking backend (a Go WebSocket server). It hosts trips, manages rosters and waiting rooms, relays movement/chat/annotations, and stores history. | Runs in the background / on a server; operators configure it |
| Admin dashboard | A web app for monitoring live trips, users, recordings, audit history, and analytics. | Administrators / instructors reviewing sessions |
The VRGS client connects to the server over a WebSocket
(ws://<host>:<port>/ws) and authenticates with a sign-in token. The server
keeps the authoritative state — who is in which trip, what role they hold, and
the shared annotations/waypoints — and broadcasts changes to everyone in the
trip.
The networking backend is a separate program (geotour-server). VRGS does not
embed it; an instructor (or your organisation's IT) runs one server that many
clients connect to. See Running the server.
Key concepts
- Trip — a live collaborative session. It has a name, an optional password, a participant cap, a leader, and a roster of everyone currently in it. A trip is active (running now) or scheduled (set to start at a future time).
- Invite code — a short code (derived from the trip's id) the host shares so others can join.
- Waiting room — when someone asks to join, they wait here until the leader or a TA approves them. This keeps uninvited people out of a class.
- Roles — every member holds one role that decides what they can do (see the permissions matrix).
- Presence / roster — the live list of who is in the trip right now, shown in the VFT panel.
- Recall & control — the leader can pull participants to their location ("recall"), or hand a participant temporary control of the shared view.
- Annotations & waypoints — shared spatial markers. Annotations are free notes pinned in 3D; waypoints are ordered stops (with optional dip/azimuth) that define a route through the scene.
- Chat & resource sharing — text messages and shared links/resources, either to the whole trip or as a direct message.
- Recording & replay — the leader can record a session; the server samples everyone's positions over time so the trip can be replayed afterwards for debrief.
- Analytics — from recorded movement the system builds position trails and an attention heatmap (where people looked), viewable in the dashboard.
Roles & permissions
There are five roles. The host of a trip is automatically the Leader; everyone admitted from the waiting room starts as a Participant. The leader can promote anyone to another role.
| Capability | Observer | Participant | Presenter | TA | Leader |
|---|---|---|---|---|---|
| See the shared scene | ✓ | ✓ | ✓ | ✓ | ✓ |
| Broadcast their own avatar / movement | — | ✓ | ✓ | ✓ | ✓ |
| Chat & share resources | — | ✓ | ✓ | ✓ | ✓ |
| Add annotations | — | ✓ | ✓ | ✓ | ✓ |
| Remove annotations | — | — | ✓ | ✓ | ✓ |
| Add / remove waypoints | — | — | ✓ | ✓ | ✓ |
| Request control of the view | — | ✓ | ✓ | ✓ | ✓ |
| Recall a single participant | — | — | — | ✓ | ✓ |
| Approve / reject the waiting room | — | — | — | ✓ | ✓ |
| Give control to a participant | — | — | — | — | ✓ |
| Recall everyone | — | — | — | — | ✓ |
| Change another member's role | — | — | — | — | ✓ |
| Start / stop recording | — | — | — | — | ✓ |
| End the trip | — | — | — | — | ✓ |
- Leader — the host. Full control of the session.
- TA (teaching assistant) — helps run a class: can admit/reject people from the waiting room and recall an individual, plus everything a presenter can do.
- Presenter — a participant who can curate the route: add/remove annotations and waypoints.
- Participant — the default. Moves freely, chats, shares resources, and adds annotations.
- Observer — a silent watcher. Does not broadcast a moving avatar and cannot chat, annotate, or share — useful for a guest who only wants to watch.
All of these permissions are enforced on the server, and always against the member's own trip — a leader of one trip cannot affect another trip. The role shown in your VFT panel is the source of truth.
Architecture (how it fits together)
VRGS client ─┐
VRGS client ─┤ WebSocket (binary protobuf) ┌── PostgreSQL (trips, participants,
VRGS client ─┼──────────────────────────────────►│ chat, annotations, waypoints,
VRGS client ─┘ ws://host:port/ws?token=… │ recordings, trails, audit)
│ │
geotour-server ──────────────┤
│ └── Valkey/Redis (live presence,
Admin dashboard ─────────────┘ rate limits, recording buffer)
(web) /api/v1 + /ws/dashboard
- Each client opens one WebSocket and exchanges compact protobuf messages (player pose, chat, annotations, trip commands).
- PostgreSQL holds durable history (who joined which trip, chat, annotations, waypoints, recordings, movement trails, and the audit log).
- Valkey (a Redis-compatible cache) holds fast-changing live state (current player positions, per-IP/per-client rate limits). It is optional — without it the server still runs, but presence-driven features (recording, analytics) and rate limiting are disabled.
- The admin dashboard talks to the server's REST API (
/api/v1/...) and a read-only live feed (/ws/dashboard).
Using VFT in VRGS
1. Open the VFT panel and sign in
Open the VFT panel in VRGS (a dockable side panel). The panel connects to the
configured geotour-server and signs you in. Your display name and identity come
from your sign-in account; in a development setup the server may accept any name
without a full login.
If the panel shows that it cannot reach the server, the backend may not be running — see Troubleshooting.
2. Host a trip
- In the VFT panel choose Create / Host a trip.
- Give it a name, and optionally a password and a participant limit.
- Optionally enable auto-record so the session is captured from the start.
- Create it — you become the Leader, and the panel shows an invite code.
- Share the invite code with your group.
You can also schedule a trip for a future start time instead of starting it immediately; it appears in the trip list and becomes joinable when its start time arrives. (Scheduled trips persist on the server, so they survive a server restart.)
3. Join a trip
- In the VFT panel choose Join, enter the invite code (and password, if the trip has one), and your display name.
- You enter the trip's waiting room and see your queue position.
- When the leader or a TA approves you, you join the live trip as a Participant. If you are rejected — or the wait times out — you are returned to the panel and can try again.
4. Admit people (leader / TA)
As the leader (or a TA), the VFT panel shows the waiting room list. For each pending person you can Approve or Reject. Approving adds them to the roster (subject to the participant cap); rejecting (or a timeout) removes them from the queue and notifies them.
5. Collaborate during a trip
Once people are in, the shared session supports:
- Presence — everyone's avatar and viewpoint are visible (except observers), updated live as people move.
- Recall — the leader can recall everyone to their current location, and a leader or TA can recall a single participant. Useful for "everyone come look at this".
- Give / request control — a participant can request control of the shared view; the leader can give control to a participant so they can drive while everyone follows.
- Annotations — pin notes in 3D. Participants and above can add them; presenters, TAs, and the leader can remove them.
- Waypoints — presenters/TAs/leader can place ordered stops (with optional dip & azimuth) that define a route through the scene.
- Chat & resource sharing — send messages to the whole trip or directly to one
member, and share resource links. (Messages are length-limited and links are
restricted to
http/https.) - Roles — the leader can promote/demote members (e.g. make a co-instructor a TA, or set a guest to Observer).
6. Record & replay
The leader can start/stop recording at any time (or host with auto-record on). While recording, the server samples everyone's position over time. Recorded sessions are listed in the admin dashboard, where they can be reviewed for debrief along with the movement analytics (position trails and attention heatmap).
7. Leave or end
- A participant can leave at any time; they are removed from the roster and everyone is notified.
- The leader can end the trip, which closes it for everyone, stops any recording, and finalises the recording for replay.
- If the leader simply disconnects (e.g. loses network), the server promotes the next member to leader so the trip keeps running; if nobody is left, the trip is ended and any recording is finalised automatically.
The admin dashboard
The dashboard is a web app for instructors and administrators. After signing in (and, in production, only for accounts granted admin access) it provides:
- Dashboard — live counts and a Live Events feed (trips created/ended, participants admitted, recordings started/stopped, disconnects).
- Trips — every trip (active, scheduled, ended) with its roster, chat, annotations, waypoints (including a GeoJSON export), and recordings. An admin can force-end a trip here.
- Recordings — recorded sessions and their snapshots, for replay/debrief.
- Users — everyone who has joined, by sign-in identity.
- Analytics — per-trip attention heatmap (where participants looked) and position scatter (where they went), built from recorded movement.
- Audit — a log of lifecycle and privileged actions (trip create/end, waiting room approve/reject, role changes, recording start/stop, admin force-end).
Running the server (for operators)
The backend is a single self-contained binary/container (geotour-server). It
needs PostgreSQL and, recommended, Valkey (Redis-compatible).
Quick start (local / development)
A docker-compose.yml brings up the server, PostgreSQL, Valkey, and Prometheus:
docker compose up -d
The dev compose file sets ALLOW_INSECURE_DEV=true, so the server runs without
authentication (any token is accepted and used as the display name) — for local
use only. Point the VRGS client's VFT panel at ws://localhost:8080/ws.