@drawtonomy/sdk 0.10.0 → 0.11.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/exporter/index.d.ts +2 -2
- package/dist/exporter/index.d.ts.map +1 -1
- package/dist/exporter/index.js +1 -1
- package/dist/exporter/index.js.map +1 -1
- package/dist/exporter/lanelet2.d.ts +12 -0
- package/dist/exporter/lanelet2.d.ts.map +1 -1
- package/dist/exporter/lanelet2.js +112 -31
- package/dist/exporter/lanelet2.js.map +1 -1
- package/dist/exporter/odrCarryThrough.d.ts +2 -2
- package/dist/exporter/odrCarryThrough.d.ts.map +1 -1
- package/dist/exporter/odrCarryThrough.js +1 -1
- package/dist/exporter/odrCarryThrough.js.map +1 -1
- package/dist/exporter/odrToShapes.d.ts.map +1 -1
- package/dist/exporter/odrToShapes.js +83 -19
- package/dist/exporter/odrToShapes.js.map +1 -1
- package/dist/exporter/opendrive.d.ts.map +1 -1
- package/dist/exporter/opendrive.js +87 -24
- package/dist/exporter/opendrive.js.map +1 -1
- package/dist/exporter/opendriveParser.d.ts +4 -0
- package/dist/exporter/opendriveParser.d.ts.map +1 -1
- package/dist/exporter/opendriveParser.js +2 -0
- package/dist/exporter/opendriveParser.js.map +1 -1
- package/dist/exporter/osmToShapes.d.ts +26 -1
- package/dist/exporter/osmToShapes.d.ts.map +1 -1
- package/dist/exporter/osmToShapes.js +54 -9
- package/dist/exporter/osmToShapes.js.map +1 -1
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -26,6 +26,7 @@ import { fitPlanView } from './odrGeometryFit';
|
|
|
26
26
|
import { originToProjString } from './projection';
|
|
27
27
|
import { escapeXml, fmt, fmtPrecise, pxToEnuX, pxToEnuY, pxToMeter } from './units';
|
|
28
28
|
import { extractOdrDocument, hashRoadState, rewriteRoadLinkTargets, } from './odrCarryThrough';
|
|
29
|
+
import { trafficSignCode } from './lanelet2';
|
|
29
30
|
/** O(1) shape lookup by id. */
|
|
30
31
|
function buildShapeMap(shapes) {
|
|
31
32
|
const map = new Map();
|
|
@@ -1076,7 +1077,7 @@ function laneIdRanges(ids) {
|
|
|
1076
1077
|
ranges.push({ fromLane: start, toLane: prev });
|
|
1077
1078
|
return ranges;
|
|
1078
1079
|
}
|
|
1079
|
-
function attachShapesToRoads(shapeMap, trafficLights, crosswalks, polygons, roads, laneIdToRoadId, laneIdToOdrLaneId, maxAttachDistanceMeter = 50, signalIdStart = 1) {
|
|
1080
|
+
function attachShapesToRoads(shapeMap, trafficLights, trafficSigns, crosswalks, polygons, roads, laneIdToRoadId, laneIdToOdrLaneId, maxAttachDistanceMeter = 50, signalIdStart = 1) {
|
|
1080
1081
|
const roadSignals = new Map();
|
|
1081
1082
|
const roadObjects = new Map();
|
|
1082
1083
|
const roadSignalRefs = new Map();
|
|
@@ -1101,7 +1102,14 @@ function attachShapesToRoads(shapeMap, trafficLights, crosswalks, polygons, road
|
|
|
1101
1102
|
}
|
|
1102
1103
|
return byRoad;
|
|
1103
1104
|
};
|
|
1104
|
-
|
|
1105
|
+
// Traffic lights (dynamic signals) and traffic signs (static signals)
|
|
1106
|
+
// attach to roads through the same projection / validity machinery; only
|
|
1107
|
+
// the emitted <signal> attributes differ per kind.
|
|
1108
|
+
const signalShapes = [
|
|
1109
|
+
...trafficLights.map(shape => ({ kind: 'traffic_light', shape })),
|
|
1110
|
+
...trafficSigns.map(shape => ({ kind: 'traffic_sign', shape })),
|
|
1111
|
+
];
|
|
1112
|
+
for (const { kind, shape: tl } of signalShapes) {
|
|
1105
1113
|
const xG = pxToEnuX(tl.x);
|
|
1106
1114
|
const yG = pxToEnuY(tl.y);
|
|
1107
1115
|
// Regulatory layer: a signal that names affected lanes attaches to the
|
|
@@ -1131,26 +1139,61 @@ function attachShapesToRoads(shapeMap, trafficLights, crosswalks, polygons, road
|
|
|
1131
1139
|
}
|
|
1132
1140
|
if (!best)
|
|
1133
1141
|
continue;
|
|
1134
|
-
const style = tl.props.style ?? '';
|
|
1135
|
-
const isPed = style.startsWith('pedestrian') || style.includes('ped');
|
|
1136
|
-
// Conventional signal type codes: 1000001 = vehicle, 1000002 = pedestrian.
|
|
1137
|
-
const sigType = isPed ? '1000002' : '1000001';
|
|
1138
1142
|
const heightM = pxToMeter(tl.props.h);
|
|
1139
1143
|
const widthM = pxToMeter(tl.props.w);
|
|
1140
1144
|
const list = roadSignals.get(best.roadId) ?? [];
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1145
|
+
let entry;
|
|
1146
|
+
if (kind === 'traffic_light') {
|
|
1147
|
+
const style = tl.props.style ?? '';
|
|
1148
|
+
const isPed = style.startsWith('pedestrian') || style.includes('ped');
|
|
1149
|
+
// Conventional signal type codes: 1000001 = vehicle, 1000002 = pedestrian.
|
|
1150
|
+
const sigType = isPed ? '1000002' : '1000001';
|
|
1151
|
+
entry = {
|
|
1152
|
+
id: signalIdCounter++,
|
|
1153
|
+
s: best.proj.s,
|
|
1154
|
+
t: best.proj.t,
|
|
1155
|
+
zOffset: isPed ? 1.5 : 4.5,
|
|
1156
|
+
height: heightM,
|
|
1157
|
+
width: widthM,
|
|
1158
|
+
name: style,
|
|
1159
|
+
type: sigType,
|
|
1160
|
+
subtype: '-1',
|
|
1161
|
+
dynamic: 'yes',
|
|
1162
|
+
orientation: best.proj.t >= 0 ? '+' : '-',
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
else {
|
|
1166
|
+
// Static traffic sign: reuse the exact OpenDRIVE type / subtype /
|
|
1167
|
+
// country recorded at import time; fresh signs fall back to type "-1"
|
|
1168
|
+
// with the sign code as the name. Full attribute round-trip rides on
|
|
1169
|
+
// <userData code="signAttributes">.
|
|
1170
|
+
const attrs = (tl.props.attributes ?? {});
|
|
1171
|
+
entry = {
|
|
1172
|
+
id: signalIdCounter++,
|
|
1173
|
+
s: best.proj.s,
|
|
1174
|
+
t: best.proj.t,
|
|
1175
|
+
zOffset: 2,
|
|
1176
|
+
height: heightM,
|
|
1177
|
+
width: widthM,
|
|
1178
|
+
name: trafficSignCode(attrs),
|
|
1179
|
+
type: attrs.odr_signal_type || '-1',
|
|
1180
|
+
subtype: attrs.odr_signal_subtype || '-1',
|
|
1181
|
+
country: attrs.odr_country || undefined,
|
|
1182
|
+
dynamic: 'no',
|
|
1183
|
+
orientation: best.proj.t >= 0 ? '+' : '-',
|
|
1184
|
+
};
|
|
1185
|
+
const stash = {};
|
|
1186
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
1187
|
+
if (k === 'type' || k === 'refers_osm_id' || k.startsWith('odr_'))
|
|
1188
|
+
continue;
|
|
1189
|
+
if (v === undefined || v === null || v === '')
|
|
1190
|
+
continue;
|
|
1191
|
+
stash[k] = String(v);
|
|
1192
|
+
}
|
|
1193
|
+
if (Object.keys(stash).length > 0) {
|
|
1194
|
+
entry.userData = [{ code: 'signAttributes', value: JSON.stringify(stash) }];
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1154
1197
|
if (affectedByRoad.size > 0) {
|
|
1155
1198
|
entry.validity = laneIdRanges(affectedByRoad.get(best.roadId));
|
|
1156
1199
|
}
|
|
@@ -1389,8 +1432,8 @@ function emitSignals(signals, references) {
|
|
|
1389
1432
|
const lines = [];
|
|
1390
1433
|
lines.push(` <signals>`);
|
|
1391
1434
|
for (const s of signals) {
|
|
1392
|
-
const attrs = `id="${s.id}" s="${fmt(s.s)}" t="${fmt(s.t)}" zOffset="${fmt(s.zOffset)}" name="${escapeXml(s.name)}" dynamic="${s.dynamic}" orientation="${s.orientation}" type="${s.type}" subtype="${s.subtype}" country="OpenDRIVE" value="0" height="${fmt(s.height)}" width="${fmt(s.width)}"`;
|
|
1393
|
-
if (s.validity?.length || s.stopLinePoints) {
|
|
1435
|
+
const attrs = `id="${s.id}" s="${fmt(s.s)}" t="${fmt(s.t)}" zOffset="${fmt(s.zOffset)}" name="${escapeXml(s.name)}" dynamic="${s.dynamic}" orientation="${s.orientation}" type="${s.type}" subtype="${s.subtype}" country="${escapeXml(s.country ?? 'OpenDRIVE')}" value="0" height="${fmt(s.height)}" width="${fmt(s.width)}"`;
|
|
1436
|
+
if (s.validity?.length || s.stopLinePoints || s.userData?.length) {
|
|
1394
1437
|
lines.push(` <signal ${attrs}>`);
|
|
1395
1438
|
for (const v of s.validity ?? []) {
|
|
1396
1439
|
lines.push(` <validity fromLane="${v.fromLane}" toLane="${v.toLane}"/>`);
|
|
@@ -1399,6 +1442,9 @@ function emitSignals(signals, references) {
|
|
|
1399
1442
|
const json = JSON.stringify(s.stopLinePoints.map((p) => [roundMm(p.x), roundMm(p.y)]));
|
|
1400
1443
|
lines.push(` <userData code="stopLine" value="${escapeXml(json)}"/>`);
|
|
1401
1444
|
}
|
|
1445
|
+
for (const ud of s.userData ?? []) {
|
|
1446
|
+
lines.push(` <userData code="${escapeXml(ud.code)}" value="${escapeXml(ud.value)}"/>`);
|
|
1447
|
+
}
|
|
1402
1448
|
lines.push(` </signal>`);
|
|
1403
1449
|
}
|
|
1404
1450
|
else {
|
|
@@ -1610,7 +1656,7 @@ const NO_OVERRIDES = new Map();
|
|
|
1610
1656
|
* Roads referencing unrecorded elements (e.g. a selective import) are never
|
|
1611
1657
|
* carried verbatim, so verbatim output cannot dangle into missing roads.
|
|
1612
1658
|
*/
|
|
1613
|
-
function planCarryThrough(sidecar, shapeMap, trafficLights, crosswalks) {
|
|
1659
|
+
function planCarryThrough(sidecar, shapeMap, trafficLights, trafficSigns, crosswalks) {
|
|
1614
1660
|
const records = sidecar?.roadRecords;
|
|
1615
1661
|
if (!sidecar || !records || Object.keys(records).length === 0)
|
|
1616
1662
|
return null;
|
|
@@ -1665,6 +1711,17 @@ function planCarryThrough(sidecar, shapeMap, trafficLights, crosswalks) {
|
|
|
1665
1711
|
controllerId: tl.props.controllerId ?? '',
|
|
1666
1712
|
}, tl.props.affectedLaneIds ?? [], tl.props.attributes?.odr_road_id);
|
|
1667
1713
|
}
|
|
1714
|
+
for (const ts of trafficSigns) {
|
|
1715
|
+
addRegState({
|
|
1716
|
+
kind: 'traffic_sign',
|
|
1717
|
+
shapeId: ts.id,
|
|
1718
|
+
numbers: [ts.x, ts.y, ts.props.w, ts.props.h, ts.rotation || 0],
|
|
1719
|
+
attributes: ts.props.attributes ?? {},
|
|
1720
|
+
affectedLaneIds: ts.props.affectedLaneIds ?? [],
|
|
1721
|
+
stopLinePts: stopLinePts(ts.props.stopLineId),
|
|
1722
|
+
controllerId: '',
|
|
1723
|
+
}, ts.props.affectedLaneIds ?? [], ts.props.attributes?.odr_road_id);
|
|
1724
|
+
}
|
|
1668
1725
|
for (const cw of crosswalks) {
|
|
1669
1726
|
addRegState({
|
|
1670
1727
|
kind: 'crosswalk',
|
|
@@ -1872,6 +1929,7 @@ export function exportToOpenDrive(snapshot, options = {}) {
|
|
|
1872
1929
|
const shapeMap = buildShapeMap(shapes);
|
|
1873
1930
|
const lanes = [];
|
|
1874
1931
|
const trafficLights = [];
|
|
1932
|
+
const trafficSigns = [];
|
|
1875
1933
|
const crosswalks = [];
|
|
1876
1934
|
const polygons = [];
|
|
1877
1935
|
for (const s of shapes) {
|
|
@@ -1879,6 +1937,8 @@ export function exportToOpenDrive(snapshot, options = {}) {
|
|
|
1879
1937
|
lanes.push(s);
|
|
1880
1938
|
else if (s.type === 'traffic_light')
|
|
1881
1939
|
trafficLights.push(s);
|
|
1940
|
+
else if (s.type === 'traffic_sign')
|
|
1941
|
+
trafficSigns.push(s);
|
|
1882
1942
|
else if (s.type === 'crosswalk')
|
|
1883
1943
|
crosswalks.push(s);
|
|
1884
1944
|
else if (s.type === 'polygon') {
|
|
@@ -1895,11 +1955,14 @@ export function exportToOpenDrive(snapshot, options = {}) {
|
|
|
1895
1955
|
}
|
|
1896
1956
|
// Carry-through: with an importer sidecar, unedited original roads are
|
|
1897
1957
|
// re-emitted verbatim and excluded from regeneration.
|
|
1898
|
-
const carry = planCarryThrough(options.sidecar, shapeMap, trafficLights, crosswalks);
|
|
1958
|
+
const carry = planCarryThrough(options.sidecar, shapeMap, trafficLights, trafficSigns, crosswalks);
|
|
1899
1959
|
const regenLanes = carry ? lanes.filter(l => !carry.verbatimLaneIds.has(l.id)) : lanes;
|
|
1900
1960
|
const regenTrafficLights = carry
|
|
1901
1961
|
? trafficLights.filter(t => !carry.consumedShapeIds.has(t.id))
|
|
1902
1962
|
: trafficLights;
|
|
1963
|
+
const regenTrafficSigns = carry
|
|
1964
|
+
? trafficSigns.filter(t => !carry.consumedShapeIds.has(t.id))
|
|
1965
|
+
: trafficSigns;
|
|
1903
1966
|
const regenCrosswalks = carry
|
|
1904
1967
|
? crosswalks.filter(c => !carry.consumedShapeIds.has(c.id))
|
|
1905
1968
|
: crosswalks;
|
|
@@ -2113,7 +2176,7 @@ export function exportToOpenDrive(snapshot, options = {}) {
|
|
|
2113
2176
|
};
|
|
2114
2177
|
const plan = planConnectivity(exportBundles, laneIdToRoadId, laneIdToOdrLaneId, nextRoadId, connectingSourceFor, connectingTargetFor, contactWidth, externalLanes);
|
|
2115
2178
|
const roads = exportBundles.map(b => ({ roadId: roadIdByBundle.get(b), geom: b.geom }));
|
|
2116
|
-
const { roadSignals, roadObjects, roadSignalRefs, signalIdByShape } = attachShapesToRoads(shapeMap, regenTrafficLights, regenCrosswalks, polygons, roads, laneIdToRoadId, laneIdToOdrLaneId, undefined, carry?.signalIdBase);
|
|
2179
|
+
const { roadSignals, roadObjects, roadSignalRefs, signalIdByShape } = attachShapesToRoads(shapeMap, regenTrafficLights, regenTrafficSigns, regenCrosswalks, polygons, roads, laneIdToRoadId, laneIdToOdrLaneId, undefined, carry?.signalIdBase);
|
|
2117
2180
|
// Verbatim road blocks first (original document order). Two minimal
|
|
2118
2181
|
// rewrites keep their links valid; nothing else is touched:
|
|
2119
2182
|
// - road links to a dirty road whose lanes regenerated into exactly one
|