Skip to content

Commit 1567f32

Browse files
committed
refactor(UrdfModel): Convert UrdfModel to TypeScript, replace loops with for-of, and improve type safety
Signed-off-by: Drew Hoener <[email protected]>
1 parent 9941569 commit 1567f32

File tree

1 file changed

+70
-54
lines changed

1 file changed

+70
-54
lines changed

src/urdf/UrdfModel.ts

Lines changed: 70 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,94 +4,110 @@
44
* @author Russell Toris - [email protected]
55
*/
66

7+
import { DOMParser, MIME_TYPE } from '@xmldom/xmldom';
78
import UrdfMaterial from './UrdfMaterial.js';
89
import UrdfLink from './UrdfLink.js';
910
import UrdfJoint from './UrdfJoint.js';
10-
import { DOMParser, MIME_TYPE } from '@xmldom/xmldom';
11+
import { isElement } from './UrdfUtils.js';
1112

1213
// See https://developer.mozilla.org/docs/XPathResult#Constants
13-
var XPATH_FIRST_ORDERED_NODE_TYPE = 9;
14+
// const XPATH_FIRST_ORDERED_NODE_TYPE = 9;
15+
16+
export interface UrdfModelOptions {
17+
/**
18+
* The XML element to parse.
19+
*/
20+
xml?: Element;
21+
/**
22+
* The XML element to parse as a string.
23+
*/
24+
string: string;
25+
}
1426

1527
/**
1628
* A URDF Model can be used to parse a given URDF into the appropriate elements.
1729
*/
1830
export default class UrdfModel {
19-
materials = {};
20-
links = {};
21-
joints = {};
22-
/**
23-
* @param {Object} options
24-
* @param {Element | null} [options.xml] - The XML element to parse.
25-
* @param {string} [options.string] - The XML element to parse as a string.
26-
*/
27-
constructor(options) {
28-
var xmlDoc = options.xml;
29-
var string = options.string;
31+
32+
name: string | null;
33+
materials: Record<string, UrdfMaterial> = {};
34+
links: Record<string, UrdfLink> = {};
35+
joints: Record<string, UrdfJoint> = {};
36+
37+
constructor({ xml, string }: UrdfModelOptions) {
38+
let xmlDoc = xml;
3039

3140
// Check if we are using a string or an XML element
3241
if (string) {
3342
// Parse the string
34-
var parser = new DOMParser();
35-
xmlDoc = parser.parseFromString(string, MIME_TYPE.XML_TEXT).documentElement;
43+
xmlDoc = new DOMParser().parseFromString(string, MIME_TYPE.XML_TEXT).documentElement;
3644
}
45+
3746
if (!xmlDoc) {
3847
throw new Error('No URDF document parsed!');
3948
}
4049

41-
// Initialize the model with the given XML node.
42-
// Get the robot tag
43-
var robotXml = xmlDoc;
44-
4550
// Get the robot name
46-
this.name = robotXml.getAttribute('name');
51+
this.name = xmlDoc.getAttribute('name');
4752

53+
const childNodes = xmlDoc.childNodes;
4854
// Parse all the visual elements we need
49-
for (var nodes = robotXml.childNodes, i = 0; i < nodes.length; i++) {
50-
/** @type {Element} */
51-
// @ts-expect-error -- unknown why this doesn't work properly.
52-
var node = nodes[i];
53-
if (node.tagName === 'material') {
54-
var material = new UrdfMaterial({
55-
xml: node
56-
});
57-
// Make sure this is unique
58-
if (this.materials[material.name] !== void 0) {
55+
for (const node of childNodes) {
56+
57+
// Safety check to make sure we're working with an element.
58+
if (!isElement(node)) {
59+
continue;
60+
}
61+
62+
switch (node.tagName) {
63+
case 'material': {
64+
const material = new UrdfMaterial({ xml: node });
65+
// Make sure this is unique
66+
if (!Object.hasOwn(this.materials, material.name)) {
67+
this.materials[material.name] = material;
68+
break;
69+
}
70+
5971
if (this.materials[material.name].isLink()) {
6072
this.materials[material.name].assign(material);
6173
} else {
62-
console.warn('Material ' + material.name + 'is not unique.');
74+
console.warn(`Material ${material.name} is not unique.`);
6375
}
64-
} else {
65-
this.materials[material.name] = material;
76+
77+
break;
6678
}
67-
} else if (node.tagName === 'link') {
68-
var link = new UrdfLink({
69-
xml: node
70-
});
71-
// Make sure this is unique
72-
if (this.links[link.name] !== void 0) {
73-
console.warn('Link ' + link.name + ' is not unique.');
74-
} else {
79+
case 'link': {
80+
const link = new UrdfLink({ xml: node });
81+
// Make sure this is unique
82+
if (Object.hasOwn(this.links, link.name)) {
83+
console.warn(`Link ${link.name} is not unique.`);
84+
break;
85+
}
86+
7587
// Check for a material
76-
for (var j = 0; j < link.visuals.length; j++) {
77-
var mat = link.visuals[j].material;
78-
if (mat !== null && mat.name) {
79-
if (this.materials[mat.name] !== void 0) {
80-
link.visuals[j].material = this.materials[mat.name];
81-
} else {
82-
this.materials[mat.name] = mat;
83-
}
88+
for (const item of link.visuals) {
89+
const mat = item.material;
90+
if (!mat?.name) {
91+
continue;
92+
}
93+
94+
if (Object.hasOwn(this.materials, mat.name)) {
95+
item.material = this.materials[mat.name];
96+
} else {
97+
this.materials[mat.name] = mat;
8498
}
8599
}
86100

87101
// Add the link
88102
this.links[link.name] = link;
103+
104+
break;
105+
}
106+
case 'joint': {
107+
const joint = new UrdfJoint({ xml: node });
108+
this.joints[joint.name] = joint;
109+
break;
89110
}
90-
} else if (node.tagName === 'joint') {
91-
var joint = new UrdfJoint({
92-
xml: node
93-
});
94-
this.joints[joint.name] = joint;
95111
}
96112
}
97113
}

0 commit comments

Comments
 (0)