Commit 391e23d6 authored by Jean Meurice's avatar Jean Meurice
Browse files

Serialization V1

parent d494fa09
Pipeline #302092 passed with stage
in 40 seconds
......@@ -8,7 +8,7 @@
<groupId>montisim</groupId>
<artifactId>commons</artifactId>
<version>2.0.1</version>
<version>2.0.2</version>
<properties>
......@@ -29,6 +29,14 @@
<artifactId>commons-math3</artifactId>
<version>RELEASE</version>
</dependency>
<!-- JUnit for testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
......
/* (c) https://github.com/MontiCore/monticore */
package de.rwth.montisim.commons.boundingbox;
import de.rwth.montisim.commons.utils.JsonTraverser;
import de.rwth.montisim.commons.utils.JsonTraverser.ObjectIterable;
import de.rwth.montisim.commons.utils.JsonWriter;
public class AABB implements BoundingBox {
public static final String TYPE_NAME = "aabb";
@Override
public void toJson(JsonWriter j) {
// TODO Auto-generated method stub
}
@Override
public void fromJson(JsonTraverser j) {
// TODO Auto-generated method stub
}
@Override
public void fromJson(JsonTraverser j, ObjectIterable it) {
// TODO Auto-generated method stub
}
}
\ No newline at end of file
/* (c) https://github.com/MontiCore/monticore */
package de.rwth.montisim.commons.boundingbox;
public interface BoundingBox {
import de.rwth.montisim.commons.utils.JsonSerializable;
import de.rwth.montisim.commons.utils.JsonTraverser;
import de.rwth.montisim.commons.utils.Pair;
import de.rwth.montisim.commons.utils.JsonTraverser.ObjectIterable;
public interface BoundingBox extends JsonSerializable {
void fromJson(JsonTraverser j, ObjectIterable it);
public static BoundingBox buildFromJson(JsonTraverser j){
Pair<String, ObjectIterable> p = j.getStructureType();
BoundingBox bbox = getBoundingBoxFromType(p.getKey());
bbox.fromJson(j, p.getValue());
return bbox;
}
public static BoundingBox getBoundingBoxFromType(String type){
if (type.equals(OBB.TYPE_NAME)){
return new OBB();
} else if (type.equals(AABB.TYPE_NAME)){
return new AABB();
} else if (type.equals(Sphere.TYPE_NAME)){
return new Sphere();
} else throw new IllegalArgumentException("Unknown BoundingBox type: "+type);
}
}
\ No newline at end of file
/* (c) https://github.com/MontiCore/monticore */
package de.rwth.montisim.commons.boundingbox;
import de.rwth.montisim.commons.utils.JsonTraverser;
import de.rwth.montisim.commons.utils.JsonWriter;
import de.rwth.montisim.commons.utils.Mat3;
import de.rwth.montisim.commons.utils.Vec3;
import de.rwth.montisim.commons.utils.JsonTraverser.Entry;
import de.rwth.montisim.commons.utils.JsonTraverser.ObjectIterable;
//@JsonSubtype("obb") or @JsonTyped("obb") ?
//@JsonObject
public class OBB implements BoundingBox {
public static final String TYPE_NAME = "obb";
public Vec3 offset = new Vec3(); // Offset from center of mass
public Vec3 half_extent = new Vec3();
public Mat3 axes = new Mat3();
@Override
public void toJson(JsonWriter j) {
j.startObject();
j.write("type", TYPE_NAME);
j.writeKey("offset");
offset.toJson(j);
j.writeKey("half_extent");
half_extent.toJson(j);
j.writeKey("axes");
axes.toJson(j);
j.endObject();
}
@Override
public void fromJson(JsonTraverser j) {
fromJson(j, j.streamObject());
}
@Override
public void fromJson(JsonTraverser j, ObjectIterable it) {
boolean a = false, b = false, c = false;
for (Entry e : it) {
if (e.key.equals("offset")) {
offset.fromJson(j);
a = true;
} else if (e.key.equals("half_extent")) {
half_extent.fromJson(j);
b = true;
} else if (e.key.equals("axes")) {
axes.fromJson(j);
c = true;
} else
j.unexpected(e);
}
if (!a)
j.expected("offset");
if (!b)
j.expected("half_extent");
if (!c)
j.expected("axes");
}
}
\ No newline at end of file
/* (c) https://github.com/MontiCore/monticore */
package de.rwth.montisim.commons.boundingbox;
import de.rwth.montisim.commons.utils.JsonTraverser;
import de.rwth.montisim.commons.utils.JsonTraverser.ObjectIterable;
import de.rwth.montisim.commons.utils.JsonWriter;
public class Sphere implements BoundingBox {
public static final String TYPE_NAME = "sphere";
@Override
public void toJson(JsonWriter j) {
// TODO Auto-generated method stub
}
@Override
public void fromJson(JsonTraverser j) {
// TODO Auto-generated method stub
}
@Override
public void fromJson(JsonTraverser j, ObjectIterable it) {
// TODO Auto-generated method stub
}
}
\ No newline at end of file
/* (c) https://github.com/MontiCore/monticore */
package de.rwth.montisim.commons.dynamicinterface;
import java.util.Vector;
import de.rwth.montisim.commons.utils.JsonTraverser;
import de.rwth.montisim.commons.utils.JsonWriter;
import de.rwth.montisim.commons.utils.Vec2;
import de.rwth.montisim.commons.utils.Vec3;
import de.rwth.montisim.commons.utils.JsonTraverser.ValueType;
public class ArrayType extends DataType {
public static enum Dimensionality {
ARRAY,
......@@ -53,4 +61,108 @@ public class ArrayType extends DataType {
ArrayType a = ((ArrayType)o);
return this.baseType.equals(a.baseType) && this.dimension.equals(a.dimension) && this.sizeOrMaxSize == a.sizeOrMaxSize;
}
@Override
public void toJson(JsonWriter j, Object o){
j.startArray();
if (baseType.type == Type.DOUBLE) {
double[] a = (double[])o;
for (double d : a) j.writeValue(d);
} else if (baseType.type == Type.FLOAT) {
float[] a = (float[])o;
for (double f : a) j.writeValue(f);
} else if (baseType.type == Type.INT) {
int[] a = (int[])o;
for (int i : a) j.writeValue(i);
} else if (baseType.type == Type.BYTE) {
byte[] a = (byte[])o;
for (byte b : a) j.writeValue(b);
} else if (baseType.type == Type.BOOLEAN) {
boolean[] a = (boolean[])o;
for (boolean b : a) j.writeValue(b);
} else if (baseType.type == Type.EMPTY) {
} else if (baseType.type == Type.VEC2) {
Vec2[] a = (Vec2[])o;
for (Vec2 v : a) v.toJson(j);
} else if (baseType.type == Type.VEC3) {
Vec3[] a = (Vec3[])o;
for (Vec3 v : a) v.toJson(j);
} else throw new IllegalArgumentException("Missing array type implementation (type: "+type+")");
j.endArray();
}
@Override
public Object fromJson(JsonTraverser j){
if (baseType.type == Type.DOUBLE) {
Vector<Double> v = new Vector<>();
for (ValueType t : j.streamArray()){
v.add(j.getDouble());
}
double[] a = new double[v.size()];
int i = 0;
for (double d : v) a[i++] = d;
return a;
} else if (baseType.type == Type.FLOAT) {
Vector<Float> v = new Vector<>();
for (ValueType t : j.streamArray()){
v.add((float)j.getDouble());
}
float[] a = new float[v.size()];
int i = 0;
for (float f : v) a[i++] = f;
return a;
} else if (baseType.type == Type.INT) {
Vector<Integer> v = new Vector<>();
for (ValueType t : j.streamArray()){
v.add((int)j.getLong());
}
int[] a = new int[v.size()];
int i = 0;
for (int f : v) a[i++] = f;
return a;
} else if (baseType.type == Type.BYTE) {
Vector<Byte> v = new Vector<>();
for (ValueType t : j.streamArray()){
v.add((byte)j.getLong());
}
byte[] a = new byte[v.size()];
int i = 0;
for (byte b : v) a[i++] = b;
return a;
} else if (baseType.type == Type.BOOLEAN) {
Vector<Boolean> v = new Vector<>();
for (ValueType t : j.streamArray()){
v.add(j.getBoolean());
}
boolean[] a = new boolean[v.size()];
int i = 0;
for (boolean b : v) a[i++] = b;
return a;
} else if (baseType.type == Type.EMPTY) {
return null;
} else if (baseType.type == Type.VEC2) {
Vector<Vec2> v = new Vector<>();
for (ValueType t : j.streamArray()){
Vec2 vec = new Vec2();
vec.fromJson(j);
v.add(vec);
}
Vec2[] a = new Vec2[v.size()];
int i = 0;
for (Vec2 b : v) a[i++] = b;
return a;
} else if (baseType.type == Type.VEC3) {
Vector<Vec3> v = new Vector<>();
for (ValueType t : j.streamArray()){
Vec3 vec = new Vec3();
vec.fromJson(j);
v.add(vec);
}
Vec3[] a = new Vec3[v.size()];
int i = 0;
for (Vec3 b : v) a[i++] = b;
return a;
} else throw new IllegalArgumentException("Missing array type implementation (type: "+type+")");
}
}
\ No newline at end of file
/* (c) https://github.com/MontiCore/monticore */
package de.rwth.montisim.commons.dynamicinterface;
import de.rwth.montisim.commons.utils.*;
import de.rwth.montisim.commons.utils.json.JsonEntry;
/**
* Reflection class for the types of Messages sent in the simulation.
*/
......@@ -17,6 +20,7 @@ public class DataType {
public static enum Type {
//@JsonEntry
DOUBLE,
FLOAT,
INT,
......@@ -94,4 +98,38 @@ public class DataType {
return false;
return this.type == ((DataType)o).type;
}
public void toJson(JsonWriter j, Object o) {
switch(type){
case DOUBLE: j.writeValue((Double)o); return;
case FLOAT: j.writeValue((Float)o); return;
case INT: j.writeValue((Integer)o); return;
case BYTE: j.writeValue((Byte)o); return;
case BOOLEAN: j.writeValue((Boolean)o); return;
case EMPTY: return;
case VEC2: ((Vec2)o).toJson(j); return;
case VEC3: ((Vec3)o).toJson(j); return;
default: throw new IllegalArgumentException("Missing type implementation (type: "+type+")");
}
}
public Object fromJson(JsonTraverser j){
switch(type){
case DOUBLE: return j.getDouble();
case FLOAT: return (float)j.getDouble();
case INT: return (int)j.getLong();
case BYTE: return (byte)j.getLong();
case BOOLEAN: return j.getBoolean();
case EMPTY: return null;
case VEC2:
Vec2 v = new Vec2();
v.fromJson(j);
return v;
case VEC3:
Vec3 v2 = new Vec3();
v2.fromJson(j);
return v2;
default: throw new IllegalArgumentException("Missing type implementation (type: "+type+")");
}
}
}
\ No newline at end of file
......@@ -8,10 +8,13 @@ import java.util.Comparator;
* Interface for a discrete event in a discrete event simulation
*/
public abstract class DiscreteEvent<EventType> {
protected final Instant time;
protected Instant time;
public DiscreteEvent(Instant time){
this.time = time;
}
protected DiscreteEvent(){
this.time = null;
}
public Instant getEventTime(){
return time;
}
......
......@@ -17,10 +17,10 @@ public abstract class DiscreteEventSimulator<EventType, T extends DiscreteEvent<
private static final DiscreteEvent.DiscreteEventComparator listComparator = new DiscreteEvent.DiscreteEventComparator();
/** point of time of simulation */
private Instant simulationTime = Instant.EPOCH;
protected Instant simulationTime = Instant.EPOCH;
/** list of all discrete events */
private final PriorityQueue<T> eventList = new PriorityQueue<>(listComparator);
protected final PriorityQueue<T> eventList = new PriorityQueue<>(listComparator);
/**
* Function that needs to be implemented in subclasses of DiscreteEventSimulator
......
/* (c) https://github.com/MontiCore/monticore */
package de.rwth.montisim.commons.simulation;
import de.rwth.montisim.commons.utils.JsonTraverser;
import de.rwth.montisim.commons.utils.JsonWriter;
import de.rwth.montisim.commons.utils.StringRef;
import de.rwth.montisim.commons.utils.Vec3;
import de.rwth.montisim.commons.utils.JsonTraverser.Entry;
/**
* Represents a dynamic object in the simulation, does have positional and rotation velocities and a mass.
*/
public class DynamicObject extends StaticObject {
public static final String TYPE = "dynamic";
public Vec3 velocity;
public Vec3 angularVelocity;
public double mass;
......@@ -19,6 +24,48 @@ public class DynamicObject extends StaticObject {
}
public String toString() {
return "{name: " + name + ", type: " + type + ", mass: " + mass + ", pos: " + pos + ", vel: " + velocity + "}";
return "{name: " + name + ", type: " + desc + ", mass: " + mass + ", pos: " + pos + ", vel: " + velocity + "}";
}
public static final String K_VEL = "vel";
public static final String K_ANGULAR_VEL = "ang_vel";
public static final String K_MASS = "mass";
@Override
public void toJson(JsonWriter j) {
j.startObject();
j.write(JsonTraverser.K_TYPE, TYPE);
writeStatic(j);
writeDynamic(j);
j.endObject();
}
protected void writeDynamic(JsonWriter j){
j.writeKey(K_VEL);
velocity.toJson(j);
j.writeKey(K_ANGULAR_VEL);
angularVelocity.toJson(j);
j.write(K_MASS, mass);
}
@Override
public void fromJson(JsonTraverser j) {
for (Entry e : j.expectStructureType(TYPE)){
if (!readStatic(j, e.key) && !readDynamic(j, e.key)) j.unexpected(e);
}
}
protected boolean readDynamic(JsonTraverser j, StringRef key){
if (key.equals(K_VEL)) {
velocity.fromJson(j);
} else if (key.equals(K_ANGULAR_VEL)) {
angularVelocity.fromJson(j);
} else if (key.equals(K_MASS)) {
mass = j.getDouble();
} else return false;
return true;
}
}
\ No newline at end of file
......@@ -4,30 +4,89 @@ package de.rwth.montisim.commons.simulation;
import java.util.Optional;
import de.rwth.montisim.commons.boundingbox.BoundingBox;
import de.rwth.montisim.commons.utils.JsonSerializable;
import de.rwth.montisim.commons.utils.JsonTraverser;
import de.rwth.montisim.commons.utils.JsonWriter;
import de.rwth.montisim.commons.utils.Mat3;
import de.rwth.montisim.commons.utils.StringRef;
import de.rwth.montisim.commons.utils.Vec3;
import de.rwth.montisim.commons.utils.JsonTraverser.Entry;
import de.rwth.montisim.commons.utils.JsonTraverser.ObjectIterable;
/**
* Data for a static object of the simulation world (cannot dynamically move, and has "infinite" mass)
* with a bounding box.
* Data for a static object of the simulation world (cannot dynamically move,
* and has "infinite" mass) with a bounding box.
*/
public class StaticObject {
public class StaticObject implements JsonSerializable {
public static final String TYPE = "static";
public String name;
/** Descriptive type. */
public String type;
public String desc;
public Vec3 pos;
public Mat3 rotation;
public Optional<BoundingBox> bbox;
public StaticObject(String type) {
public StaticObject(String desc) {
this.name = "unknown";
this.type = type;
this.desc = desc;
this.pos = new Vec3();
this.rotation = Mat3.unit();
this.bbox = Optional.empty();
}
public String toString() {
return "{name: " + name + ", type: " + type + ", pos: " + pos + "}";
return "{name: " + name + ", desc: " + desc + ", pos: " + pos + "}";
}
public static final String K_NAME = "name";
public static final String K_DESC = "desc";
public static final String K_POS = "pos";
public static final String K_ROT = "rot";
public static final String K_BBOX = "bbox";
@Override
public void toJson(JsonWriter j) {
j.startObject();
j.write(JsonTraverser.K_TYPE, TYPE);
writeStatic(j);
j.endObject();
}
protected void writeStatic(JsonWriter j){
j.write(K_NAME, name);
j.write(K_DESC, desc);
j.writeKey(K_POS);
pos.toJson(j);
j.writeKey(K_ROT);
rotation.toJson(j);
if (bbox.isPresent()){
j.writeKey(K_BBOX);
bbox.get().toJson(j);
}
}
@Override
public void fromJson(JsonTraverser j) {
for (Entry e : j.expectStructureType(TYPE)){
if (!readStatic(j, e.key)) j.unexpected(e);
}
}
protected boolean readStatic(JsonTraverser j, StringRef key){
if (key.equals(K_NAME)) {
name = j.getString().getJsonString();
} else if (key.equals(K_DESC)) {
desc = j.getString().getJsonString();
} else if (key.equals(K_POS)) {
pos.fromJson(j);
} else if (key.equals(K_ROT)) {
rotation.fromJson(j);
} else if (key.equals(K_BBOX)) {
bbox = Optional.of(BoundingBox.buildFromJson(j));
} else return false;
return true;
}
}
\ No newline at end of file
package de.rwth.montisim.commons.utils;
public interface JsonSerializable {
void toJson(JsonWriter j);
void fromJson(JsonTraverser j);
}
\ No newline at end of file
package de.rwth.montisim.commons.utils;
import java.io.*;
import java.util.Iterator;