package nbtool.data.calibration;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map.Entry;
import nbtool.data.SExpr;
import nbtool.data.json.Json;
import nbtool.data.json.Json.JsonValue;
import nbtool.data.json.JsonObject;
import nbtool.data.json.JsonString;
import nbtool.util.Debug;
import nbtool.util.SharedConstants;
import nbtool.util.ToolSettings;
import nbtool.util.test.TestBase;
import nbtool.util.test.Tests;
public class CameraOffset {
/* if the offsets are greater/smaller than these, something went wrong */
private static final double MAX_VALID = Math.PI / 4;
private static final double MIN_VALID = -1 * (MAX_VALID);
private static boolean verify(double val) {
return val > MIN_VALID && val < MAX_VALID && val != Double.NaN;
}
public boolean verify() {
if (!verify(this.d_roll)) {
Debug.error("error in d_roll: must be within {%f, %f}, is %f",
MIN_VALID, MAX_VALID, this.d_roll);
return false;
}
if (!verify(this.d_tilt)) {
Debug.error("error in d_tilt: must be within {%f, %f}, is %f",
MIN_VALID, MAX_VALID, this.d_tilt);
return false;
}
return true;
}
public double d_roll;
public double d_tilt;
public JsonObject toObject() {
JsonObject ret = Json.object();
ret.put("d_roll", d_roll);
ret.put("d_tilt", d_tilt);
return ret;
}
public CameraOffset(double r, double t) {
this.d_roll = r; this.d_tilt = t;
}
public static CameraOffset fromObject(JsonObject o) {
return new CameraOffset(
o.get("d_roll").asNumber().asDouble(),
o.get("d_tilt").asNumber().asDouble()
);
}
public static CameraOffset fromLisp(SExpr lisp) {
return new CameraOffset(lisp.get(1).valueAsDouble(), lisp.get(2).valueAsDouble());
}
public static class Pair {
public CameraOffset top;
public CameraOffset bot;
public Pair(CameraOffset t, CameraOffset b) {
this.top = t; this.bot = b;
}
}
public static class Set extends HashMap<String, Pair> {
public static Set parse(JsonObject obj) {
Set ret = new Set();
for (Entry<JsonString, JsonValue> entry : obj.entrySet()) {
String robotName = entry.getKey().value;
JsonObject topObj = entry.getValue().asObject().get("camera_TOP").asObject();
JsonObject botObj = entry.getValue().asObject().get("camera_BOT").asObject();
Pair offs = new Pair(
CameraOffset.fromObject(topObj),
CameraOffset.fromObject(botObj)
);
ret.put(robotName, offs);
}
return ret;
}
public boolean verify() {
for (Entry<String,Pair> entry : this.entrySet()) {
String robotName = entry.getKey();
if (!entry.getValue().top.verify()) {
Debug.error("error in camera TOP of %s", robotName);
return false;
}
if (!entry.getValue().bot.verify()) {
Debug.error("error in camera BOT of %s", robotName);
return false;
}
}
return true;
}
public JsonObject serialize() {
JsonObject ret = Json.object();
for (Entry<String, Pair> entry : this.entrySet()) {
JsonObject pair = Json.object();
pair.put("camera_TOP", entry.getValue().top.toObject());
pair.put("camera_BOT", entry.getValue().bot.toObject());
ret.put(entry.getKey(), pair);
}
return ret;
}
}
public static Path getPath() {
return Paths.get(ToolSettings.NBITES_DIR, SharedConstants.OFFLINE_CAMERA_OFFSET_SUFFIX());
}
public static void _NBL_ADD_TESTS_() {
Tests.add("calibration", new TestBase("CameraOffset") {
@Override
public boolean testBody() throws Exception {
JsonObject top = Json.object();
JsonObject vera = Json.object();
vera.put("camera_TOP", new CameraOffset(1,2).toObject());
vera.put("camera_BOT", new CameraOffset(3,4).toObject());
top.put("vera", vera);
JsonObject mal = Json.object();
mal.put("camera_TOP", new CameraOffset(5,8).toObject());
mal.put("camera_BOT", new CameraOffset(9,7).toObject());
top.put("mal", mal);
JsonObject backwards = Set.parse(top).serialize();
assert(backwards.congruent(top));
return true;
}
},
new TestBase("CameraOffsetExists") {
@Override
public boolean testBody() throws Exception {
Debug.print("%s", ToolSettings.NBITES_DIR_PATH);
String cpStr = new String(Files.readAllBytes(
Paths.get(ToolSettings.NBITES_DIR, SharedConstants.OFFLINE_CAMERA_OFFSET_SUFFIX())
));
Set.parse(Json.parse(cpStr).asObject());
return true;
}
});
}
public static void main(String[] args) throws IOException {
String lisp = new String(Files.readAllBytes(ToolSettings.NBITES_DIR_PATH.resolve("src/man/config/calibrationParams.txt")));
SExpr se = SExpr.deserializeFrom(lisp);
CameraOffset.Set set = new Set();
SExpr list = se.get(1);
for (int i = 0; i < list.count(); ++i) {
String robot = list.get(i).get(0).value();
CameraOffset top = new CameraOffset(list.get(i).get(1).get(1).valueAsDouble(),
list.get(i).get(1).get(2).valueAsDouble()
);
CameraOffset bot = new CameraOffset(list.get(i).get(2).get(1).valueAsDouble(),
list.get(i).get(2).get(2).valueAsDouble()
);
set.put(robot, new Pair(top,bot));
}
Debug.print("%s", set.serialize().print());
}
}