kopia lustrzana https://github.com/OpenDroneMap/NodeODM
Added more assets download options, added test processing files, small API change
rodzic
038940860d
commit
26ad42cdc2
|
@ -111,6 +111,10 @@ While in test mode all calls to OpenDroneMap's code will be simulated (see the /
|
|||
|
||||
You can find some test drone images [here](https://github.com/dakotabenjamin/odm_data).
|
||||
|
||||
## What if I need more functionality?
|
||||
|
||||
node-OpenDroneMap is meant to be a lightweight API. If you are looking for a more comprehensive solution to drone mapping, check out [WebODM](https://github.com/OpenDroneMap/WebODM), which uses node-OpenDroneMap for processing.
|
||||
|
||||
## Contributing
|
||||
|
||||
Make a pull request small contributions. For big contributions, please open a discussion first. Please use ES6 syntax while writing new Javascript code so that we can keep the code base uniform.
|
||||
|
@ -119,7 +123,7 @@ Make a pull request small contributions. For big contributions, please open a di
|
|||
|
||||
- [X] Command line options for OpenDroneMap
|
||||
- [X] GPC List support
|
||||
- [ ] Autoremove Abandoned Tasks
|
||||
- [ ] Video support when the [SLAM module](https://github.com/OpenDroneMap/OpenDroneMap/pull/317) becomes available
|
||||
- [ ] Continuous Integration Setup
|
||||
- [X] Documentation
|
||||
- [ ] Unit Testing
|
||||
|
|
|
@ -8,7 +8,7 @@ REST API to access OpenDroneMap
|
|||
|
||||
=== Version information
|
||||
[%hardbreaks]
|
||||
_Version_ : 1.0.0
|
||||
_Version_ : 1.0.1
|
||||
|
||||
|
||||
=== Contact information
|
||||
|
@ -257,7 +257,7 @@ Retrieves an asset (the output of OpenDroneMap's processing) associated with a t
|
|||
|===
|
||||
|Type|Name|Description|Schema|Default
|
||||
|*Path*|*asset* +
|
||||
_required_|Type of asset to download. Use "all" for zip file containing all assets. Other options are not yet available|enum (all)|
|
||||
_required_|Type of asset to download. Use "all.zip" for zip file containing all assets. Other options are not yet available|enum (all.zip, georeferenced_model.ply.zip, georeferenced_model.las.zip, georeferenced_model.csv.zip, orthophoto.png, orthophoto.tif, textured_model.zip)|
|
||||
|*Path*|*uuid* +
|
||||
_required_|UUID of the task|string|
|
||||
|===
|
||||
|
|
File diff suppressed because one or more lines are too long
16
index.js
16
index.js
|
@ -290,10 +290,16 @@ app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
|
|||
* - name: asset
|
||||
* in: path
|
||||
* type: string
|
||||
* description: Type of asset to download. Use "all" for zip file containing all assets. Other options are not yet available
|
||||
* description: Type of asset to download. Use "all.zip" for zip file containing all assets. Other options are not yet available
|
||||
* required: true
|
||||
* enum:
|
||||
* - all
|
||||
* - all.zip
|
||||
* - georeferenced_model.ply.zip
|
||||
* - georeferenced_model.las.zip
|
||||
* - georeferenced_model.csv.zip
|
||||
* - orthophoto.png
|
||||
* - orthophoto.tif
|
||||
* - textured_model.zip
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Asset File
|
||||
|
@ -305,8 +311,10 @@ app.get('/task/:uuid/output', getTaskFromUuid, (req, res) => {
|
|||
* $ref: '#/definitions/Error'
|
||||
*/
|
||||
app.get('/task/:uuid/download/:asset', getTaskFromUuid, (req, res) => {
|
||||
if (!req.params.asset || req.params.asset === "all"){
|
||||
res.download(req.task.getAssetsArchivePath(), "all.zip", err => {
|
||||
let asset = req.params.asset !== undefined ? req.params.asset : "all.zip";
|
||||
let filePath = req.task.getAssetsArchivePath(asset);
|
||||
if (filePath){
|
||||
res.download(filePath, filePath, err => {
|
||||
if (err) res.json({error: "Asset not ready"});
|
||||
});
|
||||
}else{
|
||||
|
|
124
libs/Task.js
124
libs/Task.js
|
@ -22,6 +22,7 @@ let async = require('async');
|
|||
let assert = require('assert');
|
||||
let logger = require('./logger');
|
||||
let fs = require('fs');
|
||||
let glob = require("glob");
|
||||
let path = require('path');
|
||||
let rmdir = require('rimraf');
|
||||
let odmRunner = require('./odmRunner');
|
||||
|
@ -118,8 +119,26 @@ module.exports = class Task{
|
|||
|
||||
// Get the path of the archive where all assets
|
||||
// outputted by this task are stored.
|
||||
getAssetsArchivePath(){
|
||||
return path.join(this.getProjectFolderPath(), "all.zip");
|
||||
getAssetsArchivePath(filename){
|
||||
switch(filename){
|
||||
case "all.zip":
|
||||
case "georeferenced_model.ply.zip":
|
||||
case "georeferenced_model.las.zip":
|
||||
case "georeferenced_model.csv.zip":
|
||||
case "textured_model.zip":
|
||||
// OK
|
||||
break;
|
||||
case "orthophoto.png":
|
||||
case "orthophoto.tif":
|
||||
// Append missing pieces to the path
|
||||
filename = path.join('odm_orthophoto', `odm_${filename}`);
|
||||
break;
|
||||
default:
|
||||
// Invalid
|
||||
return false;
|
||||
}
|
||||
|
||||
return path.join(this.getProjectFolderPath(), filename);
|
||||
}
|
||||
|
||||
// Deletes files and folders related to this task
|
||||
|
@ -198,32 +217,89 @@ module.exports = class Task{
|
|||
};
|
||||
|
||||
const postProcess = () => {
|
||||
let output = fs.createWriteStream(this.getAssetsArchivePath());
|
||||
let archive = archiver.create('zip', {});
|
||||
const createZipArchive = (outputFilename, files) => {
|
||||
return (done) => {
|
||||
let output = fs.createWriteStream(this.getAssetsArchivePath(outputFilename));
|
||||
let archive = archiver.create('zip', {});
|
||||
|
||||
archive.on('finish', () => {
|
||||
// TODO: is this being fired twice?
|
||||
this.setStatus(statusCodes.COMPLETED);
|
||||
finished();
|
||||
});
|
||||
archive.on('finish', () => {
|
||||
// TODO: is this being fired twice?
|
||||
done();
|
||||
});
|
||||
|
||||
archive.on('error', err => {
|
||||
this.setStatus(statusCodes.FAILED);
|
||||
logger.error(`Could not archive .zip file: ${err.message}`);
|
||||
finished(err);
|
||||
});
|
||||
archive.on('error', err => {
|
||||
logger.error(`Could not archive .zip file: ${err.message}`);
|
||||
done(err);
|
||||
});
|
||||
|
||||
archive.pipe(output);
|
||||
['odm_orthophoto', 'odm_georeferencing', 'odm_texturing', 'odm_meshing'].forEach(folderToArchive => {
|
||||
let sourcePath = !config.test ?
|
||||
this.getProjectFolderPath() :
|
||||
path.join("tests", "processing_results");
|
||||
|
||||
archive.directory(
|
||||
path.join(sourcePath, folderToArchive),
|
||||
folderToArchive);
|
||||
archive.pipe(output);
|
||||
let globs = [];
|
||||
|
||||
// Process files and directories first
|
||||
files.forEach(file => {
|
||||
let sourcePath = !config.test ?
|
||||
this.getProjectFolderPath() :
|
||||
path.join("tests", "processing_results");
|
||||
let filePath = path.join(sourcePath, file),
|
||||
isGlob = /\*/.test(file),
|
||||
isDirectory = !isGlob && fs.lstatSync(filePath).isDirectory();
|
||||
|
||||
if (isDirectory){
|
||||
archive.directory(filePath, file);
|
||||
}else if (isGlob){
|
||||
globs.push(filePath);
|
||||
}else{
|
||||
archive.file(filePath, {name: path.basename(file)});
|
||||
}
|
||||
});
|
||||
|
||||
// Check for globs
|
||||
if (globs.length !== 0){
|
||||
let pending = globs.length;
|
||||
|
||||
globs.forEach(pattern => {
|
||||
glob(pattern, (err, files) => {
|
||||
if (err) done(err);
|
||||
else{
|
||||
files.forEach(file => {
|
||||
if (fs.lstatSync(file).isFile()){
|
||||
archive.file(file, {name: path.basename(file)});
|
||||
}else{
|
||||
logger.debug(`Could not add ${file} from glob`);
|
||||
}
|
||||
});
|
||||
|
||||
if (--pending === 0){
|
||||
archive.finalize();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}else{
|
||||
archive.finalize()
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
async.series([
|
||||
createZipArchive("all.zip", ['odm_orthophoto', 'odm_georeferencing', 'odm_texturing', 'odm_meshing']),
|
||||
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")
|
||||
])
|
||||
], (err) => {
|
||||
if (!err){
|
||||
this.setStatus(statusCodes.COMPLETED);
|
||||
finished();
|
||||
}else{
|
||||
this.setStatus(statusCodes.FAILED);
|
||||
finished(err);
|
||||
}
|
||||
});
|
||||
archive.finalize();
|
||||
};
|
||||
|
||||
if (this.status.code === statusCodes.QUEUED){
|
||||
|
|
|
@ -39,7 +39,7 @@ module.exports = {
|
|||
for (let option in json){
|
||||
// Not all options are useful to the end user
|
||||
// (num cores can be set programmatically, so can gcpFile, etc.)
|
||||
if (["-h", "--project-path",
|
||||
if (["-h", "--project-path", "--cmvs-maxImages", "--time",
|
||||
"--zip-results", "--pmvs-num-cores", "--odm_georeferencing-useGcp",
|
||||
"--start-with", "--odm_georeferencing-gcpFile", "--end-with"].indexOf(option) !== -1) continue;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "node-opendronemap",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"description": "REST API to access OpenDroneMap",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
@ -24,6 +24,7 @@
|
|||
"async": "^2.0.0-rc.6",
|
||||
"body-parser": "^1.15.2",
|
||||
"express": "^4.14.0",
|
||||
"glob": "^7.1.1",
|
||||
"minimist": "^1.2.0",
|
||||
"morgan": "^1.7.0",
|
||||
"multer": "^1.1.0",
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
<div class="task" data-bind="css: {pulsePositive: info().status && info().status.code === 40, pulseNegative: info().status && info().status.code === 30}">
|
||||
<p data-bind="visible: loading()">Retrieving <span data-bind="text: uuid"></span> ... <span class="glyphicon glyphicon-refresh spinning"></span></p>
|
||||
<div data-bind="visible: !loading() && !info().error">
|
||||
<div class="taskItem"><strong>UUID:</strong> <a data-bind="text: info().uuid, attr: {href: '/task/' + info().uuid + '/info'}"></a></div>
|
||||
<div class="taskItem"><strong>Name:</strong> <span data-bind="text: info().name"></span></div>
|
||||
<div class="taskItem"><strong>Images:</strong> <span data-bind="text: info().imagesCount"></span></div>
|
||||
<div class="taskItem"><strong>Status:</strong> <span data-bind="text: statusDescr()"></span></div>
|
||||
|
@ -93,7 +94,11 @@
|
|||
|
||||
<div class="actionButtons">
|
||||
<button data-bind="click: download, visible: showDownload()" type="button" class="btn btn-primary btn-sm" >
|
||||
<span class="glyphicon glyphicon-download-alt"></span> Download Results
|
||||
<span class="glyphicon glyphicon-download-alt"></span> Download All Assets
|
||||
</button>
|
||||
|
||||
<button data-bind="click: downloadOrthophoto, visible: showDownload()" type="button" class="btn btn-primary btn-sm" >
|
||||
<span class="glyphicon glyphicon-picture"></span> Download Orthophoto
|
||||
</button>
|
||||
|
||||
<button data-bind="click: cancel, visible: showCancel()" type="button" class="btn btn-primary btn-sm" >
|
||||
|
@ -127,6 +132,7 @@
|
|||
<hr>
|
||||
|
||||
<footer>
|
||||
<p>Links: <a href="https://github.com/pierotofy/node-OpenDroneMap/blob/master/docs/index.adoc" target="_blank">API Docs</a> | <a href="https://github.com/OpenDroneMap/WebODM" target="_blank">WebODM</a>
|
||||
<p>This software is released under the terms of the <a href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPLv3 License</a>. See <a href="https://github.com/pierotofy/node-OpenDroneMap" target="_blank">node-opendronemap</a> on Github for more information.</p>
|
||||
</footer>
|
||||
</div> <!-- /container --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
|
||||
|
|
|
@ -259,7 +259,10 @@ $(function(){
|
|||
task.resetOutput();
|
||||
});
|
||||
Task.prototype.download = function(){
|
||||
location.href = "/task/" + this.uuid + "/download/all";
|
||||
location.href = "/task/" + this.uuid + "/download/all.zip";
|
||||
};
|
||||
Task.prototype.downloadOrthophoto = function(){
|
||||
location.href = "/task/" + this.uuid + "/download/orthophoto.tif";
|
||||
};
|
||||
|
||||
var taskList = new TaskList();
|
||||
|
|
Ładowanie…
Reference in New Issue