kopia lustrzana https://github.com/OpenDroneMap/NodeODM
Updated API to 1.02, removed uncommon asset download URLs, speeded up archiving code, added test mode for skipping orthophoto generation, updated docs, skip tiling process when orthophoto is missing
rodzic
b74fdc2e6f
commit
6ddbe1feba
|
@ -13,5 +13,6 @@
|
||||||
"deamon": false,
|
"deamon": false,
|
||||||
"parallelQueueProcessing": 2,
|
"parallelQueueProcessing": 2,
|
||||||
"cleanupTasksAfter": 3,
|
"cleanupTasksAfter": 3,
|
||||||
"test": false
|
"test": false,
|
||||||
|
"testSkipOrthophotos": false
|
||||||
}
|
}
|
|
@ -34,6 +34,7 @@ Options:
|
||||||
--parallel_queue_processing <number> Number of simultaneous processing tasks (default: 2)
|
--parallel_queue_processing <number> Number of simultaneous processing tasks (default: 2)
|
||||||
--cleanup_tasks_after <number> Number of days that elapse before deleting finished and canceled tasks (default: 3)
|
--cleanup_tasks_after <number> Number of days that elapse before deleting finished and canceled tasks (default: 3)
|
||||||
--test Enable test mode. In test mode, no commands are sent to OpenDroneMap. This can be useful during development or testing (default: false)
|
--test Enable test mode. In test mode, no commands are sent to OpenDroneMap. This can be useful during development or testing (default: false)
|
||||||
|
--test_skip_orthophotos If test mode is enabled, skip orthophoto results when generating assets. (default: false)
|
||||||
Log Levels:
|
Log Levels:
|
||||||
error | debug | info | verbose | debug | silly
|
error | debug | info | verbose | debug | silly
|
||||||
`);
|
`);
|
||||||
|
@ -78,5 +79,6 @@ config.deamon = argv.deamonize || argv.d || fromConfigFile("daemon", false);
|
||||||
config.parallelQueueProcessing = argv.parallel_queue_processing || fromConfigFile("parallelQueueProcessing", 2);
|
config.parallelQueueProcessing = argv.parallel_queue_processing || fromConfigFile("parallelQueueProcessing", 2);
|
||||||
config.cleanupTasksAfter = argv.cleanup_tasks_after || fromConfigFile("cleanupTasksAfter", 3);
|
config.cleanupTasksAfter = argv.cleanup_tasks_after || fromConfigFile("cleanupTasksAfter", 3);
|
||||||
config.test = argv.test || fromConfigFile("test", false);
|
config.test = argv.test || fromConfigFile("test", false);
|
||||||
|
config.testSkipOrthophotos = argv.test_skip_orthophotos || fromConfigFile("testSkipOrthophotos", false);
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
node generateSwaggerAPI.js
|
||||||
|
java -jar swagger2markup-cli-1.0.1.jar convert -i swagger.json -f index
|
|
@ -8,7 +8,7 @@ REST API to access OpenDroneMap
|
||||||
|
|
||||||
=== Version information
|
=== Version information
|
||||||
[%hardbreaks]
|
[%hardbreaks]
|
||||||
_Version_ : 1.0.1
|
_Version_ : 1.0.2
|
||||||
|
|
||||||
|
|
||||||
=== Contact information
|
=== Contact information
|
||||||
|
@ -257,7 +257,7 @@ Retrieves an asset (the output of OpenDroneMap's processing) associated with a t
|
||||||
|===
|
|===
|
||||||
|Type|Name|Description|Schema|Default
|
|Type|Name|Description|Schema|Default
|
||||||
|*Path*|*asset* +
|
|*Path*|*asset* +
|
||||||
_required_|Type of asset to download. Use "all.zip" for zip file containing all assets.|enum (all.zip, georeferenced_model.ply.zip, georeferenced_model.las.zip, georeferenced_model.csv.zip, orthophoto.png, orthophoto.tif, textured_model.zip, orthophoto_tiles.zip)|
|
_required_|Type of asset to download. Use "all.zip" for zip file containing all assets.|enum (all.zip, orthophoto.tif)|
|
||||||
|*Path*|*uuid* +
|
|*Path*|*uuid* +
|
||||||
_required_|UUID of the task|string|
|
_required_|UUID of the task|string|
|
||||||
|===
|
|===
|
||||||
|
|
File diff suppressed because one or more lines are too long
6
index.js
6
index.js
|
@ -295,13 +295,7 @@ app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
|
||||||
* required: true
|
* required: true
|
||||||
* enum:
|
* enum:
|
||||||
* - all.zip
|
* - all.zip
|
||||||
* - georeferenced_model.ply.zip
|
|
||||||
* - georeferenced_model.las.zip
|
|
||||||
* - georeferenced_model.csv.zip
|
|
||||||
* - orthophoto.png
|
|
||||||
* - orthophoto.tif
|
* - orthophoto.tif
|
||||||
* - textured_model.zip
|
|
||||||
* - orthophoto_tiles.zip
|
|
||||||
* responses:
|
* responses:
|
||||||
* 200:
|
* 200:
|
||||||
* description: Asset File
|
* description: Asset File
|
||||||
|
|
65
libs/Task.js
65
libs/Task.js
|
@ -121,25 +121,17 @@ module.exports = class Task{
|
||||||
// Get the path of the archive where all assets
|
// Get the path of the archive where all assets
|
||||||
// outputted by this task are stored.
|
// outputted by this task are stored.
|
||||||
getAssetsArchivePath(filename){
|
getAssetsArchivePath(filename){
|
||||||
switch(filename){
|
if (filename == 'all.zip'){
|
||||||
case "all.zip":
|
// OK, do nothing
|
||||||
case "georeferenced_model.ply.zip":
|
}else if (filename == 'orthophoto.tif'){
|
||||||
case "georeferenced_model.las.zip":
|
if (config.test){
|
||||||
case "georeferenced_model.csv.zip":
|
if (config.testSkipOrthophotos) return false;
|
||||||
case "textured_model.zip":
|
else filename = path.join('..', '..', 'processing_results', 'odm_orthophoto', `odm_${filename}`);
|
||||||
case "orthophoto_tiles.zip":
|
}else{
|
||||||
// OK
|
filename = path.join('odm_orthophoto', `odm_${filename}`);
|
||||||
break;
|
}
|
||||||
case "orthophoto.png":
|
}else{
|
||||||
case "orthophoto.tif":
|
return false; // Invalid
|
||||||
// Append missing pieces to the path
|
|
||||||
filename = !config.test ?
|
|
||||||
path.join('odm_orthophoto', `odm_${filename}`) :
|
|
||||||
path.join('..', '..', 'processing_results', 'odm_orthophoto', `odm_${filename}`);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
// Invalid
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.join(this.getProjectFolderPath(), filename);
|
return path.join(this.getProjectFolderPath(), filename);
|
||||||
|
@ -306,11 +298,20 @@ module.exports = class Task{
|
||||||
|
|
||||||
const generateTiles = (inputFile, outputDir) => {
|
const generateTiles = (inputFile, outputDir) => {
|
||||||
return (done) => {
|
return (done) => {
|
||||||
|
const inputFilePath = path.join(this.getProjectFolderPath(), inputFile);
|
||||||
|
|
||||||
|
// Not all datasets generate an orthophoto, so we skip
|
||||||
|
// tiling if the orthophoto is missing
|
||||||
|
if (fs.existsSync(inputFilePath)){
|
||||||
this.runningProcesses.push(processRunner.runTiler({
|
this.runningProcesses.push(processRunner.runTiler({
|
||||||
zoomLevels: "12-21",
|
zoomLevels: "12-21",
|
||||||
inputFile: path.join(this.getProjectFolderPath(), inputFile),
|
inputFile: inputFilePath,
|
||||||
outputDir: path.join(this.getProjectFolderPath(), outputDir)
|
outputDir: path.join(this.getProjectFolderPath(), outputDir)
|
||||||
}, handleProcessExit(done), handleOutput));
|
}, handleProcessExit(done), handleOutput));
|
||||||
|
}else{
|
||||||
|
handleOutput(`${inputFilePath} file not found, skipping tiles generation\n`);
|
||||||
|
done();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -324,19 +325,21 @@ module.exports = class Task{
|
||||||
};
|
};
|
||||||
|
|
||||||
// All paths are relative to the project directory (./data/<uuid>/)
|
// All paths are relative to the project directory (./data/<uuid>/)
|
||||||
|
let allFolders = ['odm_orthophoto', 'odm_georeferencing', 'odm_texturing', 'odm_meshing', 'orthophoto_tiles', 'potree_pointcloud'];
|
||||||
|
|
||||||
|
if (config.test && config.testSkipOrthophotos){
|
||||||
|
logger.info("Test mode will skip orthophoto generation");
|
||||||
|
|
||||||
|
// Exclude these folders from the all.zip archive
|
||||||
|
['odm_orthophoto', 'orthophoto_tiles'].forEach(dir => {
|
||||||
|
allFolders.splice(allFolders.indexOf(dir), 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
generateTiles(path.join('odm_orthophoto', 'odm_orthophoto.tif'), 'orthophoto_tiles'),
|
generateTiles(path.join('odm_orthophoto', 'odm_orthophoto.tif'), 'orthophoto_tiles'),
|
||||||
generatePotreeCloud(path.join('odm_georeferencing', 'odm_georeferenced_model.ply.las'), 'potree_pointcloud'),
|
generatePotreeCloud(path.join('odm_georeferencing', 'odm_georeferenced_model.ply.las'), 'potree_pointcloud'),
|
||||||
createZipArchive('all.zip', ['odm_orthophoto', 'odm_georeferencing', 'odm_texturing', 'odm_meshing', 'orthophoto_tiles', 'potree_pointcloud']),
|
createZipArchive('all.zip', allFolders)
|
||||||
createZipArchive('georeferenced_model.ply.zip', [path.join('odm_georeferencing', 'odm_georeferenced_model.ply')]),
|
|
||||||
createZipArchive('georeferenced_model.las.zip', [path.join('odm_georeferencing', 'odm_georeferenced_model.ply.las')]),
|
|
||||||
createZipArchive('georeferenced_model.csv.zip', [path.join('odm_georeferencing', 'odm_georeferenced_model.csv')]),
|
|
||||||
createZipArchive('textured_model.zip', [
|
|
||||||
path.join('odm_texturing', '*.jpg'),
|
|
||||||
path.join('odm_texturing', 'odm_textured_model_geo.obj'),
|
|
||||||
path.join('odm_texturing', 'odm_textured_model_geo.mtl')
|
|
||||||
]),
|
|
||||||
createZipArchive('orthophoto_tiles.zip', ['orthophoto_tiles'])
|
|
||||||
], (err) => {
|
], (err) => {
|
||||||
if (!err){
|
if (!err){
|
||||||
this.setStatus(statusCodes.COMPLETED);
|
this.setStatus(statusCodes.COMPLETED);
|
||||||
|
@ -361,7 +364,7 @@ module.exports = class Task{
|
||||||
runnerOptions["pmvs-num-cores"] = os.cpus().length;
|
runnerOptions["pmvs-num-cores"] = os.cpus().length;
|
||||||
|
|
||||||
if (this.gpcFiles.length > 0){
|
if (this.gpcFiles.length > 0){
|
||||||
runnerOptions["gcp"] = fs.realpathSync(path.join(this.getGpcFolderPath(), this.gpcFiles[0]));
|
runnerOptions.gcp = fs.realpathSync(path.join(this.getGpcFolderPath(), this.gpcFiles[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.runningProcesses.push(odmRunner.run(runnerOptions, (err, code, signal) => {
|
this.runningProcesses.push(odmRunner.run(runnerOptions, (err, code, signal) => {
|
||||||
|
|
|
@ -41,7 +41,8 @@ module.exports = {
|
||||||
// (num cores can be set programmatically, so can gcpFile, etc.)
|
// (num cores can be set programmatically, so can gcpFile, etc.)
|
||||||
if (["-h", "--project-path", "--cmvs-maxImages", "--time",
|
if (["-h", "--project-path", "--cmvs-maxImages", "--time",
|
||||||
"--zip-results", "--pmvs-num-cores",
|
"--zip-results", "--pmvs-num-cores",
|
||||||
"--start-with", "--gcp", "--end-with"].indexOf(option) !== -1) continue;
|
"--start-with", "--gcp", "--end-with", "--images",
|
||||||
|
"--slam-config", "--video"].indexOf(option) !== -1) continue;
|
||||||
|
|
||||||
let values = json[option];
|
let values = json[option];
|
||||||
|
|
||||||
|
@ -129,6 +130,9 @@ module.exports = {
|
||||||
},
|
},
|
||||||
'string': function(value){
|
'string': function(value){
|
||||||
return value; // No conversion needed
|
return value; // No conversion needed
|
||||||
|
},
|
||||||
|
'path': function(value){
|
||||||
|
return value; // No conversion needed
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -178,9 +182,9 @@ module.exports = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
regex: /^string$/,
|
regex: /^(string|path)$/,
|
||||||
validate: function(){
|
validate: function(){
|
||||||
return true; // All strings are fine
|
return true; // All strings/paths are fine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "node-opendronemap",
|
"name": "node-opendronemap",
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"description": "REST API to access OpenDroneMap",
|
"description": "REST API to access OpenDroneMap",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
Ładowanie…
Reference in New Issue