Commit a17be71e authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Tested telemetry, added ffc calibration before each image set

parent 1c75cb4c
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -191,6 +191,7 @@ public class LwirReader {
	}

	public ImagePlus [] averageMultiFrames(ImagePlus [][] sets) {
		//TODO: convert to multithreaded !
		int num_frames = sets.length;
		int num_channels = sets[0].length;
		ImagePlus [] imps_avg = new ImagePlus [num_channels];
@@ -316,6 +317,54 @@ public class LwirReader {
		return imps_synced;
	}

	public boolean calibrate(LwirReaderParameters lrp) {
		if (lrp.lwir_channels.length == 0) {
			LOGGER.error("calibrate(): No LWIR channels are configured");
			return false;
		}
		int chn = lrp.lwir_channels[0];
		int channels = 0;
		for (int c : lrp.lwir_channels) {
			channels |= 1 << c;
		}
		String hex_chan = String.format("%x", channels);
		System.out.println("Channels = "+channels+" (0x"+hex_chan);

		String url = "http://"+lrp.lwir_ip+"/parsedit.php?immediate&sensor_port="+chn+
				"&SENSOR_REGS67=0!"+hex_chan;
		Document dom=null;
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			dom = db.parse(url);
			if (!dom.getDocumentElement().getNodeName().equals("parameters")) {
				LOGGER.error("programLWIRCamera() in " + url+
						": Root element: expected 'parameters', got \"" + dom.getDocumentElement().getNodeName()+"\"");
				return false;
			}
		} catch(MalformedURLException e){
			LOGGER.error("programLWIRCamera() in " + url+ ": " + e.toString());
			return false;
		} catch(IOException  e1){
			LOGGER.error("programLWIRCamera() in " + url+ " - camera did not respond: " + e1.toString());
			return false;
		}catch(ParserConfigurationException pce) {
			LOGGER.error("programLWIRCamera() in " + url+ " - PCE error: " + pce.toString());
			return false;
		}catch(SAXException se) {
			LOGGER.error("programLWIRCamera() in " + url+ " - SAX error: " + se.toString());
			return false;
		}
		for (int i = 0; i < FRAMES_SKIP; i++) {
			if (!skipFrame(lrp)) {
				LOGGER.error("programLWIRCamera():Failed to skip frame");
			}
		}

		return true;
	}


	private double secOffs(double sec1, double sec2) {
		double aoff = Math.abs(sec2 - sec1);
		if (aoff > 30) {
@@ -370,6 +419,9 @@ public class LwirReader {
			LOGGER.error("acquire(): failed to program cameras");
			return null;
		}
		if (lrp.lwir_ffc) {
			calibrate(lrp); // seems to work. test calibration duration and if any images are sent during calibration
		}
		int num_frames = lrp.avg_number + lrp.vnir_lag + 2 * lrp.max_frame_diff;
		ImagePlus [][] imps = readAllMultiple(
				num_frames,
+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ public class LwirReaderParameters {
	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_ffc =              true;
	protected boolean lwir_telemetry =        true;
	protected double  vnir_quality =          98.0;
	protected boolean vnir_scale =           false; // restore sensor pixel values, undo camera white balancing
+121 −34
Original line number Diff line number Diff line
@@ -44,6 +44,39 @@ public class Lepton3Telemetry {
	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;
	public static final String FFC_TIME =      "FFC_TIME";      public static final int FFC_TIME_OFFSET =      30;
	public static final String ENCL_FFC_KELV = "ENCL_FFC_KELV"; public static final int ENCL_FFC_KELV_OFFSET = 32;
	public static final String AGC_ROI_TLBR =  "AGC_ROI_TLBR";  public static final int AGC_ROI_TLBR_OFFSET =  34;
	public static final String AGC_CLIP_HIGH = "AGC_CLIP_HIGH"; public static final int AGC_CLIP_HIGH_OFFSET = 38;
	public static final String AGC_CLIP_LOW =  "AGC_CLIP_LOW";  public static final int AGC_CLIP_LOW_OFFSET =  38;
	public static final String VFORMAT =       "VFORMAT";       public static final int VFORMAT_OFFSET =       72;
	public static final String FFC_LOG2 =      "FFC_LOG2";      public static final int FFC_LOG2_OFFSET =      74;
	public static final String EMISS_8192 =    "EMISS_8192";    public static final int EMISS_8192_OFFSET =    19 + 80; // row B
	public static final String BGND_KELV =     "BGND_KELV";     public static final int BGND_KELV_OFFSET =     20 + 80;
	public static final String ATMOSPH_8192 =  "ATMOSPH_8192";  public static final int ATMOSPH_8192_OFFSET =  21 + 80;
	public static final String ATMOSPH_KELV =  "ATMOSPH_KELV";  public static final int ATMOSPH_KELV_OFFSET =  22 + 80;
	public static final String WND_TRANS_8192 ="WND_TRANS_8192";public static final int WND_TRANS_8192_OFFSET =23 + 80;
	public static final String WND_REFL_8192 = "WND_REFL_8192"; public static final int WND_REFL_8192_OFFSET = 24 + 80;
	public static final String WND_KELV =      "WND_KELV";      public static final int WND_KELV_OFFSET =      25 + 80;
	public static final String WND_REFL_KELV = "WND_REFL_KELV"; public static final int WND_REFL_KELV_OFFSET = 26 + 80;
	public static final String GAIN_MODE =     "GAIN_MODE";     public static final int GAIN_MODE_OFFSET =      5 + 160; // row C
	public static final String GAIN_EFF =      "GAIN_EFF";      public static final int GAIN_EFF_OFFSET =       6 + 160;
	public static final String GAIN_DFLAG =    "GAIN_DFLAG";    public static final int GAIN_DFLAG_OFFSET =     7 + 160;
	public static final String GAIN_THR_HL_C = "GAIN_THR_HL_C"; public static final int GAIN_THR_HL_C_OFFSET =  8 + 160;
	public static final String GAIN_THR_LH_C = "GAIN_THR_LH_C"; public static final int GAIN_THR_LH_C_OFFSET =  9 + 160;
	public static final String GAIN_THR_HL_K = "GAIN_THR_HL_K"; public static final int GAIN_THR_HL_K_OFFSET = 10 + 160;
	public static final String GAIN_THR_LH_K = "GAIN_THR_LH_K"; public static final int GAIN_THR_LH_K_OFFSET = 11 + 160;
	public static final String GAIN_HL_PP =    "GAIN_HL_PP";    public static final int GAIN_HL_PP_OFFSET =    14 + 160;
	public static final String GAIN_LH_PP =    "GAIN_LH_PP";    public static final int GAIN_LH_PP_OFFSET =    15 + 160;
	public static final String GAIN_ROI_TLBR = "GAIN_ROI_TLBR"; public static final int GAIN_ROI_TLBR_OFFSET = 22 + 160;
	public static final String TLIN_EN =       "TLIN_EN";       public static final int TLIN_EN_OFFSET =       48 + 160;
	public static final String TLIN_RESOL =    "TLIN_RESOL";    public static final int TLIN_RESOL_OFFSET =    49 + 160;
	public static final String SPOT_AVG_KELV = "SPOT_AVG_KELV"; public static final int SPOT_AVG_KELV_OFFSET = 50 + 160;
	public static final String SPOT_MAX_KELV = "SPOT_MAX_KELV"; public static final int SPOT_MAX_KELV_OFFSET = 51 + 160;
	public static final String SPOT_MIN_KELV = "SPOT_MIN_KELV"; public static final int SPOT_MIN_KELV_OFFSET = 52 + 160;
	public static final String SPOT_POP_PERC = "SPOT_POP_PERC"; public static final int SPOT_POP_PERC_OFFSET = 53 + 160;
	public static final String SPOT_ROI_TLBR = "SPOT_ROI_TLBR"; public static final int SPOT_ROI_TLBR_OFFSET = 54 + 160;



	private float [] pixels =  null;
@@ -56,7 +89,16 @@ public class Lepton3Telemetry {
		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);
			byte dbg = bb.get();
			dbg = bb.get();
			dbg = bb.get();
			dbg = bb.get();
			dbg = bb.get();
			bb.position(offset);

//			this.bbtm =
			bb.get(btm, 0,btm.length);
			this.bbtm = ByteBuffer.wrap(btm);
			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(
@@ -80,24 +122,61 @@ public class Lepton3Telemetry {
		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(UPTIME,         String.format("%.3f", getSeconds (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(FPA_KELV,       String.format("%.2f", getKelv    (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));
		tm.put(ENCL_KELV,      String.format("%.2f", getKelv    (ENCL_KELV_OFFSET)));
		tm.put(FFC_KELV,       String.format("%.2f", getKelv    (FFC_KELV_OFFSET)));
		tm.put(FFC_TIME,       String.format("%.3f", getSeconds (FFC_TIME_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;
		tm.put(ENCL_FFC_KELV,  String.format("%.2f", getKelv    (ENCL_FFC_KELV_OFFSET)));
		tm.put(AGC_ROI_TLBR,
				"" +  getU16 (AGC_ROI_TLBR_OFFSET) +
				" " + getU16 (AGC_ROI_TLBR_OFFSET + 1) +
				" " + getU16 (AGC_ROI_TLBR_OFFSET + 2) +
				" " + getU16 (AGC_ROI_TLBR_OFFSET + 3));
		tm.put(AGC_CLIP_HIGH,  "" + getU16     (AGC_CLIP_HIGH_OFFSET));
		tm.put(AGC_CLIP_LOW,   "" + getU16     (AGC_CLIP_LOW_OFFSET));
		tm.put(VFORMAT,        "" + getU32     (VFORMAT_OFFSET));
		tm.put(FFC_LOG2,       "" + getU16     (FFC_LOG2_OFFSET));

 */
		tm.put(EMISS_8192,     "" + getU16     (EMISS_8192_OFFSET));
		tm.put(BGND_KELV,      String.format("%.2f", getKelv    (BGND_KELV_OFFSET)));
		tm.put(ATMOSPH_8192,   "" + getU16     (ATMOSPH_8192_OFFSET));
		tm.put(ATMOSPH_KELV,   String.format("%.2f", getKelv    (ATMOSPH_KELV_OFFSET)));
		tm.put(WND_TRANS_8192, "" + getU16     (WND_TRANS_8192_OFFSET));
		tm.put(WND_REFL_8192,  "" + getU16     (WND_REFL_8192_OFFSET));
		tm.put(WND_KELV,       String.format("%.2f", getKelv    (WND_KELV_OFFSET)));
		tm.put(WND_REFL_KELV,  String.format("%.2f", getKelv    (WND_REFL_KELV_OFFSET)));
		tm.put(GAIN_MODE,      "" + getU16     (GAIN_MODE_OFFSET));
		tm.put(GAIN_EFF,       "" + getU16     (GAIN_EFF_OFFSET));
		tm.put(GAIN_DFLAG,     "" + getU16     (GAIN_DFLAG_OFFSET));
		tm.put(GAIN_THR_HL_C,  "" + getU16     (GAIN_THR_HL_C_OFFSET));
		tm.put(GAIN_THR_LH_C,  "" + getU16     (GAIN_THR_LH_C_OFFSET));
		tm.put(GAIN_THR_HL_K,  "" + getU16     (GAIN_THR_HL_K_OFFSET));
		tm.put(GAIN_THR_LH_K,  "" + getU16     (GAIN_THR_LH_K_OFFSET));
		tm.put(GAIN_HL_PP,     "" + getU16     (GAIN_HL_PP_OFFSET));
		tm.put(GAIN_LH_PP,     "" + getU16     (GAIN_LH_PP_OFFSET));
		tm.put(GAIN_ROI_TLBR,
				"" +  getU16 (GAIN_ROI_TLBR_OFFSET) +
				" " + getU16 (GAIN_ROI_TLBR_OFFSET + 1) +
				" " + getU16 (GAIN_ROI_TLBR_OFFSET + 2) +
				" " + getU16 (GAIN_ROI_TLBR_OFFSET + 3));
		tm.put(TLIN_EN,        "" + getU16 (TLIN_EN_OFFSET));
		tm.put(TLIN_RESOL,     "" + getU16     (TLIN_RESOL_OFFSET));
		tm.put(SPOT_AVG_KELV,  String.format("%.2f", getKelv    (SPOT_AVG_KELV_OFFSET)));
		tm.put(SPOT_MAX_KELV,  String.format("%.2f", getKelv    (SPOT_MAX_KELV_OFFSET)));
		tm.put(SPOT_MIN_KELV,  String.format("%.2f", getKelv    (SPOT_MIN_KELV_OFFSET)));
		tm.put(SPOT_POP_PERC,  "" + getU16     (SPOT_POP_PERC_OFFSET));
		tm.put(SPOT_ROI_TLBR,
				"" +  getU16 (SPOT_ROI_TLBR_OFFSET) +
				" " + getU16 (SPOT_ROI_TLBR_OFFSET + 1) +
				" " + getU16 (SPOT_ROI_TLBR_OFFSET + 2) +
				" " + getU16 (SPOT_ROI_TLBR_OFFSET + 3));
		return tm;
	}
	// internal methods
@@ -112,9 +191,10 @@ public class Lepton3Telemetry {
		return bytes;
	}

	private String getString (int offset, int len) { // offset in shorts, len in shorts
		return new String(getBytes(offset, len));
	}
//	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)) {
@@ -123,10 +203,17 @@ public class Lepton3Telemetry {
		return s;
	}

	private double getKelv(int offset) {
		return 0.01*((bbtm.getShort(2 * offset)) & 0xffff);
	}
	private int getU16(int offset) {
		return (bbtm.getShort(2 * offset)) & 0xffff;
	}

	private double getSeconds(int offset) {
		return 0.001*(((long) (bbtm.getShort(2 * offset)) & 0xffff) + (((long) (bbtm.getShort(2 * (offset+1))) & 0xffff) << 16));
	}

	private long getU32(int offset) {
		return ((long) (bbtm.getShort(2 * offset)) & 0xffff) + (((long) (bbtm.getShort(2 * (offset+1))) & 0xffff) << 16);
	}