@blueharford/scrypted-spatial-awareness 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.nodejs.js +1 -1
- package/dist/main.nodejs.js.map +1 -1
- package/dist/plugin.zip +0 -0
- package/out/main.nodejs.js +73 -20
- package/out/main.nodejs.js.map +1 -1
- package/out/plugin.zip +0 -0
- package/package.json +1 -1
- package/src/main.ts +90 -21
package/out/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/main.ts
CHANGED
|
@@ -1824,8 +1824,7 @@ export class SpatialAwarenessPlugin extends ScryptedDeviceBase
|
|
|
1824
1824
|
let updated = false;
|
|
1825
1825
|
|
|
1826
1826
|
if (suggestion.type === 'landmark' && suggestion.landmark) {
|
|
1827
|
-
// Calculate
|
|
1828
|
-
// Use the first visible camera's position as a starting point, or canvas center
|
|
1827
|
+
// Calculate position for the landmark WITHIN the camera's field of view
|
|
1829
1828
|
let position = suggestion.landmark.position;
|
|
1830
1829
|
if (!position || (position.x === 0 && position.y === 0)) {
|
|
1831
1830
|
// Find a camera that can see this landmark
|
|
@@ -1833,12 +1832,35 @@ export class SpatialAwarenessPlugin extends ScryptedDeviceBase
|
|
|
1833
1832
|
const camera = visibleCameraId ? topology.cameras.find(c => c.deviceId === visibleCameraId) : null;
|
|
1834
1833
|
|
|
1835
1834
|
if (camera?.floorPlanPosition) {
|
|
1836
|
-
//
|
|
1837
|
-
const
|
|
1835
|
+
// Get camera's FOV direction and range (cast to any for flexible access)
|
|
1836
|
+
const fov = (camera.fov || { mode: 'simple', angle: 90, direction: 0, range: 80 }) as any;
|
|
1837
|
+
const direction = fov.direction || 0;
|
|
1838
|
+
const range = fov.range || 80;
|
|
1839
|
+
const fovAngle = fov.angle || 90;
|
|
1840
|
+
|
|
1841
|
+
// Count existing landmarks from this camera to spread them out
|
|
1842
|
+
const existingFromCamera = (topology.landmarks || []).filter(l =>
|
|
1843
|
+
l.visibleFromCameras?.includes(visibleCameraId)
|
|
1844
|
+
).length;
|
|
1845
|
+
|
|
1846
|
+
// Calculate position in front of camera within its FOV
|
|
1847
|
+
// Convert direction to radians (0 = up/north, 90 = right/east)
|
|
1848
|
+
const dirRad = (direction - 90) * Math.PI / 180;
|
|
1849
|
+
const halfFov = (fovAngle / 2) * Math.PI / 180;
|
|
1850
|
+
|
|
1851
|
+
// Spread landmarks across the FOV cone at varying distances
|
|
1852
|
+
const angleOffset = (existingFromCamera % 3 - 1) * halfFov * 0.6; // -0.6, 0, +0.6 of half FOV
|
|
1853
|
+
const distanceMultiplier = 0.5 + (existingFromCamera % 2) * 0.3; // 50% or 80% of range
|
|
1854
|
+
|
|
1855
|
+
const finalAngle = dirRad + angleOffset;
|
|
1856
|
+
const distance = range * distanceMultiplier;
|
|
1857
|
+
|
|
1838
1858
|
position = {
|
|
1839
|
-
x: camera.floorPlanPosition.x +
|
|
1840
|
-
y: camera.floorPlanPosition.y +
|
|
1859
|
+
x: camera.floorPlanPosition.x + Math.cos(finalAngle) * distance,
|
|
1860
|
+
y: camera.floorPlanPosition.y + Math.sin(finalAngle) * distance,
|
|
1841
1861
|
};
|
|
1862
|
+
|
|
1863
|
+
this.console.log(`[Discovery] Placing landmark "${suggestion.landmark.name}" in ${camera.name}'s FOV: dir=${direction}°, dist=${distance.toFixed(0)}px`);
|
|
1842
1864
|
} else {
|
|
1843
1865
|
// Position in a grid pattern starting from center
|
|
1844
1866
|
const landmarkCount = topology.landmarks?.length || 0;
|
|
@@ -1882,17 +1904,69 @@ export class SpatialAwarenessPlugin extends ScryptedDeviceBase
|
|
|
1882
1904
|
? topology.cameras.find(c => c.deviceId === sourceCameras[0] || c.name === sourceCameras[0])
|
|
1883
1905
|
: null;
|
|
1884
1906
|
|
|
1885
|
-
// Create
|
|
1886
|
-
let
|
|
1887
|
-
|
|
1907
|
+
// Create zone polygon WITHIN the camera's field of view
|
|
1908
|
+
let polygon: { x: number; y: number }[] = [];
|
|
1909
|
+
const timestamp = Date.now();
|
|
1910
|
+
|
|
1888
1911
|
if (camera?.floorPlanPosition) {
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1912
|
+
// Get camera's FOV direction and range (cast to any for flexible access)
|
|
1913
|
+
const fov = (camera.fov || { mode: 'simple', angle: 90, direction: 0, range: 80 }) as any;
|
|
1914
|
+
const direction = fov.direction || 0;
|
|
1915
|
+
const range = fov.range || 80;
|
|
1916
|
+
const fovAngle = fov.angle || 90;
|
|
1917
|
+
|
|
1918
|
+
// Convert direction to radians (0 = up/north, 90 = right/east)
|
|
1919
|
+
const dirRad = (direction - 90) * Math.PI / 180;
|
|
1920
|
+
const halfFov = (fovAngle / 2) * Math.PI / 180;
|
|
1921
|
+
|
|
1922
|
+
// Count existing zones from this camera to offset new ones
|
|
1923
|
+
const existingFromCamera = (topology.drawnZones || []).filter((z: any) =>
|
|
1924
|
+
z.linkedCameras?.includes(sourceCameras[0])
|
|
1925
|
+
).length;
|
|
1926
|
+
|
|
1927
|
+
// Create a wedge-shaped zone within the camera's FOV
|
|
1928
|
+
// Offset based on existing zones to avoid overlap
|
|
1929
|
+
const innerRadius = range * 0.3 + existingFromCamera * 20;
|
|
1930
|
+
const outerRadius = range * 0.8 + existingFromCamera * 20;
|
|
1931
|
+
|
|
1932
|
+
// Use a portion of the FOV for each zone
|
|
1933
|
+
const zoneSpread = halfFov * 0.7; // 70% of half FOV
|
|
1934
|
+
|
|
1935
|
+
const camX = camera.floorPlanPosition.x;
|
|
1936
|
+
const camY = camera.floorPlanPosition.y;
|
|
1937
|
+
|
|
1938
|
+
// Create arc polygon (wedge shape)
|
|
1939
|
+
const steps = 8;
|
|
1940
|
+
// Inner arc (from left to right)
|
|
1941
|
+
for (let i = 0; i <= steps; i++) {
|
|
1942
|
+
const angle = dirRad - zoneSpread + (zoneSpread * 2 * i / steps);
|
|
1943
|
+
polygon.push({
|
|
1944
|
+
x: camX + Math.cos(angle) * innerRadius,
|
|
1945
|
+
y: camY + Math.sin(angle) * innerRadius,
|
|
1946
|
+
});
|
|
1947
|
+
}
|
|
1948
|
+
// Outer arc (from right to left)
|
|
1949
|
+
for (let i = steps; i >= 0; i--) {
|
|
1950
|
+
const angle = dirRad - zoneSpread + (zoneSpread * 2 * i / steps);
|
|
1951
|
+
polygon.push({
|
|
1952
|
+
x: camX + Math.cos(angle) * outerRadius,
|
|
1953
|
+
y: camY + Math.sin(angle) * outerRadius,
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1892
1956
|
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1957
|
+
this.console.log(`[Discovery] Creating zone "${zone.name}" in ${camera.name}'s FOV: dir=${direction}°`);
|
|
1958
|
+
} else {
|
|
1959
|
+
// Fallback: rectangular zone at default location
|
|
1960
|
+
const centerX = 300 + (topology.drawnZones?.length || 0) * 120;
|
|
1961
|
+
const centerY = 200;
|
|
1962
|
+
const size = 100;
|
|
1963
|
+
polygon = [
|
|
1964
|
+
{ x: centerX - size/2, y: centerY - size/2 },
|
|
1965
|
+
{ x: centerX + size/2, y: centerY - size/2 },
|
|
1966
|
+
{ x: centerX + size/2, y: centerY + size/2 },
|
|
1967
|
+
{ x: centerX - size/2, y: centerY + size/2 },
|
|
1968
|
+
];
|
|
1969
|
+
}
|
|
1896
1970
|
|
|
1897
1971
|
// 1. Create DrawnZone (visual on floor plan)
|
|
1898
1972
|
const drawnZone = {
|
|
@@ -1900,12 +1974,7 @@ export class SpatialAwarenessPlugin extends ScryptedDeviceBase
|
|
|
1900
1974
|
name: zone.name,
|
|
1901
1975
|
type: (zone.type || 'custom') as DrawnZoneType,
|
|
1902
1976
|
description: zone.description,
|
|
1903
|
-
polygon:
|
|
1904
|
-
{ x: centerX - size/2, y: centerY - size/2 },
|
|
1905
|
-
{ x: centerX + size/2, y: centerY - size/2 },
|
|
1906
|
-
{ x: centerX + size/2, y: centerY + size/2 },
|
|
1907
|
-
{ x: centerX - size/2, y: centerY + size/2 },
|
|
1908
|
-
] as any,
|
|
1977
|
+
polygon: polygon as any,
|
|
1909
1978
|
linkedCameras: sourceCameras,
|
|
1910
1979
|
};
|
|
1911
1980
|
|