1 #====================================================================== |
1 #====================================================================== |
2 # R D I _ C O O R D S . P L |
2 # R D I _ C O O R D S . P L |
3 # doc: Sun Jan 19 17:57:53 2003 |
3 # doc: Sun Jan 19 17:57:53 2003 |
4 # dlm: Mon Jun 29 10:59:01 2020 |
4 # dlm: Wed Mar 17 23:20:13 2021 |
5 # (c) 2003 A.M. Thurnherr |
5 # (c) 2003 A.M. Thurnherr |
6 # uE-Info: 61 83 NIL 0 0 72 10 2 4 NIL ofnI |
6 # uE-Info: 66 9 NIL 0 0 72 10 2 4 NIL ofnI |
7 #====================================================================== |
7 #====================================================================== |
8 |
8 |
9 # RDI Workhorse Coordinate Transformations |
9 # RDI Workhorse Coordinate Transformations |
10 |
10 |
11 # HISTORY: |
11 # HISTORY: |
57 # Nov 26, 2017: - BUG: velBeamtoBPEarth() did not respect missing values |
57 # Nov 26, 2017: - BUG: velBeamtoBPEarth() did not respect missing values |
58 # Nov 27, 2017: - BUG: numbersp() from [antslib.pl] was used |
58 # Nov 27, 2017: - BUG: numbersp() from [antslib.pl] was used |
59 # Mar 28, 2018: - added &loadInstrumentTransformation() |
59 # Mar 28, 2018: - added &loadInstrumentTransformation() |
60 # Jun 5, 2020: - added sscorr_w & sscorr_w_mooring |
60 # Jun 5, 2020: - added sscorr_w & sscorr_w_mooring |
61 # Jun 29, 2020: - added comments for sscorr_w, which conflicts with LADCP_w_ocean |
61 # Jun 29, 2020: - added comments for sscorr_w, which conflicts with LADCP_w_ocean |
|
62 # Mar 17, 2021: - adapted velBeamToInstrument() to Nortek (checked w only) |
|
63 # - adapted velInstrumentToEarth() to Nortek, assuming Nortek pitch is gimbal pitch |
|
64 # HISTORY END |
|
65 |
|
66 # NORTEK TODO: |
|
67 # - check u, v sign convention for Nortek |
|
68 # - verify that gimbal pitch for Nortek gives better results |
|
69 # for A20 test profile 900, the differences in w have a stddev of 1.3e-5 m/s |
|
70 # - update gimbal pitch for Nortek in other routines |
62 |
71 |
63 use strict; |
72 use strict; |
64 use POSIX; |
73 use POSIX; |
65 |
74 |
66 my($PI) = 3.14159265358979; |
75 my($PI) = 3.14159265358979; |
133 my($ADCP,$ens,$v1,$v2,$v3,$v4) = @_; |
142 my($ADCP,$ens,$v1,$v2,$v3,$v4) = @_; |
134 return undef unless (defined($v1) + defined($v2) + |
143 return undef unless (defined($v1) + defined($v2) + |
135 defined($v3) + defined($v4) |
144 defined($v3) + defined($v4) |
136 >= $RDI_Coords::minValidVels); |
145 >= $RDI_Coords::minValidVels); |
137 |
146 |
138 unless (@B2I) { |
147 unless (@B2I) { # nominal transformation matrix |
139 my($a) = 1 / (2 * sin(rad($ADCP->{BEAM_ANGLE}))); |
148 my($a) = 1 / (2 * sin(rad($ADCP->{BEAM_ANGLE}))); |
140 my($b) = 1 / (4 * cos(rad($ADCP->{BEAM_ANGLE}))); |
149 my($b) = 1 / (4 * cos(rad($ADCP->{BEAM_ANGLE}))); |
141 my($c) = $ADCP->{CONVEX_BEAM_PATTERN} ? 1 : -1; |
150 my($c) = $ADCP->{CONVEX_BEAM_PATTERN} ? 1 : -1; |
142 my($d) = $a / sqrt(2); |
151 my($d) = $a / sqrt(2); |
143 @B2I = ([$c*$a, -$c*$a, 0, 0 ], |
152 @B2I = ([$c*$a, -$c*$a, 0, 0 ], |
144 [0, 0, -$c*$a, $c*$a], |
153 [0, 0, -$c*$a, $c*$a], |
145 [$b, $b, $b, $b ], |
154 [$b, $b, $b, $b ], |
146 [$d, $d, -$d, -$d ]); |
155 [$d, $d, -$d, -$d ]); |
147 } |
156 } |
148 |
157 |
149 if (!defined($v1)) { # 3-beam solutions |
158 if ($ADCP->{PRODUCER} =~ '^Nortek') { # Nortek ADCPs use different coord system |
|
159 $v1 *= -1 if defined($v1); |
|
160 $v2 *= -1 if defined($v2); |
|
161 $v3 *= -1 if defined($v3); |
|
162 $v4 *= -1 if defined($v4); |
|
163 } |
|
164 |
|
165 if (!defined($v1)) { # 3-beam solutions |
150 $RDI_Coords::threeBeamFlag = 1; |
166 $RDI_Coords::threeBeamFlag = 1; |
151 $RDI_Coords::threeBeam_1++; |
167 $RDI_Coords::threeBeam_1++; |
152 $v1 = -($v2*$B2I[3][1]+$v3*$B2I[3][2]+$v4*$B2I[3][3])/$B2I[3][0]; |
168 $v1 = -($v2*$B2I[3][1]+$v3*$B2I[3][2]+$v4*$B2I[3][3])/$B2I[3][0]; |
153 } elsif (!defined($v2)) { |
169 } elsif (!defined($v2)) { |
154 $RDI_Coords::threeBeamFlag = 1; |
170 $RDI_Coords::threeBeamFlag = 1; |
209 if ($ADCP->{HEADING_ALIGNMENT}); |
225 if ($ADCP->{HEADING_ALIGNMENT}); |
210 $hdg = $ADCP->{ENSEMBLE}[$ens]->{HEADING} - $ADCP->{HEADING_BIAS} |
226 $hdg = $ADCP->{ENSEMBLE}[$ens]->{HEADING} - $ADCP->{HEADING_BIAS} |
211 if defined($ADCP->{ENSEMBLE}[$ens]->{HEADING}); |
227 if defined($ADCP->{ENSEMBLE}[$ens]->{HEADING}); |
212 $pitch = $ADCP->{ENSEMBLE}[$ens]->{PITCH}; |
228 $pitch = $ADCP->{ENSEMBLE}[$ens]->{PITCH}; |
213 $roll = $ADCP->{ENSEMBLE}[$ens]->{ROLL}; |
229 $roll = $ADCP->{ENSEMBLE}[$ens]->{ROLL}; |
214 my($rad_gimbal_pitch) = atan(tan(rad($pitch)) * cos(rad($roll))); |
230 my($rad_gimbal_pitch); |
|
231 if ($ADCP->{PRODUCER} =~ '^Nortek') { |
|
232 $rad_gimbal_pitch = rad($pitch); # I am assuming that this is correct |
|
233 } else { |
|
234 $rad_gimbal_pitch = atan(tan(rad($pitch)) * cos(rad($roll))); |
|
235 } |
|
236 |
215 my($rad_calc_pitch) = ($RDI_Coords::beamTransformation eq 'RDI') ? $rad_gimbal_pitch : |
237 my($rad_calc_pitch) = ($RDI_Coords::beamTransformation eq 'RDI') ? $rad_gimbal_pitch : |
216 asin(sin($rad_gimbal_pitch)*cos(rad($roll)) / |
238 asin(sin($rad_gimbal_pitch)*cos(rad($roll)) / |
217 sqrt(1-sin(rad($roll))**2*sin($rad_gimbal_pitch)**2)); |
239 sqrt(1-sin(rad($roll))**2*sin($rad_gimbal_pitch)**2)); |
218 my($sh,$ch) = (sin(rad($hdg)),cos(rad($hdg))) |
240 my($sh,$ch) = (sin(rad($hdg)),cos(rad($hdg))) |
219 if defined($hdg); |
241 if defined($hdg); |