rclnodejs
Version:
ROS2.0 JavaScript client with Node.js
109 lines (89 loc) • 3.09 kB
JavaScript
// Data integrity + throughput test for subscription
;
const rclnodejs = require('./index.js');
const PUBLISH_HZ = 50;
const TEST_DURATION_SEC = 10;
async function main() {
await rclnodejs.init();
const pubNode = new rclnodejs.Node('data_pub_node');
const subNode = new rclnodejs.Node('data_sub_node');
const publisher = pubNode.createPublisher(
'std_msgs/msg/Float64MultiArray',
'/data_integrity_topic'
);
let msgCount = 0;
let errCount = 0;
let lastTs = null;
const hzSamples = [];
const errors = [];
subNode.createSubscription(
'std_msgs/msg/Float64MultiArray',
'/data_integrity_topic',
(msg) => {
const now = Date.now();
msgCount++;
// --- Data validation ---
// Each published message has data = [seqNo, seqNo*1.5, seqNo*2.5]
// Verify structure and values
if (!msg || !msg.data) {
errCount++;
errors.push(`msg#${msgCount}: missing data field, got: ${JSON.stringify(msg)}`);
} else if (!Array.isArray(msg.data) && !(msg.data instanceof Float64Array)) {
errCount++;
errors.push(`msg#${msgCount}: data is not array-like, type=${typeof msg.data}`);
} else if (msg.data.length !== 3) {
errCount++;
errors.push(`msg#${msgCount}: expected 3 elements, got ${msg.data.length}`);
} else {
const seqNo = msg.data[0];
const expectedB = seqNo * 1.5;
const expectedC = seqNo * 2.5;
if (Math.abs(msg.data[1] - expectedB) > 1e-9) {
errCount++;
errors.push(
`msg#${msgCount}: data[1] expected ${expectedB}, got ${msg.data[1]}`
);
}
if (Math.abs(msg.data[2] - expectedC) > 1e-9) {
errCount++;
errors.push(
`msg#${msgCount}: data[2] expected ${expectedC}, got ${msg.data[2]}`
);
}
}
if (lastTs) {
hzSamples.push(1000 / (now - lastTs));
}
lastTs = now;
}
);
pubNode.spin();
subNode.spin();
let pubSeq = 0;
const pubInterval = setInterval(() => {
pubSeq++;
publisher.publish({ data: [pubSeq, pubSeq * 1.5, pubSeq * 2.5] });
}, 1000 / PUBLISH_HZ);
setTimeout(() => {
clearInterval(pubInterval);
console.log(`\n=== Data Integrity Test Results ===`);
console.log(`Published: ${pubSeq} messages at ${PUBLISH_HZ} Hz`);
console.log(`Received: ${msgCount} messages`);
console.log(`Data errors: ${errCount}`);
if (errors.length > 0) {
console.log(`\nFirst 10 errors:`);
errors.slice(0, 10).forEach((e) => console.log(` ${e}`));
}
if (hzSamples.length > 0) {
const avgHz = hzSamples.reduce((a, b) => a + b, 0) / hzSamples.length;
console.log(`\nAvg Hz: ${avgHz.toFixed(2)}`);
}
const pass = errCount === 0 && msgCount > 0;
console.log(`\nResult: ${pass ? 'PASS - all data correct' : 'FAIL'}`);
pubNode.stop();
subNode.stop();
rclnodejs.shutdown();
process.exit(pass ? 0 : 1);
}, TEST_DURATION_SEC * 1000);
}
main().catch(console.error);