├── 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 | --------------------------------------------------------------------------------