poe-svelte-ui-lib 1.94.0 → 1.96.0
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/WidgetMap/README.md +1 -0
- package/dist/WidgetMap/mission/MapAgro.svelte +34 -15
- package/dist/WidgetMap/mission/MapRoute.svelte +35 -16
- package/dist/WidgetMap/mission/fit.d.ts +3 -0
- package/dist/WidgetMap/mission/fit.js +36 -0
- package/dist/locales/translations.js +13 -3
- package/dist/options.js +8 -8
- package/package.json +1 -1
package/dist/WidgetMap/README.md
CHANGED
|
@@ -52,6 +52,7 @@ Telemetry_SendObject(g_telemetry_stream, g_mcfg.DevSN, "Data", dev, sizeof(dev)
|
|
|
52
52
|
- **Свежесть.** Маркер зелёный, пока значения объекта менялись в пределах таймаута. Без изменений он красный, а ещё через таймаут скрывается до новых данных.
|
|
53
53
|
- **Траектория.** Точка добавляется только при смене координат. Курс и высота могут меняться чаще.
|
|
54
54
|
- **«Показать все»** в шапке вписывает все видимые объекты в экран, один объект приближает. Сама карта вид не меняет, ведь объектов может быть много.
|
|
55
|
+
- **«Показать все» в «Маршруте» и «Агро»** вписывает весь маршрут или все поля, зоны и точку взлёта. Когда карта появляется (загрузка страницы, разворачивание виджета), она вписывается сама, без анимации.
|
|
55
56
|
- **Клик по маркеру** открывает карточку: имя, группа, координаты, высота, курс, спутники, серийный номер. Кнопки «Копировать» (всё в буфер обмена) и «Скрыть» (до следующего обновления объекта).
|
|
56
57
|
- **Слежение.** Кнопка «Следить» в карточке залипает. Один отслеживаемый объект всегда в центре карты. Несколько вписываются в карту при включении слежения, дальше карта держит в центре их середину. Масштаб остаётся за оператором: карта сама отдаляется, только когда объект уходит за край. Под маркером отслеживаемого объекта точка, она видна и при закрытой карточке. Если объект пропал с карты, слежение за ним продолжится, когда он появится снова. «Скрыть» снимает слежение.
|
|
57
58
|
- **Шапка** показывает, сколько объектов на связи. Зелёный значит все, серый часть, красный ни одного.
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
import * as UI from "../.."
|
|
12
12
|
import { MapLibre, NavigationControl, ScaleControl, FullScreenControl, CustomControl } from "../mapWrapper"
|
|
13
13
|
import MissionLayers from "./MissionLayers.svelte"
|
|
14
|
+
import FitIcon from "../FitIcon.svelte"
|
|
15
|
+
import { createAutoFit, fitMapTo } from "./fit"
|
|
14
16
|
import MissionSim from "./MissionSim.svelte"
|
|
15
17
|
import SpinnerIcon from "./SpinnerIcon.svelte"
|
|
16
18
|
import HelpText from "./HelpText.svelte"
|
|
@@ -430,6 +432,14 @@
|
|
|
430
432
|
void isDarkMode
|
|
431
433
|
mapColors = readMapColors(rootEl)
|
|
432
434
|
})
|
|
435
|
+
/* «Показать все» в шапке и вписывание при появлении карты */
|
|
436
|
+
const missionPoints = (): LngLat[] => [...fields.flat(), ...plan.holes.flat(), ...(plan.start ? [plan.start] : [])]
|
|
437
|
+
const fitAll = (animate = true) => fitMapTo(mapInstance, missionPoints(), animate)
|
|
438
|
+
const autoFit = createAutoFit()
|
|
439
|
+
$effect(() => {
|
|
440
|
+
const map = mapInstance
|
|
441
|
+
untrack(() => autoFit(map, () => fitAll(false)))
|
|
442
|
+
})
|
|
433
443
|
|
|
434
444
|
/* Мелкие зоны в м², остальное в га */
|
|
435
445
|
const areaText = (m2: number) => (m2 < 1000 ? `${fmt(m2, 0)} ${$T("widget.mission.m2")}` : `${fmt(m2 / 10000, 2)} ${$T("widget.mission.ha")}`)
|
|
@@ -494,22 +504,31 @@
|
|
|
494
504
|
>
|
|
495
505
|
<WidgetHeader icon={MissionIcon} label={label?.name || $T("widget.mission.title")} bind:collapsed {hints}>
|
|
496
506
|
{#snippet right()}
|
|
497
|
-
<
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
507
|
+
<div class="flex items-center gap-3">
|
|
508
|
+
<UI.Button
|
|
509
|
+
wrapperClass="w-auto"
|
|
510
|
+
componentClass="bg-transparent px-3"
|
|
511
|
+
content={{ icon: FitIcon, name: $T("constructor.props.map.fitAll"), info: { text: $T("widget.mission.fitHint"), side: "bottom" } }}
|
|
512
|
+
disabled={collapsed || missionPoints().length === 0}
|
|
513
|
+
onClick={() => fitAll()}
|
|
514
|
+
/>
|
|
515
|
+
<span class="flex items-center gap-3 text-[12px] font-semibold text-(--muted-color) tabular-nums">
|
|
516
|
+
{#if headerProgress !== null}
|
|
517
|
+
<span class="flex items-center gap-1.5" title={simulate ? $T("widget.sim.title") : $T("widget.mission.progressHint")}>
|
|
518
|
+
<span class="h-1.5 w-14 overflow-hidden rounded-full bg-(--hairline-color)"
|
|
519
|
+
><span class="block h-full rounded-full bg-(--accent-color)" style="width: {Math.round(headerProgress * 100)}%"></span></span
|
|
520
|
+
>
|
|
521
|
+
{Math.round(headerProgress * 100)}%{#if live}
|
|
522
|
+
· {$T("widget.mission.treated")} {fmt(treatedHa, 2)} {$T("widget.mission.ha")}{/if}
|
|
523
|
+
</span>
|
|
524
|
+
{/if}
|
|
525
|
+
{#if stats}
|
|
526
|
+
<span class="text-[12px] font-semibold text-(--muted-color) tabular-nums"
|
|
527
|
+
>{fmt(stats.ha, 2)} {$T("widget.mission.ha")} · {fmt(stats.total, 2)} {$T("widget.mission.km")}</span
|
|
502
528
|
>
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
{/if}
|
|
507
|
-
{#if stats}
|
|
508
|
-
<span class="text-[12px] font-semibold text-(--muted-color) tabular-nums"
|
|
509
|
-
>{fmt(stats.ha, 2)} {$T("widget.mission.ha")} · {fmt(stats.total, 2)} {$T("widget.mission.km")}</span
|
|
510
|
-
>
|
|
511
|
-
{/if}
|
|
512
|
-
</span>
|
|
529
|
+
{/if}
|
|
530
|
+
</span>
|
|
531
|
+
</div>
|
|
513
532
|
{/snippet}
|
|
514
533
|
</WidgetHeader>
|
|
515
534
|
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
import * as UI from "../.."
|
|
12
12
|
import { MapLibre, NavigationControl, ScaleControl, FullScreenControl, CustomControl } from "../mapWrapper"
|
|
13
13
|
import MissionLayers from "./MissionLayers.svelte"
|
|
14
|
+
import FitIcon from "../FitIcon.svelte"
|
|
15
|
+
import { createAutoFit, fitMapTo } from "./fit"
|
|
14
16
|
import MissionSim from "./MissionSim.svelte"
|
|
15
17
|
import { missionProgress } from "./progress"
|
|
16
18
|
import MapIcon from "../MapIcon.svelte"
|
|
@@ -234,6 +236,14 @@
|
|
|
234
236
|
void isDarkMode
|
|
235
237
|
mapColors = readMapColors(rootEl)
|
|
236
238
|
})
|
|
239
|
+
/* «Показать все» в шапке и вписывание при появлении карты */
|
|
240
|
+
const missionPoints = (): LngLat[] => [...(route.start ? [route.start] : []), ...route.points.map((p) => p.point)]
|
|
241
|
+
const fitAll = (animate = true) => fitMapTo(mapInstance, missionPoints(), animate)
|
|
242
|
+
const autoFit = createAutoFit()
|
|
243
|
+
$effect(() => {
|
|
244
|
+
const map = mapInstance
|
|
245
|
+
untrack(() => autoFit(map, () => fitAll(false)))
|
|
246
|
+
})
|
|
237
247
|
|
|
238
248
|
const fmt = (v: number, d = 1) => v.toLocaleString(undefined, { minimumFractionDigits: d, maximumFractionDigits: d })
|
|
239
249
|
/* Кнопки панели на карте: стили кнопок MapLibre (размер 29px, прозрачный фон, без рамки) перебиваются */
|
|
@@ -281,22 +291,31 @@
|
|
|
281
291
|
>
|
|
282
292
|
<WidgetHeader icon={MapIcon} label={label?.name || $T("widget.route.title")} bind:collapsed {hints}>
|
|
283
293
|
{#snippet right()}
|
|
284
|
-
<
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
294
|
+
<div class="flex items-center gap-3">
|
|
295
|
+
<UI.Button
|
|
296
|
+
wrapperClass="w-auto"
|
|
297
|
+
componentClass="bg-transparent px-3"
|
|
298
|
+
content={{ icon: FitIcon, name: $T("constructor.props.map.fitAll"), info: { text: $T("widget.route.fitHint"), side: "bottom" } }}
|
|
299
|
+
disabled={collapsed || missionPoints().length === 0}
|
|
300
|
+
onClick={() => fitAll()}
|
|
301
|
+
/>
|
|
302
|
+
<span class="flex items-center gap-3 text-[12px] font-semibold text-(--muted-color) tabular-nums">
|
|
303
|
+
{#if headerProgress !== null}
|
|
304
|
+
<span class="flex items-center gap-1.5" title={simulate ? $T("widget.sim.title") : $T("widget.mission.progressHint")}>
|
|
305
|
+
<span class="h-1.5 w-14 overflow-hidden rounded-full bg-(--hairline-color)"
|
|
306
|
+
><span class="block h-full rounded-full bg-(--accent-color)" style="width: {Math.round(headerProgress * 100)}%"></span></span
|
|
307
|
+
>
|
|
308
|
+
{Math.round(headerProgress * 100)}%{#if live}
|
|
309
|
+
· {live.finished
|
|
310
|
+
? $T("widget.route.finished")
|
|
311
|
+
: live.target > route.points.length
|
|
312
|
+
? $T("widget.route.returning")
|
|
313
|
+
: `${$T("widget.route.toPoint")} ${live.target}/${route.points.length}`}{/if}
|
|
314
|
+
</span>
|
|
315
|
+
{/if}
|
|
316
|
+
<span>{stats.points} {$T("widget.route.pts")} · {km(stats.length)}</span>
|
|
317
|
+
</span>
|
|
318
|
+
</div>
|
|
300
319
|
{/snippet}
|
|
301
320
|
</WidgetHeader>
|
|
302
321
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/* Вписывает точки в карту с отступом; одна точка - приближение к ней */
|
|
2
|
+
export const fitMapTo = (map, points, animate = true) => {
|
|
3
|
+
if (!map || !points.length)
|
|
4
|
+
return;
|
|
5
|
+
const duration = animate ? 500 : 0;
|
|
6
|
+
if (points.length === 1)
|
|
7
|
+
return map.easeTo({ center: points[0], zoom: 17, duration });
|
|
8
|
+
const lngs = points.map((p) => p[0]);
|
|
9
|
+
const lats = points.map((p) => p[1]);
|
|
10
|
+
map.fitBounds([
|
|
11
|
+
[Math.min(...lngs), Math.min(...lats)],
|
|
12
|
+
[Math.max(...lngs), Math.max(...lats)],
|
|
13
|
+
], { padding: 50, maxZoom: 18, duration });
|
|
14
|
+
};
|
|
15
|
+
/* Сколько после появления карты её размер ещё может меняться: виджет разворачивается с анимацией */
|
|
16
|
+
const SETTLE_MS = 600;
|
|
17
|
+
/* Один раз на каждый новый экземпляр карты: после загрузки без анимации и ещё раз при каждой смене размера, пока виджет разворачивается */
|
|
18
|
+
export const createAutoFit = () => {
|
|
19
|
+
let fitted = null;
|
|
20
|
+
return (map, fit) => {
|
|
21
|
+
if (!map || map === fitted)
|
|
22
|
+
return;
|
|
23
|
+
fitted = map;
|
|
24
|
+
const born = performance.now();
|
|
25
|
+
const onResize = () => {
|
|
26
|
+
if (performance.now() - born > SETTLE_MS)
|
|
27
|
+
return map.off("resize", onResize);
|
|
28
|
+
fit();
|
|
29
|
+
};
|
|
30
|
+
map.on("resize", onResize);
|
|
31
|
+
if (map.loaded())
|
|
32
|
+
fit();
|
|
33
|
+
else
|
|
34
|
+
map.once("load", fit);
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -121,9 +121,9 @@ const translations = {
|
|
|
121
121
|
zh: "🎯 **用途**\n主飞行显示器(PFD) - 飞行监控的主要仪表:姿态、速度、高度、航向和系统状态。\n\n📦 **数据包**\n- `MAV` 分组的字段 - MAVLink 自驾仪遥测(可通过设置中的前缀更改),无需绑定变量\n- 遥测流:`Roll`、`Pitch`、`Heading`、`Load`、`Slip` 约每秒 10-20 次,其余每秒 1-2 次\n- 仅显示,不发送任何数据\n\n🔑 **键**\n- `Roll`、`Pitch` - 数字,°:坡度(向右 +)和俯仰(向上 +)\n- `Heading` - 数字,0-360°:航向\n- `GSpeed`、`ASpeed` - 数字,m/s:地速和空速\n- `Alt` - 数字,m:相对起飞点高度;`AltMSL` - 海拔高度\n- `Climb` - 数字,m/s:升降速度(向上 +)\n- `Load` - 数字,g:法向过载(1 - 平飞);`Slip` - 侧向过载,g(向右 +);非数字 - 不显示 G 和侧滑球\n- `Thr` - 数字,%:油门\n- `WindDir`、`WindSpd` - 风:来向,°,和风速,m/s\n- `Lat`、`Lon` - 数字,°:坐标\n- `Vx`、`Vy` - 数字,m/s:向北和向东的速度 - 用于航迹\n- `Fix` - 数字:GPS 定位类型,`0`-`1` 无、`2` 2D、`3` 3D、`4`-`6` DGPS/RTK;`Sat` - 卫星数\n- `BV` - V;`BC` - A(`-1` 未测量);`BRem` - %(`-1` 未知)\n- `Mode` - 数字:自驾仪模式;`VType` - 机型(决定模式名称);`Armed` - `1` 已解锁\n- `HomeLat`、`HomeLon` - 数字,°:起飞点,`0` - 未知\n- `Press` - hPa,`Temp` - °C\n- `WPNum` - 航点编号(`0` - 无任务);`WPDist`、`WPBrg` - 到航点的距离,m,和方位,°\n- `AltErr`、`SpdErr` - 目标减当前:高度,m,空速,m/s;`XTE` - 偏航距离,m\n- `RSSI`、`RemRSSI` - 本地和远端信号,%(`-1` 未知);`Drop` - 丢包率,%\n- `HDOP` - GPS 精度(1 以下优秀,大于 2 不准确);`EKF` - 导航滤波器方差(0.5 起注意,0.8 起告警);`SensErr` - 故障传感器数\n- `Msg`、`MsgSev`、`MsgSeq` - 自驾仪消息、严重程度(`0`-`3` 错误、`4` 警告、`5`-`7` 信息)、编号\n\n✨ **特点**\n- 数据包之间的姿态经过平滑\n- 将鼠标悬停在仪表或行中的任意元素上 - 在地平线底部的信息行中显示含义和当前值;可通过标题栏中的「?」按钮关闭\n- 速度带和高度带下方的角落:空速(相对空气)和升降速度(+ 爬升、− 下降)\n- 地平线上方两角:`G` - 过载(超出限值为红色,最小和最大值见提示)和 `THR` - 油门\n- 风 - 位于 `G` 下方:箭头为相对机头的风吹去方向(向下 - 逆风,向上 - 顺风),旁边为风速\n- 「航线」组显示按当前地速到航点的时间\n- 坡度指针下方的侧滑球:居中 - 无侧滑,偏离 - 侧滑或外滑(方向舵朝球的方向)\n- 速度带上的黄色箭头 - 趋势:以当前加速度 10 秒后地速将到达的位置\n- 航向带上的粉色 ▲ 为航迹:载具相对地面的实际运动方向(由 `Vx`、`Vy` 计算);绿色 ● - 起飞点方向;仪表下方有带角度的图例\n- 超过设定时间无数据 - 仪表被划叉并标记「无数据」\n- 在窄单元格中,速度带和高度带变为地平线上的数字\n- 行已分组:上方「系统 / GPS / 链路 / 电池」 - 状态,下方「航线 / 起飞点 / 航迹 / 位置 / 空气」 - 去向与位置\n- 青色标记 - 当前航点的目标:速度带和高度带上的速度与高度,航向带上的方位 ◆\n- 自驾仪消息 - 在地平线底部同一信息行显示 10 秒,颜色按严重程度;悬停该行可查看历史\n- 键 `Lat`、`Lon`、`Alt`、`Heading`、`Sat` 与「地图」通用 - 一个分组同时供两个组件使用\n\n⚙️ **设置**\n- 分组前缀(ID)、主色\n- 限值:最小/最大速度和最大高度 - 速度带和高度带上的红色区域;最大坡度 - 红色弧线;最小/最大过载 - G 值变红;低电量;「无数据」前的时间",
|
|
122
122
|
},
|
|
123
123
|
"component.info.WidgetMap": {
|
|
124
|
-
ru: "🎯 **Назначение**\nКарта объектов в реальном времени: положение, курс и траектория каждого объекта. Два других режима строят миссию: «Маршрут» - планировщик из точек, «Агро» - генератор миссии опрыскивания для агродрона.\n\n📦 **Пакет данных**\n- Поля групп устройства, по группе на объект: по умолчанию `MAV`, несколько - через пробел (`MAV GNSS`); привязывать переменные не нужно\n- Поток телеметрии: координаты - раз в 0.5-1 с, имя и серийный номер - реже\n- «Объекты» только показывают; «Маршрут» и «Агро» отдают миссию наружу через `onSend`, план хранит владелец карты (`route` / `plan` и их колбэки)\n\n🔑 **Ключи**\n- `Lat` - число, °: широта, обязательный; `Lat` и `Lon` = 0 - нет фикса, объект не рисуется\n- `Lon` - число, °: долгота, обязательный\n- `Alt` - число, м: высота\n- `Heading` - число, 0-360°: курс, поворачивает маркер\n- `Sat` - число спутников\n- `DevName` - строка: имя объекта, подпись маркера; без него - имя группы\n- `DevSN` - строка: серийный номер\n- `WPNum` - номер текущей команды миссии; нужен только «Маршруту» и «Агро» для прогресса в шапке\n\n✨ **Особенности**\n- Ключи общие с «Пилотажным дисплеем» и «Об устройстве» - один пакет питает несколько виджетов\n- Клик по объекту - карточка со всеми значениями, кнопки «Копировать», «Следить» и «Скрыть»\n- Траекторию, число её точек и таймаут маркеров оператор переключает на карте; объект без новых данных краснеет, ещё через таймаут скрывается\n- «Показать все» в шапке вписывает объекты в экран; сама карта вид не меняет\n- В шапке - сколько объектов на связи из заданных\n- Только 2D: правой кнопкой мыши карта поворачивается, компас под зумом возвращает её на север\n- Мастер-цвет красит весь виджет: кнопки, линию маршрута, точки, точку взлёта, переходы и аппарат в имитации. Цвета со смыслом не меняются: поля зелёные, запретные зоны красные, развороты оранжевые; «Очистить», удаление и ошибка отправки красные\n\n⚙️ **Настройки**\n- Группы полей, мастер-цвет\n- Высота карты `S`/`M`/`L`/`XL`, иконка маркера\n- Начальные значения: траектория и число её точек\n- Режим: «Объекты», «Маршрут» или «Агро»\n- Режим имитации: шесть аппаратов в «Объектах», полёт по траектории в «Маршруте» и «Агро»; панель имитации внизу карты по центру\n\n📍 **Режим «Маршрут»**\n- Обычный планировщик: точки по порядку облёта, у каждой своя высота и скорость\n- «Редактор точек» в левом верхнем углу карты включает правку: клик по карте добавляет точку, точки перетаскиваются, середина отрезка вставляет точку, правый клик удаляет; «Готово» или Esc заканчивают правку; без правки видны только номера\n- Высота, скорость и удаление - в списке точек блока «Итог», порядок меняется перетаскиванием строки; возврат с посадкой (RTL)\n- Миссия QGC WPL 110: взлёт, точки, RTL; «Скачать», «Копировать», «Отправить»; аппараты из групп видны поверх маршрута\n- Прогресс в шапке: в имитации - по ней, иначе по `WPNum` и положению аппарата первой группы\n\n🌾 **Режим «Агро»**\n- Одно или несколько полей и запретные зоны на карте превращаются в траекторию опрыскивания\n- «Редактор полей» и «Редактор запретных зон» в левом верхнем углу карты: контур обводится кликами, замыкается кликом по первой точке, двойным кликом, Enter или «Замкнуть»; вершины перетаскиваются, середина стороны добавляет точку, правый клик удаляет; точка взлёта перетаскивается всегда\n- Запретная зона может лежать в поле, выходить за его край или стоять вне полей. Из проходов вырезается только её часть внутри поля, площадь поля уменьшается только на эту часть\n- ⚠️ Перелёты от точки взлёта к полю, между полями и домой обходят все зоны с отступом. Опоры ЛЭП, вышки, деревья и постройки между полями обязательно обводите зонами, иначе аппарат полетит напрямую и может в них врезаться\n- Проходы с шагом не больше ширины захвата; крайние проходы на отступе от края, от зон тоже держится отступ; по умолчанию захват 5 м, отступ 2 м\n- Зоны и вырезы делят поле на ячейки; порядок ячеек до 10 штук перебирается полностью, больше - от ближайшей с улучшением 2-opt; переходы и развороты идут по кратчайшему пути в обход зон\n- Поля облетаются по очереди от ближайшего, у каждого поля свой угол проходов\n- «Авторасчёт» подбирает угол каждого поля по полной траектории: цена - время облёта плюс 4 с на разворот плюс штраф за недолив (метр недолитого прохода как три метра полёта). Поиск: шаг 5° и направления сторон поля, затем 1° около трёх лучших, затем 0.1° около победителя; около 75 расчётов на поле, прогресс на карте. Кнопка «i» рядом открывает оператору подробную справку\n- В блоке «Итог» наведение на поле или зону подсвечивает контур на карте, нажатие на название приближает к нему карту\n- Покрытие меньше 100 % в основном из-за отступа от границ и зон\n- Распылитель включается на проходах и выключается на разворотах и переходах: `DO_SPRAYER` или `DO_SET_SERVO`\n- Миссия QGC WPL 110: «Скачать», «Копировать», «Отправить» на борт; аппараты из групп видны поверх поля\n- В имитации квадрокоптер облетает проходы, зелёный во время распыления\n- Без `plan` открывается демо: три поля под Минском с зонами внутри полей, на их краях и между полями",
|
|
125
|
-
en: '🎯 **Purpose**\nA real-time map of objects: position, heading and track of each object. Two other modes build a mission: "Route" is a waypoint planner, "Agro" is a spraying mission generator for an agricultural drone.\n\n📦 **Data packet**\n- Device field groups, one group per object: `MAV` by default, several separated by spaces (`MAV GNSS`); no variable binding needed\n- Telemetry stream: coordinates every 0.5-1 s, name and serial number less often\n- "Objects" only displays; "Route" and "Agro" pass the mission out through `onSend`, the plan is kept by the map owner (`route` / `plan` and their callbacks)\n\n🔑 **Keys**\n- `Lat` - number, °: latitude, required; `Lat` and `Lon` = 0 - no fix, the object is not drawn\n- `Lon` - number, °: longitude, required\n- `Alt` - number, m: altitude\n- `Heading` - number, 0-360°: heading, rotates the marker\n- `Sat` - satellite count\n- `DevName` - string: object name, the marker label; without it - the group name\n- `DevSN` - string: serial number\n- `WPNum` - number of the current mission command; only "Route" and "Agro" use it for progress in the header\n\n✨ **Features**\n- Keys are shared with the "Flight Display" and "About Device" - one packet feeds several widgets\n- Click an object - a card with all values, "Copy", "Follow" and "Hide" buttons\n- The operator switches the track, its point count and marker timeout on the map; an object without new data turns red, after one more timeout it is hidden\n- "Show all" in the header fits all objects into view; the map never moves by itself\n- The header shows how many of the configured objects are online\n- 2D only: the right mouse button rotates the map, the compass under the zoom returns it to north\n- The master color paints the whole widget: buttons, route line, points, takeoff point, transits and the vehicle in simulation. Meaningful colors stay: fields green, no-fly zones red, turns orange; "Clear", delete and send error red\n\n⚙️ **Settings**\n- Field groups, master color\n- Map height `S`/`M`/`L`/`XL`, marker icon\n- Defaults: track and its point count\n- Mode: "Objects", "Route" or "Agro"\n- Simulation mode: six vehicles in "Objects", a flight along the path in "Route" and "Agro"; the simulation panel is at the bottom center of the map\n\n📍 **Route mode**\n- A regular planner: points in flight order, each with its own altitude and speed\n- "Waypoint editor" in the top left corner of the map turns on editing: a click adds a point, points can be dragged, a segment midpoint inserts one, right-click removes; "Done" or Esc ends editing; otherwise only numbers are shown\n- Altitude, speed and removal in the point list of the Summary block, order is changed by dragging a row; return and land (RTL)\n- QGC WPL 110 mission: takeoff, points, RTL; "Download", "Copy", "Send"; vehicles from the groups are shown over the route\n- Progress in the header: from the simulation, otherwise from `WPNum` and the position of the vehicle from the first group\n\n🌾 **Agro mode**\n- One or more fields and no-fly zones on the map become a spraying path\n- "Field editor" and "No-fly zone editor" in the top left corner of the map: an outline is traced by clicks and closed by clicking the first point, a double click, Enter or "Close"; vertices can be dragged, a side midpoint adds a point, right-click removes; the takeoff point can always be dragged\n- A no-fly zone can lie inside a field, stick out over its edge or stand outside fields. Only its part inside the field is cut from the passes, and the field area is reduced only by that part\n- ⚠️ Transits from takeoff to a field, between fields and back home avoid all zones with the margin. Be sure to outline power line poles, towers, trees and buildings between fields as zones, otherwise the vehicle flies straight and may crash into them\n- Passes are spaced no wider than the swath; the outer passes keep the margin from the edge, zones are kept at the margin too; defaults: swath 5 m, margin 2 m\n- Zones and notches split a field into cells; up to 10 cells their order is checked exhaustively, beyond that nearest first with 2-opt improvement; transits and turns follow the shortest path around zones\n- Fields are flown one after another, nearest first, each field has its own pass angle\n- "Auto-calculate" picks each field\'s angle from the full path: cost is flight time plus 4 s per turn plus a penalty for missed spraying (a missed meter of pass counts as three meters of flight). Search: 5° steps and field side directions, then 1° around the three best, then 0.1° around the winner; about 75 calculations per field, progress on the map. The "i" button next to it opens a detailed explanation for the operator\n- In the Summary block hovering a field or zone highlights its outline on the map, clicking its name zooms the map to it\n- Coverage below 100 % is mostly due to the margin from boundaries and zones\n- The sprayer is on during passes and off on turns and transits: `DO_SPRAYER` or `DO_SET_SERVO`\n- QGC WPL 110 mission: "Download", "Copy", "Send" to the vehicle; vehicles from the groups are shown over the field\n- In simulation a quadcopter flies the passes, green while spraying\n- Without `plan` a demo opens: three fields near Minsk with zones inside fields, on their edges and between fields',
|
|
126
|
-
zh: "🎯 **用途**\n实时对象地图:每个对象的位置、航向和轨迹。另外两个模式用于生成任务:「航线」是航点规划器,「农业」是农业无人机喷洒任务生成器。\n\n📦 **数据包**\n- 设备字段分组,每个分组一个对象:默认 `MAV`,多个用空格分隔(`MAV GNSS`);无需绑定变量\n- 遥测流:坐标每 0.5-1 秒一次,名称和序列号频率更低\n- 「对象」仅显示;「航线」和「农业」通过 `onSend` 输出任务,计划由地图的使用方保存(`route` / `plan` 及其回调)\n\n🔑 **键**\n- `Lat` - 数字,°:纬度,必需;`Lat` 和 `Lon` 为 0 - 无定位,不绘制对象\n- `Lon` - 数字,°:经度,必需\n- `Alt` - 数字,m:高度\n- `Heading` - 数字,0-360°:航向,旋转标记\n- `Sat` - 卫星数\n- `DevName` - 字符串:对象名称,标记标签;缺省时为分组名\n- `DevSN` - 字符串:序列号\n- `WPNum` - 当前任务指令编号;仅「航线」和「农业」用于标题栏中的进度\n\n✨ **特点**\n- 键与「飞行显示器」和「关于设备」通用 - 一个数据包可供多个组件使用\n- 点击对象 - 显示所有值的卡片,带「复制」、「跟随」和「隐藏」按钮\n- 操作员在地图上切换轨迹、轨迹点数和标记超时;无新数据的对象变红,再过一个超时后隐藏\n- 标题栏中的「显示全部」将对象纳入视野;地图本身不会自动移动\n- 标题栏显示已配置对象中在线的数量\n- 仅 2D:按住鼠标右键旋转地图,缩放按钮下方的指南针将其恢复为正北\n- 主色作用于整个组件:按钮、航线、航点、起飞点、转场以及模拟中的飞行器。有含义的颜色保持不变:田块为绿色,禁飞区为红色,转弯为橙色;「清除」、删除和发送错误为红色\n\n⚙️ **设置**\n- 字段分组、主色\n- 地图高度 `S`/`M`/`L`/`XL`、标记图标\n- 默认值:轨迹及其点数\n- 模式:「对象」、「航线」或「农业」\n- 模拟模式:「对象」中六架飞行器,「航线」和「农业」中沿航线飞行;模拟面板位于地图底部中央\n\n📍 **航线模式**\n- 常规规划:按飞行顺序放置航点,每个航点有自己的高度和速度\n- 地图左上角的「航点编辑」开启编辑:点击地图添加航点,航点可拖动,拖动线段中点插入,右键删除;「完成」或 Esc 结束编辑;未开启时仅显示编号\n- 在“汇总”的航点列表中设置高度、速度和删除,拖动行可调整顺序;返航降落 (RTL)\n- QGC WPL 110 任务:起飞、航点、RTL;「下载」、「复制」、「发送」;分组中的飞行器显示在航线上方\n- 标题中的进度:模拟时取自模拟,否则根据第一个分组飞行器的 `WPNum` 和位置\n\n🌾 **农业模式**\n- 地图上的一个或多个田块和禁飞区生成喷洒航线\n- 地图左上角的「田块编辑」和「禁飞区编辑」:点击绘制轮廓,点击第一个点、双击、Enter 或「闭合」完成;顶点可拖动,拖动边的中点添加顶点,右键删除;起飞点可随时拖动\n- 禁飞区可以位于田块内、跨出田块边缘或位于田块外。作业行只去掉其在田块内的部分,田块面积也只减去这部分\n- ⚠️ 从起飞点到田块、田块之间以及返航的转场都会按边距绕开所有禁飞区。务必把田块之间的电力线杆、塔、树木和建筑圈为禁飞区,否则飞行器会直线飞行并可能撞上它们\n- 作业行间距不大于喷幅;最外侧作业行与边缘保持边距,与禁飞区也保持边距;默认喷幅 5 m,边距 2 m\n- 禁飞区和缺口把田块分成若干单元;不超过 10 个单元时完整遍历顺序,更多时从最近的开始并用 2-opt 改进;转场和转弯沿绕开禁飞区的最短路径\n- 田块按由近到远依次作业,每个田块有自己的作业行角度\n- 「自动计算」按完整航线为每个田块选择角度:代价为飞行时间加每次转弯 4 s,再加漏喷惩罚(漏喷一米作业行按三米飞行计算)。搜索:5° 步长并加上田块各边方向,然后在三个最佳附近以 1° 步长,最后在胜出角度附近以 0.1° 步长;每个田块约 75 次计算,进度显示在地图上。旁边的「i」按钮为操作员打开详细说明\n- 在“汇总”中将鼠标悬停在田块或禁飞区上会在地图上高亮其轮廓,点击名称会将地图缩放到该处\n- 覆盖率低于 100 % 主要是由于与边界和禁飞区的边距\n- 喷洒器在作业行开启,在转弯和转场时关闭:`DO_SPRAYER` 或 `DO_SET_SERVO`\n- QGC WPL 110 任务:「下载」、「复制」、「发送」到飞行器;分组中的飞行器显示在田块上方\n- 模拟中四旋翼沿作业行飞行,喷洒时为绿色\n- 未传入 `plan` 时打开演示:明斯克附近三个田块,禁飞区位于田块内、田块边缘以及田块之间",
|
|
124
|
+
ru: "🎯 **Назначение**\nКарта объектов в реальном времени: положение, курс и траектория каждого объекта. Два других режима строят миссию: «Маршрут» - планировщик из точек, «Агро» - генератор миссии опрыскивания для агродрона.\n\n📦 **Пакет данных**\n- Поля групп устройства, по группе на объект: по умолчанию `MAV`, несколько - через пробел (`MAV GNSS`); привязывать переменные не нужно\n- Поток телеметрии: координаты - раз в 0.5-1 с, имя и серийный номер - реже\n- «Объекты» только показывают; «Маршрут» и «Агро» отдают миссию наружу через `onSend`, план хранит владелец карты (`route` / `plan` и их колбэки)\n\n🔑 **Ключи**\n- `Lat` - число, °: широта, обязательный; `Lat` и `Lon` = 0 - нет фикса, объект не рисуется\n- `Lon` - число, °: долгота, обязательный\n- `Alt` - число, м: высота\n- `Heading` - число, 0-360°: курс, поворачивает маркер\n- `Sat` - число спутников\n- `DevName` - строка: имя объекта, подпись маркера; без него - имя группы\n- `DevSN` - строка: серийный номер\n- `WPNum` - номер текущей команды миссии; нужен только «Маршруту» и «Агро» для прогресса в шапке\n\n✨ **Особенности**\n- Ключи общие с «Пилотажным дисплеем» и «Об устройстве» - один пакет питает несколько виджетов\n- Клик по объекту - карточка со всеми значениями, кнопки «Копировать», «Следить» и «Скрыть»\n- Траекторию, число её точек и таймаут маркеров оператор переключает на карте; объект без новых данных краснеет, ещё через таймаут скрывается\n- «Показать все» в шапке вписывает объекты в экран; сама карта вид не меняет\n- В шапке - сколько объектов на связи из заданных\n- Только 2D: правой кнопкой мыши карта поворачивается, компас под зумом возвращает её на север\n- Мастер-цвет красит весь виджет: кнопки, линию маршрута, точки, точку взлёта, переходы и аппарат в имитации. Цвета со смыслом не меняются: поля зелёные, запретные зоны красные, развороты оранжевые; «Очистить», удаление и ошибка отправки красные\n\n⚙️ **Настройки**\n- Группы полей, мастер-цвет\n- Высота карты `S`/`M`/`L`/`XL`, иконка маркера\n- Начальные значения: траектория и число её точек\n- Режим: «Объекты», «Маршрут» или «Агро»\n- Режим имитации: шесть аппаратов в «Объектах», полёт по траектории в «Маршруте» и «Агро»; панель имитации внизу карты по центру\n\n📍 **Режим «Маршрут»**\n- Обычный планировщик: точки по порядку облёта, у каждой своя высота и скорость\n- «Редактор точек» в левом верхнем углу карты включает правку: клик по карте добавляет точку, точки перетаскиваются, середина отрезка вставляет точку, правый клик удаляет; «Готово» или Esc заканчивают правку; без правки видны только номера\n- Высота, скорость и удаление - в списке точек блока «Итог», порядок меняется перетаскиванием строки; возврат с посадкой (RTL)\n- Миссия QGC WPL 110: взлёт, точки, RTL; «Скачать», «Копировать», «Отправить»; аппараты из групп видны поверх маршрута\n- Прогресс в шапке: в имитации - по ней, иначе по `WPNum` и положению аппарата первой группы\n- «Показать все» в шапке вписывает весь маршрут и точку взлёта; при появлении карты (загрузка, разворачивание виджета) это происходит само\n\n🌾 **Режим «Агро»**\n- Одно или несколько полей и запретные зоны на карте превращаются в траекторию опрыскивания\n- «Редактор полей» и «Редактор запретных зон» в левом верхнем углу карты: контур обводится кликами, замыкается кликом по первой точке, двойным кликом, Enter или «Замкнуть»; вершины перетаскиваются, середина стороны добавляет точку, правый клик удаляет; точка взлёта перетаскивается всегда\n- Запретная зона может лежать в поле, выходить за его край или стоять вне полей. Из проходов вырезается только её часть внутри поля, площадь поля уменьшается только на эту часть\n- ⚠️ Перелёты от точки взлёта к полю, между полями и домой обходят все зоны с отступом. Опоры ЛЭП, вышки, деревья и постройки между полями обязательно обводите зонами, иначе аппарат полетит напрямую и может в них врезаться\n- Проходы с шагом не больше ширины захвата; крайние проходы на отступе от края, от зон тоже держится отступ; по умолчанию захват 5 м, отступ 2 м\n- Зоны и вырезы делят поле на ячейки; порядок ячеек до 10 штук перебирается полностью, больше - от ближайшей с улучшением 2-opt; переходы и развороты идут по кратчайшему пути в обход зон\n- Поля облетаются по очереди от ближайшего, у каждого поля свой угол проходов\n- «Авторасчёт» подбирает угол каждого поля по полной траектории: цена - время облёта плюс 4 с на разворот плюс штраф за недолив (метр недолитого прохода как три метра полёта). Поиск: шаг 5° и направления сторон поля, затем 1° около трёх лучших, затем 0.1° около победителя; около 75 расчётов на поле, прогресс на карте. Кнопка «i» рядом открывает оператору подробную справку\n- «Показать все» в шапке вписывает все поля, зоны и точку взлёта; при появлении карты (загрузка, разворачивание виджета) это происходит само\n- В блоке «Итог» наведение на поле или зону подсвечивает контур на карте, нажатие на название приближает к нему карту\n- Покрытие меньше 100 % в основном из-за отступа от границ и зон\n- Распылитель включается на проходах и выключается на разворотах и переходах: `DO_SPRAYER` или `DO_SET_SERVO`\n- Миссия QGC WPL 110: «Скачать», «Копировать», «Отправить» на борт; аппараты из групп видны поверх поля\n- В имитации квадрокоптер облетает проходы, зелёный во время распыления\n- Без `plan` открывается демо: три поля под Минском с зонами внутри полей, на их краях и между полями",
|
|
125
|
+
en: '🎯 **Purpose**\nA real-time map of objects: position, heading and track of each object. Two other modes build a mission: "Route" is a waypoint planner, "Agro" is a spraying mission generator for an agricultural drone.\n\n📦 **Data packet**\n- Device field groups, one group per object: `MAV` by default, several separated by spaces (`MAV GNSS`); no variable binding needed\n- Telemetry stream: coordinates every 0.5-1 s, name and serial number less often\n- "Objects" only displays; "Route" and "Agro" pass the mission out through `onSend`, the plan is kept by the map owner (`route` / `plan` and their callbacks)\n\n🔑 **Keys**\n- `Lat` - number, °: latitude, required; `Lat` and `Lon` = 0 - no fix, the object is not drawn\n- `Lon` - number, °: longitude, required\n- `Alt` - number, m: altitude\n- `Heading` - number, 0-360°: heading, rotates the marker\n- `Sat` - satellite count\n- `DevName` - string: object name, the marker label; without it - the group name\n- `DevSN` - string: serial number\n- `WPNum` - number of the current mission command; only "Route" and "Agro" use it for progress in the header\n\n✨ **Features**\n- Keys are shared with the "Flight Display" and "About Device" - one packet feeds several widgets\n- Click an object - a card with all values, "Copy", "Follow" and "Hide" buttons\n- The operator switches the track, its point count and marker timeout on the map; an object without new data turns red, after one more timeout it is hidden\n- "Show all" in the header fits all objects into view; the map never moves by itself\n- The header shows how many of the configured objects are online\n- 2D only: the right mouse button rotates the map, the compass under the zoom returns it to north\n- The master color paints the whole widget: buttons, route line, points, takeoff point, transits and the vehicle in simulation. Meaningful colors stay: fields green, no-fly zones red, turns orange; "Clear", delete and send error red\n\n⚙️ **Settings**\n- Field groups, master color\n- Map height `S`/`M`/`L`/`XL`, marker icon\n- Defaults: track and its point count\n- Mode: "Objects", "Route" or "Agro"\n- Simulation mode: six vehicles in "Objects", a flight along the path in "Route" and "Agro"; the simulation panel is at the bottom center of the map\n\n📍 **Route mode**\n- A regular planner: points in flight order, each with its own altitude and speed\n- "Waypoint editor" in the top left corner of the map turns on editing: a click adds a point, points can be dragged, a segment midpoint inserts one, right-click removes; "Done" or Esc ends editing; otherwise only numbers are shown\n- Altitude, speed and removal in the point list of the Summary block, order is changed by dragging a row; return and land (RTL)\n- QGC WPL 110 mission: takeoff, points, RTL; "Download", "Copy", "Send"; vehicles from the groups are shown over the route\n- Progress in the header: from the simulation, otherwise from `WPNum` and the position of the vehicle from the first group\n- "Show all" in the header fits the whole route and the takeoff point into view; this also happens by itself when the map appears (page load, widget expanded)\n\n🌾 **Agro mode**\n- One or more fields and no-fly zones on the map become a spraying path\n- "Field editor" and "No-fly zone editor" in the top left corner of the map: an outline is traced by clicks and closed by clicking the first point, a double click, Enter or "Close"; vertices can be dragged, a side midpoint adds a point, right-click removes; the takeoff point can always be dragged\n- A no-fly zone can lie inside a field, stick out over its edge or stand outside fields. Only its part inside the field is cut from the passes, and the field area is reduced only by that part\n- ⚠️ Transits from takeoff to a field, between fields and back home avoid all zones with the margin. Be sure to outline power line poles, towers, trees and buildings between fields as zones, otherwise the vehicle flies straight and may crash into them\n- Passes are spaced no wider than the swath; the outer passes keep the margin from the edge, zones are kept at the margin too; defaults: swath 5 m, margin 2 m\n- Zones and notches split a field into cells; up to 10 cells their order is checked exhaustively, beyond that nearest first with 2-opt improvement; transits and turns follow the shortest path around zones\n- Fields are flown one after another, nearest first, each field has its own pass angle\n- "Auto-calculate" picks each field\'s angle from the full path: cost is flight time plus 4 s per turn plus a penalty for missed spraying (a missed meter of pass counts as three meters of flight). Search: 5° steps and field side directions, then 1° around the three best, then 0.1° around the winner; about 75 calculations per field, progress on the map. The "i" button next to it opens a detailed explanation for the operator\n- "Show all" in the header fits all fields, zones and the takeoff point into view; this also happens by itself when the map appears (page load, widget expanded)\n- In the Summary block hovering a field or zone highlights its outline on the map, clicking its name zooms the map to it\n- Coverage below 100 % is mostly due to the margin from boundaries and zones\n- The sprayer is on during passes and off on turns and transits: `DO_SPRAYER` or `DO_SET_SERVO`\n- QGC WPL 110 mission: "Download", "Copy", "Send" to the vehicle; vehicles from the groups are shown over the field\n- In simulation a quadcopter flies the passes, green while spraying\n- Without `plan` a demo opens: three fields near Minsk with zones inside fields, on their edges and between fields',
|
|
126
|
+
zh: "🎯 **用途**\n实时对象地图:每个对象的位置、航向和轨迹。另外两个模式用于生成任务:「航线」是航点规划器,「农业」是农业无人机喷洒任务生成器。\n\n📦 **数据包**\n- 设备字段分组,每个分组一个对象:默认 `MAV`,多个用空格分隔(`MAV GNSS`);无需绑定变量\n- 遥测流:坐标每 0.5-1 秒一次,名称和序列号频率更低\n- 「对象」仅显示;「航线」和「农业」通过 `onSend` 输出任务,计划由地图的使用方保存(`route` / `plan` 及其回调)\n\n🔑 **键**\n- `Lat` - 数字,°:纬度,必需;`Lat` 和 `Lon` 为 0 - 无定位,不绘制对象\n- `Lon` - 数字,°:经度,必需\n- `Alt` - 数字,m:高度\n- `Heading` - 数字,0-360°:航向,旋转标记\n- `Sat` - 卫星数\n- `DevName` - 字符串:对象名称,标记标签;缺省时为分组名\n- `DevSN` - 字符串:序列号\n- `WPNum` - 当前任务指令编号;仅「航线」和「农业」用于标题栏中的进度\n\n✨ **特点**\n- 键与「飞行显示器」和「关于设备」通用 - 一个数据包可供多个组件使用\n- 点击对象 - 显示所有值的卡片,带「复制」、「跟随」和「隐藏」按钮\n- 操作员在地图上切换轨迹、轨迹点数和标记超时;无新数据的对象变红,再过一个超时后隐藏\n- 标题栏中的「显示全部」将对象纳入视野;地图本身不会自动移动\n- 标题栏显示已配置对象中在线的数量\n- 仅 2D:按住鼠标右键旋转地图,缩放按钮下方的指南针将其恢复为正北\n- 主色作用于整个组件:按钮、航线、航点、起飞点、转场以及模拟中的飞行器。有含义的颜色保持不变:田块为绿色,禁飞区为红色,转弯为橙色;「清除」、删除和发送错误为红色\n\n⚙️ **设置**\n- 字段分组、主色\n- 地图高度 `S`/`M`/`L`/`XL`、标记图标\n- 默认值:轨迹及其点数\n- 模式:「对象」、「航线」或「农业」\n- 模拟模式:「对象」中六架飞行器,「航线」和「农业」中沿航线飞行;模拟面板位于地图底部中央\n\n📍 **航线模式**\n- 常规规划:按飞行顺序放置航点,每个航点有自己的高度和速度\n- 地图左上角的「航点编辑」开启编辑:点击地图添加航点,航点可拖动,拖动线段中点插入,右键删除;「完成」或 Esc 结束编辑;未开启时仅显示编号\n- 在“汇总”的航点列表中设置高度、速度和删除,拖动行可调整顺序;返航降落 (RTL)\n- QGC WPL 110 任务:起飞、航点、RTL;「下载」、「复制」、「发送」;分组中的飞行器显示在航线上方\n- 标题中的进度:模拟时取自模拟,否则根据第一个分组飞行器的 `WPNum` 和位置\n- 标题栏中的「显示全部」将整条航线和起飞点纳入视野;地图出现时(页面加载、展开组件)会自动执行\n\n🌾 **农业模式**\n- 地图上的一个或多个田块和禁飞区生成喷洒航线\n- 地图左上角的「田块编辑」和「禁飞区编辑」:点击绘制轮廓,点击第一个点、双击、Enter 或「闭合」完成;顶点可拖动,拖动边的中点添加顶点,右键删除;起飞点可随时拖动\n- 禁飞区可以位于田块内、跨出田块边缘或位于田块外。作业行只去掉其在田块内的部分,田块面积也只减去这部分\n- ⚠️ 从起飞点到田块、田块之间以及返航的转场都会按边距绕开所有禁飞区。务必把田块之间的电力线杆、塔、树木和建筑圈为禁飞区,否则飞行器会直线飞行并可能撞上它们\n- 作业行间距不大于喷幅;最外侧作业行与边缘保持边距,与禁飞区也保持边距;默认喷幅 5 m,边距 2 m\n- 禁飞区和缺口把田块分成若干单元;不超过 10 个单元时完整遍历顺序,更多时从最近的开始并用 2-opt 改进;转场和转弯沿绕开禁飞区的最短路径\n- 田块按由近到远依次作业,每个田块有自己的作业行角度\n- 「自动计算」按完整航线为每个田块选择角度:代价为飞行时间加每次转弯 4 s,再加漏喷惩罚(漏喷一米作业行按三米飞行计算)。搜索:5° 步长并加上田块各边方向,然后在三个最佳附近以 1° 步长,最后在胜出角度附近以 0.1° 步长;每个田块约 75 次计算,进度显示在地图上。旁边的「i」按钮为操作员打开详细说明\n- 标题栏中的「显示全部」将所有田块、禁飞区和起飞点纳入视野;地图出现时(页面加载、展开组件)会自动执行\n- 在“汇总”中将鼠标悬停在田块或禁飞区上会在地图上高亮其轮廓,点击名称会将地图缩放到该处\n- 覆盖率低于 100 % 主要是由于与边界和禁飞区的边距\n- 喷洒器在作业行开启,在转弯和转场时关闭:`DO_SPRAYER` 或 `DO_SET_SERVO`\n- QGC WPL 110 任务:「下载」、「复制」、「发送」到飞行器;分组中的飞行器显示在田块上方\n- 模拟中四旋翼沿作业行飞行,喷洒时为绿色\n- 未传入 `plan` 时打开演示:明斯克附近三个田块,禁飞区位于田块内、田块边缘以及田块之间",
|
|
127
127
|
},
|
|
128
128
|
"component.info.WidgetStackInfo": {
|
|
129
129
|
ru: '🎯 **Назначение**\nОтладка прошивки: свободная память и запас стека задач.\n\n📦 **Пакет данных**\n- Один объект `StackInfo` из ответа на `GET StackInfo`, привязывать переменные не нужно\n- Запрос - кнопкой «Обновить» или автоопросом\n\n🔑 **Ключи**\n- `Heap` - массив `[{ "Name", "Total", "Free", "MinFree" }]`, байт: кучи памяти - `Internal` встроенная и `PSRAM` внешняя ОЗУ у ESP, `Heap` у STM, в виджете понятными подписями; `MinFree` - минимум свободного с момента старта\n- `Tasks` - массив `[{ "Name", "State", "Prio", "Core", "CPU", "FreeMin" }]`: задачи; `State` - `0` выполняется, `1` готова, `2` ждёт, `3` приостановлена, `4` удалена; `Core` - ядро (только ESP32, `-1` без привязки); `CPU` - загрузка задачи, % одного ядра с прошлого ответа; `FreeMin` - минимальный запас стека, байт\n\n✨ **Особенности**\n- Светлая часть полосы кучи - пик занятости\n- Задачи отсортированы по запасу стека - самые рискованные сверху\n- Загрузка от 50 % - оранжевым, от 80 % - красным (кроме `IDLE` - это свободное время ядра); колонка есть, если прошивка её присылает\n- Свёрнутый виджет не опрашивает устройство\n\n⚙️ **Настройки**\n- Порог запаса стека: меньше порога - красным, меньше удвоенного - оранжевым\n- Автоопрос: выкл / 1 / 5 / 10 с; мастер-цвет',
|
|
@@ -758,6 +758,16 @@ const translations = {
|
|
|
758
758
|
"widget.mission.passes": { ru: "Маршрут", en: "Route", zh: "航线" },
|
|
759
759
|
"widget.mission.angle": { ru: "Угол проходов", en: "Pass angle", zh: "作业角度" },
|
|
760
760
|
"widget.mission.auto": { ru: "Авторасчёт", en: "Auto-calculate", zh: "自动计算" },
|
|
761
|
+
"widget.mission.fitHint": {
|
|
762
|
+
ru: "Вписать в карту все поля, зоны и точку взлёта",
|
|
763
|
+
en: "Fit all fields, zones and the takeoff point into view",
|
|
764
|
+
zh: "将所有田块、禁飞区和起飞点纳入视野",
|
|
765
|
+
},
|
|
766
|
+
"widget.route.fitHint": {
|
|
767
|
+
ru: "Вписать в карту весь маршрут и точку взлёта",
|
|
768
|
+
en: "Fit the whole route and the takeoff point into view",
|
|
769
|
+
zh: "将整条航线和起飞点纳入视野",
|
|
770
|
+
},
|
|
761
771
|
"widget.mission.showOnMap": { ru: "Показать на карте", en: "Show on the map", zh: "在地图上显示" },
|
|
762
772
|
"widget.mission.autoInfoTitle": { ru: "Как работает авторасчёт", en: "How auto-calculate works", zh: "自动计算的原理" },
|
|
763
773
|
"widget.mission.autoInfo": {
|
package/dist/options.js
CHANGED
|
@@ -60,16 +60,16 @@ export const optionsStore = derived(T, ($T) => {
|
|
|
60
60
|
{ id: id(), value: "underline", name: $T("constructor.props.underline"), icon: PROPS_ICONS.underline },
|
|
61
61
|
{ id: id(), value: "background", name: $T("constructor.props.background"), icon: PROPS_ICONS.highlight },
|
|
62
62
|
],
|
|
63
|
-
/* Семантическая палитра
|
|
63
|
+
/* Семантическая палитра темы: те же роли, что у мастер-цвета виджетов; свотч показывает чистый цвет Apple (--X-mark), как у тегов; bg-max - нейтральный вариант, свотч с ним отмечается рамкой */
|
|
64
64
|
COLOR_OPTIONS: [
|
|
65
65
|
{ id: id(), name: "-", value: "bg-max", class: "bg-max text-transparent" },
|
|
66
|
-
{ id: id(), name: "", value: "bg-red", class: "bg-red" },
|
|
67
|
-
{ id: id(), name: "", value: "bg-orange", class: "bg-orange" },
|
|
68
|
-
{ id: id(), name: "", value: "bg-yellow", class: "bg-yellow" },
|
|
69
|
-
{ id: id(), name: "", value: "bg-green", class: "bg-green" },
|
|
70
|
-
{ id: id(), name: "", value: "bg-blue", class: "bg-blue" },
|
|
71
|
-
{ id: id(), name: "", value: "bg-purple", class: "bg-purple" },
|
|
72
|
-
{ id: id(), name: "", value: "bg-gray", class: "bg-gray" },
|
|
66
|
+
{ id: id(), name: "", value: "bg-red", class: "bg-red [--bg-color:var(--red-mark)]!" },
|
|
67
|
+
{ id: id(), name: "", value: "bg-orange", class: "bg-orange [--bg-color:var(--orange-mark)]!" },
|
|
68
|
+
{ id: id(), name: "", value: "bg-yellow", class: "bg-yellow [--bg-color:var(--yellow-mark)]!" },
|
|
69
|
+
{ id: id(), name: "", value: "bg-green", class: "bg-green [--bg-color:var(--green-mark)]!" },
|
|
70
|
+
{ id: id(), name: "", value: "bg-blue", class: "bg-blue [--bg-color:var(--blue-mark)]!" },
|
|
71
|
+
{ id: id(), name: "", value: "bg-purple", class: "bg-purple [--bg-color:var(--purple-mark)]!" },
|
|
72
|
+
{ id: id(), name: "", value: "bg-gray", class: "bg-gray [--bg-color:var(--gray-mark)]!" },
|
|
73
73
|
],
|
|
74
74
|
TEXT_COLOR_OPTIONS: [
|
|
75
75
|
{
|