781 lines
36 KiB
HTML
781 lines
36 KiB
HTML
<!doctype html>
|
||
<html lang="vi">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>LiDAR Manager</title>
|
||
<link rel="stylesheet" href="/style.css" />
|
||
</head>
|
||
<body>
|
||
<div class="shell">
|
||
<aside class="sidebar">
|
||
<div class="brand">
|
||
<div class="brandIcon">R</div>
|
||
<div class="brandText">
|
||
<div class="brandTitle">PhenikaaX</div>
|
||
<div class="brandSub">RobotApp</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="navTitle">WORKSPACE</div>
|
||
<nav class="nav">
|
||
<a class="navItem active" href="#" data-page="dashboard" aria-current="page">
|
||
<span class="navDot"></span>
|
||
Dashboard
|
||
</a>
|
||
<a class="navItem" href="#" data-page="config">
|
||
<span class="navDot"></span>
|
||
Cấu hình
|
||
</a>
|
||
</nav>
|
||
|
||
<div class="navTitle">CÀI ĐẶT</div>
|
||
<nav class="nav">
|
||
<a class="navItem" href="#" data-page="missions">
|
||
<span class="navDot"></span>
|
||
Missions
|
||
</a>
|
||
</nav>
|
||
|
||
<div class="sidebarFooter">
|
||
<div class="statusBadge">
|
||
<span class="statusLed"></span>
|
||
<span id="status" class="statusText">…</span>
|
||
</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<div class="body">
|
||
<header class="topbar">
|
||
<div class="topbarTitle">
|
||
<div class="kicker">PhenikaaX Robotics</div>
|
||
<div class="pageTitle">Cấu Hình</div>
|
||
</div>
|
||
<div class="topbarActions">
|
||
<button id="refreshBtn" type="button" class="btn subtle">Tải lại</button>
|
||
<button id="saveLayoutBtn" class="btn primary" type="button">Lưu layout</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="content">
|
||
<div class="page" id="pageOverview" data-page-content="dashboard" hidden>
|
||
<div class="dashboardPage">
|
||
<section class="card">
|
||
<div class="cardHeader">
|
||
<div>
|
||
<div class="cardTitle">Dashboard</div>
|
||
<div class="cardSub">Widget mission — chạy, xếp hàng và tạm dừng giống MiR Fleet.</div>
|
||
</div>
|
||
<div class="dashboardToolbar">
|
||
<button id="dashboardAddWidgetBtn" type="button" class="btn subtle">Thêm widget</button>
|
||
<button id="dashboardEditBtn" type="button" class="btn subtle">Sửa layout</button>
|
||
</div>
|
||
</div>
|
||
<div class="cardBody">
|
||
<div id="dashboardGrid" class="dashboardGrid"></div>
|
||
<p id="dashboardEmpty" class="mutedNote dashboardEmpty" hidden>Chưa có widget. Bấm «Thêm widget» để bắt đầu.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card dashboardInfoCard">
|
||
<div class="cardHeader">
|
||
<div>
|
||
<div class="cardTitle">Hệ thống</div>
|
||
<div class="cardSub">Trạng thái backend và layout đang active.</div>
|
||
</div>
|
||
</div>
|
||
<div class="cardBody dashboardInfoGrid">
|
||
<div class="row rowWide">
|
||
<label>Backend</label>
|
||
<div id="overviewBackend" class="mutedNote">—</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Layout</label>
|
||
<div id="overviewActiveLayout" class="mutedNote">—</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Model robot</label>
|
||
<div id="overviewActiveModel" class="mutedNote">—</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>LiDAR / IMU</label>
|
||
<div id="overviewActiveSensors" class="mutedNote">—</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="page" id="pageConfig" data-page-content="config">
|
||
<div class="contentLeft">
|
||
<section class="card" id="layoutManagerCard">
|
||
<div class="cardHeader">
|
||
<div>
|
||
<div class="cardTitle">Quản lý layout</div>
|
||
<div class="cardSub">Nhiều cấu hình robot — mỗi layout có LiDAR và model riêng.</div>
|
||
</div>
|
||
</div>
|
||
<div class="cardBody">
|
||
<div class="row rowWide">
|
||
<label>Layout hiện tại</label>
|
||
<select id="layoutSelect"></select>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Tên layout mới</label>
|
||
<input id="layoutNewName" type="text" placeholder="VD: AGV kho A" />
|
||
</div>
|
||
<div class="checkRow">
|
||
<label>
|
||
<input id="layoutCloneCurrent" type="checkbox" />
|
||
Sao chép từ layout đang mở
|
||
</label>
|
||
</div>
|
||
<div class="layoutManagerActions">
|
||
<button id="layoutCreateBtn" type="button" class="btn subtle">Tạo layout</button>
|
||
<button id="layoutDeleteBtn" type="button" class="btn subtle danger">Xóa</button>
|
||
</div>
|
||
<p id="layoutActiveHint" class="mutedNote">—</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card collapsible" id="lidarListCard">
|
||
<div
|
||
class="cardHeader cardHeaderToggle"
|
||
id="lidarListCardToggle"
|
||
role="button"
|
||
tabindex="0"
|
||
aria-expanded="true"
|
||
aria-controls="lidarListCardBody"
|
||
>
|
||
<div>
|
||
<div class="cardTitle">LiDARs</div>
|
||
<div class="cardSub">Đăng ký tên, IP, port và chỉnh pose theo robot frame.</div>
|
||
</div>
|
||
<span class="cardChevron" aria-hidden="true"></span>
|
||
</div>
|
||
|
||
<div class="cardBody" id="lidarListCardBody">
|
||
<form id="lidarForm" class="form">
|
||
<div class="row">
|
||
<label>Tên</label>
|
||
<input id="name" placeholder="Lidar trước" required />
|
||
</div>
|
||
<div class="row">
|
||
<label>IP</label>
|
||
<input id="ip" placeholder="192.168.0.10" required />
|
||
</div>
|
||
<div class="row">
|
||
<label>Port</label>
|
||
<input id="port" type="number" min="1" max="65535" value="2112" required />
|
||
</div>
|
||
<div class="actions">
|
||
<button id="addLidarBtn" class="btn primary" type="button">Thêm</button>
|
||
</div>
|
||
<p id="lidarFormHint" class="formHint" hidden></p>
|
||
</form>
|
||
|
||
<div id="lidarList" class="list"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card collapsible" id="imuListCard">
|
||
<div
|
||
class="cardHeader cardHeaderToggle"
|
||
id="imuListCardToggle"
|
||
role="button"
|
||
tabindex="0"
|
||
aria-expanded="true"
|
||
aria-controls="imuListCardBody"
|
||
>
|
||
<div>
|
||
<div class="cardTitle">IMU</div>
|
||
<div class="cardSub">Cảm biến quán tính — frame, topic và pose trên robot.</div>
|
||
</div>
|
||
<span class="cardChevron" aria-hidden="true"></span>
|
||
</div>
|
||
|
||
<div class="cardBody" id="imuListCardBody">
|
||
<form id="imuForm" class="form">
|
||
<div class="row">
|
||
<label>Tên</label>
|
||
<input id="imuName" placeholder="IMU chính" required />
|
||
</div>
|
||
<div class="row">
|
||
<label>Frame ID</label>
|
||
<input id="imuFrameId" placeholder="imu_link" required />
|
||
</div>
|
||
<div class="row">
|
||
<label>Topic</label>
|
||
<input id="imuTopic" placeholder="imu/data" value="imu/data" required />
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Nguồn</label>
|
||
<select id="imuSource">
|
||
<option value="external">Ngoài (ROS topic)</option>
|
||
<option value="lidar_builtin">Tích hợp LiDAR</option>
|
||
<option value="onboard">Onboard robot</option>
|
||
</select>
|
||
</div>
|
||
<div class="row">
|
||
<label>Tần số (Hz)</label>
|
||
<input id="imuRateHz" type="number" min="1" max="1000" step="1" value="100" />
|
||
</div>
|
||
<div class="checkRow">
|
||
<label>
|
||
<input id="imuEnabled" type="checkbox" checked />
|
||
Bật IMU
|
||
</label>
|
||
</div>
|
||
<div class="actions">
|
||
<button id="addImuBtn" class="btn primary" type="button">Thêm IMU</button>
|
||
</div>
|
||
<p id="imuFormHint" class="formHint" hidden></p>
|
||
</form>
|
||
|
||
<div id="imuList" class="list"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card collapsible" id="robotModelCard">
|
||
<div
|
||
class="cardHeader cardHeaderToggle"
|
||
id="robotModelCardToggle"
|
||
role="button"
|
||
tabindex="0"
|
||
aria-expanded="true"
|
||
aria-controls="robotModelCardBody"
|
||
>
|
||
<div>
|
||
<div class="cardTitle">Model robot</div>
|
||
<div class="cardSub">Kinematic differential — bánh, động cơ và giới hạn vận tốc.</div>
|
||
</div>
|
||
<span class="cardChevron" aria-hidden="true"></span>
|
||
</div>
|
||
<div class="cardBody" id="robotModelCardBody">
|
||
<div class="modelForm">
|
||
<div class="row rowWide">
|
||
<label>Model</label>
|
||
<select id="robotModel">
|
||
<option value="diff">Differential (2 bánh)</option>
|
||
<option value="bicycle">Bicycle</option>
|
||
</select>
|
||
</div>
|
||
<div id="diffParams" class="modelParams">
|
||
<details class="acc" open>
|
||
<summary>Hình học bánh</summary>
|
||
<div class="accBody">
|
||
<div class="row rowWide">
|
||
<label>Khoảng cách 2 bánh</label>
|
||
<div class="inputUnit">
|
||
<input id="wheelSeparationM" type="number" min="0.05" max="5" step="0.01" value="1.0" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Bán kính bánh</label>
|
||
<div class="inputUnit">
|
||
<input id="wheelRadiusM" type="number" min="0.02" max="1" step="0.01" value="0.3" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Tỷ lệ hiển thị</label>
|
||
<div class="inputUnit">
|
||
<input id="scaleMPerPx" type="number" min="0.001" max="0.1" step="0.001" value="0.005" />
|
||
<span class="unit">m/px</span>
|
||
</div>
|
||
</div>
|
||
<details class="acc accNested">
|
||
<summary>Hiệu chỉnh (nâng cao)</summary>
|
||
<div class="accBody">
|
||
<div class="row rowWide">
|
||
<label>b multiplier</label>
|
||
<input id="wheelSeparationMult" type="number" min="0.5" max="2" step="0.01" value="1.0" />
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>r multiplier</label>
|
||
<input id="wheelRadiusMult" type="number" min="0.5" max="2" step="0.01" value="1.0" />
|
||
</div>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="acc">
|
||
<summary>Động cơ</summary>
|
||
<div class="accBody">
|
||
<p class="mutedNote">Mỗi bánh gán một động cơ — chọn hãng và model.</p>
|
||
<div id="motorWheels" class="motorWheels"></div>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="acc">
|
||
<summary>Giới hạn vận tốc</summary>
|
||
<div class="accBody">
|
||
<div class="row rowWide">
|
||
<label>cmd_vel timeout</label>
|
||
<div class="inputUnit">
|
||
<input id="cmdVelTimeout" type="number" min="0.05" max="5" step="0.05" value="0.25" />
|
||
<span class="unit">s</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Linear max</label>
|
||
<div class="inputUnit">
|
||
<input id="linearMaxVel" type="number" min="0.01" max="5" step="0.05" value="1.0" />
|
||
<span class="unit">m/s</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Linear min</label>
|
||
<div class="inputUnit">
|
||
<input id="linearMinVel" type="number" min="-5" max="0" step="0.05" value="-0.5" />
|
||
<span class="unit">m/s</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Linear accel max</label>
|
||
<div class="inputUnit">
|
||
<input id="linearMaxAccel" type="number" min="0.01" max="10" step="0.05" value="0.8" />
|
||
<span class="unit">m/s²</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Angular max</label>
|
||
<div class="inputUnit">
|
||
<input id="angularMaxVel" type="number" min="0.01" max="10" step="0.05" value="1.7" />
|
||
<span class="unit">rad/s</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Angular accel max</label>
|
||
<div class="inputUnit">
|
||
<input id="angularMaxAccel" type="number" min="0.01" max="10" step="0.05" value="1.5" />
|
||
<span class="unit">rad/s²</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</details>
|
||
|
||
<p id="diffValidation" class="validation" hidden></p>
|
||
</div>
|
||
|
||
<div id="bicycleParams" class="modelParams" hidden>
|
||
<p class="mutedNote">
|
||
Kinematic bicycle — tham chiếu trục sau, quan hệ
|
||
<span class="mono">ω = v·tan(δ)/L</span>
|
||
(<a href="https://thomasfermi.github.io/Algorithms-for-Automated-Driving/Control/BicycleModel.html" target="_blank" rel="noopener">mô hình</a>).
|
||
</p>
|
||
<details class="acc" open>
|
||
<summary>Hình học (wheelbase)</summary>
|
||
<div class="accBody">
|
||
<div class="row rowWide">
|
||
<label>Wheelbase L</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleWheelbaseM" type="number" min="0.2" max="5" step="0.05" value="1.2" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Bán kính bánh</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleWheelRadiusM" type="number" min="0.02" max="1" step="0.01" value="0.15" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Tỷ lệ hiển thị</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleScaleMPerPx" type="number" min="0.001" max="0.1" step="0.001" value="0.005" />
|
||
<span class="unit">m/px</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Góc lái xem trước</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleSteerPreviewDeg" type="number" min="-45" max="45" step="1" value="15" />
|
||
<span class="unit">°</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</details>
|
||
<details class="acc">
|
||
<summary>Động cơ</summary>
|
||
<div class="accBody">
|
||
<p class="mutedNote">Bánh sau (drive) và bánh trước (steer).</p>
|
||
<div id="bicycleMotorWheels" class="motorWheels"></div>
|
||
</div>
|
||
</details>
|
||
<details class="acc">
|
||
<summary>Giới hạn</summary>
|
||
<div class="accBody">
|
||
<div class="row rowWide">
|
||
<label>δ max (lái)</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleSteerMaxDeg" type="number" min="5" max="60" step="1" value="35" />
|
||
<span class="unit">°</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>cmd_vel timeout</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleCmdVelTimeout" type="number" min="0.05" max="5" step="0.05" value="0.25" />
|
||
<span class="unit">s</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Linear max</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleLinearMaxVel" type="number" min="0.01" max="5" step="0.05" value="1.0" />
|
||
<span class="unit">m/s</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Linear accel max</label>
|
||
<div class="inputUnit">
|
||
<input id="bicycleLinearMaxAccel" type="number" min="0.01" max="10" step="0.05" value="0.8" />
|
||
<span class="unit">m/s²</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</details>
|
||
<p id="bicycleValidation" class="validation" hidden></p>
|
||
</div>
|
||
|
||
<details class="acc">
|
||
<summary>Footprint</summary>
|
||
<div class="accBody">
|
||
<p class="mutedNote">Hình dạng robot (ROS polygon) — tọa độ theo robot frame.</p>
|
||
<div class="row rowWide">
|
||
<label>Hình dạng</label>
|
||
<select id="footprintShape">
|
||
<option value="rectangle">Hình chữ nhật</option>
|
||
<option value="circle">Hình tròn</option>
|
||
<option value="regular_polygon">Đa giác đều</option>
|
||
<option value="custom">Tùy chỉnh (đa giác)</option>
|
||
</select>
|
||
</div>
|
||
<div id="footprintPresetPanel" class="footprintPresetPanel">
|
||
<div id="fpRectParams" class="fpShapeParams">
|
||
<div class="row rowWide">
|
||
<label>Chiều dài</label>
|
||
<div class="inputUnit">
|
||
<input id="fpLengthM" type="number" min="0.1" max="10" step="0.05" value="1.4" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Chiều rộng</label>
|
||
<div class="inputUnit">
|
||
<input id="fpWidthM" type="number" min="0.1" max="10" step="0.05" value="1.1" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="fpCircleParams" class="fpShapeParams" hidden>
|
||
<div class="row rowWide">
|
||
<label>Bán kính</label>
|
||
<div class="inputUnit">
|
||
<input id="fpRadiusM" type="number" min="0.1" max="5" step="0.05" value="0.55" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Độ mịn (cạnh)</label>
|
||
<input id="fpCircleSegments" type="number" min="8" max="64" step="1" value="32" />
|
||
</div>
|
||
</div>
|
||
<div id="fpPolyParams" class="fpShapeParams" hidden>
|
||
<div class="row rowWide">
|
||
<label>Bán kính</label>
|
||
<div class="inputUnit">
|
||
<input id="fpPolyRadiusM" type="number" min="0.1" max="5" step="0.05" value="0.6" />
|
||
<span class="unit">m</span>
|
||
</div>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label>Số cạnh</label>
|
||
<input id="fpPolySides" type="number" min="3" max="32" step="1" value="6" />
|
||
</div>
|
||
</div>
|
||
<button id="applyFootprintPresetBtn" type="button" class="btn subtle btnBlock">Áp dụng hình dạng</button>
|
||
</div>
|
||
<div id="footprintCustomPanel" class="footprintCustomPanel hidden">
|
||
<div class="fpVertexRow">
|
||
<span class="fpVertexLabel">Số đỉnh: <strong id="fpVertexCount">0</strong></span>
|
||
<span id="fpSelectedVertexText" class="fpSelectedVertex mutedNote">—</span>
|
||
</div>
|
||
<div class="fpVertexActions">
|
||
<button id="fpAddVertexBtn" type="button" class="btn subtle">Thêm đỉnh</button>
|
||
<button id="fpRemoveVertexBtn" type="button" class="btn subtle" disabled>Xóa đỉnh</button>
|
||
</div>
|
||
</div>
|
||
<button id="editFootprintBtn" type="button" class="btn subtle btnBlock">Sửa footprint</button>
|
||
<div id="footprintEditHint" class="fpHint" hidden></div>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div class="page" id="pageMissions" data-page-content="missions" hidden>
|
||
<div id="missionsListView" class="missionsPage">
|
||
<section class="card">
|
||
<div class="cardHeader">
|
||
<div>
|
||
<div class="cardTitle">Missions</div>
|
||
<div class="cardSub">Setup → Missions — danh sách nhiệm vụ robot.</div>
|
||
</div>
|
||
<button id="missionCreateOpenBtn" type="button" class="btn primary">Create mission</button>
|
||
</div>
|
||
<div class="cardBody">
|
||
<div id="missionListEmpty" class="mutedNote" hidden>Chưa có mission. Bấm Create mission để bắt đầu.</div>
|
||
<div id="missionList" class="missionList"></div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card" id="missionQueueCard">
|
||
<div class="cardHeader">
|
||
<div>
|
||
<div class="cardTitle">Mission queue</div>
|
||
<div class="cardSub">Thêm mission bằng biểu tượng queue — robot chạy theo thứ tự từ trên xuống.</div>
|
||
</div>
|
||
<button id="missionQueueClearBtn" type="button" class="btn subtle danger">Xóa queue</button>
|
||
</div>
|
||
<div class="cardBody">
|
||
<div id="missionQueueRunner" class="missionQueueRunner mutedNote">—</div>
|
||
<div id="missionQueueEmpty" class="mutedNote">Queue trống. Bấm <span class="mono">▤</span> trên mission để thêm.</div>
|
||
<div id="missionQueueList" class="missionQueueList"></div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<div id="missionEditorView" class="missionsPage" hidden>
|
||
<section class="card missionEditorCard">
|
||
<div class="missionEditorTop">
|
||
<div class="missionEditorTitleWrap">
|
||
<button id="missionEditorBackBtn" type="button" class="btn subtle missionBackBtn" aria-label="Quay lại danh sách">←</button>
|
||
<div>
|
||
<div class="missionEditorKicker">Mission editor</div>
|
||
<div class="missionEditorTitleRow">
|
||
<h2 id="missionEditorTitle" class="missionEditorTitle">—</h2>
|
||
<button id="missionSettingsBtn" type="button" class="iconBtn" title="Cài đặt mission" aria-label="Cài đặt mission">⚙</button>
|
||
</div>
|
||
<div id="missionEditorMeta" class="missionEditorMeta">—</div>
|
||
</div>
|
||
</div>
|
||
<div class="missionEditorTopActions">
|
||
<span id="missionEditorDirty" class="missionDirtyBadge" hidden>Chưa lưu</span>
|
||
<button id="missionSaveAsBtn" type="button" class="btn subtle">Save as</button>
|
||
<button id="missionSaveBtn" type="button" class="btn primary">Save</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="missionActionBar" id="missionActionBar" role="toolbar" aria-label="Thêm action">
|
||
<div class="missionGroupTabs" id="missionGroupTabs"></div>
|
||
</div>
|
||
|
||
<div class="missionEditorBody">
|
||
<p class="missionFlowHint">Thực thi từ trên xuống dưới. Kéo biểu tượng ↔ để đổi thứ tự. Với Loop: kéo action vào vùng bên trong.</p>
|
||
<div id="missionActionList" class="missionActionList"></div>
|
||
<div id="missionActionListEmpty" class="missionActionListEmpty mutedNote">Chọn action từ menu phía trên để bắt đầu.</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="configSplitter" class="splitter" role="separator" aria-orientation="vertical" tabindex="0"></div>
|
||
|
||
<div class="contentRight" id="contentRight">
|
||
<section class="card">
|
||
<div class="cardHeader">
|
||
<div>
|
||
<div class="cardTitle">Bố trí trên robot</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="cardBody">
|
||
<div class="canvasWrap" id="canvasWrap">
|
||
<canvas id="canvas"></canvas>
|
||
</div>
|
||
<div class="metaBar">
|
||
<div class="viewHint">Cuộn chuột: zoom • Shift + kéo: di chuyển vùng nhìn</div>
|
||
<div id="robotDiffSummary" class="robotDiffSummary">—</div>
|
||
<div>Robot center: <span id="robotCenterText"></span></div>
|
||
<div>Selected: <span id="selectedText">none</span></div>
|
||
<div>Pose: <span id="selectedRelText">—</span></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<dialog id="missionCreateDialog" class="missionDialog">
|
||
<form id="missionCreateForm" method="dialog" class="missionDialogForm">
|
||
<div class="missionDialogHeader">
|
||
<h3>Create mission</h3>
|
||
<button type="button" class="iconBtn missionDialogClose" data-close-dialog="missionCreateDialog" aria-label="Đóng">×</button>
|
||
</div>
|
||
<div class="missionDialogBody">
|
||
<div class="row rowWide">
|
||
<label for="missionCreateName">Tên mission</label>
|
||
<input id="missionCreateName" type="text" required placeholder="VD: Go to charging station" />
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label for="missionCreateGroup">Nhóm mission</label>
|
||
<select id="missionCreateGroup"></select>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label for="missionCreateGroupNew">Hoặc nhóm mới</label>
|
||
<input id="missionCreateGroupNew" type="text" placeholder="Tùy chọn" />
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label for="missionCreateDesc">Mô tả</label>
|
||
<textarea id="missionCreateDesc" rows="2" placeholder="Tùy chọn"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="missionDialogFooter">
|
||
<button type="button" class="btn subtle" data-close-dialog="missionCreateDialog">Hủy</button>
|
||
<button type="submit" class="btn primary">Create mission</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="missionSettingsDialog" class="missionDialog">
|
||
<form id="missionSettingsForm" method="dialog" class="missionDialogForm">
|
||
<div class="missionDialogHeader">
|
||
<h3>Cài đặt mission</h3>
|
||
<button type="button" class="iconBtn missionDialogClose" data-close-dialog="missionSettingsDialog" aria-label="Đóng">×</button>
|
||
</div>
|
||
<div class="missionDialogBody">
|
||
<div class="row rowWide">
|
||
<label for="missionSettingsName">Tên</label>
|
||
<input id="missionSettingsName" type="text" required />
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label for="missionSettingsGroup">Nhóm</label>
|
||
<select id="missionSettingsGroup"></select>
|
||
</div>
|
||
<div class="row rowWide">
|
||
<label for="missionSettingsDesc">Mô tả</label>
|
||
<textarea id="missionSettingsDesc" rows="2"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="missionDialogFooter">
|
||
<button type="button" class="btn subtle" data-close-dialog="missionSettingsDialog">Hủy</button>
|
||
<button type="submit" class="btn primary">Áp dụng</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="missionSaveAsDialog" class="missionDialog">
|
||
<form id="missionSaveAsForm" method="dialog" class="missionDialogForm">
|
||
<div class="missionDialogHeader">
|
||
<h3>Save mission as</h3>
|
||
<button type="button" class="iconBtn missionDialogClose" data-close-dialog="missionSaveAsDialog" aria-label="Đóng">×</button>
|
||
</div>
|
||
<div class="missionDialogBody">
|
||
<div class="row rowWide">
|
||
<label for="missionSaveAsName">Tên mission mới</label>
|
||
<input id="missionSaveAsName" type="text" required />
|
||
</div>
|
||
</div>
|
||
<div class="missionDialogFooter">
|
||
<button type="button" class="btn subtle" data-close-dialog="missionSaveAsDialog">Hủy</button>
|
||
<button type="submit" class="btn primary">Lưu bản sao</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="missionActionConfigDialog" class="missionDialog missionDialogWide">
|
||
<form id="missionActionConfigForm" method="dialog" class="missionDialogForm">
|
||
<div class="missionDialogHeader">
|
||
<h3 id="missionActionConfigTitle">Cấu hình action</h3>
|
||
<button type="button" class="iconBtn missionDialogClose" data-close-dialog="missionActionConfigDialog" aria-label="Đóng">×</button>
|
||
</div>
|
||
<div class="missionDialogBody" id="missionActionConfigBody"></div>
|
||
<div class="missionDialogFooter">
|
||
<button type="button" class="btn subtle" data-close-dialog="missionActionConfigDialog">Hủy</button>
|
||
<button type="submit" class="btn primary">Áp dụng</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="missionQueueDialog" class="missionDialog">
|
||
<form id="missionQueueForm" method="dialog" class="missionDialogForm">
|
||
<div class="missionDialogHeader">
|
||
<h3>Thêm vào mission queue</h3>
|
||
<button type="button" class="iconBtn missionDialogClose" data-close-dialog="missionQueueDialog" aria-label="Đóng">×</button>
|
||
</div>
|
||
<div class="missionDialogBody">
|
||
<p id="missionQueueDialogMission" class="mutedNote">—</p>
|
||
<div id="missionQueueVarFields" class="missionConfigGrid"></div>
|
||
<p id="missionQueueVarHint" class="mutedNote" hidden>Tham số đã chọn sẽ hiển thị màu xanh trong queue.</p>
|
||
</div>
|
||
<div class="missionDialogFooter">
|
||
<button type="button" class="btn subtle" data-close-dialog="missionQueueDialog">Hủy</button>
|
||
<button type="submit" class="btn primary">Thêm vào queue</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
|
||
</dialog>
|
||
|
||
<dialog id="dashboardAddWidgetDialog" class="missionDialog">
|
||
<form id="dashboardAddWidgetForm" method="dialog" class="missionDialogForm">
|
||
<div class="missionDialogHeader">
|
||
<h3>Thêm widget</h3>
|
||
<button type="button" class="iconBtn missionDialogClose" data-close-dialog="dashboardAddWidgetDialog" aria-label="Đóng">×</button>
|
||
</div>
|
||
<div class="missionDialogBody">
|
||
<div class="row rowWide">
|
||
<label for="dashboardWidgetType">Loại widget</label>
|
||
<select id="dashboardWidgetType" required>
|
||
<option value="mission_button">Mission button</option>
|
||
<option value="mission_group">Mission group</option>
|
||
<option value="mission_queue">Mission queue</option>
|
||
<option value="pause_continue">Pause / Continue</option>
|
||
</select>
|
||
</div>
|
||
<div id="dashboardAddWidgetFields" class="missionConfigGrid"></div>
|
||
</div>
|
||
<div class="missionDialogFooter">
|
||
<button type="button" class="btn subtle" data-close-dialog="dashboardAddWidgetDialog">Hủy</button>
|
||
<button type="submit" class="btn primary">Thêm</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<dialog id="dashboardEditWidgetDialog" class="missionDialog">
|
||
<form id="dashboardEditWidgetForm" method="dialog" class="missionDialogForm">
|
||
<div class="missionDialogHeader">
|
||
<h3>Cấu hình widget</h3>
|
||
<button type="button" class="iconBtn missionDialogClose" data-close-dialog="dashboardEditWidgetDialog" aria-label="Đóng">×</button>
|
||
</div>
|
||
<div class="missionDialogBody">
|
||
<input type="hidden" id="dashboardEditWidgetId" />
|
||
<div class="row rowWide">
|
||
<label for="dashboardEditWidgetType">Loại</label>
|
||
<input id="dashboardEditWidgetType" type="text" readonly />
|
||
</div>
|
||
<div id="dashboardEditWidgetFields" class="missionConfigGrid"></div>
|
||
</div>
|
||
<div class="missionDialogFooter">
|
||
<button type="button" class="btn subtle danger" id="dashboardDeleteWidgetBtn">Xóa widget</button>
|
||
<button type="button" class="btn subtle" data-close-dialog="dashboardEditWidgetDialog">Hủy</button>
|
||
<button type="submit" class="btn primary">Lưu</button>
|
||
</div>
|
||
</form>
|
||
</dialog>
|
||
|
||
<script src="/missions.js"></script>
|
||
<script src="/dashboard.js"></script>
|
||
<script src="/app.js"></script>
|
||
</body>
|
||
</html>
|