(() => { function stripComment(line) { const pos = line.indexOf("#"); return pos === -1 ? line : line.slice(0, pos); } function trim(s) { return String(s || "").trim(); } function parseOriginArray(value) { const start = value.indexOf("["); const end = value.indexOf("]"); if (start === -1 || end === -1 || end <= start) return null; const parts = value .slice(start + 1, end) .split(",") .map((p) => Number(trim(p))) .filter((n) => !Number.isNaN(n)); if (parts.length < 2) return null; return { origin_x: parts[0], origin_y: parts[1], origin_yaw: parts[2] || 0 }; } function parseNumber(value) { const n = Number(value); return Number.isFinite(n) ? n : null; } function parseIntField(value) { const n = parseInt(value, 10); return Number.isFinite(n) ? n : null; } /** * Parse ROS map_server yaml (resolution, origin, thresholds). * @param {string} text * @param {{ requireImage?: boolean }} opts */ function parse(text, opts = {}) { const requireImage = !!opts.requireImage; const out = { image: "", resolution: null, origin_x: 0, origin_y: 0, origin_yaw: 0, negate: 0, occupied_thresh: 0.65, free_thresh: 0.196, }; for (const rawLine of String(text || "").split(/\r?\n/)) { const line = trim(stripComment(rawLine)); if (!line) continue; const colon = line.indexOf(":"); if (colon === -1) continue; const key = trim(line.slice(0, colon)); const value = trim(line.slice(colon + 1)); if (!value && key !== "image") continue; if (key === "image") out.image = value; else if (key === "resolution") out.resolution = parseNumber(value); else if (key === "origin") { const origin = parseOriginArray(value); if (origin) Object.assign(out, origin); } else if (key === "negate") { const n = parseIntField(value); if (n != null) out.negate = n; } else if (key === "occupied_thresh") { const n = parseNumber(value); if (n != null) out.occupied_thresh = n; } else if (key === "free_thresh") { const n = parseNumber(value); if (n != null) out.free_thresh = n; } } if (requireImage && !out.image) return { error: "yaml missing image field" }; if (out.resolution == null || out.resolution <= 0) return { error: "yaml missing resolution field" }; return out; } function serialize(meta) { const image = meta.image || "map.png"; const resolution = meta.resolution != null ? meta.resolution : 0.05; const ox = meta.origin_x != null ? meta.origin_x : 0; const oy = meta.origin_y != null ? meta.origin_y : 0; const oyaw = meta.origin_yaw != null ? meta.origin_yaw : 0; const negate = meta.negate != null ? meta.negate : 0; const occ = meta.occupied_thresh != null ? meta.occupied_thresh : 0.65; const free = meta.free_thresh != null ? meta.free_thresh : 0.196; return [ `image: ${image}`, `resolution: ${Number(resolution).toFixed(6)}`, `origin: [${Number(ox).toFixed(6)}, ${Number(oy).toFixed(6)}, ${Number(oyaw).toFixed(6)}]`, `negate: ${negate}`, `occupied_thresh: ${Number(occ).toFixed(3)}`, `free_thresh: ${Number(free).toFixed(3)}`, "", ].join("\n"); } window.MapYaml = { parse, serialize }; })();