import * as THREE from './lib/three.module.js'; import { PCDLoader } from './lib/PCDLoader.js'; import { matmul, euler_angle_to_rotate_matrix_3by3} from "./util.js" //todo: clean arrows function AuxLidar(sceneMeta, world, frameInfo, auxLidarName){ this.world = world; this.frameInfo = frameInfo; this.name = auxLidarName; this.sceneMeta = sceneMeta; this.coordinatesOffset = world.coordinatesOffset; this.showPointsOnly = true; this.showCalibBox = false; //this.cssStyleSelector = this.sceneMeta.calib.aux_lidar[this.name].cssstyleselector; this.color = this.sceneMeta.calib.aux_lidar[this.name].color; if (!this.color) { this.color = [ this.world.data.cfg.point_brightness, this.world.data.cfg.point_brightness, this.world.data.cfg.point_brightness, ]; } this.lidar_points = null; // read from file, centered at 0 this.elements = null; // geometry points this.preloaded = false; this.loaded = false; this.go_cmd_received = false; this.webglScene = null; this.on_go_finished = null; this.go = function(webglScene, on_go_finished){ this.webglScene = webglScene; if (this.preloaded){ if (this.elements){ this.webglScene.add(this.elements.points); if (this.showCalibBox) this.webglScene.add(this.calib_box); } this.loaded = true; if (on_go_finished) on_go_finished(); } //anyway we save go cmd { this.go_cmd_received = true; this.on_go_finished = on_go_finished; } }; this.showCalibBox = function(){ this.showCalibBox = true; this.webglScene.add(this.calib_box); }; this.hideCalibBox = function(){ this.showCalibBox = false; this.webglScene.remove(this.calib_box); }; this.get_unoffset_lidar_points = function(){ if (this.elements){ let pts = this.elements.points.geometry.getAttribute("position").array; return pts.map((p,i)=>p-this.world.coordinatesOffset[i %3]); } else{ return []; } }; // todo: what if it's not preloaded yet this.unload = function(keep_box){ if (this.elements){ this.webglScene.remove(this.elements.points); if (!this.showPointsOnly) this.elements.arrows.forEach(a=>this.webglScene.remove(a)); if (!keep_box) this.webglScene.remove(this.calib_box); } this.loaded = false; }; // todo: its possible to remove points before preloading, this.deleteAll = function(keep_box){ if (this.loaded){ this.unload(); } if (this.elements){ //this.scene.remove(this.points); this.world.data.dbg.free(); if (this.elements.points) { this.elements.points.geometry.dispose(); this.elements.points.material.dispose(); } if (this.elements.arrows) { this.elements.arrows.forEach(a=>{ this.world.data.dbg.free(); a.geometry.dispose(); a.material.dispose(); }) } this.elements = null; } if (!keep_box && this.calib_box){ this.world.data.dbg.free(); this.calib_box.geometry.dispose(); this.calib_box.material.dispose(); this.calib_box = null; } }; this.filterPoints = function(position){ let filtered_position = []; if (pointsGlobalConfig.enableFilterPoints) { for(let i = 0; i <= position.length; i+=3) { if (position[i+2] <= pointsGlobalConfig.filterPointsZ) { filtered_position.push(position[i]); filtered_position.push(position[i+1]); filtered_position.push(position[i+2]); } } } return filtered_position; }; this.preload = function(on_preload_finished){ this.on_preload_finished = on_preload_finished; var loader = new PCDLoader(); var _self = this; loader.load( this.frameInfo.get_aux_lidar_path(this.name), //ok function ( pcd ) { var position = pcd.position; //_self.points_parse_time = new Date().getTime(); //console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "parse pionts ", _self.points_parse_time - _self.create_time, "ms"); _self.lidar_points = position; // add one box to calibrate lidar with lidar _self.calib_box = _self.createCalibBox(); // install callback for box changing _self.calib_box.on_box_changed = ()=>{ _self.move_lidar(_self.calib_box); }; //position = _self.transformPointsByOffset(position); position = _self.move_points(_self.calib_box); let elements = _self.buildGeometry(position); _self.elements = elements; //_self.points_backup = mesh; _self._afterPreload(); }, // on progress, function(){}, // on error function(){ //error console.log("load lidar failed."); _self._afterPreload(); }, // on file loaded function(){ //_self.points_readfile_time = new Date().getTime(); //console.log(_self.points_load_time, _self.frameInfo.scene, _self.frameInfo.frame, "read file ", _self.points_readfile_time - _self.create_time, "ms"); } ); }; // internal funcs below this._afterPreload = function(){ this.preloaded = true; console.log(`lidar ${this.auxLidarName} preloaded`); if (this.on_preload_finished){ this.on_preload_finished(); } if (this.go_cmd_received){ this.go(this.webglScene, this.on_go_finished); } }; this.createCalibBox = function(){ if (this.sceneMeta.calib.aux_lidar && this.sceneMeta.calib.aux_lidar[this.name]){ return this.world.annotation.createCuboid( { x: this.sceneMeta.calib.aux_lidar[this.name].translation[0] + this.coordinatesOffset[0], y: this.sceneMeta.calib.aux_lidar[this.name].translation[1] + this.coordinatesOffset[1], z: this.sceneMeta.calib.aux_lidar[this.name].translation[2] + this.coordinatesOffset[2], }, {x:0.5, y:0.5, z:0.5}, { x: this.sceneMeta.calib.aux_lidar[this.name].rotation[0], y: this.sceneMeta.calib.aux_lidar[this.name].rotation[1], z: this.sceneMeta.calib.aux_lidar[this.name].rotation[2], }, "lidar", this.name); }else { return this.world.annotation.createCuboid( {x: this.coordinatesOffset[0], y: this.coordinatesOffset[1], z: this.coordinatesOffset[2]}, {x:0.5, y:0.5, z:0.5}, {x:0,y:0,z:0}, "lidar", this.name); } }; this.buildPoints = function(position){ // build geometry this.world.data.dbg.alloc(); let geometry = new THREE.BufferGeometry(); if ( position.length > 0 ) geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( position, 3 ) ); let pointColor = this.color; let color=[]; for (var i =0; i< position.length; i+=3){ color.push(pointColor[0]); color.push(pointColor[1]); color.push(pointColor[2]); } geometry.addAttribute( 'color', new THREE.Float32BufferAttribute(color, 3 ) ); geometry.computeBoundingSphere(); // build material let pointSize = this.sceneMeta.calib.aux_lidar[this.name].point_size; if (!pointSize) pointSize = 1; let material = new THREE.PointsMaterial( { size: pointSize, vertexColors: THREE.VertexColors } ); //material.size = 2; material.sizeAttenuation = false; // build mesh let mesh = new THREE.Points( geometry, material ); mesh.name = "lidar"; return mesh; }; this.buildGeometry = function(position){ let points = this.buildPoints(position); return { points: points, }; }; this.move_points = function(box){ let points = this.lidar_points; let trans = euler_angle_to_rotate_matrix_3by3(box.rotation); let rotated_points = matmul(trans, points, 3); let translation=[box.position.x, box.position.y, box.position.z]; let translated_points = rotated_points.map((p,i)=>{ return p + translation[i % 3]; }); let filtered_position = this.filterPoints(translated_points); return filtered_position; }; this.move_lidar= function(box){ let translated_points = this.move_points(box); let elements = this.buildGeometry(translated_points); // remove old points this.unload(true); this.deleteAll(true); this.elements = elements; //_self.points_backup = mesh; if (this.go_cmd_received) // this should be always true { this.webglScene.add(this.elements.points); if (!this.showPointsOnly) this.elements.arrows.forEach(a=>this.webglScene.add(a)); } }; } function AuxLidarManager(sceneMeta, world, frameInfo){ this.lidarList = []; if (world.data.cfg.enableAuxLidar && sceneMeta.aux_lidar){ let lidars = []; for (let r in sceneMeta.calib.aux_lidar){ if (!sceneMeta.calib.aux_lidar[r].disable) lidars.push(r); } this.lidarList = lidars.map(name=>{ return new AuxLidar(sceneMeta, world, frameInfo, name); }); } this.getAllBoxes = function() { if (this.showCalibBox) { return this.lidarList.map(r=>r.calib_box); } else { return []; } }; this.preloaded = function(){ for (let r in this.lidarList){ if (!this.lidarList[r].preloaded) return false; } return true; }; this.go = function(webglScene, on_go_finished){ this.lidarList.forEach(r=>r.go(webglScene, on_go_finished)); }; this.preload = function(on_preload_finished){ this.lidarList.forEach(r=>r.preload(on_preload_finished)); }; this.unload = function(){ this.lidarList.forEach(r=>r.unload()); }; this.deleteAll = function(){ this.lidarList.forEach(r=>r.deleteAll()); }; this.getOperableObjects = function(){ return this.lidarList.flatMap(r=>r.getOperableObjects()); }; this.showCalibBox = false; this.showCalibBox = function(){ this.showCalibBox = true; this.lidarList.forEach(r=>r.showCalibBox()); }; this.hideCalibBox = function(){ this.showCalibBox = false; this.lidarList.forEach(r=>r.hideCalibBox()); } }; export {AuxLidarManager}