RasterProcessTool/Toolbox/SimulationSARTool/SimulationSAR/GPUBPTool.cu

293 lines
8.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <memory>
#include <cmath>
#include <complex>
#include <device_launch_parameters.h>
#include <cuda_runtime.h>
#include <cublas_v2.h>
#include <cuComplex.h>
#include "BaseConstVariable.h"
#include "GPUTool.cuh"
#include "GPUBPTool.cuh"
#include <cmath>
#include <stdio.h>
#include <cassert>
#define EPSILON 1e-12
#define MAX_ITER 50
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
__device__ double angleBetweenVectors(Vector3 a, Vector3 b, bool returnDegrees ) {
// 计算点积
double dotProduct = a.x * b.x + a.y * b.y + a.z * b.z;
// 计算模长
double magA = sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
double magB = sqrt(b.x * b.x + b.y * b.y + b.z * b.z);
// 处理零向量异常
if (magA == 0.0 || magB == 0.0) {
return NAN;
}
double cosTheta = dotProduct / (magA * magB);
cosTheta = cosTheta < -1 ? -1 : cosTheta>1 ? 1 : cosTheta; // 截断到[-1, 1]
double angleRad = acos(cosTheta);
return returnDegrees ? angleRad * 180.0 / M_PI : angleRad;
}
// 向量运算
__device__ Vector3 vec_sub(Vector3 a, Vector3 b) {
return { a.x - b.x, a.y - b.y, a.z - b.z };
}
__device__ double vec_dot(Vector3 a, Vector3 b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
}
__device__ Vector3 vec_cross(Vector3 a, Vector3 b) {
return { a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x };
}
__device__ Vector3 vec_normalize(Vector3 v) {
double len = sqrt(vec_dot(v, v));
return (len > 1e-12) ? Vector3{ v.x / len, v.y / len, v.z / len } : v;
}
// 标准正交基底坐标计算
__device__ Vector3 coordinates_orthonormal_basis(Vector3& A,
Vector3& e1,
Vector3& e2,
Vector3& e3) {
//// 验证基底正交性和单位长度容差1e-10
//const double tolerance = 1e-10;
//assert(fabs(dot(e1, e2)) < tolerance);
//assert(fabs(dot(e1, e3)) < tolerance);
//assert(fabs(dot(e2, e3)) < tolerance);
//assert(fabs(norm(e1) - 1.0) < tolerance);
//assert(fabs(norm(e2) - 1.0) < tolerance);
//assert(fabs(norm(e3) - 1.0) < tolerance);
// 计算投影坐标
return Vector3{
vec_dot(A, e1),
vec_dot(A, e2),
vec_dot(A, e3)
};
}
// 计算视线交点T
extern __device__ Vector3 compute_T(Vector3 S, Vector3 ray, double H) {
Vector3 dir = vec_normalize(ray);
double a_h = WGS84_A + H;
double A = (dir.x * dir.x + dir.y * dir.y) / (a_h * a_h) + dir.z * dir.z / (WGS84_B * WGS84_B); // A > 0
double B = 2.0 * (S.x * dir.x / (a_h * a_h) + S.y * dir.y / (a_h * a_h) + S.z * dir.z / (WGS84_B * WGS84_B));
double C = (S.x * S.x + S.y * S.y) / (a_h * a_h) + S.z * S.z / (WGS84_B * WGS84_B) - 1.0;
double disc = B * B - 4 * A * C;
if (disc < 0) return Vector3{ NAN, NAN, NAN };
double sqrt_d = sqrt(disc);
double t = fmin((-B - sqrt_d) / (2 * A), (-B + sqrt_d) / (2 * A));// 取最小值
return (t > 1e-6) ? Vector3{ S.x + dir.x * t, S.y + dir.y * t, S.z + dir.z * t }
: Vector3{ NAN, NAN, NAN };
}
// 主计算函数A
extern __device__ Vector3 compute_P(Vector3 S, Vector3 T, double R, double H) {
Vector3 ex, ey, ez; // 平面基函数
Vector3 ST = vec_normalize(vec_sub(T, S));// S->T
Vector3 SO = vec_normalize(vec_sub(Vector3{ 0, 0, 0 }, S)); // S->O
Vector3 st1 = vec_sub(T, S);
double R0 = sqrt(st1.x * st1.x + st1.y * st1.y + st1.z * st1.z);
// S (Z .) --------Y
// |\
// | \
// | \
// X \
// | -> T
// | /
// | /
// | /
// |/
// O
ez = vec_normalize(vec_cross(SO, ST)); // Z 轴
ey = vec_normalize(vec_cross(ez, SO)); // Y 轴 与 ST 同向 --这个结论在星地几何约束,便是显然的;
ex = vec_normalize(SO); //X轴
// 大致的理论推导
// 这里考虑 成像几何,所以点 P 一定在 ex-0-ey 平面上所以t3=0;
// 定义 SP 的向量与 ex的夹角为 theta , 目标长度为 t
// t1=t*cos(Q);
// t2=t*sin(Q);
// h=(a+H)
// Xp=Sx+t1*ex.x+t2*ey.x +t3*ez.x; //因为 t3=0
// Yp=Sy+t1*ex.y+t2*ey.y +t3*ez.y;
// Zp=Sz+t1*ex.z+t2*ey.z +t3*ez.z;
// Xp^2+Yp^2 Zp^2 Xp^2+Yp^2 Zp^2
// ---------- + ------- = 1 ==> ---------- + ------- = 1
// (a+H)^2 b^2 h^2 b^2
double h2 = (WGS84_A + H) * (WGS84_A + H);
double b2 = WGS84_B * WGS84_B;
double R2 = R * R;
double A = R2 * ((ex.x * ex.x + ex.y * ex.y) / h2 + (ex.z * ex.z) / b2);
double B = R2 * ((ex.x * ey.x + ex.y * ey.y) / h2 + (ex.z * ey.z) / b2) * 2;
double C = R2 * ((ey.x * ey.x + ey.y * ey.y) / h2 + (ey.z * ey.z) / b2);
double D = 1 - ((S.x * S.x + S.y * S.y) / h2 + (S.z * S.z) / b2);
double E = 2 * R * ((S.x * ex.x + S.y * ex.y) / h2 + (S.z * ex.z) / b2);
double F = 2 * R * ((S.x * ey.x + S.y * ey.y) / h2 + (S.z * ey.z) / b2);
// f(Q)=Acos^2(Q)+Bsin(Q)cos(Q)+Csin^2(Q)+E*cos(Q)+F*sin(Q)-D
// f'(Q)=(CA)sin(2Q)+2Bcos(2Q)-Esin(Q)+Fcos(Q)
// 牛顿迭代
// f(Q)
// Q(t+1)=Q - -----------
// f'(Q)
// 求解初始值
double Q0 = angleBetweenVectors(SO, ST, false);
double dQ = 0;
double fQ = 0;
double dfQ = 0;
double Q = R < R0 ? Q0 - 1e-3 : Q0 + 1e-3;
// 牛顿迭代法
for (int iter = 0; iter < MAX_ITER * 10; ++iter) {
fQ = A * cos(Q) * cos(Q) + B * sin(Q) * cos(Q) + C * sin(Q) * sin(Q) + E * cos(Q) + F * sin(Q) - D;
dfQ = (C - A) * sin(2 * Q) + B * cos(2 * Q) - E * sin(Q) + F * cos(Q);
dQ = fQ / dfQ;
if (abs(dQ) < 1e-8) {
break;
}
else {
dQ = abs(dQ) < d2r * 2 ? dQ : abs(dQ) / dQ * d2r;
Q = Q - dQ;
}
}
double t1 = R * cos(Q);
double t2 = R * sin(Q);
Vector3 P = {
S.x + t1 * ex.x + t2 * ey.x, //因为 t3=0
S.y + t1 * ex.y + t2 * ey.y,
S.z + t1 * ex.z + t2 * ey.z,
};
// 椭球验证
double check = (P.x * P.x + P.y * P.y) / ((WGS84_A + H) * (WGS84_A + H))
+ P.z * P.z / (WGS84_B * WGS84_B);
if (isnan(Q) || isinf(Q) || fabs(check - 1.0) > 1e-6) {
return Vector3{ NAN,NAN,NAN };
printf("check value =%f\n", fabs(check - 1.0));
}
return P;
}
__device__ double angleBetweenVectors_single(Vector3_single a, Vector3_single b, bool returnDegrees)
{
// 计算点积
float dotProduct = a.x * b.x + a.y * b.y + a.z * b.z;
// 计算模长
float magA = sqrtf(a.x * a.x + a.y * a.y + a.z * a.z);
float magB = sqrtf(b.x * b.x + b.y * b.y + b.z * b.z);
// 处理零向量异常
if (magA == 0.0 || magB == 0.0) {
return NAN;
}
float cosTheta = dotProduct / (magA * magB);
cosTheta = cosTheta < -1 ? -1 : cosTheta>1 ? 1 : cosTheta; // 截断到[-1, 1]
float angleRad = acosf(cosTheta);
return returnDegrees ? angleRad * 180.0 / M_PI : angleRad;
}
__device__ Vector3_single vec_sub_single(Vector3_single a, Vector3_single b)
{
return { a.x - b.x, a.y - b.y, a.z - b.z };
}
__device__ float vec_dot_single(Vector3_single a, Vector3_single b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
__device__ Vector3_single vec_cross_single(Vector3_single a, Vector3_single b)
{
return Vector3_single{ a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x };
}
//// 参数校验与主函数
//int main() {
// Vector3 S = { -2.8e6, -4.2e6, 3.5e6 }; // 卫星位置 (m)
// Vector3 ray = { 0.6, 0.4, -0.7 }; // 视线方向
// double H = 500.0; // 平均高程
// double R = 1000.0; // 目标距离
//
// // 参数校验
// if (R <= 0 || H < -WGS84_A * 0.1 || H > WGS84_A * 0.1) {
// printf("参数错误:\n H范围±%.1f km\n R必须>0\n", WGS84_A * 0.1 / 1000);
// return 1;
// }
//
// // Step 1: 计算交点T
// Vector3 T = compute_T(S, ray, H);
// if (isnan(T.x)) {
// printf("错误:视线未与椭球相交\n");
// return 1;
// }
//
// // Step 2: 计算目标点P
// Vector3 P = compute_P(S, T, R, H);
//
// if (!isnan(P.x)) {
// printf("计算结果:\n");
// printf("P = (%.3f, %.3f, %.3f) m\n", P.x, P.y, P.z);
//
// // 验证距离
// Vector3 SP = vec_sub(P, S);
// double dist = sqrt(vec_dot(SP, SP));
// printf("实际距离:%.3f m (期望:%.1f m)\n", dist, R);
//
// // 验证椭球
// double check = (P.x * P.x + P.y * P.y) / ((WGS84_A + H) * (WGS84_A + H))
// + P.z * P.z / (WGS84_B * WGS84_B);
// printf("椭球验证:%.6f (期望1.0)\n", check);
//
// // 验证最近距离
// Vector3 PT = vec_sub(P, T);
// printf("到T点距离%.3f m\n", sqrt(vec_dot(PT, PT)));
// }
// else {
// printf("未找到有效解\n");
// }
//
// return 0;
//}
//