Commit cde73fef authored by Andrey Filippov's avatar Andrey Filippov

implemented 'neck' parameters (rotating/shifting camera as a whole), old bug fixes

parent 782eb01a
...@@ -109,7 +109,7 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene ...@@ -109,7 +109,7 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene
private Panel panelGoniometer; private Panel panelGoniometer;
private Panel panelPixelMapping, panelStereo,panelStereo1; private Panel panelPixelMapping, panelStereo,panelStereo1;
private Panel panelLWIR; private Panel panelLWIR;
private Panel panelLWIR16; // private Panel panelLWIR16;
private ShowDoubleFloatArrays SDFA_INSTANCE; // just for debugging? private ShowDoubleFloatArrays SDFA_INSTANCE; // just for debugging?
JP46_Reader_camera JP4_INSTANCE; JP46_Reader_camera JP4_INSTANCE;
...@@ -508,6 +508,9 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi ...@@ -508,6 +508,9 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
0.0, 0.0,
0.0, 0.0,
0.0, 0.0, 2360, //double [] GXYZ // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system 0.0, 0.0, 2360, //double [] GXYZ // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
0.0,
0.0,
0.0, 0.0,
2592, // int sensorWidth= 2592; 2592, // int sensorWidth= 2592;
1936, //int sensorHeight= 1936; 1936, //int sensorHeight= 1936;
2, //int shrinkGridForMask=2; //shrink detected grids by one point for/vert this number of times before calculating masks 2, //int shrinkGridForMask=2; //shrink detected grids by one point for/vert this number of times before calculating masks
...@@ -692,14 +695,15 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi ...@@ -692,14 +695,15 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
panelRun = new Panel(); panelRun = new Panel();
panelRun.setLayout(new GridLayout(1, 0, 5, 5)); panelRun.setLayout(new GridLayout(1, 0, 5, 5));
addButton("Process Calibration Files",panelRun); addButton("Process Calibration Files",panelRun);
addButton("Save",panelRun); addButton("Save", panelRun);
addButton("Save Selected",panelRun); addButton("Save Selected", panelRun);
addButton("Restore",panelRun,color_restore); addButton("Restore", panelRun,color_restore);
addButton("Restore no autoload",panelRun); addButton("Restore no autoload",panelRun);
addButton("Restore SFE Latest",panelRun,color_restore); addButton("Properties clear", panelRun, color_stop);
addButton("List SFE",panelRun,color_report); addButton("Restore SFE Latest", panelRun, color_restore);
addButton("Stop",panelRun,color_stop); addButton("List SFE", panelRun,color_report);
addButton("Abort",panelRun,color_stop); addButton("Stop", panelRun,color_stop);
addButton("Abort", panelRun,color_stop);
add(panelRun); add(panelRun);
...@@ -1257,6 +1261,10 @@ if (MORE_BUTTONS) { ...@@ -1257,6 +1261,10 @@ if (MORE_BUTTONS) {
} else if (label.equals("Restore") || label.equals("Restore no autoload")) { } else if (label.equals("Restore") || label.equals("Restore no autoload")) {
restore(label.equals("Restore no autoload")); restore(label.equals("Restore no autoload"));
return; return;
/* ======================================================================== */
} else if (label.equals("Properties clear")) {
PROPERTIES=new Properties();
return;
/* ======================================================================== */ /* ======================================================================== */
} else if (label.equals("Process Calibration Files")) { } else if (label.equals("Process Calibration Files")) {
processCalibrationFiles(); processCalibrationFiles();
...@@ -5977,7 +5985,7 @@ if (MORE_BUTTONS) { ...@@ -5977,7 +5985,7 @@ if (MORE_BUTTONS) {
return; return;
} }
GenericDialog gd=new GenericDialog ("Select list mode"); GenericDialog gd=new GenericDialog ("Select list mode");
gd.addNumericField("Mode 0 - pointers, 1 - shift/Rots, 2 - points/extra, 3 - rms", 3, 0); gd.addNumericField("Mode 0 - pointers, 1 - shift/Rots, 2 - points/extra, 3 - rms, 4 - image numbers", 3, 0);
gd.showDialog(); gd.showDialog();
if (gd.wasCanceled()) return; if (gd.wasCanceled()) return;
int listMode= (int) gd.getNextNumber(); int listMode= (int) gd.getNextNumber();
...@@ -440,7 +440,7 @@ import ij.text.TextWindow; ...@@ -440,7 +440,7 @@ import ij.text.TextWindow;
public class GridImageSet{ public class GridImageSet{
private int numPars=53; // 27; private int numPars=57; // before neck:53; // 27;
private int thisParsStartIndex=6; private int thisParsStartIndex=6;
public int stationNumber=0; // changes when camera/goniometer is moved to new position public int stationNumber=0; // changes when camera/goniometer is moved to new position
...@@ -448,17 +448,19 @@ import ij.text.TextWindow; ...@@ -448,17 +448,19 @@ import ij.text.TextWindow;
// public GridImageParameters firstImage=null; // first non-null image in the sert (update to have current parameters?) // public GridImageParameters firstImage=null; // first non-null image in the sert (update to have current parameters?)
public double timeStamp; public double timeStamp;
public int [] motors=null; public int [] motors=null;
public double goniometerAxial=Double.NaN; public double goniometerAxial=Double.NaN; // 6
public double goniometerTilt=Double.NaN; public double goniometerTilt=Double.NaN; // 7
public double interAxisDistance; // 8 distance in mm between two goniometer axes public double interAxisDistance; // 8 distance in mm between two goniometer axes
public double interAxisAngle; // 9 angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated public double interAxisAngle; // 9 angle in degrees between two goniometer axes minus 90. negative if "vertical" axis is rotated
public double horAxisErrPhi; //10 angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW) public double horAxisErrPhi; //10 angle in degrees "horizontal" goniometer axis is rotated around target Y axis from target X axis (CW)
public double horAxisErrPsi; //11 angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up) public double horAxisErrPsi; //11 angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up)
public double entrancePupilForward; //12 common to all lenses - distance from the sensor to the lens entrance pupil public double entrancePupilForward; //12 common to all lenses - distance from the sensor to the lens entrance pupil
public double centerAboveHorizontal;//13 camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each public double centerAboveHorizontal; //13 camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
public double [] GXYZ=new double [3]; //14 (12) coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system public double [] GXYZ=new double [3]; //14 (12) coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
// this.GXYZ[stationNumber][1], //15 (13) y public double neckRight; //17 angle in degrees of the camera as a whole rotated clockwise around axis to the target
// this.GXYZ[stationNumber][2], //16 (14) z public double neckBack; //18 angle in degrees of the camera as a whole rotated clockwise around axis to the target
public double [] neckXZ=new double [2]; //19,20 optical head offset in mm relative to the mount point (centerAboveHorizontal as Y)
public boolean orientationEstimated=true; // orientation is estimated from other stes, not adjusted by LMA public boolean orientationEstimated=true; // orientation is estimated from other stes, not adjusted by LMA
public double setWeight=0.0; // weight of this set when calculating errors public double setWeight=0.0; // weight of this set when calculating errors
public void setEstimatedFromNonNaN(){ public void setEstimatedFromNonNaN(){
...@@ -471,7 +473,7 @@ import ij.text.TextWindow; ...@@ -471,7 +473,7 @@ import ij.text.TextWindow;
return this.thisParsStartIndex+getSetVector().length; return this.thisParsStartIndex+getSetVector().length;
} }
public double [] getSetVector(){ public double [] getSetVector(){ // was 11, now 15
double [] sv={ double [] sv={
this.goniometerTilt, this.goniometerTilt,
this.goniometerAxial, this.goniometerAxial,
...@@ -484,6 +486,11 @@ import ij.text.TextWindow; ...@@ -484,6 +486,11 @@ import ij.text.TextWindow;
this.GXYZ[0], this.GXYZ[0],
this.GXYZ[1], this.GXYZ[1],
this.GXYZ[2] this.GXYZ[2]
,this.neckRight,
this.neckBack,
this.neckXZ[0],
this.neckXZ[1]
}; };
return sv; return sv;
} }
...@@ -504,6 +511,11 @@ import ij.text.TextWindow; ...@@ -504,6 +511,11 @@ import ij.text.TextWindow;
this.GXYZ[0]= vector[ 8]; this.GXYZ[0]= vector[ 8];
this.GXYZ[1]= vector[ 9]; this.GXYZ[1]= vector[ 9];
this.GXYZ[2]= vector[10]; this.GXYZ[2]= vector[10];
this.neckRight= vector[11];
this.neckBack= vector[12];
this.neckXZ[0]= vector[13];
this.neckXZ[1]= vector[14];
} }
public double getParameterValue(int index){ public double getParameterValue(int index){
...@@ -535,6 +547,10 @@ import ij.text.TextWindow; ...@@ -535,6 +547,10 @@ import ij.text.TextWindow;
case 8: this.GXYZ[0]= value; break; case 8: this.GXYZ[0]= value; break;
case 9: this.GXYZ[1]= value; break; case 9: this.GXYZ[1]= value; break;
case 10: this.GXYZ[2]= value; break; case 10: this.GXYZ[2]= value; break;
case 11: this.neckRight= value; break;
case 12: this.neckBack= value; break;
case 13: this.neckXZ[0]= value; break;
case 14: this.neckXZ[1]= value; break;
} }
} }
...@@ -584,6 +600,10 @@ import ij.text.TextWindow; ...@@ -584,6 +600,10 @@ import ij.text.TextWindow;
this.GXYZ[0]= vector[this.thisParsStartIndex+ 8]; this.GXYZ[0]= vector[this.thisParsStartIndex+ 8];
this.GXYZ[1]= vector[this.thisParsStartIndex+ 9]; this.GXYZ[1]= vector[this.thisParsStartIndex+ 9];
this.GXYZ[2]= vector[this.thisParsStartIndex+10]; this.GXYZ[2]= vector[this.thisParsStartIndex+10];
this.neckRight= vector[this.thisParsStartIndex+11];
this.neckBack= vector[this.thisParsStartIndex+12];
this.neckXZ[0]= vector[this.thisParsStartIndex+13];
this.neckXZ[1]= vector[this.thisParsStartIndex+14];
} }
public void updateSetFromParameterVector(double [] vector, boolean [] mask){ public void updateSetFromParameterVector(double [] vector, boolean [] mask){
...@@ -603,8 +623,12 @@ import ij.text.TextWindow; ...@@ -603,8 +623,12 @@ import ij.text.TextWindow;
if (mask[this.thisParsStartIndex+ 8]) this.GXYZ[0]= vector[this.thisParsStartIndex+ 8]; if (mask[this.thisParsStartIndex+ 8]) this.GXYZ[0]= vector[this.thisParsStartIndex+ 8];
if (mask[this.thisParsStartIndex+ 9]) this.GXYZ[1]= vector[this.thisParsStartIndex+ 9]; if (mask[this.thisParsStartIndex+ 9]) this.GXYZ[1]= vector[this.thisParsStartIndex+ 9];
if (mask[this.thisParsStartIndex+10]) this.GXYZ[2]= vector[this.thisParsStartIndex+10]; if (mask[this.thisParsStartIndex+10]) this.GXYZ[2]= vector[this.thisParsStartIndex+10];
if (mask[this.thisParsStartIndex+11]) this.neckRight= vector[this.thisParsStartIndex+11];
if (mask[this.thisParsStartIndex+12]) this.neckBack= vector[this.thisParsStartIndex+12];
if (mask[this.thisParsStartIndex+13]) this.neckXZ[0]= vector[this.thisParsStartIndex+13];
if (mask[this.thisParsStartIndex+14]) this.neckXZ[1]= vector[this.thisParsStartIndex+14];
} }
public double getSetWeight(){return this.setWeight;} public double getSetWeight(){return this.setWeight;}
public int getStationNumber(){ // TODO: make only a single station number - in GridImageSet? public int getStationNumber(){ // TODO: make only a single station number - in GridImageSet?
return this.stationNumber; return this.stationNumber;
...@@ -627,7 +651,12 @@ import ij.text.TextWindow; ...@@ -627,7 +651,12 @@ import ij.text.TextWindow;
{"subcamForward", "Subcamera distance from the vertical rotation axis, positive - towards the target","mm","S","E"}, // 1 {"subcamForward", "Subcamera distance from the vertical rotation axis, positive - towards the target","mm","S","E"}, // 1
null, // 2 null, // 2
{"subcamHeading", "Optical axis heading (0 - to the target, positive - CW looking from top)","degrees","S","E"}}; // 3 {"subcamHeading", "Optical axis heading (0 - to the target, positive - CW looking from top)","degrees","S","E"}}; // 3
/*
* [3] == "S" - subcamera
* [3] == "R" - orientation
* [3] == "T" - location
* [4] == "I" - intrinsic
*/
public String [][] parameterDescriptions ={ public String [][] parameterDescriptions ={
{"subcamAzimuth", "Subcamera azimuth, clockwise looking from top","degrees","S","E"}, // 0 {"subcamAzimuth", "Subcamera azimuth, clockwise looking from top","degrees","S","E"}, // 0
{"subcamDistance", "Subcamera distance from the axis","mm","S","E"}, // 1 {"subcamDistance", "Subcamera distance from the axis","mm","S","E"}, // 1
...@@ -646,49 +675,55 @@ import ij.text.TextWindow; ...@@ -646,49 +675,55 @@ import ij.text.TextWindow;
{"GXYZ0", "Goniometer reference point position X (target coordinates, left)","mm","T","E"}, //14 (12) {"GXYZ0", "Goniometer reference point position X (target coordinates, left)","mm","T","E"}, //14 (12)
{"GXYZ1", "Goniometer reference point position Y (target coordinates, up)","mm","T","E"}, //15 (13) {"GXYZ1", "Goniometer reference point position Y (target coordinates, up)","mm","T","E"}, //15 (13)
{"GXYZ2", "Goniometer reference point position Z (target coordinates, away)","mm","T","E"} , //16 (14) {"GXYZ2", "Goniometer reference point position Z (target coordinates, away)","mm","T","E"} , //16 (14)
{"subcamFocalLength", "Lens focal length","mm","S","I"}, //17 (15)
{"subcamPX0", "Lens axis on the sensor (horizontal, from left edge)","pixels","S","I"}, //18 (16) {"neckRight", "Camera tilt righ around its \"neck\"","degrees","C","E"}, // 17
{"subcamPY0", "Lens axis on the sensor (vertical, from top edge)","pixels","S","I"}, //19 (17) {"neckBack", "Camera tilt back around its \"neck\"","degrees","C","E"}, // 18
{"subcamDistortionA8", "Distortion A8(r^5)","relative","S","I"}, //20 (18) {"neckXZ0", "Camera shift X at its \"neck\" (common right)","mm","C","E"}, // 19
{"subcamDistortionA7", "Distortion A7(r^5)","relative","S","I"}, //21 (19) {"neckXZ1", "Camera shift Z at its \"neck\" (common -forward)","mm","C","E"}, // 20
{"subcamDistortionA6", "Distortion A6(r^5)","relative","S","I"}, //22 (20)
{"subcamDistortionA5", "Distortion A5(r^5)","relative","S","I"}, //23 (21) {"subcamFocalLength", "Lens focal length","mm","S","I"}, // 21 //17 (15)
{"subcamDistortionA", "Distortion A (r^4)","relative","S","I"}, //24 (22) {"subcamPX0", "Lens axis on the sensor (horizontal, from left edge)","pixels","S","I"}, // 22 //18 (16)
{"subcamDistortionB", "Distortion B (r^3)","relative","S","I"}, //25 (23) {"subcamPY0", "Lens axis on the sensor (vertical, from top edge)","pixels","S","I"}, // 23 //19 (17)
{"subcamDistortionC", "Distortion C (r^2)","relative","S","I"}, //26 (24) {"subcamDistortionA8", "Distortion A8(r^5)","relative","S","I"}, // 24 //20 (18)
{"subcamDistortionA7", "Distortion A7(r^5)","relative","S","I"}, // 25 //21 (19)
{"subcamElong_C_o", "Orthogonal elongation for r^2","relative","S","I"}, // 27 39 (37) {"subcamDistortionA6", "Distortion A6(r^5)","relative","S","I"}, // 26 //22 (20)
{"subcamElong_C_d", "Diagonal elongation for r^2","relative","S","I"}, // 28 40 (38) {"subcamDistortionA5", "Distortion A5(r^5)","relative","S","I"}, // 27 //23 (21)
{"subcamDistortionA", "Distortion A (r^4)","relative","S","I"}, // 28 //24 (22)
{"subcamEccen_B_x", "Distortion center shift X for r^3","relative","S","I"}, // 29 27 (25) {"subcamDistortionB", "Distortion B (r^3)","relative","S","I"}, // 29 //25 (23)
{"subcamEccen_B_y", "Distortion center shift Y for r^3","relative","S","I"}, // 30 28 (26) {"subcamDistortionC", "Distortion C (r^2)","relative","S","I"}, // 30 //26 (24)
{"subcamElong_B_o", "Orthogonal elongation for r^3","relative","S","I"}, // 31 41 (39)
{"subcamElong_B_d", "Diagonal elongation for r^3","relative","S","I"}, // 32 42 (40) {"subcamElong_C_o", "Orthogonal elongation for r^2","relative","S","I"}, // 31 // 27 39 (37)
{"subcamElong_C_d", "Diagonal elongation for r^2","relative","S","I"}, // 32 // 28 40 (38)
{"subcamEccen_A_x", "Distortion center shift X for r^4","relative","S","I"}, // 33 29 (27)
{"subcamEccen_A_y", "Distortion center shift Y for r^4","relative","S","I"}, // 34 30 (28) {"subcamEccen_B_x", "Distortion center shift X for r^3","relative","S","I"}, // 33 // 29 27 (25)
{"subcamElong_A_o", "Orthogonal elongation for r^4","relative","S","I"}, // 35 43 (41) {"subcamEccen_B_y", "Distortion center shift Y for r^3","relative","S","I"}, // 34 // 30 28 (26)
{"subcamElong_A_d", "Diagonal elongation for r^4","relative","S","I"}, // 36 44 (42) {"subcamElong_B_o", "Orthogonal elongation for r^3","relative","S","I"}, // 35 // 31 41 (39)
{"subcamElong_B_d", "Diagonal elongation for r^3","relative","S","I"}, // 36 // 32 42 (40)
{"subcamEccen_A5_x", "Distortion center shift X for r^5","relative","S","I"}, // 37 31 (29)
{"subcamEccen_A5_y", "Distortion center shift Y for r^5","relative","S","I"}, // 38 32 (30) {"subcamEccen_A_x", "Distortion center shift X for r^4","relative","S","I"}, // 37 // 33 29 (27)
{"subcamElong_A5_o", "Orthogonal elongation for r^5","relative","S","I"}, // 39 45 (43) {"subcamEccen_A_y", "Distortion center shift Y for r^4","relative","S","I"}, // 38 // 34 30 (28)
{"subcamElong_A5_d", "Diagonal elongation for r^5","relative","S","I"}, // 40 46 (44) {"subcamElong_A_o", "Orthogonal elongation for r^4","relative","S","I"}, // 39 // 35 43 (41)
{"subcamElong_A_d", "Diagonal elongation for r^4","relative","S","I"}, // 40 // 36 44 (42)
{"subcamEccen_A6_x", "Distortion center shift X for r^6","relative","S","I"}, // 41 33 (31)
{"subcamEccen_A6_y", "Distortion center shift Y for r^6","relative","S","I"}, // 42 34 (32) {"subcamEccen_A5_x", "Distortion center shift X for r^5","relative","S","I"}, // 41 // 37 31 (29)
{"subcamElong_A6_o", "Orthogonal elongation for r^6","relative","S","I"}, // 43 47 (45) {"subcamEccen_A5_y", "Distortion center shift Y for r^5","relative","S","I"}, // 42 // 38 32 (30)
{"subcamElong_A6_d", "Diagonal elongation for r^6","relative","S","I"}, // 44 48 (46) {"subcamElong_A5_o", "Orthogonal elongation for r^5","relative","S","I"}, // 43 // 39 45 (43)
{"subcamElong_A5_d", "Diagonal elongation for r^5","relative","S","I"}, // 44 // 40 46 (44)
{"subcamEccen_A7_x", "Distortion center shift X for r^7","relative","S","I"}, // 45 35 (33)
{"subcamEccen_A7_y", "Distortion center shift Y for r^7","relative","S","I"}, // 46 36 (34) {"subcamEccen_A6_x", "Distortion center shift X for r^6","relative","S","I"}, // 45 // 41 33 (31)
{"subcamElong_A7_o", "Orthogonal elongation for r^7","relative","S","I"}, // 47 49 (47) {"subcamEccen_A6_y", "Distortion center shift Y for r^6","relative","S","I"}, // 46 // 42 34 (32)
{"subcamElong_A7_d", "Diagonal elongation for r^7","relative","S","I"}, // 48 50 (48) {"subcamElong_A6_o", "Orthogonal elongation for r^6","relative","S","I"}, // 47 // 43 47 (45)
{"subcamElong_A6_d", "Diagonal elongation for r^6","relative","S","I"}, // 48 // 44 48 (46)
{"subcamEccen_A8_x", "Distortion center shift X for r^8","relative","S","I"}, // 49 37 (35)
{"subcamEccen_A8_y", "Distortion center shift Y for r^8","relative","S","I"}, // 50 38 (36) {"subcamEccen_A7_x", "Distortion center shift X for r^7","relative","S","I"}, // 49 // 45 35 (33)
{"subcamElong_A8_o", "Orthogonal elongation for r^8","relative","S","I"}, // 51 51 (49) {"subcamEccen_A7_y", "Distortion center shift Y for r^7","relative","S","I"}, // 50 // 46 36 (34)
{"subcamElong_A8_d", "Diagonal elongation for r^8","relative","S","I"} // 52 52 (50) {"subcamElong_A7_o", "Orthogonal elongation for r^7","relative","S","I"}, // 51 // 47 49 (47)
{"subcamElong_A7_d", "Diagonal elongation for r^7","relative","S","I"}, // 52 // 48 50 (48)
{"subcamEccen_A8_x", "Distortion center shift X for r^8","relative","S","I"}, // 53 // 49 37 (35)
{"subcamEccen_A8_y", "Distortion center shift Y for r^8","relative","S","I"}, // 54 // 50 38 (36)
{"subcamElong_A8_o", "Orthogonal elongation for r^8","relative","S","I"}, // 55 // 51 51 (49)
{"subcamElong_A8_d", "Diagonal elongation for r^8","relative","S","I"} // 56 // 52 52 (50)
}; };
public String [] channelSuffixes={ // natural order (same as array indices, may be modified to camera/subcamera public String [] channelSuffixes={ // natural order (same as array indices, may be modified to camera/subcamera
...@@ -928,10 +963,8 @@ import ij.text.TextWindow; ...@@ -928,10 +963,8 @@ import ij.text.TextWindow;
int station; int station;
String [] paths; String [] paths;
String [] spaths; // can be null String [] spaths; // can be null
// String dir;
double ts; double ts;
int getStation() {return station;} int getStation() {return station;}
// String getDir() {return dir;}
double getTs() {return ts;} double getTs() {return ts;}
String [] getPaths() {return paths;} String [] getPaths() {return paths;}
String [] getSourcePaths() {return spaths;} // may not be null String [] getSourcePaths() {return spaths;} // may not be null
...@@ -943,7 +976,6 @@ import ij.text.TextWindow; ...@@ -943,7 +976,6 @@ import ij.text.TextWindow;
MultipleExtensionsFileFilter sourceFilter) MultipleExtensionsFileFilter sourceFilter)
{ {
this.station = station; this.station = station;
// this.dir = dir;
int dot_index = dir.lastIndexOf("_"); int dot_index = dir.lastIndexOf("_");
String digits = "0123456789"; String digits = "0123456789";
// allow "_<comment> after timestanp // allow "_<comment> after timestanp
...@@ -1001,9 +1033,6 @@ import ij.text.TextWindow; ...@@ -1001,9 +1033,6 @@ import ij.text.TextWindow;
int numSubCameras=(eyesisCameraParameters==null)?1:eyesisCameraParameters.eyesisSubCameras[0].length; int numSubCameras=(eyesisCameraParameters==null)?1:eyesisCameraParameters.eyesisSubCameras[0].length;
this.numSubCameras=numSubCameras; this.numSubCameras=numSubCameras;
this.eyesisCameraParameters.numStations=stationFilenames.length; this.eyesisCameraParameters.numStations=stationFilenames.length;
// int numFiles=0;
// DirTs [][] dirTs = new DirTs [stationFilenames.length][];
ArrayList<DirTs> dirTsList = new ArrayList<DirTs>(); ArrayList<DirTs> dirTsList = new ArrayList<DirTs>();
for (int numStation=0;numStation<stationFilenames.length;numStation++){ for (int numStation=0;numStation<stationFilenames.length;numStation++){
for (int is = 0; is < stationFilenames[numStation].length; is++) { for (int is = 0; is < stationFilenames[numStation].length; is++) {
...@@ -1772,6 +1801,12 @@ import ij.text.TextWindow; ...@@ -1772,6 +1801,12 @@ import ij.text.TextWindow;
} }
} }
public void listCameraParameters(){ public void listCameraParameters(){
boolean is_lwir16 = (getNumEo()==4) && (getNumLwir()==16);
double eoRollDegPerTurn = -0.45/33.5*180/Math.PI; // -0.769644799429464 deg/turn, CW screw increases roll, degrees per 1 screw turn
if (is_lwir16) eoRollDegPerTurn = -0.35/34.3*180/Math.PI; // -0.769644799429464 deg/turn, CW screw increases roll, degrees per 1 screw turn
double eoHeadDegPerTurn = 0.45/34.5*180/Math.PI; // 0.7473362545184652 deg/turn, both screws CW decreases heading (degree/turn)
double eoElevDegPerTurn = 0.45/14*180/Math.PI; // 1.8416500557776463 deg/turn, top CW, bottom CCW decreases elevation (degree/turn)
int numSubCameras=getNumSubCameras(); int numSubCameras=getNumSubCameras();
if (this.gIP!=null) { if (this.gIP!=null) {
int maxChn=0; int maxChn=0;
...@@ -1855,8 +1890,52 @@ import ij.text.TextWindow; ...@@ -1855,8 +1890,52 @@ import ij.text.TextWindow;
for (int i=1;i<numSubCameras;i++) sb.append("\t---"); for (int i=1;i<numSubCameras;i++) sb.append("\t---");
sb.append("\n"); sb.append("\n");
} }
if (stationNumber == 0) { // calculating adjustment screws
if (is_lwir16) {
int num_lwir = getNumLwir(); // 16
int num_eo = getNumEo(); // 4
int eo0 = num_lwir; // 16
double [] eoRollCorrTurns = new double[num_eo];
double [] eoTopCorrTurns = new double[num_eo];
double [] eoBotCorrTurns = new double[num_eo];
for (int i = 0; i < num_eo; i++) {
eoRollCorrTurns[i] =
cameraPars[i + eo0][getParameterIndexByName("subcamRoll")] / eoRollDegPerTurn;
eoTopCorrTurns[i] =
cameraPars[i + eo0][getParameterIndexByName("subcamHeading")] / eoHeadDegPerTurn +
cameraPars[i + eo0][getParameterIndexByName("subcamElevation")] / eoElevDegPerTurn;
eoBotCorrTurns[i] =
cameraPars[i + eo0][getParameterIndexByName("subcamHeading")] / eoHeadDegPerTurn -
cameraPars[i + eo0][getParameterIndexByName("subcamElevation")] / eoElevDegPerTurn;
}
sb.append("---"); for (int i=-1;i<numSubCameras;i++) sb.append("\t"); sb.append("\n");
sb.append("Screw roll"+"\t"+"turns CW");
for (int i = 0; i < eo0; i++) sb.append("\t");
for (int i=0;i<num_eo;i++) sb.append("\t"+IJ.d2s(eoRollCorrTurns[i],2));
sb.append("\n");
sb.append("Screw top"+"\t"+"turns CW");
for (int i = 0; i < eo0; i++) sb.append("\t");
for (int i=0;i<num_eo;i++) sb.append("\t"+IJ.d2s(eoTopCorrTurns[i],2));
sb.append("\n");
sb.append("Screw bottom"+"\t"+"turns CW");
for (int i = 0; i < eo0; i++) sb.append("\t");
for (int i=0;i<num_eo;i++) sb.append("\t"+IJ.d2s(eoBotCorrTurns[i],2));
sb.append("\n");
sb.append("---"); for (int i=-1;i<numSubCameras;i++) sb.append("\t"); sb.append("\n");
}
}
} }
new TextWindow("Camera parameters", header, sb.toString(), 85*(numSubCameras+3),600); new TextWindow("Camera_parameters", header, sb.toString(), 85*(numSubCameras+3),600);
} }
public void listCameraParametersXcam(){ // getNumSubCameras() should be 4! public void listCameraParametersXcam(){ // getNumSubCameras() should be 4!
...@@ -2053,7 +2132,7 @@ import ij.text.TextWindow; ...@@ -2053,7 +2132,7 @@ import ij.text.TextWindow;
} }
*/ */
} }
new TextWindow("Camera parameters", header, sb.toString(), 85*(numSubCameras+3),600); new TextWindow("Camera_parameters", header, sb.toString(), 85*(numSubCameras+3),600);
} }
...@@ -2275,10 +2354,21 @@ import ij.text.TextWindow; ...@@ -2275,10 +2354,21 @@ import ij.text.TextWindow;
} }
} }
break; break;
case 4:
for (int n=0;n<this.gIS[i].imageSet.length;n++){
sb.append("\t");
if (this.gIS[i].imageSet[n]!=null) {
sb.append(this.gIS[i].imageSet[n].imgNumber);
} else {
sb.append("---");
}
}
break;
} }
sb.append("\n"); sb.append("\n");
} }
new TextWindow("Image calibration state (pointers/hinted state)", header, sb.toString(), 1400, 900); // new TextWindow("Image calibration state (pointers/hinted state)", header, sb.toString(), 1400, 900);
new TextWindow("imgSets-M"+mode, header, sb.toString(), 1400, 900);
} }
...@@ -2466,7 +2556,11 @@ import ij.text.TextWindow; ...@@ -2466,7 +2556,11 @@ import ij.text.TextWindow;
} }
/* Disable no-pointer, new, number of points less than required */ /* Disable no-pointer, new, number of points less than required */
if (this.gIP[i].enabled && !wasEnabled && (this.gIP[i].matchedPointers==0) && (this.gIP[i].pixelsXY.length<minGridNodes)){ if (this.gIP[i].enabled &&
!wasEnabled &&
(this.gIP[i].matchedPointers==0) &&
this.gIP[i].gridImageSet.orientationEstimated &&
(this.gIP[i].pixelsXY.length < minGridNodes)){
this.gIP[i].enabled=false; this.gIP[i].enabled=false;
notEnoughNodes++; notEnoughNodes++;
} }
...@@ -2544,42 +2638,7 @@ import ij.text.TextWindow; ...@@ -2544,42 +2638,7 @@ import ij.text.TextWindow;
return this.gIS.length; return this.gIS.length;
} }
/** // TODO: Does it need to be updated for neck*?
* Create array of image sets ("panoramas"), sorted by timestamps
* @param all // use all images (false - only enabled)
* @return number of sets
*/
public int buildImageSetsOld(boolean all){
List <Double> timeStampList=new ArrayList<Double>(this.gIP.length);
int numChannels=0;
for (int i=0;i<this.gIP.length;i++) if (all || this.gIP[i].enabled){
if (this.gIP[i].channel>numChannels) numChannels=this.gIP[i].channel;
int j=0;
Double ts=this.gIP[i].timestamp;
if (!timeStampList.contains(ts)){
for (;(j<timeStampList.size()) && (ts>timeStampList.get(j));j++);
timeStampList.add(j,ts);
}
}
numChannels++;
this.gIS=new GridImageSet[timeStampList.size()];
for (int i=0;i<this.gIS.length;i++){
this.gIS[i]=new GridImageSet();
this.gIS[i].timeStamp=timeStampList.get(i);
this.gIS[i].imageSet=new GridImageParameters [numChannels];
for (int j=0;j<numChannels;j++) this.gIS[i].imageSet[j]=null;
}
for (int i=0;i<this.gIP.length;i++) if (all || this.gIP[i].enabled){
Double ts=this.gIP[i].timestamp;
int iIS=timeStampList.indexOf(ts);
this.gIS[iIS].imageSet[this.gIP[i].channel]=this.gIP[i];
if (this.gIP[i].motors!=null) this.gIS[iIS].motors=this.gIP[i].motors;
}
return this.gIS.length;
}
/** /**
* Set goniometer initial orientation from the image with maximal number of laser pointers (make averaging later?) * Set goniometer initial orientation from the image with maximal number of laser pointers (make averaging later?)
* Needed before LMA to have some reasonable initial orientation * Needed before LMA to have some reasonable initial orientation
...@@ -2687,35 +2746,8 @@ import ij.text.TextWindow; ...@@ -2687,35 +2746,8 @@ import ij.text.TextWindow;
System.out.println(""+this.gIS[i].goniometerTilt+" ===== orientationEstimated==true ====="); System.out.println(""+this.gIS[i].goniometerTilt+" ===== orientationEstimated==true =====");
} }
} }
}
}
/*
* Remove old method completely
if (overwriteAll || Double.isNaN(this.gIS[i].goniometerAxial)){
double subcam_heading = (esp.heading + (esp.cartesian? 0: esp.azimuth));
this.gIS[i].goniometerAxial=-subcam_heading;
for (int j=0;j<this.gIS[i].imageSet.length;j++) if (this.gIS[i].imageSet[j]!=null) setGA(this.gIS[i].imageSet[j].imgNumber,this.gIS[i].goniometerAxial);
this.gIS[i].orientationEstimated=true;
if (this.debugLevel>1) {
System.out.print(String.format("Setting goniometerAxial for the image set #%4d (%18.6f) to ", i, this.gIS[i].timeStamp));
System.out.println(""+this.gIS[i].goniometerAxial+" +++++ orientationEstimated==true +++++");
} }
} }
if (overwriteAll || Double.isNaN(this.gIS[i].goniometerTilt )){
this.gIS[i].goniometerTilt= -esp.theta;
for (int j=0;j<this.gIS[i].imageSet.length;j++) if (this.gIS[i].imageSet[j]!=null) setGH(this.gIS[i].imageSet[j].imgNumber,this.gIS[i].goniometerTilt);
this.gIS[i].orientationEstimated=true;
if (this.debugLevel>1) {
System.out.print(String.format("Setting goniometerTilt for the image set #%4d (%18.6f) to ", i, this.gIS[i].timeStamp));
System.out.println(""+this.gIS[i].goniometerTilt+" ===== orientationEstimated==true =====");
}
}
*/
} }
} }
} }
...@@ -2809,38 +2841,6 @@ import ij.text.TextWindow; ...@@ -2809,38 +2841,6 @@ import ij.text.TextWindow;
} }
} }
public void updateSetOrientationOld(boolean [] selectedImages){
if (this.gIS==null){
String msg="Image set is not initilaized";
System.out.println(msg);
IJ.showMessage(msg);
}
for (int i=0; i<this.gIS.length;i++){
if (selectedImages==null){ // if all selected - remove orientation if there are no enabled images (i.e. after removeOutliers)
this.gIS[i].goniometerAxial=Double.NaN;
this.gIS[i].goniometerTilt= Double.NaN;
this.gIS[i].orientationEstimated=true;
}
for (int j=0;j<this.gIS[i].imageSet.length;j++) if ((this.gIS[i].imageSet[j]!=null) && this.gIS[i].imageSet[j].enabled){
if ((selectedImages==null) || selectedImages[this.gIS[i].imageSet[j].imgNumber]) {
this.gIS[i].goniometerAxial=getGA(this.gIS[i].imageSet[j].imgNumber); //update - most likely will do nothing (if set has non-NaN)
this.gIS[i].goniometerTilt= getGH(this.gIS[i].imageSet[j].imgNumber);
this.gIS[i].goniometerAxial-=360.0*Math.floor((this.gIS[i].goniometerAxial+180.0)/360.0);
this.gIS[i].orientationEstimated=false;
break; // set from the first non-null, enabled image
}
}
// now fill that data to all disabled images of the same set (just for listing RMS errors and debugging)
if (!Double.isNaN(this.gIS[i].goniometerAxial) && !Double.isNaN(this.gIS[i].goniometerTilt)){
for (int j=0;j<this.gIS[i].imageSet.length;j++) if (this.gIS[i].imageSet[j]!=null) { // fill even those that are enabled
setGA(this.gIS[i].imageSet[j].imgNumber,this.gIS[i].goniometerAxial );
setGH(this.gIS[i].imageSet[j].imgNumber,this.gIS[i].goniometerTilt );
}
}
}
}
public boolean isEstimated(int imgNum){ public boolean isEstimated(int imgNum){
if (this.gIS==null) { if (this.gIS==null) {
String msg="Image sets are not initialized"; String msg="Image sets are not initialized";
...@@ -2859,21 +2859,7 @@ import ij.text.TextWindow; ...@@ -2859,21 +2859,7 @@ import ij.text.TextWindow;
IJ.showMessage("Error",msg); IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg); throw new IllegalArgumentException (msg);
} }
public boolean isEstimatedOld(int imgNum){
if (this.gIS==null) {
String msg="Image sets are not initialized";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
for (int i=0;i<this.gIS.length;i++) if (this.gIS[i].imageSet!=null){
for (int j=0;j<this.gIS[i].imageSet.length;j++) if ((this.gIS[i].imageSet[j]!=null) && (this.gIS[i].imageSet[j].imgNumber==imgNum)){
return this.gIS[i].orientationEstimated;
}
}
String msg="Image with index "+imgNum+" is not in the image set";
IJ.showMessage("Error",msg);
throw new IllegalArgumentException (msg);
}
public int getNumberOfEstimated(boolean enabledOnly) { public int getNumberOfEstimated(boolean enabledOnly) {
int numEstimated=0; int numEstimated=0;
if (this.gIS==null) return 0; if (this.gIS==null) return 0;
...@@ -2971,6 +2957,7 @@ import ij.text.TextWindow; ...@@ -2971,6 +2957,7 @@ import ij.text.TextWindow;
} }
return estimated; return estimated;
} }
public void enableSelected(boolean [] selected){ public void enableSelected(boolean [] selected){
for (int i=0;i<this.gIP.length ;i++) if (this.gIP[i]!=null){ for (int i=0;i<this.gIP.length ;i++) if (this.gIP[i]!=null){
int i1=i; int i1=i;
...@@ -4353,27 +4340,6 @@ import ij.text.TextWindow; ...@@ -4353,27 +4340,6 @@ import ij.text.TextWindow;
// TODO: Move all custom image properties (including encode/decode from JP4_reader_camera) to a separate class. // TODO: Move all custom image properties (including encode/decode from JP4_reader_camera) to a separate class.
// below is a duplicate from MatchSimulatedPattern // below is a duplicate from MatchSimulatedPattern
@Deprecated
public double[][] getPointersXY(ImagePlus imp, int numPointers){
// read image info to properties (if it was not done yet - should it?
if ((imp.getProperty("timestamp")==null) || (((String) imp.getProperty("timestamp")).length()==0)) {
JP46_Reader_camera jp4_instance= new JP46_Reader_camera(false);
jp4_instance.decodeProperiesFromInfo(imp);
}
double [][] pointersXY=new double[numPointers][];
int numPointerDetected=0;
for (int i=0;i<pointersXY.length;i++) {
pointersXY[i]=null;
if ((imp.getProperty("POINTER_X_"+i)!=null) && (imp.getProperty("POINTER_Y_"+i)!=null)) {
pointersXY[i]=new double[2];
pointersXY[i][0]=Double.parseDouble((String) imp.getProperty("POINTER_X_"+i));
pointersXY[i][1]=Double.parseDouble((String) imp.getProperty("POINTER_Y_"+i));
numPointerDetected++;
}
}
if (numPointerDetected>0) return pointersXY;
else return null;
}
public int [] getMotorPositions(ImagePlus imp, int numMotors){ public int [] getMotorPositions(ImagePlus imp, int numMotors){
// read image info to properties (if it was not done yet - should it? // read image info to properties (if it was not done yet - should it?
...@@ -4417,14 +4383,27 @@ import ij.text.TextWindow; ...@@ -4417,14 +4383,27 @@ import ij.text.TextWindow;
} }
public boolean hasSmallSensors() { public boolean hasSmallSensors() {
return small_period_frac > 0.0; boolean [] ss = getSmallSensors();
if (small_period_frac > 0.0) return true; // old mode
for (boolean b:ss) {
if (b) return true;
}
return false;
} }
public boolean [] getSmallSensors() { public boolean [] getSmallSensors() {
if (small_sensors == null) {
small_sensors = new boolean[eyesisCameraParameters.eyesisSubCameras[0].length];
for (int i = 0; i < small_sensors.length; i++) {
small_sensors[i]= eyesisCameraParameters.eyesisSubCameras[0][i].isLWIR();
}
}
return small_sensors; return small_sensors;
} }
public boolean isSmallSensor(int numImg) { public boolean isSmallSensor(int numImg) {
if ((this.gIP != null) && (numImg >= 0) && (numImg < this.gIP.length) && (small_sensors != null)){ boolean [] ss = getSmallSensors();
return small_sensors[this.gIP[numImg].getChannel()]; if ((this.gIP != null) && (numImg >= 0) && (numImg < this.gIP.length)){
return ss[this.gIP[numImg].getChannel()];
} }
return false; return false;
} }
...@@ -4433,8 +4412,6 @@ import ij.text.TextWindow; ...@@ -4433,8 +4412,6 @@ import ij.text.TextWindow;
public double getSmallPeriodFrac() { public double getSmallPeriodFrac() {
return small_period_frac; return small_period_frac;
} }
// public boolean [] small_sensors = null; // set by filter grids
// public double small_period_frac = 0; // set by filter grids - ratio of small sensor period to large sensor period
// depending on camera type, return group, groups, group name // depending on camera type, return group, groups, group name
// camera type: eyesis26, lwir/eo (2 resolutions) , single, other // camera type: eyesis26, lwir/eo (2 resolutions) , single, other
...@@ -4670,7 +4647,7 @@ import ij.text.TextWindow; ...@@ -4670,7 +4647,7 @@ import ij.text.TextWindow;
return this.pars[numImg][index_ga]; return this.pars[numImg][index_ga];
} }
public void setParameters(double [] parameters, int numImg, boolean[] mask){ public void setParameters(double [] parameters, int numImg, boolean[] mask){ // not used?
if ((numImg<0) || (numImg>=this.pars.length)) { if ((numImg<0) || (numImg>=this.pars.length)) {
String msg="There are only "+this.pars.length+" images defined, requested #"+numImg; String msg="There are only "+this.pars.length+" images defined, requested #"+numImg;
IJ.showMessage("Error",msg); IJ.showMessage("Error",msg);
......
...@@ -27,6 +27,7 @@ import java.awt.Point; ...@@ -27,6 +27,7 @@ import java.awt.Point;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
//import java.util.Arrays; //import java.util.Arrays;
//import java.io.StringWriter; //import java.io.StringWriter;
import java.util.List; import java.util.List;
...@@ -3321,10 +3322,12 @@ For each point in the image ...@@ -3321,10 +3322,12 @@ For each point in the image
int numSuccess=0; int numSuccess=0;
DistortionCalibrationData dcd=fittingStrategy.distortionCalibrationData; DistortionCalibrationData dcd=fittingStrategy.distortionCalibrationData;
for (int numGridImage=0;numGridImage<dcd.gIP.length;numGridImage++) { for (int numGridImage=0;numGridImage<dcd.gIP.length;numGridImage++) {
/*
if (numGridImage >= 1680) { if (numGridImage >= 1680) {
System.out.println("Processing debug image "+numGridImage); System.out.println("Processing debug image "+numGridImage);
System.out.println("Processing debug image "+numGridImage); System.out.println("Processing debug image "+numGridImage);
} }
*/
int set_number = dcd.gIP[numGridImage].getSetNumber(); int set_number = dcd.gIP[numGridImage].getSetNumber();
if ((set_number >= start_set) && if ((set_number >= start_set) &&
(set_number <= end_set) && (set_number <= end_set) &&
...@@ -10747,17 +10750,31 @@ M * V = B ...@@ -10747,17 +10750,31 @@ M * V = B
EyesisCameraParameters eyesisCameraParameters EyesisCameraParameters eyesisCameraParameters
){ ){
boolean resetParametersToZero=false; boolean resetParametersToZero=false;
boolean updateAllSubcameras = false;
boolean [] parameterMask= new boolean[distortionCalibrationData.getNumParameters()]; boolean [] parameterMask= new boolean[distortionCalibrationData.getNumParameters()];
boolean [] channelMask= new boolean[distortionCalibrationData.getNumSubCameras()]; boolean [] channelMask= new boolean[distortionCalibrationData.getNumSubCameras()];
boolean [] stationMask= new boolean[distortionCalibrationData.getNumStations()]; boolean [] stationMask= new boolean[distortionCalibrationData.getNumStations()];
String [] source_stations = new String[stationMask.length+1];
source_stations[0] = "---";
for (int i = 0; i < stationMask.length; i++) {
source_stations[i+1]=""+i;
}
for (int i=0;i<parameterMask.length;i++) parameterMask[i]=false; for (int i=0;i<parameterMask.length;i++) parameterMask[i]=false;
for (int i=0;i<channelMask.length;i++) channelMask[i]= true; for (int i=0;i<channelMask.length;i++) channelMask[i]= true;
for (int i=0;i<stationMask.length;i++) stationMask[i]= true; for (int i=0;i<stationMask.length;i++) stationMask[i]= true;
GenericDialog gd=new GenericDialog("Update (new) image settings from known data"); GenericDialog gd=new GenericDialog("Update (new) image settings from known data");
// //
gd.addCheckbox("Reset selected parameters to zero (false - update from camera parameters)", resetParametersToZero); gd.addCheckbox("Reset selected parameters to zero (false - update from camera parameters)", resetParametersToZero);
if (stationMask.length > 1) {
gd.addChoice("Copy selected parameters from tis station to all other stations" , source_stations, source_stations[0]);
}
gd.addMessage("Select which individual image parameters to be updated from the camera parameters (or reset to 0)"); gd.addMessage("Select which individual image parameters to be updated from the camera parameters (or reset to 0)");
for (int i=0;i<parameterMask.length;i++) gd.addCheckbox(i+": "+distortionCalibrationData.getParameterName(i), parameterMask[i]);
gd.addCheckbox("Update all subcamera parameters", updateAllSubcameras);
for (int i=0;i<parameterMask.length;i++) {
gd.addCheckbox(i+": "+distortionCalibrationData.getParameterName(i), parameterMask[i]);
}
gd.addMessage("----------"); gd.addMessage("----------");
gd.addMessage("Select which channels (sub-cameras) to update"); gd.addMessage("Select which channels (sub-cameras) to update");
for (int i=0;i<channelMask.length;i++) gd.addCheckbox("Subcamera "+i, channelMask[i]); for (int i=0;i<channelMask.length;i++) gd.addCheckbox("Subcamera "+i, channelMask[i]);
...@@ -10776,6 +10793,12 @@ M * V = B ...@@ -10776,6 +10793,12 @@ M * V = B
gd.showDialog(); gd.showDialog();
if (gd.wasCanceled()) return false; if (gd.wasCanceled()) return false;
resetParametersToZero=gd.getNextBoolean(); resetParametersToZero=gd.getNextBoolean();
int source_station = -1;
if (stationMask.length > 1) {
source_station = gd.getNextChoiceIndex() - 1;
}
updateAllSubcameras = gd.getNextBoolean();
for (int i=0;i<parameterMask.length;i++) parameterMask[i]= gd.getNextBoolean(); for (int i=0;i<parameterMask.length;i++) parameterMask[i]= gd.getNextBoolean();
for (int i=0;i<channelMask.length;i++) channelMask[i]= gd.getNextBoolean(); for (int i=0;i<channelMask.length;i++) channelMask[i]= gd.getNextBoolean();
if (stationMask.length>1) { if (stationMask.length>1) {
...@@ -10784,6 +10807,25 @@ M * V = B ...@@ -10784,6 +10807,25 @@ M * V = B
boolean updateFromTimestamps= gd.getNextBoolean(); boolean updateFromTimestamps= gd.getNextBoolean();
boolean allowClosest= gd.getNextBoolean(); boolean allowClosest= gd.getNextBoolean();
boolean reCenterVertically= gd.getNextBoolean(); boolean reCenterVertically= gd.getNextBoolean();
if (updateAllSubcameras) {
resetParametersToZero = false; // just for safety
for (int i=0;i<parameterMask.length;i++) {
parameterMask[i] |= distortionCalibrationData.isSubcameraParameter(i);
}
}
if (source_station >= 0) {
updateOtherStations(
eyesisCameraParameters,
source_station,
parameterMask,
channelMask,
stationMask);
}
if (reCenterVertically){ if (reCenterVertically){
eyesisCameraParameters.recenterVertically(channelMask, stationMask); eyesisCameraParameters.recenterVertically(channelMask, stationMask);
for (int i=0;i<channelMask.length;i++) channelMask[i]= true; for (int i=0;i<channelMask.length;i++) channelMask[i]= true;
...@@ -10903,6 +10945,38 @@ M * V = B ...@@ -10903,6 +10945,38 @@ M * V = B
return true; return true;
} }
/**
* Update selected parameters from sourceStation to selected (stationMask) stations, filtered by channelMask
* @param eyesisCameraParameters
* @param sourceStation
* @param parameterMask
* @param channelMask
* @param stationMask
*/
public void updateOtherStations(
EyesisCameraParameters eyesisCameraParameters,
int sourceStation,
boolean [] parameterMask,
boolean [] channelMask,
boolean [] stationMask
) {
for (int stationNumber = 0; stationNumber < stationMask.length; stationNumber++) if (stationMask[stationNumber]) {
for (int subCam=0; subCam < channelMask.length; subCam++) if (channelMask[subCam]) {
double [] oldVector=eyesisCameraParameters.getParametersVector(stationNumber,subCam);
double [] newVector=eyesisCameraParameters.getParametersVector(sourceStation,subCam);
for (int j=0;j<oldVector.length;j++) if (parameterMask[j]){
oldVector[j]=newVector[j];
}
eyesisCameraParameters.setParametersVector(
newVector,
parameterMask,
stationNumber,
subCam);
}
}
}
/** /**
* Copies selected parameters from the camera parameters to per-image parameters (i.e. for new/previously disabled images) * Copies selected parameters from the camera parameters to per-image parameters (i.e. for new/previously disabled images)
...@@ -11078,6 +11152,10 @@ M * V = B ...@@ -11078,6 +11152,10 @@ M * V = B
int numSeries=allImages?(-1):this.fittingStrategy.currentSeriesNumber; int numSeries=allImages?(-1):this.fittingStrategy.currentSeriesNumber;
boolean [] selectedImages=fittingStrategy.selectedImages(numSeries); // all enabled boolean [] selectedImages=fittingStrategy.selectedImages(numSeries); // all enabled
boolean [] selectedImagesDebug=null; boolean [] selectedImagesDebug=null;
boolean include_disabled = allImages;
if (include_disabled) {
Arrays.fill(selectedImages, true);
}
boolean debugThis=false; boolean debugThis=false;
int maxDebugImages=10; int maxDebugImages=10;
if (this.debugLevel>0) System.out.println("updateCameraParametersFromCalculated("+allImages+")"); if (this.debugLevel>0) System.out.println("updateCameraParametersFromCalculated("+allImages+")");
...@@ -11108,6 +11186,7 @@ M * V = B ...@@ -11108,6 +11186,7 @@ M * V = B
System.out.println(i+": "+fittingStrategy.distortionCalibrationData.getParameterName(i)+" = "+par[i]); System.out.println(i+": "+fittingStrategy.distortionCalibrationData.getParameterName(i)+" = "+par[i]);
} }
} }
// System.out.println(numImg+"[21]: "+fittingStrategy.distortionCalibrationData.getParameterName(21)+" = "+par[21]);
} }
if (this.debugLevel>1) System.out.println("updateCameraParametersFromCalculated("+allImages+") for series="+numSeries); if (this.debugLevel>1) System.out.println("updateCameraParametersFromCalculated("+allImages+") for series="+numSeries);
// Next line is not needed anymore (will harm as will set orientationEstimated for all unselected sets) // Next line is not needed anymore (will harm as will set orientationEstimated for all unselected sets)
......
...@@ -669,6 +669,9 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit ...@@ -669,6 +669,9 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
*/ */
public int buildParameterMap (int numSeries){ public int buildParameterMap (int numSeries){
return buildParameterMap (numSeries, true);
}
public int buildParameterMap (int numSeries, boolean mark_disabled){
int numPars=this.distortionCalibrationData.getNumParameters(); int numPars=this.distortionCalibrationData.getNumParameters();
int numImg=this.distortionCalibrationData.getNumImages(); int numImg=this.distortionCalibrationData.getNumImages();
int numTPars=this.parameterMode[numSeries].length; int numTPars=this.parameterMode[numSeries].length;
...@@ -681,7 +684,11 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit ...@@ -681,7 +684,11 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
// int [][] tmpMap=new int[numTPars][3]; // temporary array parameterMap[][] (will be truncated) // int [][] tmpMap=new int[numTPars][3]; // temporary array parameterMap[][] (will be truncated)
int [][] tmpMap=new int[numPars*numImg][3]; // temporary array parameterMap[][] (will be truncated) int [][] tmpMap=new int[numPars*numImg][3]; // temporary array parameterMap[][] (will be truncated)
double masterTS=this.distortionCalibrationData.getImageTimestamp(this.masterImages[numSeries]); // timestamp of the master image double masterTS=this.distortionCalibrationData.getImageTimestamp(this.masterImages[numSeries]); // timestamp of the master image
int [] masterVectorIndices = new int [numTPars]; int [] masterVectorIndices = new int [numTPars]; //[855]
// all but [4][21] are 0,[4][21] is 2 (modeSupercommon),
// [4][63,105,147,189,231,273,315,357,399,441,483,525,567,609,651,]=10
// [4][693]= 2 EO(==16)?
// [4][733,777,819]= 26
// iterate through all global/subcamera parameters // iterate through all global/subcamera parameters
for (int numTPar=0;numTPar<numTPars;numTPar++) if (this.parameterMode[numSeries][numTPar]!=modeFixed){ // skip "fixed" for (int numTPar=0;numTPar<numTPars;numTPar++) if (this.parameterMode[numSeries][numTPar]!=modeFixed){ // skip "fixed"
boolean isCommon= boolean isCommon=
...@@ -695,7 +702,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit ...@@ -695,7 +702,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
int numPar=this.parameterList[numTPar][1]; // number of per-image parameter for this total parameter index int numPar=this.parameterList[numTPar][1]; // number of per-image parameter for this total parameter index
boolean isSubCamera=this.distortionCalibrationData.isSubcameraParameter(numPar); boolean isSubCamera=this.distortionCalibrationData.isSubcameraParameter(numPar);
// is it "same as" ? // is it "same as" ?
int sameAs = this.parameterMode[numSeries][numTPar] - this.definedModesAll.length; // number of subcamera to use int sameAs = this.parameterMode[numSeries][numTPar] - this.definedModesAll.length; // number of subcamera to use (this.definedModesAll.length==10)
int numTParMaster = -1; int numTParMaster = -1;
int vectorIndexMaster = -1; int vectorIndexMaster = -1;
if (sameAs < 0 ) { if (sameAs < 0 ) {
...@@ -713,54 +720,70 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit ...@@ -713,54 +720,70 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
vectorIndexMaster = masterVectorIndices[numTParMaster]; // use as vectorIndex for slaves vectorIndexMaster = masterVectorIndices[numTParMaster]; // use as vectorIndex for slaves
} }
if (this.debugLevel>2) System.out.println("numTPar="+numTPar+" numSub="+numSub+" numPar="+numPar+" numTParMaster="+numTParMaster); if (this.debugLevel > 2) System.out.println("numTPa = "+numTPar+" numSub="+numSub+" numPar="+numPar+" numTParMaster="+numTParMaster);
// iterate through available images // iterate through available images
for (int numThisImg=0;numThisImg<numImg;numThisImg++) { for (int numThisImg=0;numThisImg<numImg;numThisImg++) {
if ((selectedEnabledImages[numThisImg]) && // if ((selectedEnabledImages[numThisImg]) &&
(!isSubCamera || (numSub==this.distortionCalibrationData.getImageSubcamera(numThisImg))) && // (!isSubCamera || (numSub==this.distortionCalibrationData.getImageSubcamera(numThisImg))) &&
(this.reverseParameterMap[numThisImg][numPar]<0)){ // image used, this cell is not (yet) defined // (this.reverseParameterMap[numThisImg][numPar]<0)){ // image used, this cell is not (yet) defined
if((!isSubCamera || (numSub==this.distortionCalibrationData.getImageSubcamera(numThisImg))) &&
(this.reverseParameterMap[numThisImg][numPar]<0)){ // image used, this cell is not (yet) defined
if (this.debugLevel>2){ if (this.debugLevel>2){
System.out.println("buildParameterMap("+numSeries+"): numThisImg="+numThisImg+", numPar="+numPar+", vectorIndex="+vectorIndex); System.out.println("buildParameterMap("+numSeries+"): numThisImg="+numThisImg+", numPar="+numPar+", vectorIndex="+vectorIndex);
} }
// is it "same as" ? // is it "same as" ? // "same as" is only applicable to subcamera parameters
if (vectorIndexMaster >= 0){ if (vectorIndexMaster >= 0){
this.reverseParameterMap[numThisImg][numPar] = vectorIndexMaster; if (mark_disabled || selectedEnabledImages[numThisImg]) {
this.reverseParameterMap[numThisImg][numPar] = vectorIndexMaster;
}
// does not look for same parameter in later images - leave it for the master? // does not look for same parameter in later images - leave it for the master?
} else { } else {
if (selectedEnabledImages[numThisImg]) {
// assign it a new parameter // assign it a new parameter
this.reverseParameterMap[numThisImg][numPar]=vectorIndex; this.reverseParameterMap[numThisImg][numPar]=vectorIndex;
masterVectorIndices[numTPar] = vectorIndex; masterVectorIndices[numTPar] = vectorIndex;
double thisTS=this.distortionCalibrationData.getImageTimestamp(numThisImg); double thisTS=this.distortionCalibrationData.getImageTimestamp(numThisImg);
int thisStation=this.distortionCalibrationData.gIP[numThisImg].getStationNumber(); int thisStation=this.distortionCalibrationData.gIP[numThisImg].getStationNumber();
// set pointer to this first image // set pointer to this first image
tmpMap[vectorIndex][0]=numThisImg; // vectorindex==22 > tmpMap.length? tmpMap[vectorIndex][0]=numThisImg; // vectorindex==22 > tmpMap.length?
tmpMap[vectorIndex][1]=numPar; tmpMap[vectorIndex][1]=numPar;
tmpMap[vectorIndex][2]=this.parameterMode[numSeries][numTPar]; tmpMap[vectorIndex][2]=this.parameterMode[numSeries][numTPar];
double minDist=Math.abs(this.distortionCalibrationData.getImageTimestamp(numThisImg)-masterTS); double minDist=Math.abs(this.distortionCalibrationData.getImageTimestamp(numThisImg)-masterTS);
if (this.debugLevel>2) System.out.println("vectorIndex="+vectorIndex+" numThisImg="+numThisImg); if (this.debugLevel>2) System.out.println("vectorIndex="+vectorIndex+" numThisImg="+numThisImg);
// see if same parameter in some other (later) image(s) is shared // see if same parameter in some other (later) image(s) is shared
for (int numOtherImg=numThisImg + 1; numOtherImg < numImg; numOtherImg++) // for (int numOtherImg=numThisImg + 1; numOtherImg < numImg; numOtherImg++) {
if ((selectedEnabledImages[numOtherImg]) && // OOB 1 boolean proc_disabled = mark_disabled && (isCommon || isStation || isGroup);
(!isSubCamera || (numSub==this.distortionCalibrationData.getImageSubcamera(numOtherImg))) && for (int numOtherImg=0; numOtherImg < numImg; numOtherImg++) {
(this.reverseParameterMap[numOtherImg][numPar]<0)){ // image used, this cell is not (yet) defined // 06.03.2021: old way for enabled images - only assign to later images
if ((this.distortionCalibrationData.getImageTimestamp(numOtherImg)==thisTS) || // same parameter same timestamp - same group even if is set differently // disabled or unselected images - assign to even earlier ones
(isStation && (this.distortionCalibrationData.gIP[numOtherImg].getStationNumber()==thisStation)) || // new if ((selectedEnabledImages[numOtherImg] && (numOtherImg > numThisImg)) || (proc_disabled && !selectedEnabledImages[numOtherImg])) {
isCommon || // if ((selectedEnabledImages[numOtherImg]) && // OOB 1
(isGroup && (this.parameterGroups[numSeries][numTPar][numThisImg]== if ((!isSubCamera || (numSub==this.distortionCalibrationData.getImageSubcamera(numOtherImg))) &&
this.parameterGroups[numSeries][numTPar][numOtherImg]))){ (this.reverseParameterMap[numOtherImg][numPar]<0)){ // image used, this cell is not (yet) defined
if ((this.distortionCalibrationData.getImageTimestamp(numOtherImg)==thisTS) || // same parameter same timestamp - same group even if is set differently
(isStation && (this.distortionCalibrationData.gIP[numOtherImg].getStationNumber()==thisStation)) || // new
isCommon ||
(isGroup && (this.parameterGroups[numSeries][numTPar][numThisImg]==
this.parameterGroups[numSeries][numTPar][numOtherImg]))){
// assign it a the same parameter // assign it a the same parameter
this.reverseParameterMap[numOtherImg][numPar]=vectorIndex; this.reverseParameterMap[numOtherImg][numPar]=vectorIndex;
double thisDist=Math.abs(this.distortionCalibrationData.getImageTimestamp(numThisImg)-masterTS); double thisDist=Math.abs(this.distortionCalibrationData.getImageTimestamp(numThisImg)-masterTS);
if (thisDist<minDist) { if (thisDist<minDist) {
minDist=thisDist; minDist=thisDist;
tmpMap[vectorIndex][0]=numOtherImg; tmpMap[vectorIndex][0]=numOtherImg;
} }
} }
} }
vectorIndex++; }
}
vectorIndex++;
}
} }
} }
} }
// second pass
} }
// reverseParameterMap built, vectorIndex equals to the total number of parameters needed for fitting // reverseParameterMap built, vectorIndex equals to the total number of parameters needed for fitting
...@@ -1140,7 +1163,9 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit ...@@ -1140,7 +1163,9 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
" nSub="+nSub+" distortionCalibrationData.getImageSubcamera("+numImg+")="+distortionCalibrationData.getImageSubcamera(numImg)+ " nSub="+nSub+" distortionCalibrationData.getImageSubcamera("+numImg+")="+distortionCalibrationData.getImageSubcamera(numImg)+
" vector["+vPar+"]="+vector[vPar]); " vector["+vPar+"]="+vector[vPar]);
} }
if ((!isSubCamera) || (nSub==this.distortionCalibrationData.getImageSubcamera(numImg))) { // if ((!isSubCamera) || (nSub==this.distortionCalibrationData.getImageSubcamera(numImg))) {
if ((!isSubCamera) || (nSub==this.distortionCalibrationData.getImageSubcamera(numImg)) ||
(this.reverseParameterMap[numImg][nPar] == vPar)) { // 06.03.2021
// this.distortionCalibrationData.pars[numImg][nPar]=vector[vPar]; // this.distortionCalibrationData.pars[numImg][nPar]=vector[vPar];
this.distortionCalibrationData.setParameterValue(numImg,nPar,vector[vPar],true); this.distortionCalibrationData.setParameterValue(numImg,nPar,vector[vPar],true);
} }
...@@ -1170,7 +1195,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit ...@@ -1170,7 +1195,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
return vector; return vector;
} }
/** /**
* Calculates which of all parameters for the particular sensor are to be adjusted (to reduce calcualtions) * Calculates which of all parameters for the particular sensor are to be adjusted (to reduce calculations)
* @param numImg number of image * @param numImg number of image
* @param vector parameters vector * @param vector parameters vector
* @return mask vector to be used with the results of getImageParametersVector() * @return mask vector to be used with the results of getImageParametersVector()
...@@ -2334,7 +2359,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit ...@@ -2334,7 +2359,7 @@ I* - special case when the subcamera is being adjusted/replaced. How to deal wit
thisChoice = theseChoices[indx]; thisChoice = theseChoices[indx];
System.out.println("selectStrategyStep(): this.parameterMode["+numSeries+"]["+i+"]=" + this.parameterMode[numSeries][i]+" indx = "+indx); // System.out.println("selectStrategyStep(): this.parameterMode["+numSeries+"]["+i+"]=" + this.parameterMode[numSeries][i]+" indx = "+indx);
} }
gd.addChoice( // ArrayIndexOutOfBoundsException: 9 gd.addChoice( // ArrayIndexOutOfBoundsException: 9
(this.distortionCalibrationData.isSubcameraParameter(parIndex)?"":"* ") + (this.distortionCalibrationData.isSubcameraParameter(parIndex)?"":"* ") +
......
...@@ -22,7 +22,7 @@ import ij.gui.GenericDialog; ...@@ -22,7 +22,7 @@ import ij.gui.GenericDialog;
*/ */
// lens parameters (add more later) // lens parameters (add more later)
final int numInputs= 53; //27; // with A8...// 24; // parameters in subcamera+... final int numInputs= 57; // with neck*, was 53; //27; // with A8...// 24; // parameters in subcamera+...
final int numOutputs=42; //16; // with A8...//13; // parameters in a single camera final int numOutputs=42; //16; // with A8...//13; // parameters in a single camera
// final // final
// boolean cummulativeCorrection=true; // r_xy, r_od for higher terms are relative to lower ones // boolean cummulativeCorrection=true; // r_xy, r_od for higher terms are relative to lower ones
...@@ -724,7 +724,7 @@ dPXmmc/dphi= ...@@ -724,7 +724,7 @@ dPXmmc/dphi=
*/ */
/** /**
* extract needed ones, and reorder partial derivatives to match calcInterParameters * extract needed ones, and reorder partial derivatives to match lensCalcInterParamers (LDP1862)
* @param srcDerivatives - values and 15 derivatives for px, py * @param srcDerivatives - values and 15 derivatives for px, py
*/ */
public double [][] reorderPartialDerivatives (double [][] srcDerivatives){ public double [][] reorderPartialDerivatives (double [][] srcDerivatives){
...@@ -736,16 +736,16 @@ dPXmmc/dphi= ...@@ -736,16 +736,16 @@ dPXmmc/dphi=
2, // 4 public double pitch=0.0; // angle in degrees from perpendicular to the pattern, 0 - towards wall, positive - up 2, // 4 public double pitch=0.0; // angle in degrees from perpendicular to the pattern, 0 - towards wall, positive - up
3, // 5 public double roll=0.0; // angle in degrees rotation around camera optical axis (perpendicular to pattern if yaw==0, pitch==0), positive - clockwise 3, // 5 public double roll=0.0; // angle in degrees rotation around camera optical axis (perpendicular to pattern if yaw==0, pitch==0), positive - clockwise
7, // 6 public double focalLength=4.5; 7, // 6 public double focalLength=4.5;
16, // 7 public double px0=1296.0; // center of the lens on the sensor, pixels 16, // 7 public double px0=1296.0; // center of the lens on the sensor, pixels
17, // 8 public double py0=968.0; // center of the lens on the sensor, pixels 17, // 8 public double py0=968.0; // center of the lens on the sensor, pixels
// public double distortionRadius= 2.8512; // mm - half width of the sensor // public double distortionRadius= 2.8512; // mm - half width of the sensor
9, // 9 public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?) 9, // 9 public double distortionA8=0.0; // r^5 (normalized to focal length or to sensor half width?)
10, // 10 public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?) 10, // 10 public double distortionA7=0.0; // r^5 (normalized to focal length or to sensor half width?)
11, // 11 public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?) 11, // 11 public double distortionA6=0.0; // r^5 (normalized to focal length or to sensor half width?)
12, // 12 public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?) 12, // 12 public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?)
13, // 13 public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?) 13, // 13 public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?)
14, // 14 public double distortionB=0.0; // r^3 14, // 14 public double distortionB=0.0; // r^3
15, // 15 public double distortionC=0.0; // r^2 15, // 15 public double distortionC=0.0; // r^2
18, // 16 Orthogonal elongation for r^2" 18, // 16 Orthogonal elongation for r^2"
19, // 17 Diagonal elongation for r^2" 19, // 17 Diagonal elongation for r^2"
20, // 18 Distortion center shift X for r^3" 20, // 18 Distortion center shift X for r^3"
...@@ -802,15 +802,15 @@ dPXmmc/dphi= ...@@ -802,15 +802,15 @@ dPXmmc/dphi=
2, // 4 public double pitch=0.0; // angle in degrees from perpendicular to the pattern, 0 - towards wall, positive - up 2, // 4 public double pitch=0.0; // angle in degrees from perpendicular to the pattern, 0 - towards wall, positive - up
3, // 5 public double roll=0.0; // angle in degrees rotation around camera optical axis (perpendicular to pattern if yaw==0, pitch==0), positive - clockwise 3, // 5 public double roll=0.0; // angle in degrees rotation around camera optical axis (perpendicular to pattern if yaw==0, pitch==0), positive - clockwise
7, // 6 public double focalLength=4.5; 7, // 6 public double focalLength=4.5;
16, // 7 public double px0=1296.0; // center of the lens on the sensor, pixels 16, // 7 public double px0=1296.0; // center of the lens on the sensor, pixels
17, // 8 public double py0=968.0; // center of the lens on the sensor, pixels 17, // 8 public double py0=968.0; // center of the lens on the sensor, pixels
9, // 9 public double distortionA8=0.0; // r^5 (normalized to focal length or to sensor half width?) 9, // 9 public double distortionA8=0.0; // r^8 (normalized to focal length or to sensor half width?)
10, // 10 public double distortionA7=0.0; // r^5 (normalized to focal length or to sensor half width?) 10, // 10 public double distortionA7=0.0; // r^7 (normalized to focal length or to sensor half width?)
11, // 11 public double distortionA6=0.0; // r^5 (normalized to focal length or to sensor half width?) 11, // 11 public double distortionA6=0.0; // r^6 (normalized to focal length or to sensor half width?)
12, // 12 public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?) 12, // 12 public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?)
13, // 13 public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?) 13, // 13 public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?)
14, // 14 public double distortionB=0.0; // r^3 14, // 14 public double distortionB=0.0; // r^3
15, // 15 public double distortionC=0.0; // r^2 15, // 15 public double distortionC=0.0; // r^2
18, // 16 Orthogonal elongation for r^2" 18, // 16 Orthogonal elongation for r^2"
19, // 17 Diagonal elongation for r^2" 19, // 17 Diagonal elongation for r^2"
...@@ -1880,19 +1880,24 @@ dPXmmc/dphi= ...@@ -1880,19 +1880,24 @@ dPXmmc/dphi=
double height= parVect[2]; double height= parVect[2];
double phi_cyl= cartesian? Double.NaN: parVect[3]; double phi_cyl= cartesian? Double.NaN: parVect[3];
double heading_cart= cartesian? parVect[3]: Double.NaN; double heading_cart= cartesian? parVect[3]: Double.NaN;
double theta= parVect[4]; double theta= parVect[4];
double psi= parVect[5]; double psi= parVect[5];
double goniometerHorizontal=parVect[6]; double goniometerHorizontal= parVect[6];
double goniometerAxial=parVect[7]; double goniometerAxial= parVect[7];
double interAxisDistance=parVect[8]; double interAxisDistance= parVect[8];
double interAxisAngle=parVect[9]; double interAxisAngle= parVect[9];
double horAxisErrPhi=parVect[10]; double horAxisErrPhi= parVect[10];
double horAxisErrPsi=parVect[11]; double horAxisErrPsi= parVect[11];
double entrancePupilForward=parVect[12]; double entrancePupilForward= parVect[12];
double centerAboveHorizontal=parVect[13]; double centerAboveHorizontal= parVect[13];
double GXYZ0=parVect[14]; double GXYZ0= parVect[14];
double GXYZ1=parVect[15]; double GXYZ1= parVect[15];
double GXYZ2=parVect[16]; double GXYZ2= parVect[16];
double neck_right = parVect[17];
double neck_back = parVect[18];
double neck_x = parVect[19];
double neck_z = parVect[20];
double cPS= Math.cos(psi*Math.PI/180); // subCam.psi double cPS= Math.cos(psi*Math.PI/180); // subCam.psi
double sPS= Math.sin(psi*Math.PI/180); // subCam.psi double sPS= Math.sin(psi*Math.PI/180); // subCam.psi
...@@ -1915,7 +1920,13 @@ dPXmmc/dphi= ...@@ -1915,7 +1920,13 @@ dPXmmc/dphi=
double cHAEPH=Math.cos(horAxisErrPhi*Math.PI/180); //eyesisCameraParameters.horAxisErrPhi double cHAEPH=Math.cos(horAxisErrPhi*Math.PI/180); //eyesisCameraParameters.horAxisErrPhi
double sHAEPH=Math.sin(horAxisErrPhi*Math.PI/180); //eyesisCameraParameters.horAxisErrPhi double sHAEPH=Math.sin(horAxisErrPhi*Math.PI/180); //eyesisCameraParameters.horAxisErrPhi
double cHAEPS=Math.cos(horAxisErrPsi*Math.PI/180); //eyesisCameraParameters.horAxisErrPsi double cHAEPS=Math.cos(horAxisErrPsi*Math.PI/180); //eyesisCameraParameters.horAxisErrPsi
double sHAEPS=Math.sin(horAxisErrPsi*Math.PI/180); //eyesisCameraParameters.horAxisErrPsi\ double sHAEPS=Math.sin(horAxisErrPsi*Math.PI/180); //eyesisCameraParameters.horAxisErrPsi
double cNR= Math.cos(neck_right*Math.PI/180);
double sNR= Math.sin(neck_right*Math.PI/180);
double cNB= Math.cos(neck_back*Math.PI/180);
double sNB= Math.sin(neck_back*Math.PI/180);
/* /*
0) Translate by distance to entrance pupil (lens center) 0) Translate by distance to entrance pupil (lens center)
...@@ -1951,19 +1962,42 @@ dPXmmc/dphi= ...@@ -1951,19 +1962,42 @@ dPXmmc/dphi=
*/ */
double [][] aR3={{cAZP,0.0,sAZP},{0.0,1.0,0.0},{-sAZP,0.0,cAZP}}; double [][] aR3={{cAZP,0.0,sAZP},{0.0,1.0,0.0},{-sAZP,0.0,cAZP}};
Matrix R3=new Matrix(aR3); Matrix R3=new Matrix(aR3);
/* /**
4) Now axes are aligned, just translate to get to eyesis coordinates: Vey= T1+Vc3 4) Now axes are aligned, just translate to get to eyesis coordinates: Vey= T1+Vc3
| Xey | | r * sin (azimuth) | |Xc3| | Xey | | r * sin (azimuth) | |Xc3|
| Yey | = | height+centerAboveHorizontal | + |Yc3| | Yey | = | height+centerAboveHorizontal | + |Yc3|
| Zey | | r * cos (azimuth) | |Zc3| | Zey | | r * cos (azimuth) | |Zc3|
adding neck shift:
| Xey | | r * sin (azimuth) + neck_x | |Xc3|
| Yey | = | height+centerAboveHorizontal | + |Yc3|
| Zey | | r * cos (azimuth) + neck_z | |Zc3| // to target
*/ */
double [][] aT1_cyl= {{radius_cyl*sAZ_cyl},{(height+centerAboveHorizontal)},{radius_cyl*cAZ_cyl}}; // {{subCam.radius*sAZ},{subCam.height},{subCam.radius*cAZ}}; double [][] aT1_cyl= {{radius_cyl*sAZ_cyl + neck_x},
double [][] aT1_cart={{right_cart}, {(height+centerAboveHorizontal)},{forward_cart}}; // {{subCam.radius*sAZ},{subCam.height},{subCam.radius*cAZ}}; {(height+centerAboveHorizontal)},
{radius_cyl*cAZ_cyl + neck_z}}; // {{subCam.radius*sAZ},{subCam.height},{subCam.radius*cAZ}};
double [][] aT1_cart={{right_cart + neck_x},
{(height+centerAboveHorizontal)},
{forward_cart + neck_z}}; // {{subCam.radius*sAZ},{subCam.height},{subCam.radius*cAZ}};
double [][] aT1= cartesian ? aT1_cart : aT1_cyl; double [][] aT1= cartesian ? aT1_cart : aT1_cyl;
Matrix T1=new Matrix(aT1); Matrix T1=new Matrix(aT1);
/**
* Rotate camera neck around Z (right tilt)
*/
double [][] aRNR = {{ cNR, sNR, 0.0},
{-sNR, cNR, 0.0},
{ 0.0, 0.0, 1.0}};
Matrix RNR=new Matrix(aRNR);
/** /**
* Rotate camera neck around X (back tilt)
*/
double [][] aRNB = {{ 1.0, 0.0, 0.0},
{ 0.0, cNB, sNB},
{ 0.0,-sNB, cNB}};
Matrix RNB=new Matrix(aRNB);
/*
5) rotate around moving goniometer axis, by (-goniometerAxial) - same as around EY: Vgm1=R4*Vey 5) rotate around moving goniometer axis, by (-goniometerAxial) - same as around EY: Vgm1=R4*Vey
| Xgm1 | | 1 0 0 | |Xey| | Xgm1 | | 1 0 0 | |Xey|
| Ygm1 | = | 0 cos(goniometerAxial) sin(goniometerAxial) | * |Yey| | Ygm1 | = | 0 cos(goniometerAxial) sin(goniometerAxial) | * |Yey|
...@@ -1978,6 +2012,7 @@ dPXmmc/dphi= ...@@ -1978,6 +2012,7 @@ dPXmmc/dphi=
*/ */
double [][] aR4_goniometer={{cGA,0.0,sGA},{0.0,1.0,0.0},{-sGA,0.0,cGA}}; double [][] aR4_goniometer={{cGA,0.0,sGA},{0.0,1.0,0.0},{-sGA,0.0,cGA}};
Matrix R4=new Matrix(isTripod?aR4_tripod:aR4_goniometer); Matrix R4=new Matrix(isTripod?aR4_tripod:aR4_goniometer);
/* /*
6) move to the goniometer horizontal axis:Vgm2=T2+Vgm1 6) move to the goniometer horizontal axis:Vgm2=T2+Vgm1
| Xgm2 | | 0 | |Xgm1| | Xgm2 | | 0 | |Xgm1|
...@@ -1994,7 +2029,7 @@ dPXmmc/dphi= ...@@ -1994,7 +2029,7 @@ dPXmmc/dphi=
*/ */
double [][] aR5={{cGIAA,sGIAA,0.0},{-sGIAA,cGIAA,0.0},{0.0,0.0,1.0}}; double [][] aR5={{cGIAA,sGIAA,0.0},{-sGIAA,cGIAA,0.0},{0.0,0.0,1.0}};
Matrix R5=new Matrix(aR5); Matrix R5=new Matrix(aR5);
/** /*
8) rotate around goniometer horizontal axis (Xgm3) by -goniometerHorizontal: Vgm4=R6*Vgm3 8) rotate around goniometer horizontal axis (Xgm3) by -goniometerHorizontal: Vgm4=R6*Vgm3
| Xgm4 | | cos(goniometerHorizontal) 0 sin(goniometerHorizontal) | |Xgm3| | Xgm4 | | cos(goniometerHorizontal) 0 sin(goniometerHorizontal) | |Xgm3|
| Ygm4 | = | 0 1 0 | * |Ygm3| | Ygm4 | = | 0 1 0 | * |Ygm3|
...@@ -2045,11 +2080,13 @@ dPXmmc/dphi= ...@@ -2045,11 +2080,13 @@ dPXmmc/dphi=
Matrix T3=new Matrix(aT3); Matrix T3=new Matrix(aT3);
// MA=R8*R7*R6*R5*R4*R3*R2*R1; // MA=R8*R7*R6*R5*R4*R3*R2*R1;
// MB=T3+(R8*R7*R6*R5*(T2+R4*T1)); - old
// MB=T3+(R8*R7*R6*R5*(T2+R4*(T1+R3*R2*R1*T0))); // MB=T3+(R8*R7*R6*R5*(T2+R4*(T1+R3*R2*R1*T0)));
Matrix MA=R8.times(R7.times(R6.times(R5.times(R4.times(R3.times(R2.times(R1))))))); // Matrix MA=R8.times(R7.times(R6.times(R5.times(R4.times(R3.times(R2.times(R1))))))); // before neck
// Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1))))))); Matrix MA=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(R1)))))))));
Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1.plus(R3.times(R2.times(R1.times(T0)))) ))))))); // Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1.plus(R3.times(R2.times(R1.times(T0)))) ))))))); // before neck
Matrix T1M=T1.plus(R3.times(R2.times(R1.times(T0))));
Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(RNB.times(RNR.times(T1M)))))))));
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("MA:"); System.out.println("MA:");
MA.print(10, 5); MA.print(10, 5);
...@@ -2059,7 +2096,7 @@ dPXmmc/dphi= ...@@ -2059,7 +2096,7 @@ dPXmmc/dphi=
T3.print(10, 5); T3.print(10, 5);
// System.out.println("interParameterDerivatives[0]="+sprintfArray(interParameterDerivatives[0])); // System.out.println("interParameterDerivatives[0]="+sprintfArray(interParameterDerivatives[0]));
} }
double [] extrinsicParams=parametersFromMAMB(MA,MB); // all after 6 are 0; double [] extrinsicParams=parametersFromMAMB(MA,MB); // [6] all after 6 are 0;
lensDistortionParameters.pixelSize = pixelSize; lensDistortionParameters.pixelSize = pixelSize;
lensDistortionParameters.distortionRadius = distortionRadius; lensDistortionParameters.distortionRadius = distortionRadius;
...@@ -2071,22 +2108,22 @@ dPXmmc/dphi= ...@@ -2071,22 +2108,22 @@ dPXmmc/dphi=
lensDistortionParameters.pitch=extrinsicParams[4]; lensDistortionParameters.pitch=extrinsicParams[4];
lensDistortionParameters.yaw= extrinsicParams[3]; lensDistortionParameters.yaw= extrinsicParams[3];
lensDistortionParameters.roll= extrinsicParams[5]; lensDistortionParameters.roll= extrinsicParams[5];
// offsetting by 4 for neck parameters
lensDistortionParameters.focalLength=parVect[17]; //subCam.focalLength; lensDistortionParameters.focalLength= parVect[21]; //[17]; //subCam.focalLength;
lensDistortionParameters.px0=parVect[18]; //subCam.px0; lensDistortionParameters.px0= parVect[22]; //[18]; //subCam.px0;
lensDistortionParameters.py0=parVect[19]; //subCam.py0; lensDistortionParameters.py0= parVect[23]; //[19]; //subCam.py0;
lensDistortionParameters.distortionA8=parVect[20]; //subCam.distortion5; lensDistortionParameters.distortionA8=parVect[24]; //[20]; //subCam.distortion5;
lensDistortionParameters.distortionA7=parVect[21]; //subCam.distortion5; lensDistortionParameters.distortionA7=parVect[25]; //[21]; //subCam.distortion5;
lensDistortionParameters.distortionA6=parVect[22]; //subCam.distortion5; lensDistortionParameters.distortionA6=parVect[26]; //[22]; //subCam.distortion5;
lensDistortionParameters.distortionA5=parVect[23]; //subCam.distortion5; lensDistortionParameters.distortionA5=parVect[27]; //[23]; //subCam.distortion5;
lensDistortionParameters.distortionA=parVect[24]; //subCam.distortionA; lensDistortionParameters.distortionA= parVect[28]; //[24]; //subCam.distortionA;
lensDistortionParameters.distortionB=parVect[25]; //subCam.distortionB; lensDistortionParameters.distortionB= parVect[29]; //[25]; //subCam.distortionB;
lensDistortionParameters.distortionC=parVect[26]; //subCam.distortionC; lensDistortionParameters.distortionC= parVect[30]; //[26]; //subCam.distortionC;
lensDistortionParameters.r_xy=new double [6][2]; lensDistortionParameters.r_xy=new double [6][2];
lensDistortionParameters.r_od=new double [7][2]; lensDistortionParameters.r_od=new double [7][2];
int index=27; int index= 31; // before neck*: 27; // index in parVect
for (int i=0;i<lensDistortionParameters.r_od.length;i++){ for (int i=0;i<lensDistortionParameters.r_od.length;i++){
if (i>0){ if (i>0){
lensDistortionParameters.r_xy[i-1][0]=parVect[index++]; lensDistortionParameters.r_xy[i-1][0]=parVect[index++];
...@@ -2149,42 +2186,48 @@ dPXmmc/dphi= ...@@ -2149,42 +2186,48 @@ dPXmmc/dphi=
14(12) x public double [] GXYZ=null; // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system 14(12) x public double [] GXYZ=null; // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
15(13) y 15(13) y
16(14) z 16(14) z
17(15) public double focalLength=4.5;
18(16) public double px0=1296.0; // center of the lens on the sensor, pixels 17 double neck_right = parVect[17];
19(17) public double py0=968.0; // center of the lens on the sensor, pixels 18 double neck_back = parVect[18];
20(18) public double distortionA8=0.0; // r^8 (normalized to focal length or to sensor half width?) 19 double neck_x = parVect[19];
21(19) public double distortionA7=0.0; // r^7 (normalized to focal length or to sensor half width?) 20 double neck_z = parVect[20];
22(20) public double distortionA6=0.0; // r^6 (normalized to focal length or to sensor half width?)
23(21) public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?) 21 17(15) public double focalLength=4.5;
24(22) public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?) 22 18(16) public double px0=1296.0; // center of the lens on the sensor, pixels
25(23) public double distortionB=0.0; // r^3 23 19(17) public double py0=968.0; // center of the lens on the sensor, pixels
26(24) public double distortionC=0.0; // r^2 24 20(18) public double distortionA8=0.0; // r^8 (normalized to focal length or to sensor half width?)
27 Distortion center shift X for r^3" 25 21(19) public double distortionA7=0.0; // r^7 (normalized to focal length or to sensor half width?)
28 Distortion center shift Y for r^3" 26 22(20) public double distortionA6=0.0; // r^6 (normalized to focal length or to sensor half width?)
29 Distortion center shift X for r^4" 27 23(21) public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?)
30 Distortion center shift Y for r^4" 28 24(22) public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?)
31 Distortion center shift X for r^5" 29 25(23) public double distortionB=0.0; // r^3
32 Distortion center shift Y for r^5" 30 26(24) public double distortionC=0.0; // r^2
33 Distortion center shift X for r^6" 31 27 Distortion center shift X for r^3"
34 Distortion center shift Y for r^6" 32 28 Distortion center shift Y for r^3"
35 Distortion center shift X for r^7" 33 29 Distortion center shift X for r^4"
36 Distortion center shift Y for r^7" 34 30 Distortion center shift Y for r^4"
37 Distortion center shift X for r^8" 35 31 Distortion center shift X for r^5"
38 Distortion center shift Y for r^8" 36 32 Distortion center shift Y for r^5"
39 Orthogonal elongation for r^2" 37 33 Distortion center shift X for r^6"
40 Diagonal elongation for r^2" 38 34 Distortion center shift Y for r^6"
41 Orthogonal elongation for r^3" 39 35 Distortion center shift X for r^7"
42 Diagonal elongation for r^3" 40 36 Distortion center shift Y for r^7"
43 Orthogonal elongation for r^4" 41 37 Distortion center shift X for r^8"
44 Diagonal elongation for r^4" 42 38 Distortion center shift Y for r^8"
45 Orthogonal elongation for r^5" 43 39 Orthogonal elongation for r^2"
46 Diagonal elongation for r^5" 44 40 Diagonal elongation for r^2"
47 Orthogonal elongation for r^6" 45 41 Orthogonal elongation for r^3"
48 Diagonal elongation for r^6" 46 42 Diagonal elongation for r^3"
49 Orthogonal elongation for r^7" 47 43 Orthogonal elongation for r^4"
50 Diagonal elongation for r^7" 48 44 Diagonal elongation for r^4"
51 Orthogonal elongation for r^8" 49 45 Orthogonal elongation for r^5"
52 Diagonal elongation for r^8" 50 46 Diagonal elongation for r^5"
51 47 Orthogonal elongation for r^6"
52 48 Diagonal elongation for r^6"
53 49 Orthogonal elongation for r^7"
54 50 Diagonal elongation for r^7"
55 51 Orthogonal elongation for r^8"
56 52 Diagonal elongation for r^8"
* Output parameters (rows): * Output parameters (rows):
0 public double x0=0; // lens axis from pattern center, mm (to the right) 0 public double x0=0; // lens axis from pattern center, mm (to the right)
...@@ -2236,12 +2279,19 @@ dPXmmc/dphi= ...@@ -2236,12 +2279,19 @@ dPXmmc/dphi=
//calculate dMA_azimuth //calculate dMA_azimuth
//calculate dMB_azimuth //calculate dMB_azimuth
/* /*
Before neck
// MA=R8*R7*R6*R5*R4*R3*R2*R1; // MA=R8*R7*R6*R5*R4*R3*R2*R1;
// MB=T3+(R8*R7*R6*R5*(T2+R4*T1)); - old // MB=T3+(R8*R7*R6*R5*(T2+R4*T1)); - old
// MB=T3+(R8*R7*R6*R5*(T2+R4*(T1+R3*R2*R1*T0))); // MB=T3+(R8*R7*R6*R5*(T2+R4*(T1+R3*R2*R1*T0)));
Matrix MA=R8.times(R7.times(R6.times(R5.times(R4.times(R3.times(R2.times(R1))))))); Matrix MA=R8.times(R7.times(R6.times(R5.times(R4.times(R3.times(R2.times(R1)))))));
Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1))))))); old Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1))))))); old
Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1.plus(R3.times(R2.times(R1.times(T0)))) ))))))); Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1.plus(R3.times(R2.times(R1.times(T0)))) )))))));
After neck
// MA=R8*R7*R6*R5*R4*RNB*RNR*R3*R2*R1;
// MB=T3+(R8*R7*R6*R5*(T2+R4*RN*(T1+R3*R2*R1*T0)));
Matrix MA=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(R1))))))));
Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(RNB.times(RNR.times(T1.plus(R3.times(R2.times(R1.times(T0)))) )))))))));
3) rotate by -(azimuth+phi) around C2Y:Vc3= R3*Vc2 3) rotate by -(azimuth+phi) around C2Y:Vc3= R3*Vc2
| Xc3 | | cos(azimuth+phi) 0 sin(azimuth+phi) | |Xc2| | Xc3 | | cos(azimuth+phi) 0 sin(azimuth+phi) | |Xc2|
| Yc3 | = | 0 1 0 | * |Yc2| | Yc3 | = | 0 1 0 | * |Yc2|
...@@ -2269,27 +2319,38 @@ dPXmmc/dphi= ...@@ -2269,27 +2319,38 @@ dPXmmc/dphi=
} }
Which parameters affect which matrices Which parameters affect which matrices
R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 || T0 | T1 | T2 | T3 | R1 | R2 | R3 | RNR | RNB | R4 | R5 | R6 | R7 | R8 || T0 | T1 | T2 | T3 |
0 public double azimuth_cyl; // | | + | | | | | || | + | | | 0 public double azimuth_cyl; // | | + | | | | | | | || | + | | |
1 public double radius_cyl; // | | | | | | | || | + | | | 1 public double radius_cyl; // | | | | | | | | | || | + | | |
0 public double right_cart; // | | | | | | | || | + | | | 0 public double right_cart; // | | | | | | | | | || | + | | |
1 public double forward_cart; // | | | | | | | || | + | | | 1 public double forward_cart; // | | | | | | | | | || | + | | |
2 public double height; // | | | | | | | || | + | | | 2 public double height; // | | | | | | | | | || | + | | |
3 public double phi_cyl; // | | + | | | | | || | | | | 3 public double phi_cyl; // | | + | | | | | | | || | | | |
3 public double head_cart; // | | + | | | | | || | | | | 3 public double head_cart; // | | + | | | | | | | || | | | |
4 public double theta; // | + | | | | | | || | | | | 4 public double theta; // | + | | | | | | | | || | | | |
5 public double psi; // + | | | | | | | || | | | | 5 public double psi; // + | | | | | | | | | || | | | |
6 public double goniometerHorizontal; // | | | | | + | | || | | | | 6 public double goniometerHorizontal; // | | | | | | | + | | || | | | |
7 public double goniometerAxial; // | | | + | | | | || | | | | 7 public double goniometerAxial; // | | | | | + | | | | || | | | |
8 public double interAxisDistance; // | | | | | | | || | | + | | 8 public double interAxisDistance; // | | | | | | | | | || | | + | |
9 public double interAxisAngle; // | | | | + | | | || | | | | 9 public double interAxisAngle; // | | | | | | + | | | || | | | |
10 public double horAxisErrPhi; // | | | | | | | + || | | | | 10 public double horAxisErrPhi; // | | | | | | | | | + || | | | |
11 public double horAxisErrPsi; // | | | | | | + | || | | | | 11 public double horAxisErrPsi; // | | | | | | | | + | || | | | |
12 public double entrancePupilForward // | | | | | | | || + | | | | 12 public double entrancePupilForward // | | | | | | | | | || + | | | |
13 public double centerAboveHorizontal // | | | | | | | || | + | | | 13 public double centerAboveHorizontal // | | | | | | | | | || | + | | |
14 x public double [] GXYZ=null; // | | | | | | | || | | | + | 14 x public double [] GXYZ=null; // | | | | | | | | | || | | | + |
15 y // | | | | | | | || | | | + | 15 y // | | | | | | | | | || | | | + |
16 z // | | | | | | | || | | | + | 16 z // | | | | | | | | | || | | | + |
17 neckRight // | | | + | | | | | | || | | | |
18 neckBack // | | | | + | | | | | || | | | |
19 neckXZ[0] (X) +common right // | | | | | | | | | || | + | | |
20 neckXZ[1] (Z) -common forward // | | | | | | | | | || | + | | |
// MA=R8*R7*R6*R5*R4*RNB*RNR*R3*R2*R1;
// MB=T3+(R8*R7*R6*R5*(T2+R4*RN*(T1+R3*R2*R1*T0)));
Matrix MA=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(R1))))))));
Matrix MB=T3.plus(R8.times(R7.times(R6.times(R5.times(T2.plus(R4.times(RNB.times(RNR.times(T1.plus(R3.times(R2.times(R1.times(T0)))) )))))))));
*/ */
// Below can be optimized with common intermediate results // Below can be optimized with common intermediate results
...@@ -2304,7 +2365,7 @@ dPXmmc/dphi= ...@@ -2304,7 +2365,7 @@ dPXmmc/dphi=
double [][] adT1_right_cart={{1.0},{0.0},{0.0}}; double [][] adT1_right_cart={{1.0},{0.0},{0.0}};
Matrix dT1_right_cart=new Matrix(adT1_right_cart); Matrix dT1_right_cart=new Matrix(adT1_right_cart);
Matrix dMA_right_cart=new Matrix(3,3,0.0); // zero Matrix dMA_right_cart=new Matrix(3,3,0.0); // zero
Matrix dMB_right_cart=R8.times(R7.times(R6.times(R5.times(R4.times(dT1_right_cart))))); Matrix dMB_right_cart=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_right_cart)))))));
interParameterDerivatives[0]=d_parametersFromMAMB(dMA_right_cart,dMB_right_cart,MA,MB,false); interParameterDerivatives[0]=d_parametersFromMAMB(dMA_right_cart,dMB_right_cart,MA,MB,false);
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_right_cart:"); System.out.println("dMA_right_cart:");
...@@ -2320,8 +2381,8 @@ dPXmmc/dphi= ...@@ -2320,8 +2381,8 @@ dPXmmc/dphi=
double [][] adT1_azimuth_cyl={{radius_cyl*cAZ_cyl},{0.0},{-radius_cyl*sAZ_cyl}}; //{{subCam.radius*cAZ},{subCam.height},{-subCam.radius*sAZ}} double [][] adT1_azimuth_cyl={{radius_cyl*cAZ_cyl},{0.0},{-radius_cyl*sAZ_cyl}}; //{{subCam.radius*cAZ},{subCam.height},{-subCam.radius*sAZ}}
Matrix dT1_azimuth_cyl=new Matrix(adT1_azimuth_cyl); Matrix dT1_azimuth_cyl=new Matrix(adT1_azimuth_cyl);
Matrix dMA_azimuth_cyl=R8.times(R7.times(R6.times(R5.times(R4.times(dR3_azimuth_cyl.times(R2.times(R1))))))); Matrix dMA_azimuth_cyl=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dR3_azimuth_cyl.times(R2.times(R1)))))))));
Matrix dMB0_azimuth_cyl=R8.times(R7.times(R6.times(R5.times(R4.times(dT1_azimuth_cyl))))); Matrix dMB0_azimuth_cyl=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_azimuth_cyl)))))));
Matrix dMB_azimuth_cyl=dMB0_azimuth_cyl.plus(dMA_azimuth_cyl.times(T0)); // new term Matrix dMB_azimuth_cyl=dMB0_azimuth_cyl.plus(dMA_azimuth_cyl.times(T0)); // new term
interParameterDerivatives[0]=d_parametersFromMAMB(dMA_azimuth_cyl,dMB_azimuth_cyl,MA,MB,true); // all after 6 are 0; interParameterDerivatives[0]=d_parametersFromMAMB(dMA_azimuth_cyl,dMB_azimuth_cyl,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
...@@ -2339,7 +2400,7 @@ dPXmmc/dphi= ...@@ -2339,7 +2400,7 @@ dPXmmc/dphi=
double [][] adT1_forward_cart={{0.0},{0.0},{1.0}}; //{{subCam.radius*sAZ},{0.0},{subCam.radius*cAZ}} double [][] adT1_forward_cart={{0.0},{0.0},{1.0}}; //{{subCam.radius*sAZ},{0.0},{subCam.radius*cAZ}}
Matrix dT1_forward_cart=new Matrix(adT1_forward_cart); Matrix dT1_forward_cart=new Matrix(adT1_forward_cart);
Matrix dMA_forward_cart=new Matrix(3,3,0.0); Matrix dMA_forward_cart=new Matrix(3,3,0.0);
Matrix dMB_forward_cart=R8.times(R7.times(R6.times(R5.times(R4.times(dT1_forward_cart))))); Matrix dMB_forward_cart=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_forward_cart)))))));
interParameterDerivatives[1]=d_parametersFromMAMB(dMA_forward_cart,dMB_forward_cart,MA,MB,false); // all after 6 are 0; interParameterDerivatives[1]=d_parametersFromMAMB(dMA_forward_cart,dMB_forward_cart,MA,MB,false); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_forward_cart:"); System.out.println("dMA_forward_cart:");
...@@ -2352,7 +2413,7 @@ dPXmmc/dphi= ...@@ -2352,7 +2413,7 @@ dPXmmc/dphi=
double [][] adT1_radius_cyl={{sAZ_cyl},{0.0},{cAZ_cyl}}; //{{subCam.radius*sAZ},{0.0},{subCam.radius*cAZ}} double [][] adT1_radius_cyl={{sAZ_cyl},{0.0},{cAZ_cyl}}; //{{subCam.radius*sAZ},{0.0},{subCam.radius*cAZ}}
Matrix dT1_radius_cyl=new Matrix(adT1_radius_cyl); Matrix dT1_radius_cyl=new Matrix(adT1_radius_cyl);
Matrix dMA_radius_cyl=new Matrix(3,3,0.0); Matrix dMA_radius_cyl=new Matrix(3,3,0.0);
Matrix dMB_radius_cyl=R8.times(R7.times(R6.times(R5.times(R4.times(dT1_radius_cyl))))); Matrix dMB_radius_cyl=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_radius_cyl)))))));
interParameterDerivatives[1]=d_parametersFromMAMB(dMA_radius_cyl,dMB_radius_cyl,MA,MB,false); // all after 6 are 0; interParameterDerivatives[1]=d_parametersFromMAMB(dMA_radius_cyl,dMB_radius_cyl,MA,MB,false); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_radius_cyl:"); System.out.println("dMA_radius_cyl:");
...@@ -2368,7 +2429,7 @@ dPXmmc/dphi= ...@@ -2368,7 +2429,7 @@ dPXmmc/dphi=
double [][] adT1_height={{0.0},{1.0},{0.0}}; double [][] adT1_height={{0.0},{1.0},{0.0}};
Matrix dT1_height=new Matrix(adT1_height); Matrix dT1_height=new Matrix(adT1_height);
Matrix dMA_height=new Matrix(3,3,0.0); Matrix dMA_height=new Matrix(3,3,0.0);
Matrix dMB_height=R8.times(R7.times(R6.times(R5.times(R4.times(dT1_height))))); Matrix dMB_height=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_height)))))));
interParameterDerivatives[2]=d_parametersFromMAMB(dMA_height,dMB_height,MA,MB,false); // all after 6 are 0; interParameterDerivatives[2]=d_parametersFromMAMB(dMA_height,dMB_height,MA,MB,false); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_height:"); System.out.println("dMA_height:");
...@@ -2382,8 +2443,7 @@ dPXmmc/dphi= ...@@ -2382,8 +2443,7 @@ dPXmmc/dphi=
if (mask[3]) { // here the same for cartesian if (mask[3]) { // here the same for cartesian
double [][] adR3_phi={{-sAZP,0.0,cAZP},{0.0,0.0,0.0},{-cAZP,0.0,-sAZP}}; // same as adR3_azimuth double [][] adR3_phi={{-sAZP,0.0,cAZP},{0.0,0.0,0.0},{-cAZP,0.0,-sAZP}}; // same as adR3_azimuth
Matrix dR3_phi=new Matrix(adR3_phi); // same as dR3_azimuth Matrix dR3_phi=new Matrix(adR3_phi); // same as dR3_azimuth
Matrix dMA_phi=R8.times(R7.times(R6.times(R5.times(R4.times(dR3_phi.times(R2.times(R1))))))); //same as dMA_azimuth Matrix dMA_phi=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dR3_phi.times(R2.times(R1))))))))); //same as dMA_azimuth
// Matrix dMB_phi=new Matrix(3,1,0.0);
Matrix dMB_phi=dMA_phi.times(T0); // new term Matrix dMB_phi=dMA_phi.times(T0); // new term
interParameterDerivatives[3]=d_parametersFromMAMB(dMA_phi,dMB_phi,MA,MB,true); // all after 6 are 0; interParameterDerivatives[3]=d_parametersFromMAMB(dMA_phi,dMB_phi,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
...@@ -2398,8 +2458,7 @@ dPXmmc/dphi= ...@@ -2398,8 +2458,7 @@ dPXmmc/dphi=
if (mask[4]) { if (mask[4]) {
double [][] adR2_theta={{0.0,0.0,0.0},{0.0,-sTH,cTH},{0.0,-cTH,-sTH}}; double [][] adR2_theta={{0.0,0.0,0.0},{0.0,-sTH,cTH},{0.0,-cTH,-sTH}};
Matrix dR2_theta=new Matrix(adR2_theta); Matrix dR2_theta=new Matrix(adR2_theta);
Matrix dMA_theta=R8.times(R7.times(R6.times(R5.times(R4.times(R3.times(dR2_theta.times(R1))))))); Matrix dMA_theta=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(dR2_theta.times(R1)))))))));
// Matrix dMB_theta=new Matrix(3,1,0.0);
Matrix dMB_theta=dMA_theta.times(T0); // new term Matrix dMB_theta=dMA_theta.times(T0); // new term
interParameterDerivatives[4]=d_parametersFromMAMB(dMA_theta,dMB_theta,MA,MB,true); // all after 6 are 0; interParameterDerivatives[4]=d_parametersFromMAMB(dMA_theta,dMB_theta,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
...@@ -2414,8 +2473,7 @@ dPXmmc/dphi= ...@@ -2414,8 +2473,7 @@ dPXmmc/dphi=
if (mask[5]) { if (mask[5]) {
double [][] adR1_psi={{-sPS,cPS,0.0},{-cPS,-sPS,0.0},{0.0,0.0,0.0}}; double [][] adR1_psi={{-sPS,cPS,0.0},{-cPS,-sPS,0.0},{0.0,0.0,0.0}};
Matrix dR1_psi=new Matrix(adR1_psi); Matrix dR1_psi=new Matrix(adR1_psi);
Matrix dMA_psi=R8.times(R7.times(R6.times(R5.times(R4.times(R3.times(R2.times(dR1_psi))))))); Matrix dMA_psi=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(dR1_psi)))))))));
// Matrix dMB_psi=new Matrix(3,1,0.0);
Matrix dMB_psi=dMA_psi.times(T0); // new term Matrix dMB_psi=dMA_psi.times(T0); // new term
interParameterDerivatives[5]=d_parametersFromMAMB(dMA_psi,dMB_psi,MA,MB,true); // all after 6 are 0; interParameterDerivatives[5]=d_parametersFromMAMB(dMA_psi,dMB_psi,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
...@@ -2441,8 +2499,9 @@ dPXmmc/dphi= ...@@ -2441,8 +2499,9 @@ dPXmmc/dphi=
double [][] adR6_goniometerHorizontal_tripod= {{-sGH,0.0,cGH},{0.0, 0.0,0.0},{-cGH, 0.0,-sGH}}; double [][] adR6_goniometerHorizontal_tripod= {{-sGH,0.0,cGH},{0.0, 0.0,0.0},{-cGH, 0.0,-sGH}};
double [][] adR6_goniometerHorizontal_goniometer={{ 0.0,0.0,0.0},{0.0,-sGH,cGH},{ 0.0,-cGH,-sGH}}; double [][] adR6_goniometerHorizontal_goniometer={{ 0.0,0.0,0.0},{0.0,-sGH,cGH},{ 0.0,-cGH,-sGH}};
Matrix dR6_goniometerHorizontal=new Matrix(isTripod?adR6_goniometerHorizontal_tripod:adR6_goniometerHorizontal_goniometer); Matrix dR6_goniometerHorizontal=new Matrix(isTripod?adR6_goniometerHorizontal_tripod:adR6_goniometerHorizontal_goniometer);
Matrix dMA_goniometerHorizontal=R8.times(R7.times(dR6_goniometerHorizontal.times(R5.times(R4.times(R3.times(R2.times(R1))))))); Matrix dMA_goniometerHorizontal=R8.times(R7.times(dR6_goniometerHorizontal.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(R1)))))))));
Matrix dMB_goniometerHorizontal=R8.times(R7.times(dR6_goniometerHorizontal.times(R5.times(T2.plus(R4.times(T1)))))); // Matrix dMB_goniometerHorizontal=R8.times(R7.times(dR6_goniometerHorizontal.times(R5.times(T2.plus(R4.times(T1)))))); // Bug noticed 05/31/2021, using T1M
Matrix dMB_goniometerHorizontal=R8.times(R7.times(dR6_goniometerHorizontal.times(R5.times(T2.plus(R4.times(RNB.times(RNR.times(T1M))))))));
interParameterDerivatives[6]=d_parametersFromMAMB(dMA_goniometerHorizontal,dMB_goniometerHorizontal,MA,MB,true); // all after 6 are 0; interParameterDerivatives[6]=d_parametersFromMAMB(dMA_goniometerHorizontal,dMB_goniometerHorizontal,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_goniometerHorizontal:"); System.out.println("dMA_goniometerHorizontal:");
...@@ -2458,8 +2517,10 @@ dPXmmc/dphi= ...@@ -2458,8 +2517,10 @@ dPXmmc/dphi=
double [][] adR4_goniometerAxial_tripod= {{ 0.0,0.0,0.0},{0.0,-sGA,cGA},{ 0.0,-cGA,-sGA}}; double [][] adR4_goniometerAxial_tripod= {{ 0.0,0.0,0.0},{0.0,-sGA,cGA},{ 0.0,-cGA,-sGA}};
double [][] adR4_goniometerAxial_goniometer={{-sGA,0.0,cGA},{0.0, 0.0,0.0},{-cGA, 0.0,-sGA}}; double [][] adR4_goniometerAxial_goniometer={{-sGA,0.0,cGA},{0.0, 0.0,0.0},{-cGA, 0.0,-sGA}};
Matrix dR4_goniometerAxial=new Matrix(isTripod?adR4_goniometerAxial_tripod:adR4_goniometerAxial_goniometer); Matrix dR4_goniometerAxial=new Matrix(isTripod?adR4_goniometerAxial_tripod:adR4_goniometerAxial_goniometer);
Matrix dMA_goniometerAxial=R8.times(R7.times(R6.times(R5.times(dR4_goniometerAxial.times(R3.times(R2.times(R1))))))); Matrix dMA_goniometerAxial=R8.times(R7.times(R6.times(R5.times(dR4_goniometerAxial.times(RNB.times(RNR.times(R3.times(R2.times(R1)))))))));
Matrix dMB_goniometerAxial=R8.times(R7.times(R6.times(R5.times(dR4_goniometerAxial.times(T1))))); // Matrix dMB_goniometerAxial=R8.times(R7.times(R6.times(R5.times(dR4_goniometerAxial.times(T1 ))))); // Bug noticed 05/31/2021
Matrix dMB_goniometerAxial=R8.times(R7.times(R6.times(R5.times(dR4_goniometerAxial.times(RNB.times(RNR.times(T1M)))))));
interParameterDerivatives[7]=d_parametersFromMAMB(dMA_goniometerAxial,dMB_goniometerAxial,MA,MB,true); // all after 6 are 0; interParameterDerivatives[7]=d_parametersFromMAMB(dMA_goniometerAxial,dMB_goniometerAxial,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_goniometerAxial:"); System.out.println("dMA_goniometerAxial:");
...@@ -2488,8 +2549,8 @@ dPXmmc/dphi= ...@@ -2488,8 +2549,8 @@ dPXmmc/dphi=
if (mask[9]) { if (mask[9]) {
double [][] adR5_interAxisAngle={{-sGIAA,cGIAA,0.0},{-cGIAA,-sGIAA,0.0},{0.0,0.0,0.0}}; double [][] adR5_interAxisAngle={{-sGIAA,cGIAA,0.0},{-cGIAA,-sGIAA,0.0},{0.0,0.0,0.0}};
Matrix dR5_interAxisAngle=new Matrix(adR5_interAxisAngle); Matrix dR5_interAxisAngle=new Matrix(adR5_interAxisAngle);
Matrix dMA_interAxisAngle=R8.times(R7.times(R6.times(dR5_interAxisAngle.times(R4.times(R3.times(R2.times(R1))))))); Matrix dMA_interAxisAngle=R8.times(R7.times(R6.times(dR5_interAxisAngle.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(R1)))))))));
Matrix dMB_interAxisAngle=R8.times(R7.times(R6.times(dR5_interAxisAngle.times(T2.plus(R4.times(T1)))))); Matrix dMB_interAxisAngle=R8.times(R7.times(R6.times(dR5_interAxisAngle.times(T2.plus(R4.times(RNB.times(RNR.times(T1M))))))));
interParameterDerivatives[9]=d_parametersFromMAMB(dMA_interAxisAngle,dMB_interAxisAngle,MA,MB,true); // all after 6 are 0; interParameterDerivatives[9]=d_parametersFromMAMB(dMA_interAxisAngle,dMB_interAxisAngle,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_interAxisAngle:"); System.out.println("dMA_interAxisAngle:");
...@@ -2506,8 +2567,8 @@ dPXmmc/dphi= ...@@ -2506,8 +2567,8 @@ dPXmmc/dphi=
double [][] adR8_horAxisErrPhi_tripod= {{0.0, 0.0, 0.0},{0.0,-sHAEPH,cHAEPH},{ 0.0,-cHAEPH,-sHAEPH}}; double [][] adR8_horAxisErrPhi_tripod= {{0.0, 0.0, 0.0},{0.0,-sHAEPH,cHAEPH},{ 0.0,-cHAEPH,-sHAEPH}};
double [][] adR8_horAxisErrPhi_goniometer={{-sHAEPH,0.0,cHAEPH},{0.0, 0.0, 0.0},{-cHAEPH, 0.0,-sHAEPH}}; double [][] adR8_horAxisErrPhi_goniometer={{-sHAEPH,0.0,cHAEPH},{0.0, 0.0, 0.0},{-cHAEPH, 0.0,-sHAEPH}};
Matrix dR8_horAxisErrPhi=new Matrix(isTripod?adR8_horAxisErrPhi_tripod:adR8_horAxisErrPhi_goniometer); Matrix dR8_horAxisErrPhi=new Matrix(isTripod?adR8_horAxisErrPhi_tripod:adR8_horAxisErrPhi_goniometer);
Matrix dMA_horAxisErrPhi=dR8_horAxisErrPhi.times(R7.times(R6.times(R5.times(R4.times(R3.times(R2.times(R1))))))); Matrix dMA_horAxisErrPhi=dR8_horAxisErrPhi.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(R1)))))))));
Matrix dMB_horAxisErrPhi=dR8_horAxisErrPhi.times(R7.times(R6.times(R5.times(T2.plus(R4.times(T1)))))); Matrix dMB_horAxisErrPhi=dR8_horAxisErrPhi.times(R7.times(R6.times(R5.times(T2.plus(R4.times(RNB.times(RNR.times(T1M))))))));
interParameterDerivatives[10]=d_parametersFromMAMB(dMA_horAxisErrPhi,dMB_horAxisErrPhi,MA,MB,true); // all after 6 are 0; interParameterDerivatives[10]=d_parametersFromMAMB(dMA_horAxisErrPhi,dMB_horAxisErrPhi,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_horAxisErrPhi:"); System.out.println("dMA_horAxisErrPhi:");
...@@ -2521,8 +2582,8 @@ dPXmmc/dphi= ...@@ -2521,8 +2582,8 @@ dPXmmc/dphi=
if (mask[11]) { if (mask[11]) {
double [][] adR7_horAxisErrPsi={{-sHAEPS,cHAEPS,0.0},{-cHAEPS,-sHAEPS,0.0},{0.0,0.0,0.0}}; double [][] adR7_horAxisErrPsi={{-sHAEPS,cHAEPS,0.0},{-cHAEPS,-sHAEPS,0.0},{0.0,0.0,0.0}};
Matrix dR7_horAxisErrPsi=new Matrix(adR7_horAxisErrPsi); Matrix dR7_horAxisErrPsi=new Matrix(adR7_horAxisErrPsi);
Matrix dMA_horAxisErrPsi=R8.times(dR7_horAxisErrPsi.times(R6.times(R5.times(R4.times(R3.times(R2.times(R1))))))); Matrix dMA_horAxisErrPsi=R8.times(dR7_horAxisErrPsi.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(R3.times(R2.times(R1)))))))));
Matrix dMB_horAxisErrPsi=R8.times(dR7_horAxisErrPsi.times(R6.times(R5.times(T2.plus(R4.times(T1)))))); Matrix dMB_horAxisErrPsi=R8.times(dR7_horAxisErrPsi.times(R6.times(R5.times(T2.plus(R4.times(RNB.times(RNR.times(T1M))))))));
interParameterDerivatives[11]=d_parametersFromMAMB(dMA_horAxisErrPsi,dMB_horAxisErrPsi,MA,MB,true); // all after 6 are 0; interParameterDerivatives[11]=d_parametersFromMAMB(dMA_horAxisErrPsi,dMB_horAxisErrPsi,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_horAxisErrPsi:"); System.out.println("dMA_horAxisErrPsi:");
...@@ -2532,9 +2593,9 @@ dPXmmc/dphi= ...@@ -2532,9 +2593,9 @@ dPXmmc/dphi=
System.out.println("interParameterDerivatives[11]="+sprintfArray(interParameterDerivatives[11])); System.out.println("interParameterDerivatives[11]="+sprintfArray(interParameterDerivatives[11]));
} }
} else interParameterDerivatives[11]=null; } else interParameterDerivatives[11]=null;
// // R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 || T0 | T1 | T2 | T3 | // R1 | R2 | R3 | RNR | RNB | R4 | R5 | R6 | R7 | R8 || T0 | T1 | T2 | T3 |
//12 public double entrancePupilForward // | | | | | | | || + | | | | // 12 public double entrancePupilForward // | | | | | | | | | || + | | | |
//13 public double centerAboveHorizontal // | | | | | | | || | + | | | // 13 public double centerAboveHorizontal // | | | | | | | | | || | + | | |
if (mask[12]) { if (mask[12]) {
double [][] adT0_entrancePupilForward={{0.0},{0.0},{1.0}}; double [][] adT0_entrancePupilForward={{0.0},{0.0},{1.0}};
...@@ -2555,7 +2616,7 @@ dPXmmc/dphi= ...@@ -2555,7 +2616,7 @@ dPXmmc/dphi=
double [][] adT1_centerAboveHorizontal={{0.0},{1.0},{0.0}}; double [][] adT1_centerAboveHorizontal={{0.0},{1.0},{0.0}};
Matrix dT1_centerAboveHorizontal=new Matrix(adT1_centerAboveHorizontal); Matrix dT1_centerAboveHorizontal=new Matrix(adT1_centerAboveHorizontal);
Matrix dMA_centerAboveHorizontal=new Matrix(3,3,0.0); Matrix dMA_centerAboveHorizontal=new Matrix(3,3,0.0);
Matrix dMB_centerAboveHorizontal=R8.times(R7.times(R6.times(R5.times(R4.times(dT1_centerAboveHorizontal))))); Matrix dMB_centerAboveHorizontal=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_centerAboveHorizontal)))))));
interParameterDerivatives[13]=d_parametersFromMAMB(dMA_centerAboveHorizontal,dMB_centerAboveHorizontal,MA,MB,false); // all after 6 are 0; interParameterDerivatives[13]=d_parametersFromMAMB(dMA_centerAboveHorizontal,dMB_centerAboveHorizontal,MA,MB,false); // all after 6 are 0;
if (this.debugLevel>2) { if (this.debugLevel>2) {
System.out.println("dMA_centerAboveHorizontal:"); System.out.println("dMA_centerAboveHorizontal:");
...@@ -2581,7 +2642,7 @@ dPXmmc/dphi= ...@@ -2581,7 +2642,7 @@ dPXmmc/dphi=
System.out.println("interParameterDerivatives[14]="+sprintfArray(interParameterDerivatives[14])); System.out.println("interParameterDerivatives[14]="+sprintfArray(interParameterDerivatives[14]));
} }
} else interParameterDerivatives[14]=null; } else interParameterDerivatives[14]=null;
//13 y //15 y
if (mask[15]) { if (mask[15]) {
// double [][] adT3_GXYZ1={{0.0},{1.0},{0.0}}; // double [][] adT3_GXYZ1={{0.0},{1.0},{0.0}};
double [][] adT3_GXYZ1={{0.0},{-1.0},{0.0}}; // up - positive double [][] adT3_GXYZ1={{0.0},{-1.0},{0.0}}; // up - positive
...@@ -2597,7 +2658,7 @@ dPXmmc/dphi= ...@@ -2597,7 +2658,7 @@ dPXmmc/dphi=
System.out.println("interParameterDerivatives[15]="+sprintfArray(interParameterDerivatives[15])); System.out.println("interParameterDerivatives[15]="+sprintfArray(interParameterDerivatives[15]));
} }
} else interParameterDerivatives[15]=null; } else interParameterDerivatives[15]=null;
//14 z //16 z
if (mask[16]) { if (mask[16]) {
// double [][] adT3_GXYZ2={{0.0},{0.0},{1.0}}; // double [][] adT3_GXYZ2={{0.0},{0.0},{1.0}};
double [][] adT3_GXYZ2={{0.0},{0.0},{-1.0}}; // away - positive double [][] adT3_GXYZ2={{0.0},{0.0},{-1.0}}; // away - positive
...@@ -2612,26 +2673,96 @@ dPXmmc/dphi= ...@@ -2612,26 +2673,96 @@ dPXmmc/dphi=
System.out.println("interParameterDerivatives[16]="+sprintfArray(interParameterDerivatives[16])); System.out.println("interParameterDerivatives[16]="+sprintfArray(interParameterDerivatives[16]));
} }
} else interParameterDerivatives[16]=null; } else interParameterDerivatives[16]=null;
// 17 neckRight
if (mask[17]) {
double [][] adRNR_neckRight={
{-sNR, cNR, 0.0},
{-cNR,-sNR, 0.0},
{ 0.0, 0.0, 0.0}};
Matrix dRNR_neckRight=new Matrix(adRNR_neckRight);
Matrix dMA_neckRight=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(dRNR_neckRight.times(R3.times(R2.times(R1)))))))));
Matrix dMB_neckRight=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(dRNR_neckRight.times(T1M)))))));
interParameterDerivatives[17]=d_parametersFromMAMB(dMA_neckRight,dMB_neckRight,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) {
System.out.println("dMA_neckRight:");
dMA_neckRight.print(10, 5);
System.out.println("dMB_neckRight:");
dMB_neckRight.print(10, 5);
System.out.println("interParameterDerivatives[17]="+sprintfArray(interParameterDerivatives[17]));
}
} else interParameterDerivatives[17]=null;
// 18 neckBack
if (mask[18]) {
double [][] adRNB_neckBack={
{ 0.0, 0.0, 0.0},
{ 0.0,-sNB, cNB},
{ 0.0,-cNB,-sNB}};
Matrix dRNB_neckBack=new Matrix(adRNB_neckBack);
Matrix dMA_neckBack=R8.times(R7.times(R6.times(R5.times(R4.times(dRNB_neckBack.times(RNR.times(R3.times(R2.times(R1)))))))));
Matrix dMB_neckBack=R8.times(R7.times(R6.times(R5.times(R4.times(dRNB_neckBack.times(RNR.times(T1M)))))));
interParameterDerivatives[18]=d_parametersFromMAMB(dMA_neckBack,dMB_neckBack,MA,MB,true); // all after 6 are 0;
if (this.debugLevel>2) {
System.out.println("dMA_neckBack:");
dMA_neckBack.print(10, 5);
System.out.println("dMB_neckBack:");
dMB_neckBack.print(10, 5);
System.out.println("interParameterDerivatives[18]="+sprintfArray(interParameterDerivatives[18]));
}
} else interParameterDerivatives[18]=null;
// 19 neckX
if (mask[19]) {
double [][] adT1_neckX={{1.0},{0.0},{0.0}};
Matrix dT1_neckX=new Matrix(adT1_neckX);
Matrix dMA_neckX=new Matrix(3,3,0.0);
Matrix dMB_neckX=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_neckX)))))));
interParameterDerivatives[19]=d_parametersFromMAMB(dMA_neckX,dMB_neckX,MA,MB,false); // all after 6 are 0;
if (this.debugLevel>2) {
System.out.println("dMA_neckX:");
dMA_neckX.print(10, 5);
System.out.println("dMB_neckX:");
dMB_neckX.print(10, 5);
System.out.println("interParameterDerivatives[19]="+sprintfArray(interParameterDerivatives[19]));
}
} else interParameterDerivatives[19]=null;
// 20 neckZ
if (mask[20]) {
double [][] adT1_neckZ={{0.0},{0.0},{1.0}};
Matrix dT1_neckZ=new Matrix(adT1_neckZ);
Matrix dMA_neckZ=new Matrix(3,3,0.0);
Matrix dMB_neckZ=R8.times(R7.times(R6.times(R5.times(R4.times(RNB.times(RNR.times(dT1_neckZ)))))));
interParameterDerivatives[20]=d_parametersFromMAMB(dMA_neckZ,dMB_neckZ,MA,MB,false); // all after 6 are 0;
if (this.debugLevel>2) {
System.out.println("dMA_neckZ:");
dMA_neckZ.print(10, 5);
System.out.println("dMB_neckZ:");
dMB_neckZ.print(10, 5);
System.out.println("interParameterDerivatives[20]="+sprintfArray(interParameterDerivatives[20]));
}
} else interParameterDerivatives[20]=null;
// now fill the rest, unchanged parameters // now fill the rest, unchanged parameters
/* /*
int numInputs=22; //was 21 parameters in subcamera+... int numInputs=22; //was 21 parameters in subcamera+...
int numOutputs=13; //was 12 parameters in a single camera int numOutputs=13; //was 12 parameters in a single camera
*/ */
//17 (15) public double focalLength=4.5; // 21 17 (15) public double focalLength=4.5;
//18 (16) public double px0=1296.0; // center of the lens on the sensor, pixels // 22 18 (16) public double px0=1296.0; // center of the lens on the sensor, pixels
//19 (17) public double py0=968.0; // center of the lens on the sensor, pixels // 23 19 (17) public double py0=968.0; // center of the lens on the sensor, pixels
//20 (18) public double distortionA8=0.0; // r^8 (normalized to focal length or to sensor half width?) // 24 20 (18) public double distortionA8=0.0; // r^8 (normalized to focal length or to sensor half width?)
//21 (19) public double distortionA7=0.0; // r^7 (normalized to focal length or to sensor half width?) // 25 21 (19) public double distortionA7=0.0; // r^7 (normalized to focal length or to sensor half width?)
//22 (20) public double distortionA6=0.0; // r^6 (normalized to focal length or to sensor half width?) // 26 22 (20) public double distortionA6=0.0; // r^6 (normalized to focal length or to sensor half width?)
//23 (21) public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?) // 27 23 (21) public double distortionA5=0.0; // r^5 (normalized to focal length or to sensor half width?)
//24 (22) public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?) // 28 24 (22) public double distortionA=0.0; // r^4 (normalized to focal length or to sensor half width?)
//25 (23) public double distortionB=0.0; // r^3 // 29 25 (23) public double distortionB=0.0; // r^3
//26 (24) public double distortionC=0.0; // r^2 // 30 26 (24) public double distortionC=0.0; // r^2
//27..52 - non-radial parameters // 31..56 27..52 - non-radial parameters
// for (int inpPar=15; inpPar<getNumInputs(); inpPar++){ // for (int inpPar=15; inpPar<getNumInputs(); inpPar++){
for (int inpPar=17; inpPar<getNumInputs(); inpPar++){ // OK with A8. Should be OK with non-radial parameters ((27..52) also // for (int inpPar=17; inpPar<getNumInputs(); inpPar++){ // OK with A8. Should be OK with non-radial parameters ((27..52) also
for (int inpPar=21; inpPar<getNumInputs(); inpPar++){ // added neck parameters, offset by 4
if (mask[inpPar]){ if (mask[inpPar]){
interParameterDerivatives[inpPar]=new double[getNumOutputs()]; interParameterDerivatives[inpPar]=new double[getNumOutputs()];
for (int outPar=0; outPar<getNumOutputs(); outPar++){ for (int outPar=0; outPar<getNumOutputs(); outPar++){
......
...@@ -483,12 +483,19 @@ import ij.io.Opener; ...@@ -483,12 +483,19 @@ import ij.io.Opener;
index++; index++;
} }
for (int n=0;n<getNumGeometricChannels();n++) titles[n]=geometricTitles[n]; for (int n=0;n<getNumGeometricChannels();n++) titles[n]=geometricTitles[n];
for (int numStation=0;numStation<this.numStations;numStation++) { for (int numStation = 0; numStation < this.numStations; numStation++) {
int numStationSrc = numStation;
if (numStationSrc >= this.photometricByView.length) {
System.out.println("Station"+numStationSrc+" >= this.photometricByView.length, saving from the last known station");
numStationSrc = this.photometricByView.length-1;
}
for (int nView=0;nView<getNumViews();nView++) { for (int nView=0;nView<getNumViews();nView++) {
for (int chn=0;chn<getNumPhotometricChannels();chn++){ for (int chn=0;chn<getNumPhotometricChannels();chn++){
// int pixIndex=getNumGeometricChannels()+chn*this.getNumPhotometricChannels()(); // int pixIndex=getNumGeometricChannels()+chn*this.getNumPhotometricChannels()();
int pixIndex=getNumGeometricChannels()+numZCorr+(nView + numStation*getNumViews()) *getNumPhotometricChannels()+chn; int pixIndex=getNumGeometricChannels()+numZCorr+(nView + numStation*getNumViews()) *getNumPhotometricChannels()+chn;
for (int i=0;i<length;i++) pixels[pixIndex][i]= (float) this.photometricByView[numStation][nView][chn][i]; //OOB 8 //oob 12 for (int i=0;i<length;i++) {
pixels[pixIndex][i]= (float) this.photometricByView[numStationSrc][nView][chn][i]; //OOB 8 //oob 12
}
titles[pixIndex]=photometricTitles[chn]+nView; titles[pixIndex]=photometricTitles[chn]+nView;
} }
} }
......
...@@ -60,7 +60,11 @@ import ij.gui.GenericDialog; ...@@ -60,7 +60,11 @@ import ij.gui.GenericDialog;
public double [] horAxisErrPsi; // angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up) public double [] horAxisErrPsi; // angle in degrees "horizontal" goniometer axis is rotated around moving X axis (up)
public double [] entrancePupilForward; // common to all lenses - distance from the sensor to the lens entrance pupil public double [] entrancePupilForward; // common to all lenses - distance from the sensor to the lens entrance pupil
public double [] centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each SFE) public double [] centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each SFE)
public double [][] GXYZ=null; // [numStations]{x,y,z} coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system public double [][] GXYZ=null; // [numStations]{x,y,z} coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
public double [] neckRight; // angle in degrees of the camera as a whole rotated clockwise around axis to the target
public double [] neckBack; // angle in degrees of the camera as a whole rotated clockwise around axis to the target
public double [][] neckXZ=null; // optical head offset in mm relative to the mount point (centerAboveHorizontal as Y)
// non-adjustable parameters, not parts of vector // non-adjustable parameters, not parts of vector
public int numStations; public int numStations;
...@@ -114,7 +118,12 @@ import ij.gui.GenericDialog; ...@@ -114,7 +118,12 @@ import ij.gui.GenericDialog;
{10.0,2.0,0.0,1.0}, // 13 centerAboveHorizontal {10.0,2.0,0.0,1.0}, // 13 centerAboveHorizontal
{10.0,2.0,0.0,1.0}, // 14 GXYZ0 {10.0,2.0,0.0,1.0}, // 14 GXYZ0
{10.0,2.0,0.0,1.0}, // 15 GXYZ1 {10.0,2.0,0.0,1.0}, // 15 GXYZ1
{10.0,2.0,0.0,1.0} // 16 GXYZ2 {10.0,2.0,0.0,1.0}, // 16 GXYZ2
{10.0,0.2,0.0,1.0}, // 17 neckRight
{10.0,0.2,0.0,1.0}, // 18 neckBack
{10.0,2.0,0.0,1.0}, // 19 neckXZ0
{10.0,2.0,0.0,1.0} // 20 neckXZ0
}; };
public boolean isTripod() { public boolean isTripod() {
...@@ -345,6 +354,10 @@ import ij.gui.GenericDialog; ...@@ -345,6 +354,10 @@ import ij.gui.GenericDialog;
double GXYZ_0, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system double GXYZ_0, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
double GXYZ_1, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system double GXYZ_1, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
double GXYZ_2, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system double GXYZ_2, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
double neck_right,
double neck_back,
double neck_x,
double neck_z,
int sensorWidth, int sensorWidth,
int sensorHeight, int sensorHeight,
int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
...@@ -372,6 +385,7 @@ import ij.gui.GenericDialog; ...@@ -372,6 +385,7 @@ import ij.gui.GenericDialog;
boolean invertUnmarkedLwirGrid boolean invertUnmarkedLwirGrid
){ ){
double [] GXYZ={GXYZ_0,GXYZ_1,GXYZ_2}; double [] GXYZ={GXYZ_0,GXYZ_1,GXYZ_2};
double [] neck_xz= {neck_x, neck_z};
setSameEyesisCameraParameters ( setSameEyesisCameraParameters (
numStations, numStations,
isTripod, isTripod,
...@@ -387,6 +401,9 @@ import ij.gui.GenericDialog; ...@@ -387,6 +401,9 @@ import ij.gui.GenericDialog;
entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
neck_right,
neck_back,
neck_xz,
sensorWidth, sensorWidth,
sensorHeight, sensorHeight,
shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
...@@ -429,6 +446,9 @@ import ij.gui.GenericDialog; ...@@ -429,6 +446,9 @@ import ij.gui.GenericDialog;
double entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil double entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
double centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each double centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
double [] GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system double [] GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
double neck_right,
double neck_back,
double [] neck_xz,
int sensorWidth, int sensorWidth,
int sensorHeight, int sensorHeight,
int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
...@@ -470,6 +490,9 @@ import ij.gui.GenericDialog; ...@@ -470,6 +490,9 @@ import ij.gui.GenericDialog;
entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
neck_right,
neck_back,
neck_xz,
sensorWidth, sensorWidth,
sensorHeight, sensorHeight,
shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
...@@ -512,6 +535,9 @@ import ij.gui.GenericDialog; ...@@ -512,6 +535,9 @@ import ij.gui.GenericDialog;
double entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil double entrancePupilForward, // common to all lenses - distance from the sensor to the lens entrance pupil
double centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each double centerAboveHorizontal, // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
double [] GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system double [] GXYZ, // coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
double neck_right,
double neck_back,
double [] neck_xz,
int defaultSensorWidth, int defaultSensorWidth,
int defaultSensorHeight, int defaultSensorHeight,
int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks int shrinkGridForMask, //shrink detected grids by one point for/vert this number of times before calculating masks
...@@ -568,7 +594,10 @@ import ij.gui.GenericDialog; ...@@ -568,7 +594,10 @@ import ij.gui.GenericDialog;
this.horAxisErrPsi=new double[numStations]; this.horAxisErrPsi=new double[numStations];
this.entrancePupilForward=new double[numStations]; // common to all lenses - distance from the sensor to the lens entrance pupil this.entrancePupilForward=new double[numStations]; // common to all lenses - distance from the sensor to the lens entrance pupil
this.centerAboveHorizontal=new double[numStations]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each this.centerAboveHorizontal=new double[numStations]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
this.GXYZ=new double[numStations][]; this.GXYZ=new double[numStations][3];
this.neckRight=new double[numStations];
this.neckBack=new double[numStations];
this.neckXZ=new double[numStations][2];
if (numSubCameras>0) this.eyesisSubCameras=new EyesisSubCameraParameters[numStations][]; if (numSubCameras>0) this.eyesisSubCameras=new EyesisSubCameraParameters[numStations][];
this.stationWeight=new double[numStations]; this.stationWeight=new double[numStations];
for (int numStation=0;numStation<numStations;numStation++) { for (int numStation=0;numStation<numStations;numStation++) {
...@@ -581,8 +610,10 @@ import ij.gui.GenericDialog; ...@@ -581,8 +610,10 @@ import ij.gui.GenericDialog;
this.horAxisErrPsi[numStation]=horAxisErrPsi; this.horAxisErrPsi[numStation]=horAxisErrPsi;
this.entrancePupilForward[numStation]=entrancePupilForward; // common to all lenses - distance from the sensor to the lens entrance pupil this.entrancePupilForward[numStation]=entrancePupilForward; // common to all lenses - distance from the sensor to the lens entrance pupil
this.centerAboveHorizontal[numStation]=centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each this.centerAboveHorizontal[numStation]=centerAboveHorizontal; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
this.GXYZ[numStation]=new double [3];
for (int i=0;i<3;i++) this.GXYZ[numStation][i]=GXYZ[i]; for (int i=0;i<3;i++) this.GXYZ[numStation][i]=GXYZ[i];
this.neckRight[numStation]=neck_right;
this.neckBack[numStation]= neck_back;
for (int i=0;i<2;i++) this.neckXZ[numStation][i]=neck_xz[i];
if (numSubCameras>0) initSubCameras(numStation,numSubCameras); if (numSubCameras>0) initSubCameras(numStation,numSubCameras);
} }
} }
...@@ -642,7 +673,11 @@ import ij.gui.GenericDialog; ...@@ -642,7 +673,11 @@ import ij.gui.GenericDialog;
destination.horAxisErrPsi=new double[destination.numStations]; destination.horAxisErrPsi=new double[destination.numStations];
destination.entrancePupilForward=new double[destination.numStations]; // common to all lenses - distance from the sensor to the lens entrance pupil destination.entrancePupilForward=new double[destination.numStations]; // common to all lenses - distance from the sensor to the lens entrance pupil
destination.centerAboveHorizontal=new double[destination.numStations]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each destination.centerAboveHorizontal=new double[destination.numStations]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
destination.GXYZ=new double[destination.numStations][]; destination.GXYZ=new double[destination.numStations][3];
destination.neckRight=new double[destination.numStations];
destination.neckBack=new double[destination.numStations];
destination.neckXZ=new double[destination.numStations][2];
if (source.eyesisSubCameras!=null) destination.eyesisSubCameras=new EyesisSubCameraParameters[destination.numStations][]; if (source.eyesisSubCameras!=null) destination.eyesisSubCameras=new EyesisSubCameraParameters[destination.numStations][];
else destination.eyesisSubCameras=null; else destination.eyesisSubCameras=null;
destination.stationWeight=new double[destination.numStations]; destination.stationWeight=new double[destination.numStations];
...@@ -658,8 +693,10 @@ import ij.gui.GenericDialog; ...@@ -658,8 +693,10 @@ import ij.gui.GenericDialog;
destination.horAxisErrPsi[numStation]=source.horAxisErrPsi[srcNumStation]; destination.horAxisErrPsi[numStation]=source.horAxisErrPsi[srcNumStation];
destination.entrancePupilForward[numStation]=source.entrancePupilForward[srcNumStation]; // common to all lenses - distance from the sensor to the lens entrance pupil destination.entrancePupilForward[numStation]=source.entrancePupilForward[srcNumStation]; // common to all lenses - distance from the sensor to the lens entrance pupil
destination.centerAboveHorizontal[numStation]=source.centerAboveHorizontal[srcNumStation]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each destination.centerAboveHorizontal[numStation]=source.centerAboveHorizontal[srcNumStation]; // camera center distance along camera axis above the closest point to horizontal rotation axis (adds to height of each
destination.GXYZ[numStation]=new double [3];
for (int i=0;i<3;i++) destination.GXYZ[numStation][i]=source.GXYZ[srcNumStation][i]; for (int i=0;i<3;i++) destination.GXYZ[numStation][i]=source.GXYZ[srcNumStation][i];
destination.neckRight[numStation]=source.neckRight[srcNumStation];
destination.neckBack[numStation]= source.neckBack[srcNumStation];
for (int i=0;i<2;i++) destination.neckXZ[numStation][i]=source.neckXZ[srcNumStation][i];
if (destination.eyesisSubCameras!=null){ if (destination.eyesisSubCameras!=null){
destination.eyesisSubCameras[numStation]=new EyesisSubCameraParameters[source.eyesisSubCameras[srcNumStation].length]; destination.eyesisSubCameras[numStation]=new EyesisSubCameraParameters[source.eyesisSubCameras[srcNumStation].length];
for (int i=0; i<destination.eyesisSubCameras[numStation].length;i++) if (source.eyesisSubCameras[srcNumStation][i]!=null){ for (int i=0; i<destination.eyesisSubCameras[numStation].length;i++) if (source.eyesisSubCameras[srcNumStation][i]!=null){
...@@ -713,6 +750,10 @@ import ij.gui.GenericDialog; ...@@ -713,6 +750,10 @@ import ij.gui.GenericDialog;
properties.setProperty(prefix+"GXYZ_0_"+numStation,this.GXYZ[numStation][0]+""); properties.setProperty(prefix+"GXYZ_0_"+numStation,this.GXYZ[numStation][0]+"");
properties.setProperty(prefix+"GXYZ_1_"+numStation,this.GXYZ[numStation][1]+""); properties.setProperty(prefix+"GXYZ_1_"+numStation,this.GXYZ[numStation][1]+"");
properties.setProperty(prefix+"GXYZ_2_"+numStation,this.GXYZ[numStation][2]+""); properties.setProperty(prefix+"GXYZ_2_"+numStation,this.GXYZ[numStation][2]+"");
properties.setProperty(prefix+"neckRight_"+numStation,this.neckRight[numStation]+"");
properties.setProperty(prefix+"neckBack_"+numStation,this.neckBack[numStation]+"");
properties.setProperty(prefix+"neckX_"+numStation,this.neckXZ[numStation][0]+"");
properties.setProperty(prefix+"neckZ_"+numStation,this.neckXZ[numStation][1]+"");
for (int i=0;i<this.eyesisSubCameras[numStation].length;i++) { for (int i=0;i<this.eyesisSubCameras[numStation].length;i++) {
this.eyesisSubCameras[numStation][i].setProperties(prefix+numStation+"_subCamera_"+i+'.',properties); this.eyesisSubCameras[numStation][i].setProperties(prefix+numStation+"_subCamera_"+i+'.',properties);
} }
...@@ -830,6 +871,19 @@ import ij.gui.GenericDialog; ...@@ -830,6 +871,19 @@ import ij.gui.GenericDialog;
this.GXYZ[numStation][1]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_1_"+numStation)); this.GXYZ[numStation][1]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_1_"+numStation));
if (properties.getProperty(prefix+"GXYZ_2_"+numStation)!=null) if (properties.getProperty(prefix+"GXYZ_2_"+numStation)!=null)
this.GXYZ[numStation][2]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_2_"+numStation)); this.GXYZ[numStation][2]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_2_"+numStation));
if (properties.getProperty(prefix+"neckRight_"+numStation)!=null)
this.neckRight[numStation]=Double.parseDouble(properties.getProperty(prefix+"neckRight_"+numStation));
if (properties.getProperty(prefix+"neckBack_"+numStation)!=null)
this.neckBack[numStation]=Double.parseDouble(properties.getProperty(prefix+"neckBack_"+numStation));
if (this.neckXZ[numStation] == null) {
this.neckXZ[numStation] = new double[2];
}
if (properties.getProperty(prefix+"neckX_"+numStation)!=null)
this.neckXZ[numStation][0]=Double.parseDouble(properties.getProperty(prefix+"neckX_"+numStation));
if (properties.getProperty(prefix+"neckZ_"+numStation)!=null)
this.neckXZ[numStation][1]=Double.parseDouble(properties.getProperty(prefix+"neckZ_"+numStation));
if (numSubCameras>0) { if (numSubCameras>0) {
initSubCameras(numStation, numSubCameras); // set array with default parameters initSubCameras(numStation, numSubCameras); // set array with default parameters
for (int i=0;i<numSubCameras;i++){ for (int i=0;i<numSubCameras;i++){
...@@ -860,6 +914,21 @@ import ij.gui.GenericDialog; ...@@ -860,6 +914,21 @@ import ij.gui.GenericDialog;
this.GXYZ[0][1]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_1")); this.GXYZ[0][1]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_1"));
if (properties.getProperty(prefix+"GXYZ_2")!=null) if (properties.getProperty(prefix+"GXYZ_2")!=null)
this.GXYZ[0][2]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_2")); this.GXYZ[0][2]=Double.parseDouble(properties.getProperty(prefix+"GXYZ_2"));
if (properties.getProperty(prefix+"neckRight")!=null)
this.neckRight[0]=Double.parseDouble(properties.getProperty(prefix+"neckRight"));
if (properties.getProperty(prefix+"neckBack")!=null)
this.neckBack[0]=Double.parseDouble(properties.getProperty(prefix+"neckBack"));
if (this.neckXZ[0] == null) {
this.neckXZ[0] = new double[2];
}
if (properties.getProperty(prefix+"neckX")!=null)
this.neckXZ[0][0]=Double.parseDouble(properties.getProperty(prefix+"neckX"));
if (properties.getProperty(prefix+"neckZ")!=null)
this.neckXZ[0][1]=Double.parseDouble(properties.getProperty(prefix+"neckZ"));
System.out.println(" === numSubCameras="+numSubCameras); System.out.println(" === numSubCameras="+numSubCameras);
if (numSubCameras>0) { if (numSubCameras>0) {
initSubCameras(0, numSubCameras); // set array with default parameters initSubCameras(0, numSubCameras); // set array with default parameters
...@@ -926,6 +995,12 @@ import ij.gui.GenericDialog; ...@@ -926,6 +995,12 @@ import ij.gui.GenericDialog;
gd.addNumericField("Goniometer reference point position X (target coordinates, left)", this.GXYZ[numStation][0], 3,7,"mm"); gd.addNumericField("Goniometer reference point position X (target coordinates, left)", this.GXYZ[numStation][0], 3,7,"mm");
gd.addNumericField("Goniometer reference point position Y (target coordinates, up)", this.GXYZ[numStation][1], 3,7,"mm"); gd.addNumericField("Goniometer reference point position Y (target coordinates, up)", this.GXYZ[numStation][1], 3,7,"mm");
gd.addNumericField("Goniometer reference point position Z (target coordinates, away)", this.GXYZ[numStation][2], 3,7,"mm"); gd.addNumericField("Goniometer reference point position Z (target coordinates, away)", this.GXYZ[numStation][2], 3,7,"mm");
gd.addNumericField("Camera \"neck\" tilt right", this.neckRight[numStation], 3,7,"degrees");
gd.addNumericField("Camera \"neck\" tilt back", this.neckBack[numStation], 3,7,"degrees");
gd.addNumericField("Camera \"neck\" shift in target X for vertical camera", this.neckXZ[numStation][0], 3,7,"mm");
gd.addNumericField("Camera \"neck\" shift in target Z for vertical camera", this.neckXZ[numStation][1], 3,7,"mm");
gd.addMessage("Camera \"neck\" shift in target Y is the same as \"Camera center above goniometer horizontal axis\"");
} }
gd.addMessage("=== Other parameters ==="); gd.addMessage("=== Other parameters ===");
...@@ -989,6 +1064,10 @@ import ij.gui.GenericDialog; ...@@ -989,6 +1064,10 @@ import ij.gui.GenericDialog;
this.GXYZ[numStation][0]= gd.getNextNumber(); this.GXYZ[numStation][0]= gd.getNextNumber();
this.GXYZ[numStation][1]= gd.getNextNumber(); this.GXYZ[numStation][1]= gd.getNextNumber();
this.GXYZ[numStation][2]= gd.getNextNumber(); this.GXYZ[numStation][2]= gd.getNextNumber();
this.neckRight[numStation]= gd.getNextNumber();
this.neckBack[numStation]= gd.getNextNumber();
this.neckXZ[numStation][0]= gd.getNextNumber();
this.neckXZ[numStation][1]= gd.getNextNumber();
} }
this.defaultSensorWidth= (int) gd.getNextNumber(); this.defaultSensorWidth= (int) gd.getNextNumber();
this.defaultSensorHeight= (int) gd.getNextNumber(); this.defaultSensorHeight= (int) gd.getNextNumber();
...@@ -1382,7 +1461,7 @@ import ij.gui.GenericDialog; ...@@ -1382,7 +1461,7 @@ import ij.gui.GenericDialog;
for (int nstation = 0; nstation < centerAboveHorizontal.length; nstation++) { for (int nstation = 0; nstation < centerAboveHorizontal.length; nstation++) {
centerAboveHorizontal[nstation] = CENTER_ABOVE_HORIZONTAL; centerAboveHorizontal[nstation] = CENTER_ABOVE_HORIZONTAL;
} }
IJ.showMessage("Camera geometry is set to LWIR16 design (16 LWIR + 4 EO)"); IJ.showMessage("Camera geometry is set to LWIR16 design (16 LWIR + 4 EO), neck* parameters are not updated");
return true; return true;
} }
...@@ -1426,42 +1505,48 @@ import ij.gui.GenericDialog; ...@@ -1426,42 +1505,48 @@ import ij.gui.GenericDialog;
this.GXYZ[stationNumber][0], //14 (12) coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system this.GXYZ[stationNumber][0], //14 (12) coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
this.GXYZ[stationNumber][1], //15 (13) y this.GXYZ[stationNumber][1], //15 (13) y
this.GXYZ[stationNumber][2], //16 (14) z this.GXYZ[stationNumber][2], //16 (14) z
subCam.focalLength, //17 (15) lens focal length
subCam.px0, //18 (16) center of the lens on the sensor, pixels this.neckRight[stationNumber], // 17
subCam.py0, //19 (17) center of the lens on the sensor, pixels this.neckBack[stationNumber], // 18
subCam.distortionA8, //20 (18) r^8 (normalized to focal length or to sensor half width?) this.neckXZ[stationNumber][0], // 19
subCam.distortionA7, //21 (19) r^7 (normalized to focal length or to sensor half width?) this.neckXZ[stationNumber][1], // 20
subCam.distortionA6, //22 (20) r^6 (normalized to focal length or to sensor half width?) // new indices after adding neck* parameters
subCam.distortionA5, //23 (21) r^5 (normalized to focal length or to sensor half width?) subCam.focalLength, // 21 17 (15) lens focal length
subCam.distortionA, //24 (22) r^4 (normalized to focal length or to sensor half width?) subCam.px0, // 22 18 (16) center of the lens on the sensor, pixels
subCam.distortionB, //25 (23) r^3 subCam.py0, // 23 19 (17) center of the lens on the sensor, pixels
subCam.distortionC, //26 (24) r^2 subCam.distortionA8, // 24 20 (18) r^8 (normalized to focal length or to sensor half width?)
subCam.r_od[0][0], subCam.distortionA7, // 25 21 (19) r^7 (normalized to focal length or to sensor half width?)
subCam.r_od[0][1], subCam.distortionA6, // 26 22 (20) r^6 (normalized to focal length or to sensor half width?)
subCam.r_xy[0][0], subCam.distortionA5, // 27 23 (21) r^5 (normalized to focal length or to sensor half width?)
subCam.r_xy[0][1], subCam.distortionA, // 28 24 (22) r^4 (normalized to focal length or to sensor half width?)
subCam.r_od[1][0], subCam.distortionB, // 29 25 (23) r^3
subCam.r_od[1][1], subCam.distortionC, // 30 26 (24) r^2
subCam.r_xy[1][0], subCam.r_od[0][0], // 31
subCam.r_xy[1][1], subCam.r_od[0][1], // 32
subCam.r_od[2][0], subCam.r_xy[0][0], // 33
subCam.r_od[2][1], subCam.r_xy[0][1], // 34
subCam.r_xy[2][0], subCam.r_od[1][0], // 35
subCam.r_xy[2][1], subCam.r_od[1][1], // 36
subCam.r_od[3][0], subCam.r_xy[1][0], // 37
subCam.r_od[3][1], subCam.r_xy[1][1], // 38
subCam.r_xy[3][0], subCam.r_od[2][0], // 39
subCam.r_xy[3][1], subCam.r_od[2][1], // 40
subCam.r_od[4][0], subCam.r_xy[2][0], // 41
subCam.r_od[4][1], subCam.r_xy[2][1], // 42
subCam.r_xy[4][0], subCam.r_od[3][0], // 43
subCam.r_xy[4][1], subCam.r_od[3][1], // 44
subCam.r_od[5][0], subCam.r_xy[3][0], // 45
subCam.r_od[5][1], subCam.r_xy[3][1], // 46
subCam.r_xy[5][0], subCam.r_od[4][0], // 47
subCam.r_xy[5][1], subCam.r_od[4][1], // 48
subCam.r_od[6][0], subCam.r_xy[4][0], // 49
subCam.r_od[6][1] subCam.r_xy[4][1], // 50
subCam.r_od[5][0], // 51
subCam.r_od[5][1], // 52
subCam.r_xy[5][0], // 53
subCam.r_xy[5][1], // 54
subCam.r_od[6][0], // 55
subCam.r_od[6][1] // 56 was 53 before neck*
}; };
// Global parameters, not adjusted - just copied once when camera is selected // Global parameters, not adjusted - just copied once when camera is selected
// or should they stay fixed and not copied at all? // or should they stay fixed and not copied at all?
...@@ -1563,7 +1648,7 @@ import ij.gui.GenericDialog; ...@@ -1563,7 +1648,7 @@ import ij.gui.GenericDialog;
int subCamNumber // int subCamNumber //
){ ){
// if (parVect.length!=27) throw new IllegalArgumentException ("Wrong length of the parameters vector: "+parVect.length+"(should be 27)"); // if (parVect.length!=27) throw new IllegalArgumentException ("Wrong length of the parameters vector: "+parVect.length+"(should be 27)");
if (parVect.length!=53) throw new IllegalArgumentException ("Wrong length of the parameters vector: "+parVect.length+"(should be 53)"); if (parVect.length!=57) throw new IllegalArgumentException ("Wrong length of the parameters vector: "+parVect.length+"(should be 57)");
if ( if (
(this.eyesisSubCameras==null) || (this.eyesisSubCameras==null) ||
(this.numStations<=stationNumber) || (this.numStations<=stationNumber) ||
...@@ -1597,42 +1682,48 @@ import ij.gui.GenericDialog; ...@@ -1597,42 +1682,48 @@ import ij.gui.GenericDialog;
if (update[14]) this.GXYZ[stationNumber][0]=parVect[14]; //14 coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system if (update[14]) this.GXYZ[stationNumber][0]=parVect[14]; //14 coordinates (in mm) of the goniometer horizontal axis closest to the moving one in target system
if (update[15]) this.GXYZ[stationNumber][1]=parVect[15]; //15 y if (update[15]) this.GXYZ[stationNumber][1]=parVect[15]; //15 y
if (update[16]) this.GXYZ[stationNumber][2]=parVect[16]; //16 z if (update[16]) this.GXYZ[stationNumber][2]=parVect[16]; //16 z
if (update[17]) subCam.focalLength=parVect[17]; //17 lens focal length // neck* parameters
if (update[18]) subCam.px0=parVect[18]; //18 center of the lens on the sensor, pixels if (update[17]) this.neckRight[stationNumber]= parVect[17]; //17 whole camera tilt right at the "neck"
if (update[19]) subCam.py0=parVect[19]; //19 center of the lens on the sensor, pixels if (update[18]) this.neckBack[stationNumber]= parVect[18]; //18 whole camera tilt back at the "neck"
if (update[20]) subCam.distortionA8=parVect[20]; //20 r^8 (normalized to focal length or to sensor half width?) if (update[19]) this.neckXZ[stationNumber][0]= parVect[19]; //19 whole camera shift X at the "neck"
if (update[21]) subCam.distortionA7=parVect[21]; //21 r^7 (normalized to focal length or to sensor half width?) if (update[20]) this.neckXZ[stationNumber][1]= parVect[20]; //20 whole camera shift Z at the "neck"
if (update[22]) subCam.distortionA6=parVect[22]; //22 r^6 (normalized to focal length or to sensor half width?)
if (update[23]) subCam.distortionA5=parVect[23]; //23 r^5 (normalized to focal length or to sensor half width?) if (update[21]) subCam.focalLength= parVect[21]; // was 17 lens focal length
if (update[24]) subCam.distortionA= parVect[24]; //24 r^4 (normalized to focal length or to sensor half width?) if (update[22]) subCam.px0= parVect[22]; // was 18 center of the lens on the sensor, pixels
if (update[25]) subCam.distortionB= parVect[25]; //25 r^3 if (update[23]) subCam.py0= parVect[23]; // was 19 center of the lens on the sensor, pixels
if (update[26]) subCam.distortionC= parVect[26]; //26 r^2 if (update[24]) subCam.distortionA8=parVect[24]; // was 20 r^8 (normalized to focal length or to sensor half width?)
if (update[27]) subCam.r_od[0][0]= parVect[27]; if (update[25]) subCam.distortionA7=parVect[25]; // was 21 r^7 (normalized to focal length or to sensor half width?)
if (update[28]) subCam.r_od[0][1]= parVect[28]; if (update[26]) subCam.distortionA6=parVect[26]; // was 22 r^6 (normalized to focal length or to sensor half width?)
if (update[29]) subCam.r_xy[0][0]= parVect[29]; if (update[27]) subCam.distortionA5=parVect[27]; // was 23 r^5 (normalized to focal length or to sensor half width?)
if (update[30]) subCam.r_xy[0][1]= parVect[30]; if (update[28]) subCam.distortionA= parVect[28]; // was 24 r^4 (normalized to focal length or to sensor half width?)
if (update[31]) subCam.r_od[1][0]= parVect[31]; if (update[29]) subCam.distortionB= parVect[29]; // was 25 r^3
if (update[32]) subCam.r_od[1][1]= parVect[32]; if (update[30]) subCam.distortionC= parVect[30]; // was 26 r^2
if (update[33]) subCam.r_xy[1][0]= parVect[33]; if (update[31]) subCam.r_od[0][0]= parVect[31];
if (update[34]) subCam.r_xy[1][1]= parVect[34]; if (update[32]) subCam.r_od[0][1]= parVect[32];
if (update[35]) subCam.r_od[2][0]= parVect[35]; if (update[33]) subCam.r_xy[0][0]= parVect[33];
if (update[36]) subCam.r_od[2][1]= parVect[36]; if (update[34]) subCam.r_xy[0][1]= parVect[34];
if (update[37]) subCam.r_xy[2][0]= parVect[37]; if (update[35]) subCam.r_od[1][0]= parVect[35];
if (update[38]) subCam.r_xy[2][1]= parVect[38]; if (update[36]) subCam.r_od[1][1]= parVect[36];
if (update[39]) subCam.r_od[3][0]= parVect[39]; if (update[37]) subCam.r_xy[1][0]= parVect[37];
if (update[40]) subCam.r_od[3][1]= parVect[40]; if (update[38]) subCam.r_xy[1][1]= parVect[38];
if (update[41]) subCam.r_xy[3][0]= parVect[41]; if (update[39]) subCam.r_od[2][0]= parVect[39];
if (update[42]) subCam.r_xy[3][1]= parVect[42]; if (update[40]) subCam.r_od[2][1]= parVect[40];
if (update[43]) subCam.r_od[4][0]= parVect[43]; if (update[41]) subCam.r_xy[2][0]= parVect[41];
if (update[44]) subCam.r_od[4][1]= parVect[44]; if (update[42]) subCam.r_xy[2][1]= parVect[42];
if (update[45]) subCam.r_xy[4][0]= parVect[45]; if (update[43]) subCam.r_od[3][0]= parVect[43];
if (update[46]) subCam.r_xy[4][1]= parVect[46]; if (update[44]) subCam.r_od[3][1]= parVect[44];
if (update[47]) subCam.r_od[5][0]= parVect[47]; if (update[45]) subCam.r_xy[3][0]= parVect[45];
if (update[48]) subCam.r_od[5][1]= parVect[48]; if (update[46]) subCam.r_xy[3][1]= parVect[46];
if (update[49]) subCam.r_xy[5][0]= parVect[49]; if (update[47]) subCam.r_od[4][0]= parVect[47];
if (update[50]) subCam.r_xy[5][1]= parVect[50]; if (update[48]) subCam.r_od[4][1]= parVect[48];
if (update[51]) subCam.r_od[6][0]= parVect[51]; if (update[49]) subCam.r_xy[4][0]= parVect[49];
if (update[52]) subCam.r_od[6][1]= parVect[52]; if (update[50]) subCam.r_xy[4][1]= parVect[50];
if (update[51]) subCam.r_od[5][0]= parVect[51];
if (update[52]) subCam.r_od[5][1]= parVect[52];
if (update[53]) subCam.r_xy[5][0]= parVect[53];
if (update[54]) subCam.r_xy[5][1]= parVect[54];
if (update[55]) subCam.r_od[6][0]= parVect[55];
if (update[56]) subCam.r_od[6][1]= parVect[56];
} }
public void updateCartesian(){ public void updateCartesian(){
...@@ -2691,6 +2782,8 @@ import ij.gui.GenericDialog; ...@@ -2691,6 +2782,8 @@ import ij.gui.GenericDialog;
false); // lwir false); // lwir
} }
} }
// TODO: add similar for neck*
public void recenterVertically(boolean [] subcams, boolean [] stations){ public void recenterVertically(boolean [] subcams, boolean [] stations){
boolean sameCenterAboveHorizontal=true; boolean sameCenterAboveHorizontal=true;
double cah=Double.NaN; double cah=Double.NaN;
......
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