Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ad9f00f
Added kush's stuff
NexInfinite Mar 6, 2025
5a1fb51
Fixing kush's branch (#539)
NexInfinite Mar 8, 2025
1b5dd00
Alpha 0.1.9/523 new missions page (#545)
Kwash67 Mar 16, 2025
306382b
542 show error stack on error boundary (#543)
NexInfinite Mar 18, 2025
9ea2523
Alpha 0.1.9/517 popout camera feed from dashboard (#541)
Jopat2409 Mar 19, 2025
eaa131f
Fix socket connection state not updating
1Blademaster Mar 8, 2025
8ae6dbc
Merge branch 'release-alpha-0.1.9' of https://github.com/project-Falc…
NexInfinite Mar 24, 2025
d28fa2c
changed tab message (#549)
bensgilbert Mar 24, 2025
d03f4a3
Alpha 0.1.9/544 Support for displaying multiple batteries (#555)
bensgilbert Mar 28, 2025
b6389b7
Alpha 0.1.9/551 update mission centre to center on full mission (#552)
Kwash67 Mar 31, 2025
f97b95e
557 Linux support (#558)
NexInfinite Apr 6, 2025
6cad1c5
Alpha 0.1.9/linux tweaks 2 (#560)
Jopat2409 Apr 7, 2025
da1cf30
550 allow different types of aircraft to connect (#561)
1Blademaster Apr 12, 2025
330d295
Alpha 0.1.9/554 preflight checklist (#556)
NexInfinite Apr 12, 2025
e65fbed
Update reposition function to use set global position int command (#563)
1Blademaster Apr 13, 2025
b22a2ea
Alpha 0.1.9/559 use done battery monitor instance in fla (#564)
Kwash67 Apr 15, 2025
1da6d30
Update map endpoint, add default map and ability to select a differen…
1Blademaster Apr 19, 2025
97792d8
567 add settings to file (#568)
NexInfinite Apr 19, 2025
7a4fd2a
Alpha 0.1.9/546 display current mission on missions page (#547)
1Blademaster Apr 20, 2025
eebc17f
added banner (#577)
NexInfinite Apr 28, 2025
86f80c4
Build Script Fix #578
NexInfinite Apr 29, 2025
8e3d516
Real time on x-axis as long as there is GPS data (#579)
Kwash67 Apr 30, 2025
cd44da1
Merge branch 'main' into release-alpha-0.1.9
NexInfinite Apr 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ If applicable, add screenshots to help explain your problem.
- What version of ArduPilot is running on the flight controller?

**Error Log**
Please share the error's found in the console tab of inspect element (found by doing `ctrl + shift + i` and clicking the `console` tab). Either a screenshot or a copy paste of the error would suffice. If there is no error found in the console tab you can leave this blank. If you are struggling to find the console tab click [here](../../help/how_to_find_error_console.png).
If you received an error message within FGCS, please click on 'Show stack log', then copy and paste it here using the button in the top right. If you don't see the stack log, please share the errors found in the console tab of inspect element (found by doing `ctrl + shift + i` and clicking the `console` tab). Either a screenshot or a copy paste of the error would suffice. If there is no error found in the console tab you can leave this blank. If you are struggling to find the console tab click [here](../../help/how_to_find_error_console.png).

**Additional context**
Add any other context about the problem here.
2 changes: 1 addition & 1 deletion .github/workflows/windows_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ jobs:

- name: Run build script
working-directory: building\windows
run: build.ps1 -Version "${{ github.event.inputs.version }}"
run: ./build.ps1 -Version "${{ github.event.inputs.version }}"

3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"RSSI",
"serialutil",
"SITL",
"statustext"
"statustext",
"SUAS"
]
}
67 changes: 37 additions & 30 deletions gcs/data/default_settings.json
Original file line number Diff line number Diff line change
@@ -1,34 +1,41 @@
{
"General": {
"maptilerAPIKey": {
"default": "",
"type": "string",
"display": "Maptiler API Key",
"hidden": true
},
"port": {
"default": "4237",
"type": "number",
"range": [
0,
65535
],
"display": "Backend Port"
},
"interfaceLanguage": {
"default": "English",
"type": "option",
"options": ["English"],
"display": "Interface Language"
},
"autoCheckForUpdates": {
"default": true,
"type": "boolean",
"display": "Automatically Check for Updates"
}
"General": {
"maptilerAPIKey": {
"default": "",
"type": "string",
"display": "Maptiler API Key",
"hidden": true
},
"Params": {},
"Config": {},
"FGCS": {
"mapStyle": {
"default": "hybrid",
"type": "option",
"options": ["satellite", "hybrid", "streets", "outdoor"],
"display": "Map Style"
},
"port": {
"default": "4237",
"type": "number",
"range": [0, 65535],
"display": "Backend Port"
},
"interfaceLanguage": {
"default": "English",
"type": "option",
"options": ["English"],
"display": "Interface Language"
},
"autoCheckForUpdates": {
"default": true,
"type": "boolean",
"display": "Automatically Check for Updates"
},
"syncMapViews": {
"default": false,
"type": "boolean",
"display": "Sync Dashboard and Missions Map Viewstate"
}
},
"Params": {},
"Config": {},
"FGCS": {}
}
85 changes: 84 additions & 1 deletion gcs/electron/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BrowserWindow, Menu, MenuItemConstructorOptions, MessageBoxOptions, app, dialog, ipcMain, nativeImage, shell } from 'electron'
import { BrowserWindow, Event, Menu, MenuItemConstructorOptions, MessageBoxOptions, Rectangle, app, dialog, ipcMain, nativeImage, shell } from 'electron'
import { ChildProcessWithoutNullStreams, spawn, spawnSync } from 'node:child_process'
import fs from 'node:fs'
import path from 'node:path'
Expand Down Expand Up @@ -26,6 +26,7 @@ app.commandLine.appendSwitch('force-device-scale-factor', '1')

let win: BrowserWindow | null
let loadingWin: BrowserWindow | null
let webcamPopoutWin: BrowserWindow | null
// 🚧 Use ['ENV_NAME'] avoid vite:define plugin - Vite@2.x
const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL']

Expand All @@ -35,6 +36,8 @@ function getWindow() {
return BrowserWindow.getFocusedWindow()
}

// Settings logic

interface Settings {
version: string,
settings: object
Expand Down Expand Up @@ -98,10 +101,68 @@ function getUserConfiguration(){
ipcMain.handle("getSettings", () => {return getUserConfiguration(); })
ipcMain.handle("setSettings", (_, settings) => {saveUserConfiguration(settings)})

// Webcam popout window

const MIN_WEBCAM_HEIGHT: number = 100
const WEBCAM_TITLEBAR_HEIGHT: number = 28

// Disable unused vars because they are needed for TS function type
// eslint-disable-next-line no-unused-vars
type ResizeCallback = (event: Event, arg1: Rectangle) => void;

let currentResizeHandler: ResizeCallback | null = null

function openWebcamPopout(videoStreamId: string, name: string, aspect: number){

if (webcamPopoutWin === null) return;

webcamPopoutWin.loadURL("http://localhost:5173/#/webcam?deviceId=" + videoStreamId + "&deviceName=" + name);
webcamPopoutWin.setTitle(name);

// Remove previous resize handler
if (currentResizeHandler)
webcamPopoutWin.off("will-resize", currentResizeHandler)

// Create resize handler to maintain aspect ratio
currentResizeHandler = function(event, newBounds){
event.preventDefault();

const newWidth = newBounds.width;
const newHeight = Math.round((newWidth / aspect) + WEBCAM_TITLEBAR_HEIGHT);

webcamPopoutWin?.setBounds({
x: newBounds.x,
y: newBounds.y,
width: newWidth,
height: newHeight
});
}

webcamPopoutWin.on('will-resize', currentResizeHandler);

// Ensure initial size fits the aspect ratio ()
webcamPopoutWin.setSize(webcamPopoutWin.getBounds().width, Math.round(webcamPopoutWin.getBounds().width / aspect) + WEBCAM_TITLEBAR_HEIGHT);

webcamPopoutWin.setMinimumSize(Math.round(aspect * (MIN_WEBCAM_HEIGHT-28)), MIN_WEBCAM_HEIGHT);
webcamPopoutWin.show();

}

function closeWebcamPopout(){
webcamPopoutWin?.hide()
webcamPopoutWin?.loadURL("http://localhost:5173/#/webcam")
win?.webContents.send("webcam-closed");
}

ipcMain.handle("openWebcamWindow", (_, videoStreamId, name, aspect) => {openWebcamPopout(videoStreamId, name, aspect)})
ipcMain.handle("closeWebcamWindow", () => closeWebcamPopout())


ipcMain.handle("isMac", () => { return process.platform == "darwin" })
ipcMain.on('close', () => {closeWithBackend()})
ipcMain.on('minimise', () => {getWindow()?.minimize()})
ipcMain.on('maximise', () => {getWindow()?.isMaximized() ? getWindow()?.unmaximize() : getWindow()?.maximize()})

ipcMain.on("reload", () => {getWindow()?.reload()})
ipcMain.on("force_reload", () => {getWindow()?.webContents.reloadIgnoringCache()})
ipcMain.on("toggle_developer_tools", () => {getWindow()?.webContents.toggleDevTools()})
Expand Down Expand Up @@ -132,6 +193,25 @@ function createWindow() {
frame: false,
})

// Create webcam window keep it hidden to avoid delay between popping out windows
webcamPopoutWin = new BrowserWindow({
width: 400,
height: 300,
frame: false,
alwaysOnTop: true,
icon: path.join(process.env.VITE_PUBLIC, 'app_icon.ico'),
show: false,
title: "Webcam",
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
},
fullscreen: false,
fullscreenable: false,
});
webcamPopoutWin.loadURL("http://localhost:5173/#/webcam")

// Open links in browser, not within the electron window.
// Note, links must have target="_blank"
win.webContents.setWindowOpenHandler((details) => {
Expand Down Expand Up @@ -287,6 +367,8 @@ function closeWithBackend() {
if (process.platform !== 'darwin') {
app.quit()
win = null
webcamPopoutWin?.close()
webcamPopoutWin = null
}

console.log('Killing backend')
Expand All @@ -306,6 +388,7 @@ app.on('before-quit', () => {
spawnSync('pkill', ['-f', 'fgcs_backend']);
pythonBackend = null
}
webcamPopoutWin?.close();
});

app.on('activate', () => {
Expand Down
5 changes: 4 additions & 1 deletion gcs/electron/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ contextBridge.exposeInMainWorld('ipcRenderer', {
getNodeEnv: () => ipcRenderer.invoke('app:get-node-env'),
getVersion: () => ipcRenderer.invoke('app:get-version'),
getSettings: () => ipcRenderer.invoke('getSettings'),
saveSettings: (settings) => ipcRenderer.invoke('setSettings', settings)
saveSettings: (settings) => ipcRenderer.invoke('setSettings', settings),
openWebcamWindow: (id, name, aspect) => ipcRenderer.invoke("openWebcamWindow", id, name, aspect),
closeWebcamWindow: () => ipcRenderer.invoke('closeWebcamWindow'),
onCameraWindowClose: (callback) => ipcRenderer.on("webcam-closed", () => callback())
})

// `exposeInMainWorld` can't detect attributes and methods of `prototype`, manually patching it.
Expand Down
14 changes: 11 additions & 3 deletions gcs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"name": "Avis-Drone-Labs"
},
"private": true,
"version": "0.1.8-alpha",
"version": "0.1.9-alpha",
"license": "GPL-3.0-only",
"homepage": "https://fgcs.projectfalcon.uk",
"bugs": {
Expand All @@ -26,14 +26,20 @@
},
"dependencies": {
"@headlessui/react": "2.1.4",
"@mantine/core": "^7.3.2",
"@mantine/hooks": "^7.3.2",
"@mantine/code-highlight": "^7.17.1",
"@mantine/core": "^7.17.3",
"@mantine/hooks": "^7.17.3",
"@mantine/notifications": "^7.4.0",
"@mantine/spotlight": "^7.15.3",
"@mantine/tiptap": "^7.17.4",
"@reduxjs/toolkit": "^2.2.7",
"@robloche/chartjs-plugin-streaming": "^3.1.0",
"@tabler/icons-react": "^2.44.0",
"@tailwindcss/container-queries": "^0.1.1",
"@tiptap/extension-link": "^2.11.6",
"@tiptap/pm": "^2.11.6",
"@tiptap/react": "^2.11.6",
"@tiptap/starter-kit": "^2.11.6",
"@tremor/react": "^3.12.1",
"@turf/turf": "^7.2.0",
"chart.js": "^4.4.2",
Expand All @@ -52,6 +58,7 @@
"react": "^18.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^5.0.0",
"react-map-gl": "^7.1.6",
"react-redux": "^9.1.2",
"react-resizable": "^3.0.5",
Expand All @@ -66,6 +73,7 @@
"tailwind-merge": "^2.1.0",
"tailwindcss": "^3.3.6",
"use-sound": "^4.0.1",
"uuid": "^11.1.0",
"vitest": "^2.0.5"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions gcs/src/components/customMantineTheme.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ export const CustomMantineTheme = createTheme({
tailwindColors.falcongrey[950],
],
},
cursorType: "pointer",
})
18 changes: 13 additions & 5 deletions gcs/src/components/dashboard/floatingToolbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// 3rd Party Imports
import { ActionIcon, Tooltip } from "@mantine/core"
import { useLocalStorage } from "@mantine/hooks"
import { centerOfMass, polygon } from "@turf/turf"
import {
IconAnchor,
IconAnchorOff,
Expand Down Expand Up @@ -47,10 +48,17 @@ export default function FloatingToolbar({
)
}

function centerMapOnFirstMissionItem() {
function centerMapOnMission() {
if (filteredMissionItems.length > 0) {
let lat = parseFloat(filteredMissionItems[0].x * 1e-7)
let lon = parseFloat(filteredMissionItems[0].y * 1e-7)
let points = filteredMissionItems.map((item) => [
item.x * 1e-7,
item.y * 1e-7,
])
points.push(points[0]) // Close the polygon
let geo = polygon([points])
let center = centerOfMass(geo).geometry.coordinates
let lat = parseFloat(center[0])
let lon = parseFloat(center[1])
mapRef.current.getMap().flyTo({
center: [lon, lat],
})
Expand Down Expand Up @@ -95,15 +103,15 @@ export default function FloatingToolbar({
</ActionIcon>
</Tooltip>

{/* Center Map on first mission item */}
{/* Center Map on full mission */}
<Tooltip
label={
!filteredMissionItems.length > 0 ? "No mission" : "Center on mission"
}
>
<ActionIcon
disabled={filteredMissionItems.length <= 0}
onClick={centerMapOnFirstMissionItem}
onClick={centerMapOnMission}
>
<IconMapPins />
</ActionIcon>
Expand Down
Loading
Loading