├── README.md
├── cal_rot_mat.m
├── data_ZY3
├── DX_ZY3_NAD_att.txt
├── DX_ZY3_NAD_gps.txt
├── DX_ZY3_NAD_imagingTime.txt
├── NAD.cbr
├── NAD.txt
└── zy3.tif
├── dem
└── n35_e114_1arc_v3.tif
├── figs
├── GCP.png
├── dem_stretch.png
└── gcp&satellite.png
├── final
├── coeff.npy
├── partial.npy
└── rpc_results.txt
├── grab_matrix.py
├── intermediate_res
├── ac_time.txt
├── b2j.npy
├── checkpt.npy
├── gcp.npy
├── gps_loc.npy
├── j2w.npy
├── range.npy
├── rot.txt
└── ux.npy
├── main.py
├── plot.py
├── precision_check.py
├── preprocessing.py
├── ref
├── RPC.pdf
├── Zy3仿真数据说明.docx
├── 利用视线向量的资源三号卫星影像严格几何处理模型.pdf
└── 有理函数模型的解算与应用_巩丹超.pdf
├── utility
├── Ext_utility.py
├── RPC_utility.py
└── Rotation_utility.py
└── yml
└── params.yml
/README.md:
--------------------------------------------------------------------------------
1 | # 🛰地形无关控制方案的RPC解算
2 |
3 | ***卫星摄影测量课程大作业***
4 |
5 | 利用严格相机模型获得虚拟控制点,通过有理函数模型(RFM)建立物方与像方关系,求解模型参数(RPC).
6 |
7 | 代码RPC解算部分采用矩阵运算与多进程加速,有较高运行效率.
8 |
9 | ## Requirements
10 |
11 | * Python 3
12 | * MATLAB
13 | * Numpy 1.18.5
14 | * Scipy 1.5.0
15 | * multiprocess 0.70.11.1
16 | * yaml
17 | ##
18 | * [GDAL 3.1.4](https://www.lfd.uci.edu/~gohlke/pythonlibs/#gdal) (Optional)
19 | * OpenCV 4.2.0.34 (Optional)
20 | * matplotlib 2.2.2 (Optional)
21 | * selenium 3.141.0 (Optional)
22 | * beautifulsoup4 4.9.3 (Optional)
23 |
24 |
25 | ##
26 |
27 | ## Procedure
28 | #### 根据预处理的文件直接解算RPC参数
29 |
30 | 结果保存至`final`文件夹中
31 | ```
32 | python main.py
33 | ```
34 |
35 | ## **Optional Operation**
36 |
37 | #### 外精度评价
38 | 根据高精度DEM建立格网,计算外精度.
39 |
40 | *(若未安装GDAL,请采用numpy.load方式获取检查点)*
41 | ```
42 | python precision_check.py
43 | ```
44 |
45 |
46 |
47 | #### 计算J2000至WGS84旋转矩阵 并初始化yaml参数
48 |
49 | 由python计算扫描行对应`UTC time` 初始化`yml/params.yml`
50 | ```
51 | python preprocessing.py
52 | ```
53 | MATLAB`dcmeci2ecef`函数计算旋转矩阵 存储至`intermediate_res/rot.txt`
54 | ```
55 | cal_rot_mat.m
56 | ```
57 |
58 | #### 从[巴黎天文台网站](https://hpiers.obspm.fr/eop-pc/index.php?index=matrice_php&lang=en)获取J2000至WGS84旋转矩阵
59 |
60 | 当前(2021.5.27)网站输入表单不可用 现提供批量处理Demo.
61 |
62 | ps:网站提供旋转矩阵为WGS84至J2000 当前场景使用时需要转置
63 |
64 | ```
65 | python grab_matrix.py
66 | ```
67 |
68 |
69 | #### 可视化虚拟格网点及卫星位置结果
70 | ```
71 | python plot.py
72 | ```
73 |
74 | ## Things U Should Know
75 |
76 | * 有理函数模型方程`易产生病态`,请选择不太小的虚拟控制点层数(eg: k>3),选择不太严格的迭代收敛方式,并予以初值(类似DLT解算);
77 | * 膨胀椭球法求交时请选择`离地心点较近的一组解`;
78 | * 可视化结果请使用`BLH大地坐标`进行表达,并将经纬度转换至角度为宜(有时往往不是你算错了而是WGS84坐标系下可视化效果不佳);
79 | * 使用MATLAB求解求解旋转矩阵时,建议不要使用`ECItoECEF`函数求解,详见[讨论](https://ww2.mathworks.cn/matlabcentral/fileexchange/28233-convert-eci-to-ecef-coordinates);
80 | * 参考文献文件夹`ref`中论文公式`存在部分错误`,仅提供思路参考.
81 |
82 | ## Acknowledgment
83 | 感谢 [zwl-wennin](https://github.com/zwl-wennin) & [Dxy-c](https://github.com/Dxy-c) 对编写工作的贡献.
84 |
--------------------------------------------------------------------------------
/cal_rot_mat.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/cal_rot_mat.m
--------------------------------------------------------------------------------
/data_ZY3/DX_ZY3_NAD_gps.txt:
--------------------------------------------------------------------------------
1 |
2 | ##gps parameter:
3 | coordinateType = WGS84;
4 | dataType = GPS;
5 | groupNumber = 101 ;
6 | gpsData_01 =
7 | {
8 | timeCode = 131862356.0000000000 ;
9 | dateTime = "2013 03 07 04:25:56.000000" ;
10 | PX = -2542786.9226337620 ;
11 | PY = 5315041.8949657725 ;
12 | PZ = 3775775.5032639573 ;
13 | VX = 3238.8209067599 ;
14 | VY = -2912.6275659467 ;
15 | VZ = 6267.1084356481 ;
16 | }
17 | gpsData_02 =
18 | {
19 | timeCode = 131862357.0000000000 ;
20 | dateTime = "2013 03 07 04:25:57.000000" ;
21 | PX = -2539546.8438784815 ;
22 | PY = 5312125.9567804988 ;
23 | PZ = 3782040.4100917163 ;
24 | VX = 3241.3357867915 ;
25 | VY = -2919.2482848048 ;
26 | VZ = 6262.7039642104 ;
27 | }
28 | gpsData_03 =
29 | {
30 | timeCode = 131862358.0000009500 ;
31 | dateTime = "2013 03 07 04:25:58.000001" ;
32 | PX = -2536304.2522364855 ;
33 | PY = 5309203.3995681088 ;
34 | PZ = 3788300.9088053894 ;
35 | VX = 3243.8459410435 ;
36 | VY = -2925.8659717691 ;
37 | VZ = 6258.2922083841 ;
38 | }
39 | gpsData_04 =
40 | {
41 | timeCode = 131862359.0000009500 ;
42 | dateTime = "2013 03 07 04:25:59.000001" ;
43 | PX = -2533059.1531731947 ;
44 | PY = 5306274.2260119291 ;
45 | PZ = 3794556.9921232038 ;
46 | VX = 3246.3513674624 ;
47 | VY = -2932.4806180146 ;
48 | VZ = 6253.8731733980 ;
49 | }
50 | gpsData_05 =
51 | {
52 | timeCode = 131862360.0000009500 ;
53 | dateTime = "2013 03 07 04:26: 0.000001" ;
54 | PX = -2529811.5510484995 ;
55 | PY = 5303338.4393332237 ;
56 | PZ = 3800808.6527686156 ;
57 | VX = 3248.8520633921 ;
58 | VY = -2939.0922153963 ;
59 | VZ = 6249.4468644891 ;
60 | }
61 | gpsData_06 =
62 | {
63 | timeCode = 131862361.0000009500 ;
64 | dateTime = "2013 03 07 04:26: 1.000001" ;
65 | PX = -2526561.4505941961 ;
66 | PY = 5300396.0425850134 ;
67 | PZ = 3807055.8834703248 ;
68 | VX = 3251.3480263864 ;
69 | VY = -2945.7007555472 ;
70 | VZ = 6245.0132869031 ;
71 | }
72 | gpsData_07 =
73 | {
74 | timeCode = 131862362.0000019100 ;
75 | dateTime = "2013 03 07 04:26: 2.000002" ;
76 | PX = -2523308.8561758497 ;
77 | PY = 5297447.0390042579 ;
78 | PZ = 3813298.6769622816 ;
79 | VX = 3253.8392538006 ;
80 | VY = -2952.3062303299 ;
81 | VZ = 6240.5724458941 ;
82 | }
83 | gpsData_08 =
84 | {
85 | timeCode = 131862363.0000019100 ;
86 | dateTime = "2013 03 07 04:26: 3.000002" ;
87 | PX = -2520053.7732673474 ;
88 | PY = 5294491.4313094253 ;
89 | PZ = 3819537.0259836917 ;
90 | VX = 3256.3257436126 ;
91 | VY = -2958.9086309321 ;
92 | VZ = 6236.1243467248 ;
93 | }
94 | gpsData_09 =
95 | {
96 | timeCode = 131862364.0000019100 ;
97 | dateTime = "2013 03 07 04:26: 4.000002" ;
98 | PX = -2516796.2062387699 ;
99 | PY = 5291529.2227545101 ;
100 | PZ = 3825770.9232790316 ;
101 | VX = 3258.8074931918 ;
102 | VY = -2965.5079492234 ;
103 | VZ = 6231.6689946662 ;
104 | }
105 | gpsData_10 =
106 | {
107 | timeCode = 131862365.0000019100 ;
108 | dateTime = "2013 03 07 04:26: 5.000002" ;
109 | PX = -2513536.1598317195 ;
110 | PY = 5288560.4164259275 ;
111 | PZ = 3832000.3615980493 ;
112 | VX = 3261.2845001196 ;
113 | VY = -2972.1041768508 ;
114 | VZ = 6227.2063949979 ;
115 | }
116 | gpsData_11 =
117 | {
118 | timeCode = 131862366.0000028600 ;
119 | dateTime = "2013 03 07 04:26: 6.000003" ;
120 | PX = -2510273.6384225111 ;
121 | PY = 5285585.0155930594 ;
122 | PZ = 3838225.3336957796 ;
123 | VX = 3263.7567617772 ;
124 | VY = -2978.6973056917 ;
125 | VZ = 6222.7365530078 ;
126 | }
127 | gpsData_12 =
128 | {
129 | timeCode = 131862367.0000028600 ;
130 | dateTime = "2013 03 07 04:26: 7.000003" ;
131 | PX = -2507008.6474926914 ;
132 | PY = 5282603.0230097780 ;
133 | PZ = 3844445.8323325473 ;
134 | VX = 3266.2242761736 ;
135 | VY = -2985.2873269466 ;
136 | VZ = 6218.2594739926 ;
137 | }
138 | gpsData_13 =
139 | {
140 | timeCode = 131862368.0000028600 ;
141 | dateTime = "2013 03 07 04:26: 8.000003" ;
142 | PX = -2503741.1914233314 ;
143 | PY = 5279614.4419623101 ;
144 | PZ = 3850661.8502739780 ;
145 | VX = 3268.6870407041 ;
146 | VY = -2991.8742324997 ;
147 | VZ = 6213.7751632571 ;
148 | }
149 | gpsData_14 =
150 | {
151 | timeCode = 131862369.0000028600 ;
152 | dateTime = "2013 03 07 04:26: 9.000003" ;
153 | PX = -2500471.2749651945 ;
154 | PY = 5276619.2755706720 ;
155 | PZ = 3856873.3802910117 ;
156 | VX = 3271.1450529775 ;
157 | VY = -2998.4580140125 ;
158 | VZ = 6209.2836261147 ;
159 | }
160 | gpsData_15 =
161 | {
162 | timeCode = 131862370.0000038100 ;
163 | dateTime = "2013 03 07 04:26:10.000004" ;
164 | PX = -2497198.9025051915 ;
165 | PY = 5273617.5271366434 ;
166 | PZ = 3863080.4151598969 ;
167 | VX = 3273.5983104009 ;
168 | VY = -3005.0386633771 ;
169 | VZ = 6204.7848678872 ;
170 | }
171 | gpsData_16 =
172 | {
173 | timeCode = 131862371.0000038100 ;
174 | dateTime = "2013 03 07 04:26:11.000004" ;
175 | PX = -2493924.0795328184 ;
176 | PY = 5270609.1994492197 ;
177 | PZ = 3869282.9476622152 ;
178 | VX = 3276.0468110144 ;
179 | VY = -3011.6161718070 ;
180 | VZ = 6200.2788939048 ;
181 | }
182 | gpsData_17 =
183 | {
184 | timeCode = 131862372.0000038100 ;
185 | dateTime = "2013 03 07 04:26:12.000004" ;
186 | PX = -2490646.8104391573 ;
187 | PY = 5267594.2958272472 ;
188 | PZ = 3875480.9705848801 ;
189 | VX = 3278.4905522392 ;
190 | VY = -3018.1905312015 ;
191 | VZ = 6195.7657095062 ;
192 | }
193 | gpsData_18 =
194 | {
195 | timeCode = 131862373.0000038100 ;
196 | dateTime = "2013 03 07 04:26:13.000004" ;
197 | PX = -2487367.0999849983 ;
198 | PY = 5264572.8194238180 ;
199 | PZ = 3881674.4767201468 ;
200 | VX = 3280.9295317119 ;
201 | VY = -3024.7617332362 ;
202 | VZ = 6191.2453200384 ;
203 | }
204 | gpsData_19 =
205 | {
206 | timeCode = 131862374.0000047700 ;
207 | dateTime = "2013 03 07 04:26:14.000005" ;
208 | PX = -2484084.9525675029 ;
209 | PY = 5261544.7735731415 ;
210 | PZ = 3887863.4588656272 ;
211 | VX = 3283.3637468653 ;
212 | VY = -3031.3297698184 ;
213 | VZ = 6186.7177308569 ;
214 | }
215 | gpsData_20 =
216 | {
217 | timeCode = 131862375.0000047700 ;
218 | dateTime = "2013 03 07 04:26:15.000005" ;
219 | PX = -2480800.3736834875 ;
220 | PY = 5258510.1610995606 ;
221 | PZ = 3894047.9098242824 ;
222 | VX = 3285.7931957707 ;
223 | VY = -3037.8946321748 ;
224 | VZ = 6182.1829473256 ;
225 | }
226 | gpsData_21 =
227 | {
228 | timeCode = 131862376.0000047700 ;
229 | dateTime = "2013 03 07 04:26:16.000005" ;
230 | PX = -2477513.3677349007 ;
231 | PY = 5255468.9853539960 ;
232 | PZ = 3900227.8224044540 ;
233 | VX = 3288.2178758753 ;
234 | VY = -3044.4563122198 ;
235 | VZ = 6177.6409748167 ;
236 | }
237 | gpsData_22 =
238 | {
239 | timeCode = 131862377.0000047700 ;
240 | dateTime = "2013 03 07 04:26:17.000005" ;
241 | PX = -2474223.9394914838 ;
242 | PY = 5252421.2495230334 ;
243 | PZ = 3906403.1894198507 ;
244 | VX = 3290.6377848431 ;
245 | VY = -3051.0148016435 ;
246 | VZ = 6173.0918187109 ;
247 | }
248 | gpsData_23 =
249 | {
250 | timeCode = 131862378.0000057200 ;
251 | dateTime = "2013 03 07 04:26:18.000006" ;
252 | PX = -2470932.0933606070 ;
253 | PY = 5249366.9569732137 ;
254 | PZ = 3912574.0036895722 ;
255 | VX = 3293.0529201328 ;
256 | VY = -3057.5700923687 ;
257 | VZ = 6168.5354843971 ;
258 | }
259 | gpsData_24 =
260 | {
261 | timeCode = 131862379.0000057200 ;
262 | dateTime = "2013 03 07 04:26:19.000006" ;
263 | PX = -2467637.8348472756 ;
264 | PY = 5246306.1105636926 ;
265 | PZ = 3918740.2580381050 ;
266 | VX = 3295.4632798473 ;
267 | VY = -3064.1221756349 ;
268 | VZ = 6163.9719772727 ;
269 | }
270 | gpsData_25 =
271 | {
272 | timeCode = 131862380.0000057200 ;
273 | dateTime = "2013 03 07 04:26:20.000006" ;
274 | PX = -2464341.1683629151 ;
275 | PY = 5243238.7136780415 ;
276 | PZ = 3924901.9452953418 ;
277 | VX = 3297.8688614593 ;
278 | VY = -3070.6710433723 ;
279 | VZ = 6159.4013027436 ;
280 | }
281 | gpsData_26 =
282 | {
283 | timeCode = 131862381.0000057200 ;
284 | dateTime = "2013 03 07 04:26:21.000006" ;
285 | PX = -2461042.0986870062 ;
286 | PY = 5240164.7695358247 ;
287 | PZ = 3931059.0582965845 ;
288 | VX = 3300.2696626607 ;
289 | VY = -3077.2166872854 ;
290 | VZ = 6154.8234662237 ;
291 | }
292 | gpsData_27 =
293 | {
294 | timeCode = 131862382.0000066800 ;
295 | dateTime = "2013 03 07 04:26:22.000007" ;
296 | PX = -2457740.6302367328 ;
297 | PY = 5237084.2815360092 ;
298 | PZ = 3937211.5898825526 ;
299 | VX = 3302.6656809360 ;
300 | VY = -3083.7590993126 ;
301 | VZ = 6150.2384731354 ;
302 | }
303 | gpsData_28 =
304 | {
305 | timeCode = 131862383.0000066800 ;
306 | dateTime = "2013 03 07 04:26:23.000007" ;
307 | PX = -2454436.7685246998 ;
308 | PY = 5233997.2525727376 ;
309 | PZ = 3943359.5328993932 ;
310 | VX = 3305.0569144195 ;
311 | VY = -3090.2982707069 ;
312 | VZ = 6145.6463289097 ;
313 | }
314 | gpsData_29 =
315 | {
316 | timeCode = 131862384.0000066800 ;
317 | dateTime = "2013 03 07 04:26:24.000007" ;
318 | PX = -2451130.5179726896 ;
319 | PY = 5230903.6860616775 ;
320 | PZ = 3949502.8801986855 ;
321 | VX = 3307.4433606097 ;
322 | VY = -3096.8341934137 ;
323 | VZ = 6141.0470389855 ;
324 | }
325 | gpsData_30 =
326 | {
327 | timeCode = 131862385.0000066800 ;
328 | dateTime = "2013 03 07 04:26:25.000007" ;
329 | PX = -2447821.8833689913 ;
330 | PY = 5227803.5852557225 ;
331 | PZ = 3955641.6246374575 ;
332 | VX = 3309.8250172264 ;
333 | VY = -3103.3668591527 ;
334 | VZ = 6136.4406088103 ;
335 | }
336 | gpsData_31 =
337 | {
338 | timeCode = 131862386.0000076300 ;
339 | dateTime = "2013 03 07 04:26:26.000008" ;
340 | PX = -2444510.8691411698 ;
341 | PY = 5224696.9535858976 ;
342 | PZ = 3961775.7590781837 ;
343 | VX = 3312.2018817799 ;
344 | VY = -3109.8962598777 ;
345 | VZ = 6131.8270438397 ;
346 | }
347 | gpsData_32 =
348 | {
349 | timeCode = 131862387.0000076300 ;
350 | dateTime = "2013 03 07 04:26:27.000008" ;
351 | PX = -2441197.4808089295 ;
352 | PY = 5221583.7939814217 ;
353 | PZ = 3967905.2763887988 ;
354 | VX = 3314.5739524358 ;
355 | VY = -3116.4223868554 ;
356 | VZ = 6127.2063495380 ;
357 | }
358 | gpsData_33 =
359 | {
360 | timeCode = 131862388.0000076300 ;
361 | dateTime = "2013 03 07 04:26:28.000008" ;
362 | PX = -2437881.7228038600 ;
363 | PY = 5218464.1098902244 ;
364 | PZ = 3974030.1694427086 ;
365 | VX = 3316.9412267185 ;
366 | VY = -3122.9452320470 ;
367 | VZ = 6122.5785313773 ;
368 | }
369 | gpsData_34 =
370 | {
371 | timeCode = 131862389.0000076300 ;
372 | dateTime = "2013 03 07 04:26:29.000008" ;
373 | PX = -2434563.5999237597 ;
374 | PY = 5215337.9045980992 ;
375 | PZ = 3980150.4311187933 ;
376 | VX = 3319.3037023757 ;
377 | VY = -3129.4647871870 ;
378 | VZ = 6117.9435948384 ;
379 | }
380 | gpsData_35 =
381 | {
382 | timeCode = 131862390.0000085800 ;
383 | dateTime = "2013 03 07 04:26:30.000009" ;
384 | PX = -2431243.1166057237 ;
385 | PY = 5212205.1815683646 ;
386 | PZ = 3986266.0543014184 ;
387 | VX = 3321.6613769436 ;
388 | VY = -3135.9810442452 ;
389 | VZ = 6113.3015454102 ;
390 | }
391 | gpsData_36 =
392 | {
393 | timeCode = 131862391.0000085800 ;
394 | dateTime = "2013 03 07 04:26:31.000009" ;
395 | PX = -2427920.2783769681 ;
396 | PY = 5209065.9437650796 ;
397 | PZ = 3992377.0318804411 ;
398 | VX = 3324.0142486191 ;
399 | VY = -3142.4939945019 ;
400 | VZ = 6108.6523885898 ;
401 | }
402 | gpsData_37 =
403 | {
404 | timeCode = 131862392.0000085800 ;
405 | dateTime = "2013 03 07 04:26:32.000009" ;
406 | PX = -2424595.0896789222 ;
407 | PY = 5205920.1946682762 ;
408 | PZ = 3998483.3567512245 ;
409 | VX = 3326.3623149527 ;
410 | VY = -3149.0036299342 ;
411 | VZ = 6103.9961298827 ;
412 | }
413 | gpsData_38 =
414 | {
415 | timeCode = 131862393.0000085800 ;
416 | dateTime = "2013 03 07 04:26:33.000009" ;
417 | PX = -2421267.5553181213 ;
418 | PY = 5202767.9375968864 ;
419 | PZ = 4004585.0218146355 ;
420 | VX = 3328.7055737198 ;
421 | VY = -3155.5099422920 ;
422 | VZ = 6099.3327748026 ;
423 | }
424 | gpsData_39 =
425 | {
426 | timeCode = 131862394.0000085800 ;
427 | dateTime = "2013 03 07 04:26:34.000009" ;
428 | PX = -2417937.6801033090 ;
429 | PY = 5199609.1758780554 ;
430 | PZ = 4010682.0199770611 ;
431 | VX = 3331.0440227024 ;
432 | VY = -3162.0129233291 ;
433 | VZ = 6094.6623288716 ;
434 | }
435 | gpsData_40 =
436 | {
437 | timeCode = 131862395.0000095400 ;
438 | dateTime = "2013 03 07 04:26:35.000010" ;
439 | PX = -2414605.4684839002 ;
440 | PY = 5196443.9130152008 ;
441 | PZ = 4016774.3441504180 ;
442 | VX = 3333.3776594691 ;
443 | VY = -3168.5125650349 ;
444 | VZ = 6089.9847976198 ;
445 | }
446 | gpsData_41 =
447 | {
448 | timeCode = 131862396.0000095400 ;
449 | dateTime = "2013 03 07 04:26:36.000010" ;
450 | PX = -2411270.9259960223 ;
451 | PY = 5193272.1520159170 ;
452 | PZ = 4022861.9872521502 ;
453 | VX = 3335.7064822723 ;
454 | VY = -3175.0088587184 ;
455 | VZ = 6085.3001865549 ;
456 | }
457 | gpsData_42 =
458 | {
459 | timeCode = 131862397.0000095400 ;
460 | dateTime = "2013 03 07 04:26:37.000010" ;
461 | PX = -2407934.0570933279 ;
462 | PY = 5190093.8964002579 ;
463 | PZ = 4028944.9422052181 ;
464 | VX = 3338.0304886790 ;
465 | VY = -3181.5017963655 ;
466 | VZ = 6080.6085012544 ;
467 | }
468 | gpsData_43 =
469 | {
470 | timeCode = 131862398.0000095400 ;
471 | dateTime = "2013 03 07 04:26:38.000010" ;
472 | PX = -2404594.8665932440 ;
473 | PY = 5186909.1495284289 ;
474 | PZ = 4035023.2019381640 ;
475 | VX = 3340.3496764989 ;
476 | VY = -3187.9913697457 ;
477 | VZ = 6075.9097472733 ;
478 | }
479 | gpsData_44 =
480 | {
481 | timeCode = 131862399.0000104900 ;
482 | dateTime = "2013 03 07 04:26:39.000010" ;
483 | PX = -2401253.3589550764 ;
484 | PY = 5183717.9149357313 ;
485 | PZ = 4041096.7593850885 ;
486 | VX = 3342.6640433271 ;
487 | VY = -3194.4775708644 ;
488 | VZ = 6071.2039301746 ;
489 | }
490 | gpsData_45 =
491 | {
492 | timeCode = 131862400.0000104900 ;
493 | dateTime = "2013 03 07 04:26:40.000010" ;
494 | PX = -2397909.5397217935 ;
495 | PY = 5180520.1956646079 ;
496 | PZ = 4047165.6074856576 ;
497 | VX = 3344.9735874310 ;
498 | VY = -3200.9603910339 ;
499 | VZ = 6066.4910555298 ;
500 | }
501 | gpsData_46 =
502 | {
503 | timeCode = 131862401.0000104900 ;
504 | dateTime = "2013 03 07 04:26:41.000010" ;
505 | PX = -2394563.4133568304 ;
506 | PY = 5177315.9952670494 ;
507 | PZ = 4053229.7391851139 ;
508 | VX = 3347.2783064198 ;
509 | VY = -3207.4398222674 ;
510 | VZ = 6061.7711289184 ;
511 | }
512 | gpsData_47 =
513 | {
514 | timeCode = 131862402.0000104900 ;
515 | dateTime = "2013 03 07 04:26:42.000010" ;
516 | PX = -2391214.9846862443 ;
517 | PY = 5174105.3171361750 ;
518 | PZ = 4059289.1474342854 ;
519 | VX = 3349.5781981313 ;
520 | VY = -3213.9158563497 ;
521 | VZ = 6057.0441559281 ;
522 | }
523 | gpsData_48 =
524 | {
525 | timeCode = 131862403.0000114400 ;
526 | dateTime = "2013 03 07 04:26:43.000011" ;
527 | PX = -2387864.2581789065 ;
528 | PY = 5170888.1648392370 ;
529 | PZ = 4065343.8251895909 ;
530 | VX = 3351.8732601863 ;
531 | VY = -3220.3884853026 ;
532 | VZ = 6052.3101421548 ;
533 | }
534 | gpsData_49 =
535 | {
536 | timeCode = 131862404.0000114400 ;
537 | dateTime = "2013 03 07 04:26:44.000011" ;
538 | PX = -2384511.2393846568 ;
539 | PY = 5167664.5414533969 ;
540 | PZ = 4071393.7654130468 ;
541 | VX = 3354.1634908839 ;
542 | VY = -3226.8577004528 ;
543 | VZ = 6047.5690932028 ;
544 | }
545 | gpsData_50 =
546 | {
547 | timeCode = 131862405.0000114400 ;
548 | dateTime = "2013 03 07 04:26:45.000011" ;
549 | PX = -2381155.9327764381 ;
550 | PY = 5164434.4505625609 ;
551 | PZ = 4077438.9610722782 ;
552 | VX = 3356.4488878592 ;
553 | VY = -3233.3234938299 ;
554 | VZ = 6042.8210146841 ;
555 | }
556 | gpsData_51 =
557 | {
558 | timeCode = 131862406.0000114400 ;
559 | dateTime = "2013 03 07 04:26:46.000011" ;
560 | PX = -2377798.3431889759 ;
561 | PY = 5161197.8955926420 ;
562 | PZ = 4083479.4051405331 ;
563 | VX = 3358.7294489780 ;
564 | VY = -3239.7858572345 ;
565 | VZ = 6038.0659122193 ;
566 | }
567 | gpsData_52 =
568 | {
569 | timeCode = 131862407.0000124000 ;
570 | dateTime = "2013 03 07 04:26:47.000012" ;
571 | PX = -2374438.4751004716 ;
572 | PY = 5157954.8801428508 ;
573 | PZ = 4089515.0905967071 ;
574 | VX = 3361.0051718573 ;
575 | VY = -3246.2447826840 ;
576 | VZ = 6033.3037914984 ;
577 | }
578 | gpsData_53 =
579 | {
580 | timeCode = 131862408.0000124000 ;
581 | dateTime = "2013 03 07 04:26:48.000012" ;
582 | PX = -2371076.3340675975 ;
583 | PY = 5154705.4073249940 ;
584 | PZ = 4095546.0104253297 ;
585 | VX = 3363.2760548577 ;
586 | VY = -3252.7002615405 ;
587 | VZ = 6028.5346580967 ;
588 | }
589 | gpsData_54 =
590 | {
591 | timeCode = 131862409.0000124000 ;
592 | dateTime = "2013 03 07 04:26:49.000012" ;
593 | PX = -2367711.9245727011 ;
594 | PY = 5151449.4807548169 ;
595 | PZ = 4101572.1576165445 ;
596 | VX = 3365.5420956404 ;
597 | VY = -3259.1522858502 ;
598 | VZ = 6023.7585176591 ;
599 | }
600 | gpsData_55 =
601 | {
602 | timeCode = 131862410.0000124000 ;
603 | dateTime = "2013 03 07 04:26:50.000012" ;
604 | PX = -2364345.2514589182 ;
605 | PY = 5148187.1038910449 ;
606 | PZ = 4107593.5251661395 ;
607 | VX = 3367.8032920988 ;
608 | VY = -3265.6008474297 ;
609 | VZ = 6018.9753758385 ;
610 | }
611 | gpsData_56 =
612 | {
613 | timeCode = 131862411.0000133500 ;
614 | dateTime = "2013 03 07 04:26:51.000013" ;
615 | PX = -2360976.3192138677 ;
616 | PY = 5144918.2803646494 ;
617 | PZ = 4113610.1060755630 ;
618 | VX = 3370.0596419061 ;
619 | VY = -3272.0459383338 ;
620 | VZ = 6014.1852382961 ;
621 | }
622 | gpsData_57 =
623 | {
624 | timeCode = 131862412.0000133500 ;
625 | dateTime = "2013 03 07 04:26:52.000013" ;
626 | PX = -2357605.1334010349 ;
627 | PY = 5141643.0133219296 ;
628 | PZ = 4119621.8933519265 ;
629 | VX = 3372.3111434243 ;
630 | VY = -3278.4875499184 ;
631 | VZ = 6009.3881107011 ;
632 | }
633 | gpsData_58 =
634 | {
635 | timeCode = 131862413.0000133500 ;
636 | dateTime = "2013 03 07 04:26:53.000013" ;
637 | PX = -2354231.6985116475 ;
638 | PY = 5138361.3064106293 ;
639 | PZ = 4125628.8800080130 ;
640 | VX = 3374.5577943408 ;
641 | VY = -3284.9256742465 ;
642 | VZ = 6004.5839987309 ;
643 | }
644 | gpsData_59 =
645 | {
646 | timeCode = 131862414.0000133500 ;
647 | dateTime = "2013 03 07 04:26:54.000013" ;
648 | PX = -2350856.0193975563 ;
649 | PY = 5135073.1631219797 ;
650 | PZ = 4131631.0590622937 ;
651 | VX = 3376.7995925769 ;
652 | VY = -3291.3603031507 ;
653 | VZ = 5999.7729080710 ;
654 | }
655 | gpsData_60 =
656 | {
657 | timeCode = 131862415.0000143100 ;
658 | dateTime = "2013 03 07 04:26:55.000014" ;
659 | PX = -2347478.1005554334 ;
660 | PY = 5131778.5871188333 ;
661 | PZ = 4137628.4235389228 ;
662 | VX = 3379.0365358318 ;
663 | VY = -3297.7914287026 ;
664 | VZ = 5994.9548444150 ;
665 | }
666 | gpsData_61 =
667 | {
668 | timeCode = 131862416.0000143100 ;
669 | dateTime = "2013 03 07 04:26:56.000014" ;
670 | PX = -2344097.9475552458 ;
671 | PY = 5128477.5815820089 ;
672 | PZ = 4143620.9664677526 ;
673 | VX = 3381.2686224991 ;
674 | VY = -3304.2190422732 ;
675 | VZ = 5990.1298134643 ;
676 | }
677 | gpsData_62 =
678 | {
679 | timeCode = 131862417.0000143100 ;
680 | dateTime = "2013 03 07 04:26:57.000014" ;
681 | PX = -2340715.5648976341 ;
682 | PY = 5125170.1501908740 ;
683 | PZ = 4149608.6808843450 ;
684 | VX = 3383.4958502923 ;
685 | VY = -3310.6431359421 ;
686 | VZ = 5985.2978209288 ;
687 | }
688 | gpsData_63 =
689 | {
690 | timeCode = 131862418.0000143100 ;
691 | dateTime = "2013 03 07 04:26:58.000014" ;
692 | PX = -2337330.9574424080 ;
693 | PY = 5121856.2964694314 ;
694 | PZ = 4155591.5598299415 ;
695 | VX = 3385.7182171745 ;
696 | VY = -3317.0637015683 ;
697 | VZ = 5980.4588724958 ;
698 | }
699 | gpsData_64 =
700 | {
701 | timeCode = 131862419.0000152600 ;
702 | dateTime = "2013 03 07 04:26:59.000015" ;
703 | PX = -2333944.1296956860 ;
704 | PY = 5118536.0241120569 ;
705 | PZ = 4161569.5963515365 ;
706 | VX = 3387.9357208572 ;
707 | VY = -3323.4807312304 ;
708 | VZ = 5975.6129739215 ;
709 | }
710 | gpsData_65 =
711 | {
712 | timeCode = 131862420.0000152600 ;
713 | dateTime = "2013 03 07 04:27: 0.000015" ;
714 | PX = -2330555.0872335001 ;
715 | PY = 5115209.3363342145 ;
716 | PZ = 4167542.7835018584 ;
717 | VX = 3390.1483597654 ;
718 | VY = -3329.8942163144 ;
719 | VZ = 5970.7601309399 ;
720 | }
721 | gpsData_66 =
722 | {
723 | timeCode = 131862421.0000152600 ;
724 | dateTime = "2013 03 07 04:27: 1.000015" ;
725 | PX = -2327163.8345658034 ;
726 | PY = 5111876.2368468000 ;
727 | PZ = 4173511.1143393680 ;
728 | VX = 3392.3561316389 ;
729 | VY = -3336.3041489169 ;
730 | VZ = 5965.9003492930 ;
731 | }
732 | gpsData_67 =
733 | {
734 | timeCode = 131862422.0000152600 ;
735 | dateTime = "2013 03 07 04:27: 2.000015" ;
736 | PX = -2323770.3765605679 ;
737 | PY = 5108536.7292064000 ;
738 | PZ = 4179474.5819282727 ;
739 | VX = 3394.5590344549 ;
740 | VY = -3342.7105209032 ;
741 | VZ = 5961.0336347307 ;
742 | }
743 | gpsData_68 =
744 | {
745 | timeCode = 131862423.0000162100 ;
746 | dateTime = "2013 03 07 04:27: 3.000016" ;
747 | PX = -2320374.7177328099 ;
748 | PY = 5105190.8171390817 ;
749 | PZ = 4185433.1793385404 ;
750 | VX = 3396.7570659649 ;
751 | VY = -3349.1133243792 ;
752 | VZ = 5956.1599930111 ;
753 | }
754 | gpsData_69 =
755 | {
756 | timeCode = 131862424.0000162100 ;
757 | dateTime = "2013 03 07 04:27: 4.000016" ;
758 | PX = -2316976.8636648753 ;
759 | PY = 5101838.5038946820 ;
760 | PZ = 4191386.8996458910 ;
761 | VX = 3398.9502246255 ;
762 | VY = -3355.5125507462 ;
763 | VZ = 5951.2794299002 ;
764 | }
765 | gpsData_70 =
766 | {
767 | timeCode = 131862425.0000162100 ;
768 | dateTime = "2013 03 07 04:27: 5.000016" ;
769 | PX = -2313576.8188757054 ;
770 | PY = 5098479.7932156920 ;
771 | PZ = 4197335.7359318212 ;
772 | VX = 3401.1385082027 ;
773 | VY = -3361.9081921179 ;
774 | VZ = 5946.3919511720 ;
775 | }
776 | gpsData_71 =
777 | {
778 | timeCode = 131862426.0000162100 ;
779 | dateTime = "2013 03 07 04:27: 6.000016" ;
780 | PX = -2310174.5882412368 ;
781 | PY = 5095114.6886912314 ;
782 | PZ = 4203279.6812836071 ;
783 | VX = 3403.3219147017 ;
784 | VY = -3368.3002403764 ;
785 | VZ = 5941.4975626086 ;
786 | }
787 | gpsData_72 =
788 | {
789 | timeCode = 131862427.0000171700 ;
790 | dateTime = "2013 03 07 04:27: 7.000017" ;
791 | PX = -2306770.1762855635 ;
792 | PY = 5091743.1940788329 ;
793 | PZ = 4209218.7287943000 ;
794 | VX = 3405.5004419003 ;
795 | VY = -3374.6886876447 ;
796 | VZ = 5936.5962700001 ;
797 | }
798 | gpsData_73 =
799 | {
800 | timeCode = 131862428.0000171700 ;
801 | dateTime = "2013 03 07 04:27: 8.000017" ;
802 | PX = -2303363.5885971501 ;
803 | PY = 5088365.3126627179 ;
804 | PZ = 4215152.8715627613 ;
805 | VX = 3407.6740882866 ;
806 | VY = -3381.0735253394 ;
807 | VZ = 5931.6880791445 ;
808 | }
809 | gpsData_74 =
810 | {
811 | timeCode = 131862429.0000171700 ;
812 | dateTime = "2013 03 07 04:27: 9.000017" ;
813 | PX = -2299954.8297036011 ;
814 | PY = 5084981.0482169734 ;
815 | PZ = 4221082.1026936434 ;
816 | VX = 3409.8428516526 ;
817 | VY = -3387.4547455919 ;
818 | VZ = 5926.7729958478 ;
819 | }
820 | gpsData_75 =
821 | {
822 | timeCode = 131862430.0000171700 ;
823 | dateTime = "2013 03 07 04:27:10.000017" ;
824 | PX = -2296543.9044889943 ;
825 | PY = 5081590.4043630622 ;
826 | PZ = 4227006.4152974095 ;
827 | VX = 3412.0067300318 ;
828 | VY = -3393.8323403008 ;
829 | VZ = 5921.8510259241 ;
830 | }
831 | gpsData_76 =
832 | {
833 | timeCode = 131862431.0000181200 ;
834 | dateTime = "2013 03 07 04:27:11.000018" ;
835 | PX = -2293130.8174861856 ;
836 | PY = 5078193.3848900199 ;
837 | PZ = 4232925.8024903461 ;
838 | VX = 3414.1657212280 ;
839 | VY = -3400.2063016065 ;
840 | VZ = 5916.9221751952 ;
841 | }
842 | gpsData_77 =
843 | {
844 | timeCode = 131862432.0000181200 ;
845 | dateTime = "2013 03 07 04:27:12.000018" ;
846 | PX = -2289715.5742895538 ;
847 | PY = 5074789.9931164011 ;
848 | PZ = 4238840.2573945625 ;
849 | VX = 3416.3198237610 ;
850 | VY = -3406.5766209416 ;
851 | VZ = 5911.9864494913 ;
852 | }
853 | gpsData_78 =
854 | {
855 | timeCode = 131862433.0000181200 ;
856 | dateTime = "2013 03 07 04:27:13.000018" ;
857 | PX = -2286298.1794357733 ;
858 | PY = 5071380.2328476105 ;
859 | PZ = 4244749.7731379988 ;
860 | VX = 3418.4690354493 ;
861 | VY = -3412.9432904545 ;
862 | VZ = 5907.0438546500 ;
863 | }
864 | gpsData_79 =
865 | {
866 | timeCode = 131862434.0000181200 ;
867 | dateTime = "2013 03 07 04:27:14.000018" ;
868 | PX = -2282878.6378163663 ;
869 | PY = 5067964.1077376409 ;
870 | PZ = 4250654.3428544393 ;
871 | VX = 3420.6133543540 ;
872 | VY = -3419.3063020611 ;
873 | VZ = 5902.0943965174 ;
874 | }
875 | gpsData_80 =
876 | {
877 | timeCode = 131862435.0000190700 ;
878 | dateTime = "2013 03 07 04:27:15.000019" ;
879 | PX = -2279456.9539730698 ;
880 | PY = 5064541.6216068650 ;
881 | PZ = 4256553.9596835263 ;
882 | VX = 3422.7527783053 ;
883 | VY = -3425.6656479193 ;
884 | VZ = 5897.1380809471 ;
885 | }
886 | gpsData_81 =
887 | {
888 | timeCode = 131862436.0000190700 ;
889 | dateTime = "2013 03 07 04:27:16.000019" ;
890 | PX = -2276033.1335061905 ;
891 | PY = 5061112.7778080497 ;
892 | PZ = 4262448.6167707406 ;
893 | VX = 3424.8873058546 ;
894 | VY = -3432.0213194773 ;
895 | VZ = 5892.1749138008 ;
896 | }
897 | gpsData_82 =
898 | {
899 | timeCode = 131862437.0000190700 ;
900 | dateTime = "2013 03 07 04:27:17.000019" ;
901 | PX = -2272607.1809607861 ;
902 | PY = 5057677.5801780829 ;
903 | PZ = 4268338.3072674489 ;
904 | VX = 3427.0169348466 ;
905 | VY = -3438.3733089016 ;
906 | VZ = 5887.2049009481 ;
907 | }
908 | gpsData_83 =
909 | {
910 | timeCode = 131862438.0000190700 ;
911 | dateTime = "2013 03 07 04:27:18.000019" ;
912 | PX = -2269179.1012365860 ;
913 | PY = 5054236.0324030491 ;
914 | PZ = 4274223.0243308814 ;
915 | VX = 3429.1416633706 ;
916 | VY = -3444.7216081248 ;
917 | VZ = 5882.2280482667 ;
918 | }
919 | gpsData_84 =
920 | {
921 | timeCode = 131862439.0000200300 ;
922 | dateTime = "2013 03 07 04:27:19.000020" ;
923 | PX = -2265748.8988834498 ;
924 | PY = 5050788.1383348824 ;
925 | PZ = 4280102.7611241499 ;
926 | VX = 3431.2614892830 ;
927 | VY = -3451.0662093227 ;
928 | VZ = 5877.2443616418 ;
929 | }
930 | gpsData_85 =
931 | {
932 | timeCode = 131862440.0000200300 ;
933 | dateTime = "2013 03 07 04:27:20.000020" ;
934 | PX = -2262316.5795076289 ;
935 | PY = 5047333.9013604131 ;
936 | PZ = 4285977.5108162574 ;
937 | VX = 3433.3764111668 ;
938 | VY = -3457.4071039595 ;
939 | VZ = 5872.2538469668 ;
940 | }
941 | gpsData_86 =
942 | {
943 | timeCode = 131862441.0000200300 ;
944 | dateTime = "2013 03 07 04:27:21.000020" ;
945 | PX = -2258882.1476628203 ;
946 | PY = 5043873.3253478119 ;
947 | PZ = 4291847.2665821044 ;
948 | VX = 3435.4864268929 ;
949 | VY = -3463.7442842194 ;
950 | VZ = 5867.2565101430 ;
951 | }
952 | gpsData_87 =
953 | {
954 | timeCode = 131862442.0000200300 ;
955 | dateTime = "2013 03 07 04:27:22.000020" ;
956 | PX = -2255445.6082561277 ;
957 | PY = 5040406.4140154812 ;
958 | PZ = 4297712.0216024946 ;
959 | VX = 3437.5915345788 ;
960 | VY = -3470.0777420524 ;
961 | VZ = 5862.2523570794 ;
962 | }
963 | gpsData_88 =
964 | {
965 | timeCode = 131862443.0000209800 ;
966 | dateTime = "2013 03 07 04:27:23.000021" ;
967 | PX = -2252006.9658463653 ;
968 | PY = 5036933.1712464318 ;
969 | PZ = 4303571.7690641480 ;
970 | VX = 3439.6917321073 ;
971 | VY = -3476.4074696520 ;
972 | VZ = 5857.2413936930 ;
973 | }
974 | gpsData_89 =
975 | {
976 | timeCode = 131862444.0000209800 ;
977 | dateTime = "2013 03 07 04:27:24.000021" ;
978 | PX = -2248566.2260449501 ;
979 | PY = 5033453.6004617931 ;
980 | PZ = 4309426.5021597017 ;
981 | VX = 3441.7870180927 ;
982 | VY = -3482.7334584988 ;
983 | VZ = 5852.2236259086 ;
984 | }
985 | gpsData_90 =
986 | {
987 | timeCode = 131862445.0000209800 ;
988 | dateTime = "2013 03 07 04:27:25.000021" ;
989 | PX = -2245123.3934142664 ;
990 | PY = 5029967.7055608686 ;
991 | PZ = 4315276.2140877238 ;
992 | VX = 3443.8773904326 ;
993 | VY = -3489.0557007948 ;
994 | VZ = 5847.1990596589 ;
995 | }
996 | gpsData_91 =
997 | {
998 | timeCode = 131862446.0000209800 ;
999 | dateTime = "2013 03 07 04:27:26.000021" ;
1000 | PX = -2241678.4728688225 ;
1001 | PY = 5026475.4902942609 ;
1002 | PZ = 4321120.8980527194 ;
1003 | VX = 3445.9628472722 ;
1004 | VY = -3495.3741885076 ;
1005 | VZ = 5842.1677008845 ;
1006 | }
1007 | gpsData_92 =
1008 | {
1009 | timeCode = 131862447.0000209800 ;
1010 | dateTime = "2013 03 07 04:27:27.000021" ;
1011 | PX = -2238231.4693248891 ;
1012 | PY = 5022976.9584206305 ;
1013 | PZ = 4326960.5472651403 ;
1014 | VX = 3448.0433867642 ;
1015 | VY = -3501.6889136089 ;
1016 | VZ = 5837.1295555336 ;
1017 | }
1018 | gpsData_93 =
1019 | {
1020 | timeCode = 131862448.0000219300 ;
1021 | dateTime = "2013 03 07 04:27:28.000022" ;
1022 | PX = -2234782.3873519297 ;
1023 | PY = 5019472.1138618924 ;
1024 | PZ = 4332795.1549413819 ;
1025 | VX = 3450.1190068244 ;
1026 | VY = -3507.9998683149 ;
1027 | VZ = 5832.0846295626 ;
1028 | }
1029 | gpsData_94 =
1030 | {
1031 | timeCode = 131862449.0000219300 ;
1032 | dateTime = "2013 03 07 04:27:29.000022" ;
1033 | PX = -2231331.2325684126 ;
1034 | PY = 5015960.9600816369 ;
1035 | PZ = 4338624.7143038064 ;
1036 | VX = 3452.1897061068 ;
1037 | VY = -3514.3070441265 ;
1038 | VZ = 5827.0329289355 ;
1039 | }
1040 | gpsData_95 =
1041 | {
1042 | timeCode = 131862450.0000219300 ;
1043 | dateTime = "2013 03 07 04:27:30.000022" ;
1044 | PX = -2227878.0095467167 ;
1045 | PY = 5012443.5010182885 ;
1046 | PZ = 4344449.2185807442 ;
1047 | VX = 3454.2554825414 ;
1048 | VY = -3520.6104332686 ;
1049 | VZ = 5821.9744596240 ;
1050 | }
1051 | gpsData_96 =
1052 | {
1053 | timeCode = 131862451.0000219300 ;
1054 | dateTime = "2013 03 07 04:27:31.000022" ;
1055 | PX = -2224422.7232108233 ;
1056 | PY = 5008919.7404624280 ;
1057 | PZ = 4350268.6610065009 ;
1058 | VX = 3456.3163343090 ;
1059 | VY = -3526.9100277305 ;
1060 | VZ = 5816.9092276079 ;
1061 | }
1062 | gpsData_97 =
1063 | {
1064 | timeCode = 131862452.0000228900 ;
1065 | dateTime = "2013 03 07 04:27:32.000023" ;
1066 | PX = -2220965.3781380411 ;
1067 | PY = 5005389.6823672643 ;
1068 | PZ = 4356083.0348213632 ;
1069 | VX = 3458.3722593516 ;
1070 | VY = -3533.2058197468 ;
1071 | VZ = 5811.8372388746 ;
1072 | }
1073 | gpsData_98 =
1074 | {
1075 | timeCode = 131862453.0000228900 ;
1076 | dateTime = "2013 03 07 04:27:33.000023" ;
1077 | PX = -2217505.9799523721 ;
1078 | PY = 5001853.3302302519 ;
1079 | PZ = 4361892.3332716115 ;
1080 | VX = 3460.4232563549 ;
1081 | VY = -3539.4978008347 ;
1082 | VZ = 5806.7584994193 ;
1083 | }
1084 | gpsData_99 =
1085 | {
1086 | timeCode = 131862454.0000228900 ;
1087 | dateTime = "2013 03 07 04:27:34.000023" ;
1088 | PX = -2214044.5332345674 ;
1089 | PY = 4998310.6880208133 ;
1090 | PZ = 4367696.5496095261 ;
1091 | VX = 3462.4693232755 ;
1092 | VY = -3545.7859632376 ;
1093 | VZ = 5801.6730152451 ;
1094 | }
1095 | gpsData_100 =
1096 | {
1097 | timeCode = 131862455.0000228900 ;
1098 | dateTime = "2013 03 07 04:27:35.000023" ;
1099 | PX = -2210581.0429155380 ;
1100 | PY = 4994761.7595616644 ;
1101 | PZ = 4373495.6770933885 ;
1102 | VX = 3464.5104583221 ;
1103 | VY = -3552.0702989627 ;
1104 | VZ = 5796.5807923628 ;
1105 | }
1106 | gpsData_101 =
1107 | {
1108 | timeCode = 131862456.0000238400 ;
1109 | dateTime = "2013 03 07 04:27:36.000024" ;
1110 | PX = -2207115.5135811353 ;
1111 | PY = 4991206.5488368850 ;
1112 | PZ = 4379289.7089875033 ;
1113 | VX = 3466.5466594632 ;
1114 | VY = -3558.3508002627 ;
1115 | VZ = 5791.4818367909 ;
1116 | }
1117 |
--------------------------------------------------------------------------------
/data_ZY3/NAD.txt:
--------------------------------------------------------------------------------
1 | starttime = 0.000000000000000
2 | pitch = 0.000000000000000
3 | Vpitch = 0.000000000000000
4 | roll = 0.000000000000000
5 | Vroll = 0.000000000000000
6 | yaw = 0.000000000000000
7 | Vyaw = 0.000000000000000
--------------------------------------------------------------------------------
/data_ZY3/zy3.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/data_ZY3/zy3.tif
--------------------------------------------------------------------------------
/dem/n35_e114_1arc_v3.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/dem/n35_e114_1arc_v3.tif
--------------------------------------------------------------------------------
/figs/GCP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/figs/GCP.png
--------------------------------------------------------------------------------
/figs/dem_stretch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/figs/dem_stretch.png
--------------------------------------------------------------------------------
/figs/gcp&satellite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/figs/gcp&satellite.png
--------------------------------------------------------------------------------
/final/coeff.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/final/coeff.npy
--------------------------------------------------------------------------------
/final/partial.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/final/partial.npy
--------------------------------------------------------------------------------
/final/rpc_results.txt:
--------------------------------------------------------------------------------
1 | LINE_OFF: 2688.090909090909 pixels
2 | SAMP_OFF: 4095.090909090909 pixels
3 | LAT_OFF: 35.88334681665021 degrees
4 | LONG_OFF: 114.73574228065243 degrees
5 | HEIGHT_OFF: 494.543231733033 meters
6 | LINE_SCALE: 2688.909090909091 pixels
7 | SAMP_SCALE: 4095.909090909091 pixels
8 | LAT_SCALE: 0.08220727575059072 degrees
9 | LONG_SCALE: 0.13128454220672836 degrees
10 | HEIGHT_SCALE: 453.0027144459248 meters
11 | LINE_NUM_COEFF_1: -0.00036391947811064904
12 | LINE_NUM_COEFF_2: 0.00020260926854126504
13 | LINE_NUM_COEFF_3: -0.3789729392164931
14 | LINE_NUM_COEFF_4: 1.2800567605131667
15 | LINE_NUM_COEFF_5: -0.00018701750144600737
16 | LINE_NUM_COEFF_6: 0.0006491218762221251
17 | LINE_NUM_COEFF_7: 0.22834767621543506
18 | LINE_NUM_COEFF_8: 9.705568088103078e-08
19 | LINE_NUM_COEFF_9: -0.03737461306675982
20 | LINE_NUM_COEFF_10: -0.33089479160213386
21 | LINE_NUM_COEFF_11: 0.0004066178676112031
22 | LINE_NUM_COEFF_12: 0.00018601938056050926
23 | LINE_NUM_COEFF_13: -0.000628345883885828
24 | LINE_NUM_COEFF_14: -6.039628809162423e-05
25 | LINE_NUM_COEFF_15: -0.873164440698929
26 | LINE_NUM_COEFF_16: -0.0006779532570817537
27 | LINE_NUM_COEFF_17: 2.925328995762129
28 | LINE_NUM_COEFF_18: -9.927673730401182e-08
29 | LINE_NUM_COEFF_19: 0.08702736273650657
30 | LINE_NUM_COEFF_20: -3.2715752330417445
31 | LINE_DEN_COEFF_1: 1.0
32 | LINE_DEN_COEFF_2: 0.0005481160594626999
33 | LINE_DEN_COEFF_3: 0.10164342418499928
34 | LINE_DEN_COEFF_4: -0.25928203894739
35 | LINE_DEN_COEFF_5: 3.817568114072856e-05
36 | LINE_DEN_COEFF_6: -0.00012463481175473134
37 | LINE_DEN_COEFF_7: 1.5288739061070373
38 | LINE_DEN_COEFF_8: -0.0004908813499611142
39 | LINE_DEN_COEFF_9: -0.22937991928847623
40 | LINE_DEN_COEFF_10: -2.5559712449604604
41 | LINE_DEN_COEFF_11: -6.82980745292383e-08
42 | LINE_DEN_COEFF_12: 7.287641332065498e-08
43 | LINE_DEN_COEFF_13: -1.6389329317301193e-08
44 | LINE_DEN_COEFF_14: -2.8334829693665853e-07
45 | LINE_DEN_COEFF_15: 0.0017809237539301304
46 | LINE_DEN_COEFF_16: 3.9986637406785874e-07
47 | LINE_DEN_COEFF_17: 0.0010766515843213254
48 | LINE_DEN_COEFF_18: 7.19171666663243e-11
49 | LINE_DEN_COEFF_19: -0.0006393632003774963
50 | LINE_DEN_COEFF_20: 0.00010669010287694958
51 | SAMP_NUM_COEFF_1: 2.2608594227778445e-05
52 | SAMP_NUM_COEFF_2: 2.967322100108291e-05
53 | SAMP_NUM_COEFF_3: 1.0943318443969694
54 | SAMP_NUM_COEFF_4: 0.1918100171290248
55 | SAMP_NUM_COEFF_5: -0.0006514122309582149
56 | SAMP_NUM_COEFF_6: -0.00011862214593882925
57 | SAMP_NUM_COEFF_7: -0.15160231556216175
58 | SAMP_NUM_COEFF_8: -5.654871482053958e-06
59 | SAMP_NUM_COEFF_9: 0.038513017132743244
60 | SAMP_NUM_COEFF_10: -0.02764049964006876
61 | SAMP_NUM_COEFF_11: -0.0008855946291248529
62 | SAMP_NUM_COEFF_12: -0.11130396930599318
63 | SAMP_NUM_COEFF_13: -0.01950844017097353
64 | SAMP_NUM_COEFF_14: -0.0010277509541083418
65 | SAMP_NUM_COEFF_15: -0.48364845656237776
66 | SAMP_NUM_COEFF_16: -0.00013619514356122409
67 | SAMP_NUM_COEFF_17: -0.4919776538422411
68 | SAMP_NUM_COEFF_18: -3.0227303039108097e-06
69 | SAMP_NUM_COEFF_19: -1.4939508449154673
70 | SAMP_NUM_COEFF_20: -0.07945688331172818
71 | SAMP_DEN_COEFF_1: 1.0
72 | SAMP_DEN_COEFF_2: -0.0013905057666114828
73 | SAMP_DEN_COEFF_3: 0.03507381954233324
74 | SAMP_DEN_COEFF_4: -0.14365056850884983
75 | SAMP_DEN_COEFF_5: -0.0009298870813836402
76 | SAMP_DEN_COEFF_6: -0.0005313847911452285
77 | SAMP_DEN_COEFF_7: -0.20261779128361468
78 | SAMP_DEN_COEFF_8: -0.10170926237142908
79 | SAMP_DEN_COEFF_9: -1.365176373899999
80 | SAMP_DEN_COEFF_10: -0.4142168882905821
81 | SAMP_DEN_COEFF_11: 0.00016014585881213295
82 | SAMP_DEN_COEFF_12: 1.4286277632058475e-05
83 | SAMP_DEN_COEFF_13: -0.00010013129882123495
84 | SAMP_DEN_COEFF_14: 0.0010844366049642673
85 | SAMP_DEN_COEFF_15: -0.0014343144920264672
86 | SAMP_DEN_COEFF_16: 0.000328513628386623
87 | SAMP_DEN_COEFF_17: 2.506002974644872e-05
88 | SAMP_DEN_COEFF_18: 8.078491423699208e-05
89 | SAMP_DEN_COEFF_19: 0.00019912729024345634
90 | SAMP_DEN_COEFF_20: -0.0003837747037787609
91 |
--------------------------------------------------------------------------------
/grab_matrix.py:
--------------------------------------------------------------------------------
1 | from selenium import webdriver
2 | from urllib import request
3 | from bs4 import BeautifulSoup
4 | import numpy as np
5 |
6 | #获取网站的矩阵为ECEF转ECI 在此场景使用前需要转置(求逆)
7 |
8 | path_url="https://hpiers.obspm.fr/eop-pc/index.php?index=matrice_php&lang=en"
9 | #demo_url="http://www.baidu.com"
10 | driver=webdriver.Chrome()
11 | driver.get(path_url)
12 |
13 | # name = driver.find_element_by_id("kw")
14 | # name.send_keys("data_operation")
15 |
16 | #year an month mois day jour
17 | #hour heure minute min second sec
18 | name=["an","mois","jour","heure","min","sec"]
19 | t=["2000","06","14","23","59","59"]
20 |
21 | path="/html/body/div[7]/center/div/center/form/table/tbody/tr/td[1]/input[5]"
22 |
23 | # for i in range(len(name)):
24 | # time.sleep(2)
25 | # #info_sender=driver.find_element_by_xpath(path).click()
26 | # info_sender=driver.find_element_by_name(name[i])
27 | # info_sender.send_keys(t[i])
28 | # print(i)
29 |
30 | #提交
31 | submit_button = driver.find_element_by_name("SUBMIT")
32 | submit_button.click()
33 |
34 | #确认
35 | ensure_button = driver.find_element_by_id("proceed-button")
36 | ensure_button.click()
37 |
38 | #获取内容
39 | url_current=driver.current_url
40 | with request.urlopen(url_current) as file:
41 | data = file.read()
42 | #print(data)
43 |
44 | soup=BeautifulSoup(data,'html.parser')
45 |
46 | text=[]
47 | for i in soup.find_all('b'):
48 | text.append(i.get_text())
49 |
50 | matrix=text[-1].split("matrice:")[1].split(" ")
51 |
52 | res=[]
53 | for i in matrix:
54 | if i=='':
55 | continue
56 | res.append(i)
57 | res=np.array(res).astype(np.float).reshape(3,3)
58 | print(res)
59 | driver.quit()
--------------------------------------------------------------------------------
/intermediate_res/b2j.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/intermediate_res/b2j.npy
--------------------------------------------------------------------------------
/intermediate_res/checkpt.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/intermediate_res/checkpt.npy
--------------------------------------------------------------------------------
/intermediate_res/gcp.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/intermediate_res/gcp.npy
--------------------------------------------------------------------------------
/intermediate_res/gps_loc.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/intermediate_res/gps_loc.npy
--------------------------------------------------------------------------------
/intermediate_res/j2w.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/intermediate_res/j2w.npy
--------------------------------------------------------------------------------
/intermediate_res/range.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/intermediate_res/range.npy
--------------------------------------------------------------------------------
/intermediate_res/ux.npy:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/intermediate_res/ux.npy
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | """"
2 | # 摄影时间 Ext.image_time shape(N,1)
3 | # 儒略历日 Ext.transformed_time shape(N,1)
4 | # 卫星姿态 Ext.att shape(N,4)
5 | # 卫星位置 Ext.gps_loc shape(N,3)
6 | # 卫星速度 Ext.gps_v shape(N,3)
7 |
8 | # 相机到本体坐标系 校准矩阵 Rotation.Ru shape(3,3)
9 | # 本体坐标系到J2000坐标系 Rotation.R_b2j shape(N_time,3,3)
10 | # J2000坐标系到WGS84坐标系 Rotation.R_j2w shape(N_time,3,3)
11 | # 初始视向量 Rotation.ux shape(3,N_pix)
12 | """""
13 |
14 | import numpy as np
15 | import os
16 | import yaml
17 | import time
18 |
19 | from multiprocessing.dummy import Pool
20 | from functools import partial
21 | from utility.RPC_utility import RPC
22 | from utility.Ext_utility import Ext
23 | from utility.Rotation_utility import Rotation
24 |
25 |
26 | if __name__== "__main__":
27 |
28 | count_start_time=time.clock()
29 |
30 | file_path = './data_ZY3'
31 | inter_path='./intermediate_res'
32 | out_path='./final'
33 |
34 | if not os.path.exists(inter_path):
35 | os.makedirs(inter_path)
36 | if not os.path.exists(out_path):
37 | os.makedirs(out_path)
38 |
39 | # ————初始值给定—————
40 | f=open("./yml/params.yml")
41 | params=yaml.load(f)
42 | f.close()
43 |
44 | m=params['ctrl_grid_m'] # grid size (w,h)
45 | n=params['ctrl_grid_n']
46 | layers=params['ctrl_layers'] # height layers
47 | z_max=params['max_height'] # height range
48 | z_min=params['min_height']
49 |
50 | w=params['img_col']
51 | h=params['img_row']
52 |
53 | iter_times=params['iter_time'] #rpc解算最大循环次数
54 | iter_thred=params['threshold'] #退出阈值
55 |
56 | # ————摄影瞬间对应的外方位元素———————
57 | attData_dir = file_path+"/DX_ZY3_NAD_att.txt"
58 | gpsData_dir = file_path+"/DX_ZY3_NAD_gps.txt"
59 | imagetime_dir = file_path+"/DX_ZY3_NAD_imagingTime.txt"
60 |
61 | exter_element=Ext(attData_dir,gpsData_dir,imagetime_dir)
62 |
63 | # ————确定每个像点的旋转矩阵———————
64 | Direct_dir=file_path+"/NAD.cbr"
65 | Ru_dir=file_path+"/NAD.txt"
66 | R_j2w_dir=inter_path+'/rot.txt'
67 | rot=Rotation(Ru_dir,Direct_dir,R_j2w_dir,exter_element)
68 |
69 | #保存旋转矩阵
70 | np.save(inter_path+'/j2w.npy',rot.R_j2w)
71 | np.save(inter_path+'/b2j.npy',rot.R_b2j)
72 | np.save(inter_path+'/ux.npy',rot.ux)
73 |
74 | # ——均匀选取像方坐标 沿扫描线方向排列——————
75 |
76 | # 对每一个扫描行
77 | photo_loc = [[int((h-1) / n * j),int((w-1) / m * i)] for j in range(0, n+1) for i in range(0, m+1)]
78 | photo_loc = np.array(photo_loc)
79 |
80 | # ————划定格网点————————
81 | #并行化处理
82 | def grid_function(range_zip,z0):
83 | i, j = range_zip #col,row
84 |
85 | return rot.get_XYZ(rot.ux[:, j], rot.R_b2j[i, :, :], rot.R_j2w[i, :, :]
86 | , exter_element.gps_loc[i, :], z0)
87 |
88 | iter=[[int((h-1) / n * j),int((w-1) / m * i)] for j in range(0, n+1) for i in range(0, m+1)]
89 | h_layer=[z_min+i*(z_max-z_min)/(layers-1) for i in range(layers)]
90 |
91 | pool = Pool(6)
92 |
93 | ground_points=np.array([])
94 | count=0
95 | for ii in h_layer:
96 | partial_func = partial(grid_function, z0=ii)
97 | base_points=np.array(pool.map(partial_func,iter)).squeeze()
98 | if count:
99 | ground_points=np.concatenate([ground_points,base_points])
100 | else:
101 | ground_points=base_points
102 |
103 | count+=1
104 | # ————WGS84 转 BLH——————
105 | ground_points = rot.XYZ2BLH(ground_points)
106 |
107 | np.save(inter_path+"/gcp.npy",ground_points)
108 | print("虚拟控制点构建时间:{:.2f} s".format(time.clock()-count_start_time))
109 | count_pre_time = time.clock()
110 |
111 | # ————RPC模型参数求解————————
112 | photo_loc=np.tile(photo_loc,(layers,1)) #扩展至与gcp相同维数
113 |
114 | rpc=RPC()
115 | a,b,c,d,condition=rpc.cal(photo_loc,ground_points,iter_times,iter_thred) #iter_time:20
116 | #a, b, c, d, condition = rpc.cal_separate(photo_loc, ground_points, 160, 1e-2) # iter_time:100
117 |
118 | print("RPC解算状态:{}".format(condition))
119 | print("有理函数多项式求解时间:{:.2f} s".format(time.clock()-count_pre_time))
120 |
121 | if condition:
122 | rpc.save_res(out_path) #保存为txt
123 | rpc.save_npy(out_path) #保存为npy 便于精度解算
124 | np.save(inter_path+'/range.npy',np.array([np.max(ground_points[:,0]),np.min(ground_points[:,0]),
125 | np.max(ground_points[:,1]),np.min(ground_points[:,1])]))
126 |
--------------------------------------------------------------------------------
/plot.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from matplotlib import pyplot as plt
3 | from mpl_toolkits.mplot3d import Axes3D
4 |
5 | def XYZ2BLH(XYZ):
6 | """
7 | :param XYZ: WGS84坐标系坐标
8 | :return: BLH:经纬度大地高
9 | """
10 | a = 6378137
11 | b = 6356752.314
12 | pi=3.1415926
13 | e2 = (a * a - b * b) / (a * a)
14 | L = np.arctan(XYZ[:, 1] / XYZ[:, 0])
15 | B = np.arctan(XYZ[:, 2] / np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2))
16 |
17 | for i in range(0, 100):
18 | N = a / np.sqrt(1 - e2 * (np.sin(B) ** 2))
19 | H = XYZ[:, 2] / np.sin(B) - N * (1 - e2)
20 |
21 | Bn = np.arctan(XYZ[:, 2] * (N + H) / ((N * (1 - e2) + H) * np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2)))
22 |
23 | if np.max(np.abs(B - Bn)) < 1e-7:
24 | break
25 | B = Bn
26 |
27 | BLH = np.zeros((len(B), 3))
28 | BLH[:, 0] = B /pi*180
29 | BLH[:, 1] = (L /pi*180) +180
30 | BLH[:, 2] = H
31 |
32 | return BLH
33 |
34 | obj=np.load('./intermediate_res/gcp.npy')
35 | gps=np.load('./intermediate_res/gps_loc.npy')
36 |
37 | gps=XYZ2BLH(gps)
38 |
39 | X=gps[:,0] #121:241
40 | Y=gps[:,1]
41 | Z=gps[:,2]
42 |
43 | #print(a)
44 | x=obj[:,0]
45 | y=obj[:,1]
46 | z=obj[:,2]
47 |
48 |
49 | fig=plt.figure()
50 | ax = Axes3D(fig)
51 | ax.scatter(x[0:121],y[0:121],z[0:121],color='c',linewidths=0.01)
52 | ax.scatter(x[121:242],y[121:242],z[121:242],color='k',linewidths=0.01)
53 | ax.scatter(x[242:363],y[242:363],z[242:363],color='b',linewidths=0.01)
54 |
55 | #ax.scatter(x,y,z,color='c',linewidths=0.01)
56 |
57 | #卫星位置
58 | #ax.scatter(X,Y,Z,color='r',linewidths=0.01)
59 |
60 | plt.show()
61 | #fig.savefig('./figs/gcp.png',bbox_inches='tight')
62 |
--------------------------------------------------------------------------------
/precision_check.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import gdal
3 | import yaml
4 | from utility.RPC_utility import RPC
5 |
6 |
7 | def BLH2XYZ(BLH):
8 | a = 6378137.0000
9 | b = 6356752.3141
10 | pi = 3.1415926
11 | e2 = 1 - (b / a) ** 2
12 |
13 | B = BLH[:, 0]
14 | L = BLH[:, 1]
15 | H = BLH[:, 2]
16 |
17 | L = L * pi / 180
18 | B = B * pi / 180
19 |
20 | N = a / np.sqrt(1 - e2 * np.sin(B) ** 2)
21 | x = (N + H) * np.cos(B) * np.cos(L)
22 | y = (N + H) * np.cos(B) * np.sin(L)
23 | z = (N * (1 - e2) + H) * np.sin(B)
24 | return np.vstack((x, y, z)).transpose()
25 |
26 | def XYZ2BLH(XYZ):
27 |
28 | a = 6378137
29 | b = 6356752.314
30 | pi= 3.1415926
31 | e2 = (a * a - b * b) / (a * a)
32 | L = np.arctan(XYZ[:, 1] / XYZ[:, 0])
33 | B = np.arctan(XYZ[:, 2] / np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2))
34 |
35 | for i in range(0, 100):
36 | N = a / np.sqrt(1 - e2 * (np.sin(B) ** 2))
37 | H = XYZ[:, 2] / np.sin(B) - N * (1 - e2)
38 |
39 | Bn = np.arctan(XYZ[:, 2] * (N + H) / ((N * (1 - e2) + H) * np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2)))
40 |
41 | if np.max(np.abs(B - Bn)) < 1e-7:
42 | print('successful transform!')
43 | break
44 | B = Bn
45 |
46 | BLH = np.zeros((len(B), 3))
47 |
48 | #记得转换为角度!!!!!!!!
49 | B=B / pi * 180
50 | L=L / pi * 180
51 |
52 | B[B<0]+=180
53 | L[L<0]+=180
54 |
55 | BLH[:, 0] = B
56 | BLH[:, 1] = L
57 | BLH[:, 2] = H
58 |
59 | return BLH
60 |
61 | def Transform(transformer,w,h):
62 | x=transformer[0]+w*transformer[1]+h*transformer[2]
63 | y=transformer[3]+w*transformer[4]+h*transformer[5]
64 | return x,y
65 |
66 | def ReverTrans(transformer,x,y):
67 | mat=np.array([[transformer[1],transformer[2]],[transformer[4],transformer[5]]])
68 | coe=np.array([[x-transformer[0]],[y-transformer[3]]])
69 | res=np.dot(np.linalg.inv(mat),coe)
70 | return res[0],res[1] # w,h
71 |
72 | def GetCheckGrid(path_range,path_dem,m,n):
73 |
74 | f = gdal.Open(path_dem)
75 |
76 | im_width = f.RasterXSize # 栅格矩阵的列数
77 | im_height = f.RasterYSize # 栅格矩阵的行数
78 | im_data = f.ReadAsArray(0, 0, im_width, im_height) # 获取数据
79 | transformer = f.GetGeoTransform()
80 |
81 | # Range
82 | #35.9, 35.84 114.8, 114.69
83 | y_max, y_min, x_max, x_min = np.load(path_range)
84 |
85 | y_max-=0.05
86 | y_min+=0.05
87 | x_max-=0.05
88 | x_min+=0.05
89 |
90 | w_max, h_max = ReverTrans(transformer,x_max, y_min)
91 | w_min, h_min = ReverTrans(transformer,x_min, y_max)
92 |
93 | # 均分格网点
94 | w, h = w_max, h_max
95 | dx, dy = w_min, h_min
96 |
97 | pts = [[int((h - dy) / n * j + dy), int((w - dx) / m * i + dx)] for j in range(0, n + 1) for i in range(0, m + 1)]
98 |
99 | res = []
100 | for pt in pts:
101 | l, b = Transform(transformer,pt[1], pt[0])
102 | hh = im_data[pt[0], pt[1]]
103 | res.append([b, l, hh])
104 |
105 | return np.array(res)
106 |
107 | # ————外精度检查——————————
108 | if __name__== "__main__":
109 |
110 | root_path='./intermediate_res/'
111 |
112 | gps_loc=np.load(root_path+'gps_loc.npy')
113 | R_j2w=np.load(root_path+'j2w.npy')
114 | R_b2j=np.load(root_path+'b2j.npy')
115 | ux=np.load(root_path+'ux.npy')
116 |
117 | #check_pt=np.load(root_path+"checkpt.npy")
118 |
119 | #根据格网获取检查点
120 | f = open("./yml/params.yml")
121 | params = yaml.load(f)
122 | f.close()
123 | grid_m=params['check_grid_m']
124 | grid_n=params['check_grid_n']
125 | check_pt = GetCheckGrid(root_path + 'range.npy','./dem/n35_e114_1arc_v3.tif',grid_m,grid_n)
126 | np.save(root_path+"checkpt.npy",check_pt)
127 |
128 | coeff=np.load('./final/coeff.npy')
129 | partial=np.load('./final/partial.npy')
130 | rpc=RPC()
131 | rpc.init_from_outer(coeff,partial)
132 |
133 | check_pt = BLH2XYZ(check_pt)
134 | pho_check, ground_check = rpc.check(check_pt, gps_loc, R_j2w, R_b2j,ux)
135 |
136 | ground_check = XYZ2BLH(ground_check)
137 | pho_check, ground_check = rpc.norm_gravi(pho_check, ground_check, rpc.center)
138 | l = pho_check.shape[0]
139 |
140 | # 计算像点坐标
141 | pho_check_pred = rpc.cal_pho_from_RFM(ground_check)
142 |
143 | print("——精度评价结果———")
144 | # 计算去重心化的坐标为宜
145 | # error_row = np.mean(np.abs(pho_check_pred[:, 0] - pho_check[:, 0]))
146 | # error_col = np.mean(np.abs(pho_check_pred[:, 1] - pho_check[:, 1]))
147 | # print('MAE in ROW(normalized):{}'.format(error_row))
148 | # print('MAE in COL(normalized):{}'.format(error_col))
149 |
150 | # 去重心化
151 | pho_check_pred = rpc.de_norm_gravi_pho(pho_check_pred, rpc.center)
152 | pho_check = rpc.de_norm_gravi_pho(pho_check, rpc.center)
153 |
154 | # MAE -mean absolute error
155 | error_row = np.mean(np.abs(pho_check_pred[:, 0] - pho_check[:, 0]))
156 | error_col = np.mean(np.abs(pho_check_pred[:, 1] - pho_check[:, 1]))
157 |
158 | print('MAE in ROW:{}'.format(error_row))
159 | print('MAE in COL:{}'.format(error_col))
160 |
--------------------------------------------------------------------------------
/preprocessing.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import gdal
3 | import yaml
4 | import cv2
5 | import jdcal
6 | import os
7 |
8 | from utility.Ext_utility import Ext
9 | '''
10 | 初始化
11 | 获得各扫描行J2000转WGS84坐标旋转矩阵
12 | 获得测区高程范围
13 | 指定格网点
14 | '''
15 |
16 | if __name__ == "__main__":
17 |
18 | ######指定参数##########
19 | yaml_path='./yml/params.yml'
20 | yaml_dict={}
21 | yaml_dict['ctrl_grid_m']=10 # 格网数(m,n) 对应 grid size (w,h)
22 | yaml_dict['ctrl_grid_n']=10
23 | yaml_dict['ctrl_layers']=6 # 分层
24 | yaml_dict['check_grid_m']=20
25 | yaml_dict['check_grid_n']=20
26 |
27 | yaml_dict['iter_time']=20 #rpc解算最大循环次数
28 | yaml_dict['threshold']=0.0015 #退出阈值
29 |
30 | img = cv2.imread('./data_ZY3/zy3.tif')
31 | h, w, _ = img.shape
32 | yaml_dict['img_row']=h
33 | yaml_dict['img_col']=w
34 | ######################
35 |
36 | # ————摄影瞬间对应的外方位元素———————
37 | file_path = './data_ZY3'
38 | attData_dir = file_path + "/DX_ZY3_NAD_att.txt"
39 | gpsData_dir = file_path + "/DX_ZY3_NAD_gps.txt"
40 | imagetime_dir = file_path + "/DX_ZY3_NAD_imagingTime.txt"
41 |
42 | exter_element = Ext(attData_dir, gpsData_dir, imagetime_dir)
43 |
44 | delta_day = exter_element.transformed_time[:, 2] - (exter_element.transformed_time[:, 2]).astype(np.int)
45 |
46 | # 儒略历日
47 | # jd_time = []
48 | # for i in range(len(exter_element.transformed_time)):
49 | # jd_time.append(sum(jdcal.gcal2jd(exter_element.transformed_time[i][0], exter_element.transformed_time[i][1],
50 | # exter_element.transformed_time[i][2])))
51 | # jd_time = np.array(jd_time)
52 | # jd_time += delta_day
53 |
54 | output_path="./intermediate_res/"
55 |
56 | if not os.path.exists(output_path):
57 | os.makedirs(output_path)
58 |
59 | #f=open(output_path+"jd_time.txt","w")
60 |
61 | # for i in jd_time:
62 | # f.write(str(i)+'\n')
63 | # f.close()
64 |
65 | #保存卫星位置
66 | np.save(output_path + "gps_loc.npy", exter_element.gps_loc)
67 |
68 | #获取高程范围
69 | f = gdal.Open('./dem/n35_e114_1arc_v3.tif')
70 |
71 | im_width = f.RasterXSize # 栅格矩阵的列数
72 | im_height = f.RasterYSize # 栅格矩阵的行数
73 | im_data = f.ReadAsArray(0, 0, im_width, im_height) # 获取数据
74 | h_max=np.max(im_data)
75 | h_min=np.min(im_data)
76 | print("————获取测区DEM信息————")
77 | print("Height! max:{} min:{} ".format(h_max, h_min))
78 |
79 | # 仿射变换得到XY
80 | transformer = f.GetGeoTransform()
81 |
82 | yaml_dict['max_height']=h_max.item()
83 | yaml_dict['min_height']=h_min.item()
84 | f=open(yaml_path,"w")
85 | yaml.dump(yaml_dict,f)
86 | f.close()
87 |
88 | def Transform(w, h):
89 | x = transformer[0] + w * transformer[1] + h * transformer[2]
90 | y = transformer[3] + w * transformer[4] + h * transformer[5]
91 | return x, y
92 |
93 |
94 | def ReverTrans(x, y):
95 | mat = np.array([[transformer[1], transformer[2]], [transformer[4], transformer[5]]])
96 | coe = np.array([[x - transformer[0]], [y - transformer[3]]])
97 | res = np.dot(np.linalg.inv(mat), coe)
98 | return res[0], res[1] # w,h
99 |
100 |
101 | top_left_x, top_left_y = Transform(0, 0)
102 | bottom_right_x, bottom_right_y = Transform(im_width - 1, im_height - 1)
103 |
104 | print("Range! top left:{:.2f} {:.2f} bottom right:{:.2f} {:.2f}"
105 | .format(top_left_x, top_left_y, bottom_right_x, bottom_right_y))
106 |
107 | #保存扫描行对应utc时间
108 | f=open(output_path+"ac_time.txt","w")
109 |
110 | hour=(delta_day*24).astype(np.int)
111 | minute=((delta_day*24-hour)*60).astype(np.int)
112 | second=(((delta_day*24-hour)*60)-minute)*60
113 |
114 | for i in range(len(exter_element.transformed_time)):
115 | f.write(str(int(exter_element.transformed_time[i][0]))+" "+str(int(exter_element.transformed_time[i][1]))+" "
116 | +str(int(exter_element.transformed_time[i][2]))+" "+str(hour[i])+" "+str(minute[i])+" "+str(second[i])
117 | +"\n")
118 |
119 | f.close()
--------------------------------------------------------------------------------
/ref/RPC.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/ref/RPC.pdf
--------------------------------------------------------------------------------
/ref/Zy3仿真数据说明.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/ref/Zy3仿真数据说明.docx
--------------------------------------------------------------------------------
/ref/利用视线向量的资源三号卫星影像严格几何处理模型.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/ref/利用视线向量的资源三号卫星影像严格几何处理模型.pdf
--------------------------------------------------------------------------------
/ref/有理函数模型的解算与应用_巩丹超.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Charrrrrlie/RPC-Calculator/323c45634d75032ab61d804689fbe2246851b749/ref/有理函数模型的解算与应用_巩丹超.pdf
--------------------------------------------------------------------------------
/utility/Ext_utility.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | from matplotlib import pyplot as plt
4 |
5 | #返回 self.image_time att gps 三者长度相同
6 |
7 | class Ext:
8 |
9 | def __init__(self,attData_dir,gpsData_dir,imgTime_dir):
10 |
11 | self.image_time=self.load_imagetime(imgTime_dir)
12 | self.gps_data,self.gps_time=self.load_gpsData(gpsData_dir)
13 | self.att_data,self.att_time=self.load_attData(attData_dir)
14 | self.transformed_time = self.transform_time(self.image_time)
15 |
16 | if len(self.image_time)==0 or len(self.gps_data)==0 or len(self.att_data)==0:
17 | print("读入外方位相关数据出错")
18 | else:
19 | self.att=self.att_interpolate(self.image_time,self.att_data,self.att_time)
20 | self.gps_loc,self.gps_v=self.gps_interpolate(self.image_time,self.gps_data,self.gps_time)
21 |
22 | def load_gpsData(self,gpsData_dir):
23 | """
24 | load gpsData from DX_ZY3_NAD_gps.txt
25 | input: gpsData_dir : file path
26 | return:
27 | gpsData(array, shape of (groupNumber,6)): PX PY PZ VX VY VZ;
28 | gpsData_time(array, shape of(groupNumber,1)): timeCode
29 | """
30 | data_info = [] # 存放所有从txt文件中读出的数据
31 | for line in open(gpsData_dir, "r"):
32 | line = line[:-1] # 逐行读,去掉每行最后的换行符
33 | data_info.append(line)
34 | # A为临时变量,将数据格式从list转为string,为了在提取数据时中使用split函数
35 | A = ''.join(data_info)
36 | B = A.split("}")[:-1]
37 |
38 | # 定义gpsData矩阵,shape = (101,6);存放离散时刻的卫星wgs84坐标下的位置;
39 | # 6个列元素分别为PX;PY;PZ;VX;VY;VZ;
40 | # 定义gpsData_time矩阵, shape = (101,1);存放对应的时刻(timeCode)
41 | gpsData = np.zeros((len(B), 6))
42 | gpsData_time = np.zeros((len(B), 1))
43 | for i in range(0, len(B)):
44 | tmp = B[i].split(";")
45 | tmp = tmp[:-1]
46 | gpsData_time[i] = ''.join(tmp[-8]).split("=")[2]
47 | for j in range(1, 7):
48 | gpsData[i][-j] = ''.join(tmp[-j]).split("=")[1]
49 |
50 | return gpsData, gpsData_time
51 |
52 | def load_attData(self,attData_dir):
53 | """"
54 | load AttData from DX_ZY3_NAD_att.txt
55 |
56 | input: AddData_dir : file path
57 | return:
58 | AttData(array, shape of (groupNumber,4)): q1 q2 q3 q4
59 | AttData_time(array, shape of(groupNumber,1)): timeCode
60 |
61 | """
62 | data_info = [] # 存放所有从txt文件中读出的数据
63 | for line in open(attData_dir, "r"):
64 | line = line[:-1] # 逐行读,去掉每行最后的换行符
65 | data_info.append(line)
66 | # A为临时变量,将数据格式从list转为string,为了在提取数据时中使用split函数
67 | A = ''.join(data_info)
68 | B = A.split("}")[:-1]
69 |
70 | # 定义gpsData矩阵,shape = (401,4) ;存放离散时刻的卫星wgs84坐标下的位置
71 | # 4个列元素分别为 q1 q2 q3 q4
72 | # 定义gpsData_time矩阵, shape = (401,1);存放对应的时刻(timeCode)
73 | AttData = np.zeros((len(B), 4))
74 | AttData_time = np.zeros((len(B), 1))
75 | for i in range(0, len(B)):
76 | tmp = B[i].split(";")
77 | tmp = tmp[:-1]
78 | AttData_time[i] = ''.join(tmp[-12]).split("=")[2]
79 | for j in range(1, 5):
80 | AttData[i][-j] = ''.join(tmp[-j]).split("=")[1]
81 |
82 | return AttData, AttData_time
83 |
84 | def load_imagetime(self, imgTime_dir): # 读取时间文件
85 | imagetime = np.loadtxt(imgTime_dir, usecols=1, skiprows=1)
86 | return imagetime
87 |
88 | def transform_time(self,imageTime):
89 | #basetime
90 | timecode0 = 131862356.2500000000
91 | dateTime0 = np.array([[2013,3,7+4.0/24+25/(24*60)+56.25/(24*60*60)]])
92 |
93 | transformed_time=dateTime0.repeat(len(imageTime),axis=0)
94 | transformed_time[:,-1] = transformed_time[:,-1]+(imageTime - timecode0)/(24*60*60)
95 | return transformed_time
96 |
97 | def att_interpolate(self,imageTime, AttData, AttData_time):
98 | """"
99 | interpolate att
100 | input:
101 | imageTime : 成像时刻
102 | AttData : 存放各离散时刻四元数的矩阵
103 | AttData_time : 存放与AttData对应的TimeCode
104 | return:
105 | qt(array, shape of (N,4)): 每一时刻的四元数
106 | """
107 | deltaTime = 0.25
108 | index = ((imageTime - AttData_time[0]) // deltaTime).astype(np.int)
109 | t0 = AttData_time[index]
110 | t = imageTime.reshape(len(imageTime),1)
111 | t1 = AttData_time[index + 1]
112 |
113 | q0 = AttData[index]
114 | q1 = AttData[index + 1]
115 | #统一插值
116 | theta = np.arccos(np.sum(np.abs(q0*q1),axis=1)).reshape(-1,1)
117 |
118 | # 退化为线性插值情况
119 | # qt=np.zeros(q0.shape)
120 | # for ii in range(len(theta)):
121 | # d1=t1[ii]-t[ii]
122 | # d2=t[ii]-t0[ii]
123 | # d =t1[ii]-t0[ii]
124 | #
125 | # if theta[ii]>0.99:
126 | # y0=d1/d
127 | # y1=d2/d
128 | # else:
129 | # y0 = np.sin(theta[ii]*d1/d)/np.sin(theta[ii])
130 | # y1 = np.sin(theta[ii]*d2/d)/np.sin(theta[ii])
131 | # qt[ii] = y0 * q0[ii] + y1 * q1[ii]
132 |
133 | y0 = np.true_divide(np.sin(theta * np.true_divide(t1 - t, t1 - t0)), np.sin(theta))
134 | y1 = np.true_divide(np.sin(theta * np.true_divide(t - t0, t1 - t0)), np.sin(theta))
135 | qt = y0 * q0 + y1 * q1
136 |
137 | #绘图测试
138 | #plt.figure("test_Draw")
139 | #l=range(len(q0))
140 | #plt.plot(l,qt[:,0])
141 | #plt.plot(l,qt[:,1])
142 | #plt.plot(l,qt[:,2])
143 | #plt.plot(l,qt[:,3])
144 |
145 | #plt.show()
146 | # f=open('intermediate_res/qt.txt','w')
147 | # for i in range(len(q0)):
148 | # f.write(str(qt[i,0])+" "+str(qt[i,1])+" "+str(qt[i,2])+" "+str(qt[i,3])+"\n")
149 | # f.close()
150 |
151 | return qt
152 |
153 | def gps_interpolate(self,imageTime, gpsData, gpsData_time):
154 | """"
155 | interpolate P V
156 | input:
157 | imageTime : 成像时刻
158 | gpsData : 存放各离散时刻gps数据的矩阵
159 | gpsData_time : 存放与gpsData对应的TimeCode
160 | return:
161 | PX(array, shape of (N,3)): 每一时刻的位置向量
162 | VX(array, shape of (N,3)): 每一时刻的速度向量
163 | """
164 | deltaTime = 1.0
165 | index = ((imageTime - gpsData_time[0]) // deltaTime).astype(np.int)
166 | l = len(imageTime)
167 | tx = imageTime.reshape(l,1)
168 | t = np.zeros((l,1,9))
169 | P = np.zeros((l,3,9))
170 | V = np.zeros((l,3,9))
171 |
172 | for i in range(0, 9):
173 | t[:,:,i] = gpsData_time[index + i - 4]
174 | P[:,:,i] = gpsData[index + i - 4, 0:3]
175 | V[:,:,i] = gpsData[index + i - 4, 3:6]
176 | PX = VX = np.zeros((l,3))
177 | for j in range(0, 9):
178 | s = np.ones((l,1))
179 | for i in range(0, 9):
180 | if i == j:
181 | continue
182 | s = np.multiply(s,np.true_divide(tx - t[:,:,i],t[:,:,j] - t[:,:,i]))
183 | sp = s * P[:,:,j]
184 | sv = s * V[:,:,j]
185 | PX = PX + sp
186 | VX = VX + sv
187 |
188 | return PX, VX
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/utility/RPC_utility.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import sys
3 | """
4 | rn=p1(X,Y,Z)/p2(X,Y,Z)
5 | cn=p3(X,Y,Z)/p4(X,Y,Z)
6 | 像方坐标 pho 重心化后 pho_g
7 | 物方坐标 obj 重心化后 obj_g
8 | """
9 |
10 | class RPC:
11 |
12 | def __init__(self):
13 | self.a=np.ones(20)
14 | self.b=np.ones(20)
15 | self.c=np.ones(20)
16 | self.d=np.ones(20)
17 |
18 | #重心化 返回像方col row物方 XYZ 重心
19 | def gravity(self,pho,obj):
20 |
21 | #gravity center
22 | c_g=pho[:,1].flatten().mean()
23 | r_g=pho[:,0].flatten().mean()
24 |
25 | c_s = max(np.max(pho[:,1]) - c_g, c_g - np.min(pho[:,1]))
26 | r_s = max(np.max(pho[:,0]) - r_g, r_g - np.min(pho[:,0]))
27 |
28 | X_g=obj[:,0].flatten().mean()
29 | Y_g=obj[:,1].flatten().mean()
30 | Z_g=obj[:,2].flatten().mean()
31 |
32 | X_s= max(np.max(obj[:,0])-X_g,X_g-np.min(obj[:,0]))
33 | Y_s= max(np.max(obj[:,1])-Y_g,Y_g-np.min(obj[:,1]))
34 | Z_s= max(np.max(obj[:,2])-Z_g,Z_g-np.min(obj[:,2]))
35 |
36 |
37 | return [c_g,r_g,c_s,r_s, X_g,Y_g,Z_g,X_s,Y_s,Z_s]
38 |
39 | #行列一同解算 以向量形式计算
40 | def diff(self,pho_loc,obj_loc):
41 |
42 | #column vector
43 | #物方坐标
44 | X=obj_loc[:,0].reshape(-1,1)
45 | Y=obj_loc[:,1].reshape(-1,1)
46 | Z=obj_loc[:,2].reshape(-1,1)
47 | #像方坐标
48 | R=pho_loc[:,0].reshape(-1,1)
49 | C=pho_loc[:,1].reshape(-1,1)
50 |
51 | l=len(X)
52 |
53 | vec=np.hstack([np.ones((l,1)),Z,Y,X,Z*Y,Z*X,Y*X,Z*Z,Y*Y,X*X,Z*Y*X,Z*Z*Y,Z*Z*X
54 | ,Y*Y*Z,Y*Y*X,Z*X*X,Y*X*X,Z*Z*Z,Y*Y*Y,X*X*X])
55 |
56 | # 误差方程系数 row
57 | # J = np.concatenate([self.a, self.b[1:]]).transpose()
58 | B=np.dot(vec,self.b.reshape(-1,1))
59 | M=np.concatenate([vec, -np.multiply(R,vec[:,1:])], axis=1)
60 | W_R=np.true_divide(np.identity(l),B)
61 |
62 | #column
63 | # K = np.concatenate([self.c, self.d[1:]]).transpose()
64 | D = np.dot(vec, self.d.reshape(-1,1))
65 | N=np.concatenate([vec,-np.multiply(C,vec[:,1:])],axis=1)
66 | W_C = np.true_divide(np.identity(l),D)
67 |
68 | # 法方程
69 | # AT*W*W*A * U= AT*W*W *L
70 | # U=np.concatenate([J,K])
71 | A=np.block(
72 | [
73 | [M , np.zeros(N.shape)],
74 | [np.zeros(M.shape), N]
75 | ])
76 | W=np.block(
77 | [
78 | [W_R, np.zeros(W_C.shape)],
79 | [np.zeros(W_R.shape), W_C]
80 | ]
81 | )
82 | L=np.concatenate([R,C])
83 |
84 | mat_t=np.dot(np.dot(np.dot(A.transpose(),W),W),A)
85 | det_val=np.linalg.det(mat_t)
86 | if det_val<1e-2:
87 | print("接近奇异矩阵!特征值为:{}".format(det_val))
88 |
89 | U=np.dot(np.dot(np.dot(np.dot(np.linalg.inv(mat_t),A.transpose()),W),W),L)
90 | v=np.dot(np.dot(W,A),U)-np.dot(W,L)
91 | return U,v
92 |
93 | #行列分别解算
94 | def diff_separate(self,pho_loc,obj_loc):
95 | # column vector
96 | # 物方坐标
97 | X = obj_loc[:, 0].reshape(-1, 1)
98 | Y = obj_loc[:, 1].reshape(-1, 1)
99 | Z = obj_loc[:, 2].reshape(-1, 1)
100 | # 像方坐标
101 | R = pho_loc[:, 0].reshape(-1, 1)
102 | C = pho_loc[:, 1].reshape(-1, 1)
103 |
104 | l = len(X)
105 |
106 | vec = np.hstack(
107 | [np.ones((l, 1)), Z, Y, X, Z * Y, Z * X, Y * X, Z * Z, Y * Y, X * X, Z * Y * X, Z * Z * Y, Z * Z * X
108 | , Y * Y * Z, Y * Y * X, Z * X * X, Y * X * X, Z * Z * Z, Y * Y * Y, X * X * X])
109 |
110 | # 误差方程系数 row
111 | # J = np.concatenate([self.a, self.b[1:]]).transpose()
112 | B = np.dot(vec, self.b.reshape(-1, 1))
113 | M = np.concatenate([vec, -np.multiply(R, vec[:, 1:])], axis=1)
114 | W_R = np.true_divide(np.identity(l), B)
115 |
116 | # column
117 | # K = np.concatenate([self.c, self.d[1:]]).transpose()
118 | D = np.dot(vec, self.d.reshape(-1, 1))
119 | N = np.concatenate([vec, -np.multiply(C, vec[:, 1:])], axis=1)
120 | W_C = np.true_divide(np.identity(l), D)
121 |
122 | mat_row = np.dot(np.dot(np.dot(M.transpose(), W_R), W_R), M)
123 | mat_col = np.dot(np.dot(np.dot(N.transpose(), W_C), W_C), N)
124 |
125 | J = np.dot(np.dot(np.dot(np.dot(np.linalg.inv(mat_row), M.transpose()), W_R), W_R), R)
126 | K = np.dot(np.dot(np.dot(np.dot(np.linalg.inv(mat_col), N.transpose()), W_C), W_C), C)
127 | v_R = np.dot(np.dot(W_R, M), J) - np.dot(W_R, R)
128 | v_C = np.dot(np.dot(W_C, N), K) - np.dot(W_C, C)
129 | return J, K, v_R, v_C
130 |
131 | #初始化
132 | def initialize(self,pho_loc,obj_loc):
133 | # column vector
134 | # 物方坐标
135 | X = obj_loc[:, 0].reshape(-1, 1)
136 | Y = obj_loc[:, 1].reshape(-1, 1)
137 | Z = obj_loc[:, 2].reshape(-1, 1)
138 | # 像方坐标
139 | R = pho_loc[:, 0].reshape(-1, 1)
140 | C = pho_loc[:, 1].reshape(-1, 1)
141 |
142 | l = len(X)
143 |
144 | vec = np.hstack(
145 | [np.ones((l, 1)), Z, Y, X, Z * Y, Z * X, Y * X, Z * Z, Y * Y, X * X, Z * Y * X, Z * Z * Y, Z * Z * X
146 | , Y * Y * Z, Y * Y * X, Z * X * X, Y * X * X, Z * Z * Z, Y * Y * Y, X * X * X])
147 | M=np.concatenate([vec, -np.multiply(R, vec[:, 1:])], axis=1)
148 | N=np.concatenate([vec, -np.multiply(C, vec[:, 1:])], axis=1)
149 |
150 | A = np.block(
151 | [
152 | [M, np.zeros(N.shape)],
153 | [np.zeros(M.shape), N]
154 | ])
155 | L = np.concatenate([R, C])
156 |
157 | temp_init=np.dot(np.dot(np.linalg.inv(np.dot(A.transpose(),A)),A.transpose()),L)
158 | self.a=temp_init[0:20].flatten(order='F')
159 | self.b[1:]=temp_init[20:39].flatten(order='F')
160 | self.c=temp_init[39:59].flatten(order='F')
161 | self.d[1:]=temp_init[59:78].flatten(order='F')
162 |
163 | #temp_init
164 |
165 | #行列分别解算
166 | def initialize_separate(self,pho_loc,obj_loc):
167 | # column vector
168 | # 物方坐标
169 | X = obj_loc[:, 0].reshape(-1, 1)
170 | Y = obj_loc[:, 1].reshape(-1, 1)
171 | Z = obj_loc[:, 2].reshape(-1, 1)
172 | # 像方坐标
173 | R = pho_loc[:, 0].reshape(-1, 1)
174 | C = pho_loc[:, 1].reshape(-1, 1)
175 |
176 | l = len(X)
177 |
178 | vec = np.hstack(
179 | [np.ones((l, 1)), Z, Y, X, Z * Y, Z * X, Y * X, Z * Z, Y * Y, X * X, Z * Y * X, Z * Z * Y, Z * Z * X
180 | , Y * Y * Z, Y * Y * X, Z * X * X, Y * X * X, Z * Z * Z, Y * Y * Y, X * X * X])
181 | M = np.concatenate([vec, -np.multiply(R, vec[:, 1:])], axis=1)
182 | N = np.concatenate([vec, -np.multiply(C, vec[:, 1:])], axis=1)
183 |
184 | ab_init = np.dot(np.dot(np.linalg.inv(np.dot(M.transpose(), M)), M.transpose()), R)
185 | cd_init = np.dot(np.dot(np.linalg.inv(np.dot(N.transpose(), N)), N.transpose()), C)
186 | self.a = ab_init[0:20].flatten(order='F')
187 | self.b[1:] = ab_init[20:39].flatten(order='F')
188 | self.c = cd_init[0:20].flatten(order='F')
189 | self.d[1:] = cd_init[20:39].flatten(order='F')
190 |
191 | #迭代求解系数
192 | def cal(self,pho,obj,times,thred):
193 |
194 | #重心化 c_g,r_g,c_s,r_s, X_g,Y_g,Z_g,X_s,Y_s,Z_s
195 | center_g=self.gravity(pho,obj)
196 |
197 | self.center=center_g
198 |
199 | pho_n=pho.astype(np.float)
200 | obj_n=obj.astype(np.float)
201 | pho_n[:,1] = (pho_n[:,1]-center_g[0])/center_g[2] # col
202 | pho_n[:,0] = (pho_n[:,0]-center_g[1])/center_g[3] # row
203 |
204 | obj_n[:,0] = (obj_n[:,0]-center_g[4])/center_g[7] # B
205 | obj_n[:,1] = (obj_n[:,1]-center_g[5])/center_g[8] # L
206 | obj_n[:,2] = (obj_n[:,2]-center_g[6])/center_g[9] # H
207 |
208 | #初始化!
209 | self.initialize(pho_n,obj_n)
210 |
211 | count=1
212 | #循环迭代
213 | while(times):
214 |
215 | temp_u,v=self.diff(pho_n,obj_n)
216 | temp_a=temp_u[0:20].flatten(order='F')
217 | temp_b=temp_u[20:39].flatten(order='F') #b从b1开始
218 | temp_c=temp_u[39:59].flatten(order='F')
219 | temp_d=temp_u[59:78].flatten(order='F') #d从d1开始
220 |
221 | # print(np.max(abs(self.a-temp_a)))
222 | # print(np.max(abs(self.b[1:]-temp_b)))
223 | # print(np.max(abs(self.c-temp_c)))
224 | # print(np.max(abs(self.d[1:]-temp_d)))
225 | # print('——————————————————')
226 |
227 |
228 | #if (abs(self.a-temp_a) 0 and x_ > 0 and xe > 0:
387 | iteration = False
388 | invalid.append(i)
389 | else:
390 | if (xs * x_ <= 0):
391 | Ne = N_
392 | elif (x_ * xe <= 0):
393 | Ns = N_
394 | else:
395 | Ns = int((Ns + N_) / 2)
396 | Ne = int((Ne + N_) / 2)
397 |
398 | if abs(Ne - Ns) <= 1:
399 | iteration = False
400 | check_x.append(int(N_))
401 | check_y.append(int(np.argmin(np.abs(y_-ux[1,:]))))
402 | #row col
403 | return np.vstack((check_x, check_y)).transpose().astype(np.float), np.delete(data,invalid,axis=0)
404 |
405 | #共线条件方程计算严密像点坐标
406 | def cal_phopt(self,N,R_j2w,R_b2j,XYZ,gps_loc):
407 | XYZs = gps_loc[N]
408 | R=np.dot(R_j2w[N],R_b2j[N])
409 | R=np.linalg.inv(R)
410 | XYZ_hat=np.dot(R,XYZ-XYZs)
411 | return -XYZ_hat[0]/XYZ_hat[2],-XYZ_hat[1]/XYZ_hat[2]
412 |
413 | #以rpc相同偏置归一
414 | def norm_gravi(self,pho,obj,center):
415 | # 重心化 c_g,r_g,c_s,r_s, X_g,Y_g,Z_g,X_s,Y_s,Z_s
416 | pho[:, 1] = (pho[:, 1] - center[0]) / center[2] # col
417 | pho[:, 0] = (pho[:, 0] - center[1]) / center[3] # row
418 |
419 | obj[:, 0] = (obj[:, 0] - center[4]) / center[7] # B
420 | obj[:, 1] = (obj[:, 1] - center[5]) / center[8] # L
421 | obj[:, 2] = (obj[:, 2] - center[6]) / center[9] # H
422 |
423 | return pho,obj
424 |
425 | #去归一化
426 | def de_norm_gravi_pho(self,pho,center):
427 | pho[:,1]=pho[:, 1]*center[2]+center[0] #col
428 | pho[:,0]=pho[:,0]*center[3]+center[1] #row
429 | return pho
430 |
431 | def de_norm_gravi_obj(self, obj, center):
432 | obj[:, 0] = obj[:, 0]*center[7] + center[4] # B
433 | obj[:, 1] = obj[:, 1]*center[8] + center[5] # L
434 | obj[:, 2] = obj[:, 2]*center[9] + center[6] # H
435 | return obj
436 |
437 | #利用正解变换计算像点坐标
438 | def cal_pho_from_RFM(self,obj):
439 | # 物方坐标
440 | X = obj[:, 0].reshape(-1, 1)
441 | Y = obj[:, 1].reshape(-1, 1)
442 | Z = obj[:, 2].reshape(-1, 1)
443 | l=len(X)
444 |
445 | vec = np.hstack(
446 | [np.ones((l, 1)), Z, Y, X, Z * Y, Z * X, Y * X, Z * Z, Y * Y, X * X, Z * Y * X, Z * Z * Y, Z * Z * X
447 | , Y * Y * Z, Y * Y * X, Z * X * X, Y * X * X, Z * Z * Z, Y * Y * Y, X * X * X])
448 |
449 | row=np.true_divide(np.dot(vec,self.a),np.dot(vec,self.b))
450 | col=np.true_divide(np.dot(vec,self.c),np.dot(vec,self.d))
451 |
452 | return np.vstack((row,col)).transpose()
453 |
454 | #外源初始化
455 | def init_from_outer(self,coeff,center):
456 | self.center=center
457 | self.a=coeff[:,0]
458 | self.b=coeff[:,1]
459 | self.c=coeff[:,2]
460 | self.d=coeff[:,3]
--------------------------------------------------------------------------------
/utility/Rotation_utility.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import math
3 | from scipy.spatial.transform import Rotation as R
4 |
5 | class Rotation:
6 |
7 | def __init__(self,path_Ru,path_Direct,path_rot,exter_element):
8 |
9 | #相机到本体坐标系 校准矩阵
10 | self.Ru=self.load_Ru(path_Ru)
11 |
12 | #本体坐标系到J2000坐标系 shape(N_time,3,3)
13 | self.R_b2j=R.from_quat(exter_element.att).as_matrix()
14 |
15 | #J2000坐标系到WGS84坐标系 shape(N_time,3,3)
16 | self.R_j2w=self.load_Rj2w(path_rot)
17 |
18 | #指向角文件 shape(N_time,2)
19 | direct_data=self.load_direct_data(path_Direct)
20 |
21 | if self.Ru==[] or self.R_b2j==[] or self.R_j2w==[] or len(direct_data)==0:
22 | print("读入旋转矩阵相关数据出错")
23 | else:
24 | #初始视向量 shape(3,N_pix)
25 | self.ux=self.get_ux(direct_data)
26 |
27 | def load_direct_data(self,dir):
28 | direct = np.loadtxt(dir, usecols=(1, 2), skiprows=1)
29 | return direct
30 |
31 | def load_Ru(self,dir):
32 | f = open(dir)
33 | data = f.readlines()
34 | f.close()
35 |
36 | #pitch phi
37 | p = float(data[1].split('=', 1)[1])
38 | #roll omega
39 | r = float(data[3].split('=', 1)[1])
40 | #yaw kappa
41 | y = float(data[5].split('=', 1)[1])
42 |
43 | R_phi=np.array([
44 | [math.cos(p),0,-math.sin(p)],
45 | [ 0 , 1, 0 ],
46 | [math.sin(p), 0, math.cos(p)],
47 | ])
48 | R_omega=np.array([
49 | [ 1 , 0 , 0 ],
50 | [ 0 ,math.cos(r), -math.sin(r)],
51 | [ 0 ,math.sin(r), math.cos(r)],
52 | ])
53 | R_kappa=np.array([
54 | [math.cos(y), -math.sin(y) ,0],
55 | [math.sin(y), math.cos(y) ,0],
56 | [0, 0, 1],
57 | ])
58 |
59 | return np.dot(np.dot(R_phi,R_omega),R_kappa)
60 |
61 | def load_Rj2w(self,dir):
62 | f = open(dir)
63 | data=f.readlines()
64 | f.close()
65 |
66 | res=[]
67 | for i in data:
68 | res.append(i.split(" ")[0:-1])
69 | res=np.array(res).reshape(-1,3,3).astype(np.float)
70 | return res
71 |
72 | def get_ux(self,directData):
73 | """
74 | :param directData: 指向角文件 id 垂轨指向角 沿轨指向角
75 | :return: 旋转前的视向量ux 3*N
76 | """
77 | length=len(directData)
78 | return np.concatenate([np.tan(directData[:,1]).reshape(1,length)
79 | ,np.tan(directData[:,0]).reshape(1,length)
80 | ,-np.ones((1,length))])
81 |
82 | #解二次函数
83 | def result(self,a, b, c):
84 | derat = b ** 2 - 4 * a * c
85 | if a == 0:
86 | if b != 0:
87 | x = -c / b
88 | return x
89 | else:
90 | return '无解 '
91 | else:
92 | if derat < 0:
93 | return '无实根 '
94 | elif derat == 0:
95 | x = -b / (2 * a)
96 | return x
97 | else:
98 | xone = (-b + math.sqrt(derat)) / (2 * a)
99 | xtwo = (-b - math.sqrt(derat)) / (2 * a)
100 | return max(xone, xtwo)
101 |
102 | #比例系数
103 | def get_M(self,UX,PX,h):
104 | """
105 | :param UX,PX: 旋转后的视向量UX,卫星坐标
106 | :return: 比例系数与焦距的乘积m=u*f
107 | """
108 | # WGS84椭球参数
109 | A=6378137+h
110 | B=6356752.3142+h
111 | #二次函数系数分别为a,b,c
112 | a=(UX[0]*UX[0]+UX[1]*UX[1])/(A*A)+UX[2]*UX[2]/(B*B)
113 | b=2*((UX[0]*PX[0]+UX[1]*PX[1])/(A*A)+UX[2]*PX[2]/(B*B))
114 | c=(PX[0]*PX[0]+PX[1]*PX[1])/(A*A)+PX[2]*PX[2]/(B*B)-1
115 | u=self.result(a,b,c)
116 | if len(u)==1:
117 | #print(u)
118 | m=u
119 | else:
120 | print('无解 a:{} b:{} c:{}'.format(a,b,c))
121 | m=0 #随便赋了个值
122 | return m
123 |
124 | def get_XYZ(self,ux,R1,R2,PX,h):
125 | """
126 | :param ux:旋转前的视向量ux
127 | :param R1:本体坐标系到J2000坐标系的转换
128 | :param R2:J2000坐标系到WGS84坐标系的转换
129 | :param Ru:相机坐标系到本体坐标系
130 | :param PX:卫星GPS位置
131 | :param h:虚拟格网点高程
132 | :return:像点对应地面坐标XYZ
133 | """
134 |
135 | # R2=np.array([[-0.6215, -0.7834 , 0.0008],
136 | # [0.7834, -0.6215, -0.0010],
137 | # [0.0013, -0.0000, 1.0000]])
138 |
139 | #f=0.043
140 | #ux*=f
141 |
142 | ux=ux.reshape(-1,1)
143 | PX=PX.reshape(-1,1)
144 |
145 | U=np.dot(self.Ru,ux)#中间变量U
146 | U=np.dot(R1,U)
147 | UX=np.dot(R2,U) #旋转后的视向量
148 |
149 | m=self.get_M(UX,PX,h)
150 | U=UX*m
151 | XYZ=PX+U
152 |
153 | return XYZ
154 |
155 | def XYZ2BLH(self,XYZ):
156 | """
157 | :param XYZ: WGS84坐标系坐标
158 | :return: BLH:经纬度大地高
159 | """
160 | a = 6378137
161 | b = 6356752.314
162 | pi= 3.1415926
163 | e2 = (a * a - b * b) / (a * a)
164 | L = np.arctan(XYZ[:, 1] / XYZ[:, 0])
165 | B = np.arctan(XYZ[:, 2] / np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2))
166 |
167 | for i in range(0, 100):
168 | N = a / np.sqrt(1 - e2 * (np.sin(B) ** 2))
169 | H = XYZ[:, 2] / np.sin(B) - N * (1 - e2)
170 |
171 | Bn = np.arctan(XYZ[:, 2] * (N + H) / ((N * (1 - e2) + H) * np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2)))
172 |
173 | if np.max(np.abs(B - Bn)) < 1e-7:
174 | print('successful transform!')
175 | break
176 | B = Bn
177 |
178 | BLH = np.zeros((len(B), 3))
179 |
180 | #记得转换为角度!!!!!!!!
181 | B=B / pi * 180
182 | L=L / pi * 180
183 |
184 | B[B<0]+=180
185 | L[L<0]+=180
186 |
187 | BLH[:, 0] = B
188 | BLH[:, 1] = L
189 | BLH[:, 2] = H
190 |
191 | return BLH
192 |
193 | def XYZ2BLH2(self,XYZ):
194 | """
195 | 第二种转换方式
196 | :param XYZ: WGS84坐标系坐标
197 | :return: BLH:经纬度大地高
198 | """
199 |
200 | a = 6378137
201 | b = 6356752.314
202 | pi = 3.1415926
203 |
204 | e2 = (a * a - b * b) / (a * a)
205 | L = np.arctan(XYZ[:, 1] / XYZ[:, 0])
206 | B = np.arctan(XYZ[:, 2] / np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2))
207 |
208 | for i in range(0, 100):
209 | N = a / np.sqrt(1 - e2 * (np.sin(B) ** 2))
210 | H = np.sqrt(XYZ[:,0]**2 + XYZ[:, 1]**2) / np.cos(B) - N
211 | Bn = np.arctan((XYZ[:, 2]+ N * e2 * np.sin(B)) / (np.sqrt(XYZ[:, 0] ** 2 + XYZ[:, 1] ** 2)))
212 |
213 | if np.max(np.abs(B - Bn)) < 1e-7:
214 | print('successful transform!')
215 | break
216 | B = Bn
217 |
218 | BLH = np.zeros((len(B), 3))
219 |
220 | # 记得转换为角度!!!!!!!!
221 | B = B / pi * 180
222 | L = L / pi * 180
223 |
224 | B[B < 0] += 180
225 | L[L < 0] += 180
226 |
227 | BLH[:, 0] = B
228 | BLH[:, 1] = L
229 | BLH[:, 2] = H
230 | return BLH
231 |
232 | def BLH2XYZ(self,BLH):
233 | a = 6378137.0000
234 | b = 6356752.3141
235 | pi = 3.1415926
236 | e2 = 1 - (b / a) ** 2
237 |
238 | B=BLH[:,0]
239 | L=BLH[:,1]
240 | H=BLH[:,2]
241 |
242 | L = L * pi / 180
243 | B = B * pi / 180
244 |
245 | N = a / np.sqrt(1 - e2 * np.sin(B) ** 2)
246 | x = (N + H) * np.cos(B) * np.cos(L)
247 | y = (N + H) * np.cos(B) * np.sin(L)
248 | z = (N * (1 - e2) + H) * np.sin(B)
249 | return np.vstack((x,y,z)).transpose()
--------------------------------------------------------------------------------
/yml/params.yml:
--------------------------------------------------------------------------------
1 | check_grid_m: 20
2 | check_grid_n: 20
3 | ctrl_grid_m: 10
4 | ctrl_grid_n: 10
5 | ctrl_layers: 6
6 | img_col: 8192
7 | img_row: 5378
8 | iter_time: 20
9 | max_height: 947
10 | min_height: 41
11 | threshold: 0.0015
12 |
--------------------------------------------------------------------------------