Working on calibration
This commit is contained in:
parent
8676b21969
commit
658fcd57c3
31
app.py
31
app.py
|
|
@ -30,14 +30,23 @@ def create_object():
|
|||
def object(id: int):
|
||||
conn = db.get()
|
||||
object = db.Object.get_from_id(id, conn)
|
||||
return render_template('object.html', object=object)
|
||||
calibration = object.calibration(conn)
|
||||
return render_template('object.html', object=object, calibration=calibration)
|
||||
|
||||
|
||||
@app.route("/calibrate/<id>")
|
||||
def calibrate(id: int):
|
||||
conn = db.get()
|
||||
object = db.Object.get_from_id(id, conn)
|
||||
return render_template('calibrate.html', object=object)
|
||||
if object.calibration_id is None:
|
||||
with conn:
|
||||
calibration = db.Calibration.create(conn)
|
||||
object.calibration_id = calibration.id
|
||||
object.save(conn)
|
||||
else:
|
||||
calibration = object.calibration(conn)
|
||||
|
||||
return render_template('calibrate.html', object=object, calibration=calibration, leds=config.LEDS_UUIDS)
|
||||
|
||||
|
||||
@app.route("/api/preview/<id>")
|
||||
|
|
@ -54,22 +63,26 @@ def preview(id: int):
|
|||
@app.route("/api/scan-for-calibration/<id>")
|
||||
def scan_calibration(id: int):
|
||||
conn = db.get()
|
||||
db.Object.get_from_id(id, conn)
|
||||
calibration = db.Calibration.get_from_id(id, conn)
|
||||
|
||||
def generate():
|
||||
length = len(config.LEDS_UUIDS)
|
||||
for index, led_uuid in enumerate(scanner.scan(join(config.DATA_DIR, id, 'calibration'))):
|
||||
for index, led_uuid in enumerate(scanner.scan(join(config.CALIBRATION_DIR, id))):
|
||||
yield f"{led_uuid},{(index+1)/length}\n"
|
||||
|
||||
with conn:
|
||||
calibration.state = db.CalibrationState.HasData
|
||||
calibration.save(conn)
|
||||
|
||||
return app.response_class(generate(), mimetype='text/plain')
|
||||
|
||||
|
||||
@app.route("/api/calibrate/<id>")
|
||||
def run_calibration(id: int):
|
||||
conn = db.get()
|
||||
db.Object.get_from_id(id, conn)
|
||||
calibration_json = calibration.calibrate(join(config.DATA_DIR, str(id), 'calibration'))
|
||||
with open(join(config.DATA_DIR, str(id), 'calibration.json'), 'w') as f:
|
||||
db.Calibration.get_from_id(id, conn)
|
||||
calibration_json = calibration.calibrate(join(config.CALIBRATION_DIR, str(id)))
|
||||
with open(join(config.CALIBRATION_DIR, str(id), 'calibration.json'), 'w') as f:
|
||||
json.dump(calibration_json, f, indent=4)
|
||||
return 'ok'
|
||||
|
||||
|
|
@ -77,8 +90,8 @@ def run_calibration(id: int):
|
|||
@app.route("/calibration/<id>")
|
||||
def calibration_page(id: int):
|
||||
conn = db.get()
|
||||
object = db.Object.get_from_id(id, conn)
|
||||
return render_template('calibration.html', object=object)
|
||||
calibration = db.Calibration.get_from_id(id, conn)
|
||||
return render_template('calibration.html', calibration=calibration)
|
||||
|
||||
|
||||
@app.route('/static/<path:path>')
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
from os.path import join
|
||||
|
||||
DATA_DIR = 'data'
|
||||
CALIBRATION_DIR = join(DATA_DIR, 'calibration')
|
||||
|
||||
LEDS_UUIDS = [
|
||||
'ac59350e-3787-46d2-88fa-743c1d34fe86',
|
||||
|
|
|
|||
72
db.py
72
db.py
|
|
@ -1,5 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from enum import IntEnum
|
||||
from flask import g
|
||||
import os
|
||||
import sqlite3
|
||||
|
|
@ -13,6 +14,8 @@ def get() -> sqlite3.Connection:
|
|||
detect_types=sqlite3.PARSE_DECLTYPES,
|
||||
)
|
||||
g.db.row_factory = sqlite3.Row
|
||||
cur = g.db.cursor()
|
||||
cur.execute('PRAGMA foreign_keys = on')
|
||||
|
||||
return g.db
|
||||
|
||||
|
|
@ -43,34 +46,75 @@ if __name__ == '__main__':
|
|||
init(db)
|
||||
|
||||
|
||||
class CalibrationState(IntEnum):
|
||||
Empty = 0
|
||||
HasData = 1
|
||||
IsValidated = 2
|
||||
|
||||
|
||||
class Calibration:
|
||||
@staticmethod
|
||||
def select_args() -> str:
|
||||
return 'id, state'
|
||||
|
||||
def __init__(self, calibration_id: int, state: int):
|
||||
self.id = calibration_id
|
||||
self.state = CalibrationState(state)
|
||||
|
||||
@staticmethod
|
||||
def create(db: sqlite3.Connection) -> 'Calibration':
|
||||
cur = db.cursor()
|
||||
response = cur.execute(
|
||||
'INSERT INTO calibration(state) VALUES (?) RETURNING ' + Calibration.select_args() + ';',
|
||||
[int(CalibrationState.Empty)]
|
||||
)
|
||||
return Calibration.from_row(response.fetchone())
|
||||
|
||||
@staticmethod
|
||||
def from_row(row: sqlite3.Row) -> 'Calibration':
|
||||
return Calibration(*row)
|
||||
|
||||
def save(self, db: sqlite3.Connection):
|
||||
cur = db.cursor()
|
||||
cur.execute(
|
||||
'UPDATE calibration SET state = ? WHERE id = ?',
|
||||
[int(self.state), self.id]
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_from_id(calibration_id: int, db: sqlite3.Connection) -> Optional['Calibration']:
|
||||
cur = db.cursor()
|
||||
response = cur.execute(
|
||||
'SELECT ' + Calibration.select_args() + ' FROM calibration WHERE id = ?;',
|
||||
[calibration_id]
|
||||
)
|
||||
return Calibration.from_row(response.fetchone())
|
||||
|
||||
|
||||
class Object:
|
||||
@staticmethod
|
||||
def select_args() -> str:
|
||||
return 'id, name, calibrated'
|
||||
return 'id, name, calibration_id'
|
||||
|
||||
def __init__(self, object_id: int, name: str, calibrated: int):
|
||||
def __init__(self, object_id: int, name: str, calibration: int):
|
||||
self.id = object_id
|
||||
self.name = name
|
||||
|
||||
# 0 means no data available
|
||||
# 1 means data available but calibration not done
|
||||
# 2 means calibration done
|
||||
self.calibrated = calibrated
|
||||
self.calibration_id = calibration
|
||||
|
||||
@staticmethod
|
||||
def create(name: str, db: sqlite3.Connection) -> 'Object':
|
||||
cur = db.cursor()
|
||||
response = cur.execute(
|
||||
'INSERT INTO object(name, calibrated) VALUES (?, ?) RETURNING ' + Object.select_args() + ';',
|
||||
[name, 0]
|
||||
'INSERT INTO object(name, calibration_id) VALUES (?, ?) RETURNING ' + Object.select_args() + ';',
|
||||
[name, None]
|
||||
)
|
||||
return Object.from_row(response.fetchone())
|
||||
|
||||
def save(self, db: sqlite3.Connection):
|
||||
cur = db.cursor()
|
||||
cur.execute(
|
||||
'UPDATE object SET name = ? WHERE id = ?',
|
||||
[self.name, self.id]
|
||||
'UPDATE object SET name = ?, calibration_id = ? WHERE id = ?',
|
||||
[self.name, self.calibration_id, self.id]
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -94,3 +138,9 @@ class Object:
|
|||
[]
|
||||
)
|
||||
return list(map(Object.from_row, response.fetchall()))
|
||||
|
||||
def calibration(self, db: sqlite3.Connection) -> Optional[Calibration]:
|
||||
if self.calibration_id is None:
|
||||
return None
|
||||
|
||||
return Calibration.get_from_id(self.calibration_id, db)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
DROP TABLE IF EXISTS object;
|
||||
DROP TABLE IF EXISTS calibration;
|
||||
|
||||
CREATE TABLE calibration (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
state INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE object (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
calibrated INT NOT NULL
|
||||
calibration_id INTEGER,
|
||||
CONSTRAINT fk_calibration FOREIGN KEY(calibration_id) REFERENCES calibration(id)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<progress id="progress-bar" class="progress is-link" style="display: none;" value="0" max="1000"></progress>
|
||||
<div id="calibrate" style="display: none;">
|
||||
<div id="calibrate" {% if calibration.state == 0 %}style="display: none;"{% endif %}>
|
||||
<p>Si les données d'étalonnage conviennent, appuyez sur le bouton ci-dessous pour procéder à l'étalonnage du scanner</p>
|
||||
<button id="calibrate-button" class="button is-link">Étalonner le scanner</button>
|
||||
<p id="calibration-info"></p>
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
{% block extrajs %}
|
||||
<script>
|
||||
let scanIndex = 0;
|
||||
let scanIndex = 1;
|
||||
let progress = 0;
|
||||
let previewButton = document.getElementById('preview-button');
|
||||
let scanButton = document.getElementById('scan-button');
|
||||
|
|
@ -74,6 +74,20 @@
|
|||
buttons.forEach(x => x.removeAttribute('disabled'));
|
||||
});
|
||||
|
||||
// If we already have calibration images, we show them right now
|
||||
if ({% if calibration.state > 0 %}true{% else %}false{% endif %}) {
|
||||
let cell, img;
|
||||
{% for led in leds %}
|
||||
cell = document.createElement('div');
|
||||
cell.classList.add('cell');
|
||||
img = document.createElement('img');
|
||||
img.classList.add('is-loading');
|
||||
img.src = '/data/calibration/{{ calibration.id }}/{{ led }}.jpg?v=0';
|
||||
cell.appendChild(img);
|
||||
grid.appendChild(cell);
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
scanButton.addEventListener('click', async () => {
|
||||
scanIndex++;
|
||||
progress = 0;
|
||||
|
|
@ -84,7 +98,7 @@
|
|||
progressBar.style.display = "block";
|
||||
grid.innerHTML = '';
|
||||
|
||||
let response = await fetch('/api/scan-for-calibration/{{ object.id }}');
|
||||
let response = await fetch('/api/scan-for-calibration/{{ calibration.id }}');
|
||||
let reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
||||
|
||||
while (true) {
|
||||
|
|
@ -103,7 +117,7 @@
|
|||
cell.classList.add('cell');
|
||||
let img = document.createElement('img');
|
||||
img.classList.add('is-loading');
|
||||
img.src = '/data/{{ object.id }}/calibration/' + uuid + '.jpg?v=' + scanIndex;
|
||||
img.src = '/data/calibration/{{ calibration.id }}/' + uuid + '.jpg?v=' + scanIndex;
|
||||
cell.appendChild(img);
|
||||
grid.appendChild(cell);
|
||||
}
|
||||
|
|
@ -113,7 +127,7 @@
|
|||
calibrateButton.classList.add('is-loading');
|
||||
|
||||
await fetch('/api/calibrate/{{ object.id }}');
|
||||
window.location.href = '/calibration/{{ object.id }}';
|
||||
window.location.href = '/calibration/{{ calibration.id }}';
|
||||
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
{% block content %}
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h1 class="title is-2">Visualisation de l'étalonnage de {{ object.name }}</h1>
|
||||
<h1 class="title is-2">Visualisation de l'étalonnage {{ calibration.id }}</h1>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h2 class="title is-3">Positions 3D des LEDs</h2>
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@
|
|||
<h1 class="title">{{ object.name }}</h1>
|
||||
<div class="field is-grouped is-grouped-multiline">
|
||||
<div class="control">
|
||||
{% if object.calibrated == 0 %}
|
||||
{% if calibration is none or calibration.state == 0 %}
|
||||
<span class="tags has-addons">
|
||||
<span class="tag is-dark">étalonnage</span>
|
||||
<span class="tag is-danger">données manquantes</span>
|
||||
<span class="tag is-danger">aucune donnée</span>
|
||||
</span>
|
||||
{% elif object.calibrated == 1 %}
|
||||
{% elif calibration.state == 1 %}
|
||||
<span class="tags has-addons">
|
||||
<span class="tag is-dark">étalonnage</span>
|
||||
<span class="tag is-warning">pas fait</span>
|
||||
</span>
|
||||
{% elif object.calibrated == 2 %}
|
||||
{% elif calibration.state == 2 %}
|
||||
<a href="/calibration/{{ object.id }}" class="tags has-addons">
|
||||
<span class="tag is-dark">étalonnage</span>
|
||||
<span class="tag is-success">fait</span>
|
||||
|
|
@ -24,8 +24,11 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if object.calibrated == 0 %}
|
||||
<a href="/calibrate/{{ object.id }}" class="button is-link">Étalonner le scanner</a>
|
||||
{% if calibration is none or calibration.state == 0 %}
|
||||
<div class="field is-grouped">
|
||||
<a href="/calibrate/{{ object.id }}" class="button is-link">Étalonner le scanner</a>
|
||||
<a href="#" title="Non implémenté" disabled="disabled" class="button is-link">Utiliser le dernier étalonnage connu</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ export class Engine {
|
|||
engine.domElement = domElement;
|
||||
engine.initHtml();
|
||||
|
||||
let request = await fetch('/data/' + objectId + '/calibration.json');
|
||||
let request = await fetch('/data/calibration/' + objectId + '/calibration.json');
|
||||
let calibration = await request.json();
|
||||
engine.initScene(calibration);
|
||||
engine.initListeners();
|
||||
|
|
@ -296,7 +296,7 @@ export class Engine {
|
|||
showImage(led: Led): void {
|
||||
if (led.on) {
|
||||
this.selectedObject.innerText = led.name.split('.')[0] + ' (' + (<number> this.leds.currentLedIndex + 1) + '/' + this.leds.children.length + ')';
|
||||
this.ledView.src = '/data/' + this.objectId + '/calibration/' + led.name;
|
||||
this.ledView.src = '/data/calibration/' + this.objectId + '/' + led.name;
|
||||
this.ledView.style.display = 'block';
|
||||
} else {
|
||||
this.selectedObject.innerText = 'aucune';
|
||||
|
|
|
|||
Loading…
Reference in New Issue