Commit 1c75cb4c authored by Andrey Filippov's avatar Andrey Filippov

Implementing telemetry data for Letnon 3.5

parent 66cd4b7e
......@@ -4838,6 +4838,7 @@ private Panel panel1,
}
ImagePlus [][] imps = LWIR_READER.readAllMultiple(
10, // final int num_frames,
// true, // use LWIR telemetry
true, // final boolean show,
false); // true); // final boolean scale)
for (ImagePlus imp: imps[0]) {
......
......@@ -65,6 +65,9 @@ public class LwirReader {
public static final String SKIP_FRAME_URL= "/towp/wait/meta"; // Wit for the next frame, return meta data
public static final int COLOR_JP4 = 5;
public static final int COLOR_RAW = 15;
public static final int LWIR_HEIGHT = 120;
public static final int LWIR_TELEMETRY_LINES = 2;
public static final int FRAMES_SKIP = 3;
public static final int MAX_THREADS = 100; // combine from all classes?
......@@ -103,13 +106,16 @@ public class LwirReader {
public ImagePlus[][] readAllMultiple(
final int num_frames,
// final boolean telemetry,
final boolean show,
final boolean scale) {
return readAllMultiple(num_frames, show, scale, "STD_");
// return readAllMultiple(num_frames, telemetry, show, scale, "STD_");
}
public ImagePlus[][] readAllMultiple(
final int num_frames,
// final boolean telemetry,
final boolean show,
final boolean scale,
final String std)
......@@ -125,6 +131,7 @@ public class LwirReader {
imagejJp4TiffMulti = new ImagejJp4TiffMulti();
for (int i = 0; i < 2; i++) {
try {
// imagejJp4TiffMulti.getMultiImages(urls0, imps[0], telemetry, scale, std);
imagejJp4TiffMulti.getMultiImages(urls0, imps[0], scale, std);
} catch (IOException e) {
LOGGER.error("readAllMultiple0: IOException, priming" );
......@@ -143,6 +150,7 @@ public class LwirReader {
for (int n = 0; n < num_frames; n++) {
LOGGER.info("---- Acquiring frame set "+n);
try {
// imagejJp4TiffMulti.getMultiImages( (n==0)? urls0:urls1, imps[n], telemetry, scale, std);
imagejJp4TiffMulti.getMultiImages( (n==0)? urls0:urls1, imps[n], scale, std);
} catch (IOException e) {
LOGGER.error("readAllMultiple0: IOException, n = " + n);
......@@ -365,6 +373,7 @@ public class LwirReader {
int num_frames = lrp.avg_number + lrp.vnir_lag + 2 * lrp.max_frame_diff;
ImagePlus [][] imps = readAllMultiple(
num_frames,
// lrp.lwir_telemetry,
false, // final boolean show,
lrp.vnir_scale);
if (imps == null) {
......@@ -433,7 +442,8 @@ public class LwirReader {
for (int chn:lrp.lwir_channels) {
urls[chn] = "http://"+lrp.lwir_ip+"/parsedit.php?immediate&sensor_port="+chn+
"&BITS=16"+
"&COLOR="+COLOR_RAW; // +"*0"; // raw mode - delay 0 - breaks compressor
"&COLOR="+COLOR_RAW+ // +"*0"; // raw mode - delay 0 - breaks compressor
"&WOI_HEIGHT="+(LWIR_HEIGHT + (lrp.lwir_telemetry?LWIR_TELEMETRY_LINES:0));
if (chn == lwir_master_port) {
urls[chn] +="&TRIG=0*0"+
"&TRIG_DELAY="+lrp.lwir_trig_dly+"*0"+
......
......@@ -33,11 +33,12 @@ import com.elphel.imagej.common.GenericJTabbedDialog;
public class LwirReaderParameters {
private boolean parameters_updated = false;
protected int avg_number = 4; // number of measurements to average
public boolean avg_all = true;
protected boolean avg_all = true;
protected String lwir_ip = "192.168.0.36";
protected String vnir_ip = "192.168.0.38";
protected int [] lwir_channels = {0, 1, 2 ,3};
protected int [] vnir_channels = {0, 1, 2 ,3};
protected boolean lwir_telemetry = true;
protected double vnir_quality = 98.0;
protected boolean vnir_scale = false; // restore sensor pixel values, undo camera white balancing
protected boolean vnir_autoexp = false;
......@@ -77,6 +78,7 @@ public class LwirReaderParameters {
properties.setProperty(prefix+"vnir_ip", this.vnir_ip+"");
properties.setProperty(prefix+"lwir_channels", arr_to_str(this.lwir_channels));
properties.setProperty(prefix+"vnir_channels", arr_to_str(this.vnir_channels));
properties.setProperty(prefix+"lwir_telemetry", this.lwir_telemetry+"");
properties.setProperty(prefix+"vnir_quality", this.vnir_quality+"");
properties.setProperty(prefix+"vnir_scale", this.vnir_scale+"");
properties.setProperty(prefix+"vnir_autoexp", this.vnir_autoexp+"");
......@@ -101,6 +103,7 @@ public class LwirReaderParameters {
if (properties.getProperty(prefix+"vnir_ip")!=null) this.vnir_ip= properties.getProperty(prefix+"vnir_ip");
if (properties.getProperty(prefix+"lwir_channels")!=null) this.lwir_channels=str_to_iarr(properties.getProperty(prefix+"lwir_channels"));
if (properties.getProperty(prefix+"vnir_channels")!=null) this.vnir_channels=str_to_iarr(properties.getProperty(prefix+"vnir_channels"));
if (properties.getProperty(prefix+"lwir_telemetry")!=null) this.lwir_telemetry= Boolean.parseBoolean(properties.getProperty(prefix+"lwir_telemetry"));
if (properties.getProperty(prefix+"vnir_quality")!=null) this.vnir_quality=Double.parseDouble(properties.getProperty(prefix+"vnir_quality"));
if (properties.getProperty(prefix+"vnir_scale")!=null) this.vnir_scale= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_scale"));
if (properties.getProperty(prefix+"vnir_autoexp")!=null) this.vnir_autoexp= Boolean.parseBoolean(properties.getProperty(prefix+"vnir_autoexp"));
......@@ -127,6 +130,7 @@ public class LwirReaderParameters {
lrp.vnir_ip= this.vnir_ip;
lrp.lwir_channels= this.lwir_channels.clone();
lrp.vnir_channels= this.vnir_channels.clone();
lrp.lwir_telemetry= this.lwir_telemetry;
lrp.vnir_quality= this.vnir_quality;
lrp.vnir_scale= this.vnir_scale;
lrp.vnir_autoexp= this.vnir_autoexp;
......@@ -160,6 +164,7 @@ public class LwirReaderParameters {
(lrp.vnir_ip.equals(this.vnir_ip)) &&
(java.util.Arrays.equals(lrp.lwir_channels, this.lwir_channels)) &&
(java.util.Arrays.equals(lrp.vnir_channels, this.vnir_channels)) &&
(lrp.lwir_telemetry == this.lwir_telemetry) &&
(lrp.vnir_quality == this.vnir_quality) &&
(lrp.vnir_scale == this.vnir_scale) &&
(lrp.vnir_autoexp == this.vnir_autoexp) &&
......@@ -187,6 +192,7 @@ public class LwirReaderParameters {
result = prime * result + vnir_ip.hashCode();
result = prime * result + arr_to_str(lwir_channels).hashCode();
result = prime * result + arr_to_str(vnir_channels).hashCode();
result = prime * result + (lwir_telemetry?1:0);
result = prime * result + (new Double(vnir_quality)).hashCode();
result = prime * result + (vnir_scale?1:0);
result = prime * result + (vnir_autoexp?1:0);
......@@ -213,6 +219,7 @@ public class LwirReaderParameters {
gd.addStringField ("VNIR IP", this.vnir_ip, 20, "Visible range high resolution camera IP address");
gd.addStringField ("LWIR channels", arr_to_str(this.lwir_channels), 20, "Space-separated list of used LWIR camera channels, such as '0 1 2 3'");
gd.addStringField ("VNIR channels", arr_to_str(this.vnir_channels), 20, "Space-separated list of used visible range camera channels, such as '0 1 2 3'");
gd.addCheckbox ("LWIR telemetry", this.lwir_telemetry, "Set LWIR sesnors to provide telemetry data in the last 2 lines (may become mandatory later)");
gd.addNumericField("VNIR quality", this.vnir_quality, 3,6,"ms", "Visible range camera JPEG compression quality (all channels)");
gd.addCheckbox ("VNIR undo white balance", this.vnir_scale, "Undo in-camera white balancing");
gd.addCheckbox ("VNIR autoexposure", this.vnir_autoexp, "Enable autoexposure for the visible range camera");
......@@ -237,6 +244,7 @@ public class LwirReaderParameters {
this.vnir_ip = gd.getNextString();
this.lwir_channels = str_to_iarr(gd.getNextString());
this.vnir_channels = str_to_iarr(gd.getNextString());
this.lwir_telemetry = gd.getNextBoolean();
this.vnir_quality = gd.getNextNumber();
this.vnir_scale = gd.getNextBoolean();
this.vnir_autoexp = gd.getNextBoolean();
......
......@@ -35,6 +35,7 @@ import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;
......@@ -65,8 +66,10 @@ public class ImagejJp4Tiff {
private static final Logger LOGGER = LoggerFactory.getLogger(ClassList.class);
private static final boolean BYPASS_SERVICES = false; // true;
private static final String TELEMETRY_PREFIX = "TLM_";
private static final String SERVICES_PATH = "services.properties.forelphel";
private static final boolean KEEP_EXTENSION = false; // remove extension for ImagePlus title
private static final boolean BOTTOM_TELEMETRY = true; // telemetry (if present) is at the bottom of the image
// -- Fields --
......@@ -186,12 +189,13 @@ public class ImagejJp4Tiff {
boolean is_le = reader.isLittleEndian();
int bytes_per_pixel = (bpp + 7) / 9;
float [] pixels = new float [bytes.length/bytes_per_pixel];
ByteBuffer bb = null;
if (bytes_per_pixel == 1) {
for (int i = 0; i < pixels.length; i++) {
pixels[i] = ((bytes[i])) & 0xff;
}
} else {
ByteBuffer bb = ByteBuffer.wrap(bytes);
bb = ByteBuffer.wrap(bytes);
if (is_le) {
bb.order( ByteOrder.LITTLE_ENDIAN);
} else {
......@@ -208,9 +212,20 @@ public class ImagejJp4Tiff {
LOGGER.error("Problem degamma/scaling of "+content_fileName);
}
ImageProcessor ip=new FloatProcessor(reader.getSizeX(), reader.getSizeY());
boolean telemetry = (bytes_per_pixel == 2);
Lepton3Telemetry lepton3Telemetry = null;
if (telemetry) {
lepton3Telemetry = new Lepton3Telemetry(bb,pixels, true); // bottom
telemetry = lepton3Telemetry.hasTelemetry();
}
ImageProcessor ip = null;
if (telemetry) {
ip=new FloatProcessor(Lepton3Telemetry.LEPTON3_IMAGE_WIDTH, Lepton3Telemetry.LEPTON3_IMAGE_HEIGHT);
ip.setPixels(lepton3Telemetry.getPixels()); // bo
} else {
ip=new FloatProcessor(reader.getSizeX(), reader.getSizeY());
ip.setPixels(pixels);
}
ip.resetMinAndMax();
String prefix = ElphelTiffReader.ELPHEL_PROPERTY_PREFIX;
String imageName = content_fileName; // path;
......@@ -234,6 +249,12 @@ public class ImagejJp4Tiff {
imp.setProperty(std+(key.replace(" ","_").replace("/","_")), meta_hash.get(key).toString());
}
}
if (telemetry) {
HashMap<String, String> telemetryMap = lepton3Telemetry.parseTelemetry();
for (String key:telemetryMap.keySet()) {
imp.setProperty(TELEMETRY_PREFIX+key, telemetryMap.get(key));
}
}
encodeProperiesToInfo(imp);
Location.mapFile(content_fileName, null);
return imp;
......
......@@ -47,6 +47,7 @@ public class ImagejJp4TiffMulti {
public ImagePlus [] getMultiImages(
final String [] urls,
final ImagePlus [] imps,
// final boolean telemetry,
final boolean scale,
final String std) throws IOException, FormatException // std - include non-elphel properties with prefix std
{
......
/**
** -----------------------------------------------------------------------------**
** Lepton3Telemetry.java
**
** Parses FLIR Lepton3 telemetry data
**
** Copyright (C) 2019 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** Lepton3Telemetry.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------**
**
*/
package com.elphel.imagej.readers;
import java.nio.ByteBuffer;
import java.util.HashMap;
public class Lepton3Telemetry {
public static final int LEPTON3_IMAGE_WIDTH = 160;
public static final int LEPTON3_IMAGE_HEIGHT = 120;
public static final int LEPTON3_TELEMETRY_LINES = 2;
public static final String REVISION = "REVISION"; public static final int REVISION_OFFSET = 0;
public static final String UPTIME = "UPTIME"; public static final int UPTIME_OFFSET = 1;
public static final String STATUS = "STATUS"; public static final int STATUS_OFFSET = 3;
public static final String MOD_SER = "MOD_SER"; public static final int MOD_SER_OFFSET = 5;
public static final String SOFT_REV = "SOFT_REV"; public static final int SOFT_REV_OFFSET = 13;
public static final String FRAME = "FRAME"; public static final int FRAME_OFFSET = 20;
public static final String MEAN = "MEAN"; public static final int MEAN_OFFSET = 22;
public static final String FPA_TCNT = "FPA_TCNT"; public static final int FPA_TCNT_OFFSET = 23;
public static final String FPA_KELV = "FPA_KELV"; public static final int FPA_KELV_OFFSET = 24;
public static final String ENCL_TCNT = "ENCL_TCNT"; public static final int ENCL_TCNT_OFFSET = 25;
public static final String ENCL_KELV = "ENCL_KELV"; public static final int ENCL_KELV_OFFSET = 26;
public static final String FFC_KELV = "FFC_KELV"; public static final int FFC_KELV_OFFSET = 29;
private float [] pixels = null;
private byte [] btm = null;
private ByteBuffer bbtm = null;
public Lepton3Telemetry(ByteBuffer bb, float [] pixels, boolean bottom) {
this.pixels = pixels;
int offset = 2*(bottom?(LEPTON3_IMAGE_WIDTH * LEPTON3_IMAGE_HEIGHT):0);
if (pixels.length > LEPTON3_IMAGE_WIDTH*LEPTON3_IMAGE_HEIGHT) {
this.btm = new byte [LEPTON3_IMAGE_WIDTH* LEPTON3_TELEMETRY_LINES * 2];
bb.position(offset);
this.bbtm = bb.get(btm, 0,btm.length);
this.bbtm.order( bb.order()); // or is it already same as in bb?
this.pixels = new float [LEPTON3_IMAGE_WIDTH * LEPTON3_IMAGE_HEIGHT];
System.arraycopy(
pixels,
(bottom? 0: LEPTON3_IMAGE_WIDTH * LEPTON3_TELEMETRY_LINES),
this.pixels,
0,
this.pixels.length);
}
}
public boolean hasTelemetry() {
return bbtm != null;
}
public float [] getPixels() {
return pixels;
}
public HashMap<String, String> parseTelemetry(){
HashMap<String, String> tm = new HashMap<String, String>();
byte [] bytes = getBytes(REVISION_OFFSET,2);
tm.put(REVISION, ""+bytes[1]+"."+bytes[0]);
tm.put(UPTIME, ""+getU32(UPTIME_OFFSET));
tm.put(STATUS, ""+getU32(STATUS_OFFSET));
tm.put(MOD_SER, ""+getHex(MOD_SER_OFFSET,8));
tm.put(SOFT_REV, ""+getHex(SOFT_REV_OFFSET,4));
tm.put(FPA_TCNT, ""+getU16(FPA_TCNT_OFFSET));
tm.put(FPA_KELV, ""+getU16(FPA_KELV_OFFSET));
tm.put(ENCL_TCNT, ""+getU16(ENCL_TCNT_OFFSET));
tm.put(ENCL_KELV, ""+getU16(ENCL_KELV_OFFSET));
tm.put(FFC_KELV, ""+getU16(FFC_KELV_OFFSET));
/*
public static final String FPA_TCNT = "FPA_TCNT"; public static final int FPA_TCNT_OFFSET = 23;
public static final String FPA_KELV = "FPA_KELV"; public static final int FPA_KELV_OFFSET = 24;
public static final String ENCL_TCNT = "ENCL_TCNT"; public static final int ENCL_TCNT_OFFSET = 25;
public static final String ENCL_KELV = "ENCL_KELV"; public static final int ENCL_KELV_OFFSET = 26;
public static final String FFC_KELV = "FFC_KELV"; public static final int FFC_KELV_OFFSET = 29;
*/
return tm;
}
// internal methods
// input byte array depends on tiff endian for short (16-bit) words, but FLIR word sequence is little endian
private byte[] getBytes (int offset, int len) { // offset in shorts, len in shorts
byte [] bytes = new byte [2*len];
for (int i = 0; i<len; i++) {
int d = (bbtm.getShort(2 * (offset + i))) & 0xffff;
bytes[2*i+0] = (byte) (d & 0xff);
bytes[2*i+1] = (byte) ((d >> 8) & 0xff);
}
return bytes;
}
private String getString (int offset, int len) { // offset in shorts, len in shorts
return new String(getBytes(offset, len));
}
private String getHex (int offset, int len) { // offset in shorts, len in shorts
String s = "";
for (byte b :getBytes(offset, len)) {
s += String.format("%02x", b);
}
return s;
}
private int getU16(int offset) {
return (bbtm.getShort(2 * offset)) & 0xffff;
}
private long getU32(int offset) {
return ((long) (bbtm.getShort(2 * offset)) & 0xffff) + (((long) (bbtm.getShort(2 * (offset+1))) & 0xffff) << 16);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment