package me.drton.flightplot.processors; import me.drton.flightplot.processors.tools.LowPassFilter; import me.drton.jmavlib.conversion.RotationConversion; import javax.vecmath.Matrix3d; import javax.vecmath.Vector3d; import java.util.HashMap; import java.util.Map; /** * User: ton Date: 14.09.13 Time: 23:45 */ public class NEDFromBodyProjection extends PlotProcessor { private String[] param_Fields; private String[] param_Fields_Att; private double param_Scale; private double param_Offset; private boolean param_Backward; private double[] param_Att_Offsets; private boolean[] show; private LowPassFilter[] lowPassFilters; private Matrix3d r; private double[] vArr; private Vector3d v; private double[] vNEDArr; private Vector3d vNED; @Override public Map<String, Object> getDefaultParameters() { Map<String, Object> params = new HashMap<String, Object>(); params.put("Fields", "IMU.AccX IMU.AccY IMU.AccZ"); params.put("Fields Att", "ATT.Roll ATT.Pitch ATT.Yaw"); params.put("Att Offsets", "0.0 0.0 0.0"); params.put("Show", "XYZ"); params.put("LPF", 0.0); params.put("Scale", 1.0); params.put("Offset", 0.0); params.put("Backward", false); return params; } @Override public void init() { param_Fields = ((String) parameters.get("Fields")).split(WHITESPACE_RE); param_Fields_Att = ((String) parameters.get("Fields Att")).split(WHITESPACE_RE); String[] attOffsStr = ((String) parameters.get("Att Offsets")).split(WHITESPACE_RE); param_Scale = (Double) parameters.get("Scale"); param_Offset = (Double) parameters.get("Offset"); param_Backward = (Boolean) parameters.get("Backward"); String showStr = ((String) parameters.get("Show")).toUpperCase(); show = new boolean[]{false, false, false}; lowPassFilters = new LowPassFilter[3]; vArr = new double[3]; v = new Vector3d(); vNEDArr = new double[3]; vNED = new Vector3d(); r = new Matrix3d(); param_Att_Offsets = new double[3]; for (int i = 0; i < 3; i++) { if (attOffsStr.length > i) { param_Att_Offsets[i] = Double.parseDouble(attOffsStr[i]); } else { param_Att_Offsets[i] = 0.0; } String axisName = "XYZ".substring(i, i + 1); show[i] = showStr.contains(axisName); if (show[i]) { LowPassFilter lowPassFilter = new LowPassFilter(); lowPassFilter.setF((Double) parameters.get("LPF")); lowPassFilters[i] = lowPassFilter; addSeries(axisName); } } } @Override public void process(double time, Map<String, Object> update) { boolean act = false; if (param_Fields_Att.length == 3) { Number roll = (Number) update.get(param_Fields_Att[0]); Number pitch = (Number) update.get(param_Fields_Att[1]); Number yaw = (Number) update.get(param_Fields_Att[2]); if (roll != null && pitch != null && yaw != null) { // Update rotation matrix r.set(RotationConversion.rotationMatrixByEulerAngles(roll.doubleValue() + param_Att_Offsets[0], pitch.doubleValue() + param_Att_Offsets[1], yaw.doubleValue() + param_Att_Offsets[2])); if (param_Backward) { r.transpose(); } act = true; } } else if (param_Fields_Att.length == 4) { double[] q = new double[4]; boolean notNull = true; for (int i = 0; i < 4; ++i) { Number qNum = (Number) update.get(param_Fields_Att[i]); if (qNum == null) { notNull = false; } else { q[i] = qNum.doubleValue(); } } if (notNull) { // Update rotation matrix r.set(RotationConversion.rotationMatrixByQuaternion(q)); r.mul(new Matrix3d(RotationConversion.rotationMatrixByEulerAngles(param_Att_Offsets[0], param_Att_Offsets[1], param_Att_Offsets[2]))); if (param_Backward) { r.transpose(); } act = true; } } for (int i = 0; i < 3; i++) { Number vNum = (Number) update.get(param_Fields[i]); if (vNum != null) { // Update source vector vArr[i] = vNum.doubleValue(); act = true; } } v.set(vArr); if (act) { vNED.set(v); r.transform(vNED); int seriesIdx = 0; vNED.get(vNEDArr); for (int i = 0; i < 3; i++) { if (show[i]) { double out = lowPassFilters[i].getOutput(time, vNEDArr[i]); addPoint(seriesIdx, time, out * param_Scale + param_Offset); seriesIdx++; } } } } }