From 8bc08ec6f2ae53662d869144df0bf663e51dc2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=A2=9E=E8=BE=89?= <3045316072@qq.com> Date: Mon, 23 Dec 2024 10:51:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9RTPC=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BaseConstVariable.h | 5 +- BaseLibraryCPP.rar | Bin 56013 -> 0 bytes BaseTool.cpp | 45 ++++- BaseTool.h | 6 +- EchoDataFormat.cpp | 18 ++ EchoDataFormat.h | 3 + GPUTool.cu | 403 ++++++++++++++++++++++++++++++++++++++---- GPUTool.cuh | 38 +++- ImageOperatorBase.cpp | 32 +++- ImageOperatorBase.h | 155 ++++++++++++---- 10 files changed, 616 insertions(+), 89 deletions(-) delete mode 100644 BaseLibraryCPP.rar diff --git a/BaseConstVariable.h b/BaseConstVariable.h index 1aaa76b..2339c16 100644 --- a/BaseConstVariable.h +++ b/BaseConstVariable.h @@ -3,7 +3,7 @@ #ifndef BASECONSTVARIABLE_H #define BASECONSTVARIABLE_H #define EIGEN_USE_MKL_ALL -#define EIGEN_NO_DEBUG +//#define EIGEN_NO_DEBUG #define EIGEN_USE_BLAS @@ -14,6 +14,7 @@ #define __CUDANVCC___ // 定义CUDA函数 +//#define __PRFDEBUG__ @@ -29,7 +30,7 @@ #define r2d 180/3.141592653589793238462643383279 #define d2r 3.141592653589793238462643383279/180 #define LIGHTSPEED 299792458 -#define PRECISIONTOLERANCE 1e-9 +#define PRECISIONTOLERANCE 1e-6 #define Radians2Degrees(Radians) Radians*PI_180 #define Degrees2Radians(Degrees) Degrees*T180_PI #define EARTHWE 0.000072292115 diff --git a/BaseLibraryCPP.rar b/BaseLibraryCPP.rar deleted file mode 100644 index 8bf6eaa698a5605ba90c1f1db1b063058b7b23fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 56013 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 /* 提供了向量结构*/ #include #include +#include @@ -500,7 +501,7 @@ long FindValueInStdVectorLast(std::vector& list, double& insertValue) long high = list.size() - 1; long mid = -1; // 处理边界 - if (list[high] <= insertValue) + if (list[high]+ PRECISIONTOLERANCE < insertValue) { return -1; } @@ -584,3 +585,45 @@ QVector SatelliteAntPos2SatellitePos(QVector pose } return antposes; } + + +QString getDebugDataPath(QString filename) +{ + QString folderName = "debugdata"; + QString appDir = QCoreApplication::applicationDirPath(); + QString folderpath = JoinPath(appDir, folderName); + if (!QDir(folderpath).exists()) { + QDir(appDir).mkdir(folderName); + } + QString datapath = JoinPath(folderpath, filename); + QFile datafile(datapath); + if (datafile.exists()) { + datafile.remove(); + } + return datapath; +} + + +std::vector split(const std::string& str, char delimiter) { + std::vector tokens; + std::string token; + std::istringstream tokenStream(str); + + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(token); + } + + return tokens; +} + + +Eigen::VectorXd linspace(double start, double stop, int num) { + Eigen::VectorXd result(num); + + double step = (stop - start) / (num - 1); // 计算步长 + for (int i = 0; i < num; ++i) { + result[i] = start + i * step; // 生成等间距数值 + } + + return result; +} \ No newline at end of file diff --git a/BaseTool.h b/BaseTool.h index ccb0c1b..a08e3bf 100644 --- a/BaseTool.h +++ b/BaseTool.h @@ -111,7 +111,7 @@ QVector SatellitePos2SatelliteAntPos(QVector pose QVector SatelliteAntPos2SatellitePos(QVector poses); - - - +QString getDebugDataPath(QString filename); +std::vector split(const std::string& str, char delimiter); +Eigen::VectorXd linspace(double start, double stop, int num); #endif \ No newline at end of file diff --git a/EchoDataFormat.cpp b/EchoDataFormat.cpp index b6ceecf..9437f61 100644 --- a/EchoDataFormat.cpp +++ b/EchoDataFormat.cpp @@ -249,6 +249,24 @@ QString EchoL0Dataset::getEchoDataFilename() return GPSPointFilePath; } +void EchoL0Dataset::initEchoArr(std::complex init0) +{ + long blockline = Memory1MB * 2000 / 8 / 2 / this->PlusePoints; + + long start = 0; + for (start = 0; start < this->PluseCount; start = start + blockline) { + long templine = start + blockline < this->PluseCount ? blockline : this->PluseCount - start; + std::shared_ptr> echotemp = this->getEchoArr(start, templine); + for (long i = 0; i < templine; i++) { + for (long j = 0; j < this->PlusePoints; j++) { + echotemp.get()[i * this->PlusePoints + j] = init0; + } + } + this->saveEchoArr(echotemp, start, templine); + qDebug() << "echo init col : " << start << "\t-\t" << start + templine << "\t/\t" << this->PluseCount; + } +} + // Getter Setter ʵ long EchoL0Dataset::getPluseCount() { return this->PluseCount; } void EchoL0Dataset::setPluseCount(long pulseCount) { this->PluseCount = pulseCount; } diff --git a/EchoDataFormat.h b/EchoDataFormat.h index 887baa4..f276bdd 100644 --- a/EchoDataFormat.h +++ b/EchoDataFormat.h @@ -108,6 +108,9 @@ public: QString getGPSPointFilename(); QString getEchoDataFilename(); + void initEchoArr(std::complex init0); + + private: // Ʒ QString folder; QString filename; diff --git a/GPUTool.cu b/GPUTool.cu index 18fce48..8eaa011 100644 --- a/GPUTool.cu +++ b/GPUTool.cu @@ -29,7 +29,8 @@ __device__ cuComplex cuCexpf(cuComplex x) // __device__ float GPU_getSigma0dB(CUDASigmaParam param, float theta) { - return param.p1 + param.p2 * exp(-param.p3 * theta) + param.p4 * cos(param.p5 * theta + param.p6); + float sigma= param.p1 + param.p2 * exp(-param.p3 * theta) + param.p4 * cos(param.p5 * theta + param.p6); + return sigma; } __device__ CUDAVector GPU_VectorAB(CUDAVector A, CUDAVector B) { @@ -96,6 +97,12 @@ __device__ float GPU_BillerInterpAntPattern(float* antpattern, float searththeta, float searchphi) { float stheta = searththeta; float sphi = searchphi; + if (stheta > 90) { + return 0; + } + else {} + + float pthetaid = (stheta - starttheta) / dtheta;// float pphiid = (sphi - startphi) / dphi; @@ -103,6 +110,7 @@ __device__ float GPU_BillerInterpAntPattern(float* antpattern, long nextTheta = lasttheta + 1; long lastphi = floorf(pphiid); long nextPhi = lastphi + 1; + if (lasttheta < 0 || nextTheta < 0 || lastphi < 0 || nextPhi < 0 || lasttheta >= thetapoints || nextTheta >= thetapoints || lastphi >= phipoints || nextPhi >= phipoints) @@ -124,10 +132,10 @@ __device__ float GPU_BillerInterpAntPattern(float* antpattern, float z22 = antpattern[nextTheta * phipoints + nextPhi]; - z11 = powf(10, z11 / 10); - z12 = powf(10, z12 / 10); - z21 = powf(10, z21 / 10); - z22 = powf(10, z22 / 10); + //z11 = powf(10, z11 / 10); // dB-> + //z12 = powf(10, z12 / 10); + //z21 = powf(10, z21 / 10); + //z22 = powf(10, z22 / 10); float GainValue = (z11 * (x2 - x) * (y2 - y) + z21 * (x - x1) * (y2 - y) @@ -170,7 +178,7 @@ __global__ void CUDA_B_DistanceA(float* Ax, float* Ay, float* Az, float Bx, floa __global__ void CUDA_make_VectorA_B(float sX, float sY, float sZ, float* tX, float* tY, float* tZ, float* RstX, float* RstY, float* RstZ, long len) { long idx = blockIdx.x * blockDim.x + threadIdx.x; if (idx < len) { - RstX[idx] = sX - tX[idx]; + RstX[idx] = sX - tX[idx]; // -> RstY[idx] = sY - tY[idx]; RstZ[idx] = sZ - tZ[idx]; } @@ -209,9 +217,9 @@ __global__ void CUDA_SatelliteAntDirectNormal(float* RstX, float* RstY, float* R , long len) { long idx = blockIdx.x * blockDim.x + threadIdx.x; if (idx < len) { - float Xst = -1 * RstX[idx]; // --> - float Yst = -1 * RstY[idx]; - float Zst = -1 * RstZ[idx]; + float Xst = -1 * RstX[idx]; // --> + float Yst = -1 * RstY[idx]; + float Zst = -1 * RstZ[idx]; float AntXaxisX = antXaxisX; float AntXaxisY = antXaxisY; float AntXaxisZ = antXaxisZ; @@ -221,17 +229,80 @@ __global__ void CUDA_SatelliteAntDirectNormal(float* RstX, float* RstY, float* R float AntZaxisX = antZaxisX; float AntZaxisY = antZaxisY; float AntZaxisZ = antZaxisZ; - // ָϵµֵ - float Xant = (Xst * (AntYaxisY * AntZaxisZ - AntYaxisZ * AntZaxisY) + Xst * (AntXaxisZ * AntZaxisY - AntXaxisY * AntZaxisZ) + Xst * (AntXaxisY * AntYaxisZ - AntXaxisZ * AntYaxisY)) / (AntXaxisX * (AntYaxisY * AntZaxisZ - AntZaxisY * AntYaxisZ) - AntYaxisX * (AntXaxisY * AntZaxisZ - AntXaxisZ * AntZaxisY) + AntZaxisX * (AntXaxisY * AntYaxisZ - AntXaxisZ * AntYaxisY)); - float Yant = (Yst * (AntYaxisZ * AntZaxisX - AntYaxisX * AntZaxisZ) + Yst * (AntXaxisX * AntZaxisZ - AntXaxisZ * AntZaxisX) + Yst * (AntYaxisX * AntXaxisZ - AntXaxisX * AntYaxisZ)) / (AntXaxisX * (AntYaxisY * AntZaxisZ - AntZaxisY * AntYaxisZ) - AntYaxisX * (AntXaxisY * AntZaxisZ - AntXaxisZ * AntZaxisY) + AntZaxisX * (AntXaxisY * AntYaxisZ - AntXaxisZ * AntYaxisY)); - float Zant = (Zst * (AntYaxisX * AntZaxisY - AntYaxisY * AntZaxisX) + Zst * (AntXaxisY * AntZaxisX - AntXaxisX * AntZaxisY) + Zst * (AntXaxisX * AntYaxisY - AntYaxisX * AntXaxisY)) / (AntXaxisX * (AntYaxisY * AntZaxisZ - AntZaxisY * AntYaxisZ) - AntYaxisX * (AntXaxisY * AntZaxisZ - AntXaxisZ * AntZaxisY) + AntZaxisX * (AntXaxisY * AntYaxisZ - AntXaxisZ * AntYaxisY)); + + // һ + float RstNorm = sqrtf(Xst * Xst + Yst * Yst + Zst * Zst); + float AntXaxisNorm = sqrtf(AntXaxisX * AntXaxisX + AntXaxisY * AntXaxisY + AntXaxisZ * AntXaxisZ); + float AntYaxisNorm = sqrtf(AntYaxisX * AntYaxisX + AntYaxisY * AntYaxisY + AntYaxisZ * AntYaxisZ); + float AntZaxisNorm = sqrtf(AntZaxisX * AntZaxisX + AntZaxisY * AntZaxisY + AntZaxisZ * AntZaxisZ); + + + float Rx = Xst / RstNorm; + float Ry = Yst / RstNorm; + float Rz = Zst / RstNorm; + float Xx = AntXaxisX / AntXaxisNorm; + float Xy = AntXaxisY / AntXaxisNorm; + float Xz = AntXaxisZ / AntXaxisNorm; + float Yx = AntYaxisX / AntYaxisNorm; + float Yy = AntYaxisY / AntYaxisNorm; + float Yz = AntYaxisZ / AntYaxisNorm; + float Zx = AntZaxisX / AntZaxisNorm; + float Zy = AntZaxisY / AntZaxisNorm; + float Zz = AntZaxisZ / AntZaxisNorm; + + float Xant = (Rx * Yy * Zz - Rx * Yz * Zy - Ry * Yx * Zz + Ry * Yz * Zx + Rz * Yx * Zy - Rz * Yy * Zx) / (Xx * Yy * Zz - Xx * Yz * Zy - Xy * Yx * Zz + Xy * Yz * Zx + Xz * Yx * Zy - Xz * Yy * Zx); + float Yant = -(Rx * Xy * Zz - Rx * Xz * Zy - Ry * Xx * Zz + Ry * Xz * Zx + Rz * Xx * Zy - Rz * Xy * Zx) / (Xx * Yy * Zz - Xx * Yz * Zy - Xy * Yx * Zz + Xy * Yz * Zx + Xz * Yx * Zy - Xz * Yy * Zx); + float Zant = (Rx * Xy * Yz - Rx * Xz * Yy - Ry * Xx * Yz + Ry * Xz * Yx + Rz * Xx * Yy - Rz * Xy * Yx) / (Xx * Yy * Zz - Xx * Yz * Zy - Xy * Yx * Zz + Xy * Yz * Zx + Xz * Yx * Zy - Xz * Yy * Zx); + + // theta phi float Norm = sqrtf(Xant * Xant + Yant * Yant + Zant * Zant); // pho float ThetaAnt = acosf(Zant / Norm); // theta Zļн - float YsinTheta = Yant / sinf(ThetaAnt); - float PhiAnt = (YsinTheta / abs(YsinTheta)) * acosf(Xant / (Norm * sinf(ThetaAnt))); - thetaAnt[idx] = ThetaAnt; - phiAnt[idx] = PhiAnt; + float PhiAnt = atanf(Yant / Xant); // -pi/2 ~pi/2 + + + if (abs(Yant) < PRECISIONTOLERANCE) { // X + PhiAnt = 0; + } + else if (abs(Xant) < PRECISIONTOLERANCE) { // Yϣԭ + if (Yant > 0) { + PhiAnt = PI / 2; + } + else { + PhiAnt = -PI / 2; + } + } + else if (Xant < 0) { + if (Yant > 0) { + PhiAnt = PI + PhiAnt; + } + else { + PhiAnt = -PI+PhiAnt ; + } + } + else { // Xant>0 X + + } + + if (isnan(PhiAnt)) { + printf("V=[%f,%f,%f];norm=%f;thetaAnt=%f;phiAnt=%f;\n", Xant, Yant, Zant,Norm, ThetaAnt, PhiAnt); + } + + //if (abs(ThetaAnt - 0) < PRECISIONTOLERANCE) { + // PhiAnt = 0; + //} + //else {} + + + thetaAnt[idx] = ThetaAnt*r2d; + phiAnt[idx] = PhiAnt*r2d; + //printf("Rst=[%f,%f,%f];AntXaxis = [%f, %f, %f];AntYaxis=[%f,%f,%f];AntZaxis=[%f,%f,%f];phiAnt=%f;thetaAnt=%f;\n", Xst, Yst, Zst + // , AntXaxisX, AntXaxisY, AntXaxisZ + // , AntYaxisX, AntYaxisY, AntYaxisZ + // , AntZaxisX, AntZaxisY, AntZaxisZ + // , phiAnt[idx] + // , thetaAnt[idx] + //); } } @@ -331,12 +402,12 @@ __global__ void CUDA_RTPC( //printf("\ntheta: %f\t,%f ,%f ,%f ,%f ,%f ,%f \n", localangle * r2d, sigma0Paramslist[clsid].p1, sigma0Paramslist[clsid].p2, sigma0Paramslist[clsid].p3, // sigma0Paramslist[clsid].p4, sigma0Paramslist[clsid].p5, sigma0Paramslist[clsid].p6); // ䷽ͼ - float transPattern = GPU_BillerInterpAntPattern(Tantpattern, + float transPattern = GPU_BillerInterpAntPattern(Tantpattern, Tstarttheta, Tstartphi, Tdtheta, Tdphi, Tthetapoints, Tphipoints, Rtanttheta.theta, Rtanttheta.phi) * r2d; // շͼ - float receivePattern = GPU_BillerInterpAntPattern(Rantpattern, + float receivePattern = GPU_BillerInterpAntPattern(Rantpattern, Rstarttheta, Rstartphi, Rdtheta, Rdphi, Rthetapoints, Rphipoints, Rtanttheta.theta, Rtanttheta.phi) * r2d; // λ @@ -352,7 +423,6 @@ __global__ void CUDA_RTPC( if (timeID < 0 || timeID >= Freqnumbers) { timeID = 0; amp = 0; - } else {} @@ -367,6 +437,127 @@ __global__ void CUDA_RTPC( } +__global__ void CUDA_TBPImage( + float* antPx, float* antPy, float* antPz, + float* imgx, float* imgy, float* imgz, + cuComplex* echoArr, cuComplex* imgArr, + float freq, float fs, float Rnear, float Rfar, + long rowcount, long colcount, + long prfid, long freqcount +) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + //printf("\nidx:\t %d %d %d\n", idx, linecount, plusepoint); + if (idx < rowcount * colcount) { + float R = sqrtf(powf(antPx[prfid] - imgx[idx], 2) + powf(antPy[prfid] - imgy[idx], 2) + powf(antPz[prfid] - imgz[idx], 2)); + float Ridf = ((R - Rnear) * 2 / LIGHTSPEED) * fs; + long Rid = floorf(Ridf); + if(Rid <0|| Rid >= freqcount){} + else { + float factorj = freq * 4 * PI / LIGHTSPEED; + cuComplex Rphi =cuCexpf(make_cuComplex(0, factorj * R));// У + imgArr[idx] = cuCaddf(imgArr[idx], cuCmulf(echoArr[Rid] , Rphi));// + } + } +} + + +__global__ void CUDA_calculationEcho(float* sigma0, float* TransAnt, float* ReciveAnt, + float* localangle, float* R, float* slopeangle, + float nearRange, float Fs, float Pt, float lamda, long FreqIDmax, + cuComplex* echoArr, long* FreqID, + long len) { + long idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < len) { + float r = R[idx]; + float amp = Pt * TransAnt[idx] * ReciveAnt[idx]; + amp = amp * sigma0[idx]; + amp = amp / (powf(4 * LAMP_CUDA_PI, 2) * powf(r, 4)); // ǿ + + // λ + float phi = (-4 * LAMP_CUDA_PI / lamda) * r; + cuComplex echophi = make_cuComplex(0, phi); + cuComplex echophiexp = cuCexpf(echophi); + + float timeR = 2 * (r - nearRange) / LIGHTSPEED * Fs; + long timeID = floorf(timeR); + if (timeID < 0 || timeID >= FreqIDmax) { + timeID = 0; + amp = 0; + } + + cuComplex echo; + echo.x = echophiexp.x * amp; + echo.y = echophiexp.y * amp; + echoArr[idx] = echo; + FreqID[idx] = timeID; + } +} + + +__global__ void CUDA_AntPatternInterpGain(float* anttheta, float* antphi, float* gain, + float* antpattern, float starttheta, float startphi, float dtheta, float dphi, int thetapoints, int phipoints, long len) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + + if (idx < len) { + + float temptheta = anttheta[idx]; + float tempphi = antphi[idx]; + + + float antPatternGain = GPU_BillerInterpAntPattern(antpattern, + starttheta, startphi, dtheta, dphi, thetapoints, phipoints, + temptheta, tempphi) ; + gain[idx] = antPatternGain; + } +} + +//__global__ void Sigma0InterpPixel(long* demcls, float* demslopeangle, CUDASigmaParam* sigma0Paramslist, float* localangle, float* sigma0list, long sigmaparamslistlen, long len) +//{ +// long idx = blockIdx.x * blockDim.x + threadIdx.x; +// if (idx < len) { +// long clsid = demcls[idx]; +// if(clsid<=) +// sigma0list[idx] = 0; +// } +//} + + +__global__ void CUDA_InterpSigma( + long* demcls, float* sigmaAmp, float* localanglearr, long len, + CUDASigmaParam* sigma0Paramslist, long sigmaparamslistlen) { + long idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < len) { + long clsid = demcls[idx]; + float localangle = localanglearr[idx] * r2d; + CUDASigmaParam tempsigma = sigma0Paramslist[clsid]; + //printf("cls:%d;localangle=%f;\n",clsid, localangle); + + if (localangle < 0 || localangle >= 90) { + sigmaAmp[idx] = 0; + } + else {} + + if (abs(tempsigma.p1)< PRECISIONTOLERANCE&& + abs(tempsigma.p2) < PRECISIONTOLERANCE && + abs(tempsigma.p3) < PRECISIONTOLERANCE && + abs(tempsigma.p4) < PRECISIONTOLERANCE&& + abs(tempsigma.p5) < PRECISIONTOLERANCE&& + abs(tempsigma.p6) < PRECISIONTOLERANCE + ) { + sigmaAmp[idx] = 0; + } + else { + float sigma = GPU_getSigma0dB(tempsigma, localangle); + sigma = powf(10.0, sigma / 10.0);// ɢϵ + //printf("cls:%d;localangle=%f;sigma0=%f;\n", clsid, localangle, sigma); + sigmaAmp[idx] = sigma; + } + } +} + + + + //ʾ void checkCudaError(cudaError_t err, const char* msg) { if (err != cudaSuccess) { @@ -380,6 +571,7 @@ void checkCudaError(cudaError_t err, const char* msg) { extern "C" void* mallocCUDAHost(long memsize) { void* ptr; cudaMallocHost(&ptr, memsize); + #ifdef __CUDADEBUG__ cudaError_t err = cudaGetLastError(); if (err != cudaSuccess) { @@ -387,6 +579,7 @@ extern "C" void* mallocCUDAHost(long memsize) { // Possibly: exit(-1) if program cannot continue.... } #endif // __CUDADEBUG__ + cudaDeviceSynchronize(); return ptr; } @@ -400,7 +593,7 @@ extern "C" void FreeCUDAHost(void* ptr) { // Possibly: exit(-1) if program cannot continue.... } #endif // __CUDADEBUG__ - + cudaDeviceSynchronize(); } // GPUڴ @@ -414,7 +607,7 @@ extern "C" void* mallocCUDADevice(long memsize) { // Possibly: exit(-1) if program cannot continue.... } #endif // __CUDADEBUG__ - + cudaDeviceSynchronize(); return ptr; } @@ -428,7 +621,7 @@ extern "C" void FreeCUDADevice(void* ptr) { // Possibly: exit(-1) if program cannot continue.... } #endif // __CUDADEBUG__ - + cudaDeviceSynchronize(); } // GPU ڴת @@ -443,7 +636,7 @@ extern "C" void HostToDevice(void* hostptr, void* deviceptr, long memsize) { } #endif // __CUDADEBUG__ - + cudaDeviceSynchronize(); } extern "C" void DeviceToHost(void* hostptr, void* deviceptr, long memsize) { @@ -455,7 +648,7 @@ extern "C" void DeviceToHost(void* hostptr, void* deviceptr, long memsize) { // Possibly: exit(-1) if program cannot continue.... } #endif // __CUDADEBUG__ - + cudaDeviceSynchronize(); } extern "C" void CUDATestHelloWorld(float a,long len) { @@ -463,7 +656,7 @@ extern "C" void CUDATestHelloWorld(float a,long len) { int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С // CUDA ˺ - CUDA_Test_HelloWorld << > > (a, len); + CUDA_Test_HelloWorld << > > (a, len); #ifdef __CUDADEBUG__ cudaError_t err = cudaGetLastError(); if (err != cudaSuccess) { @@ -474,12 +667,53 @@ extern "C" void CUDATestHelloWorld(float a,long len) { cudaDeviceSynchronize(); } +void CUDATBPImage(float* antPx, float* antPy, float* antPz, + float* imgx, float* imgy, float* imgz, + cuComplex* echoArr, cuComplex* imgArr, + float freq, float fs, float Rnear, float Rfar, + long rowcount, long colcount, + long prfid, long freqcount) +{ + int blockSize = 256; // ÿ߳ + int numBlocks = (rowcount * colcount + blockSize - 1) / blockSize; // pixelcount С + //printf("\nCUDA_RTPC_SiglePRF blockSize:%d ,numBlock:%d\n",blockSize,numBlocks); + // CUDA ˺ CUDA_RTPC_Kernel + + CUDA_TBPImage << > > ( + antPx, antPy, antPz, + imgx, imgy, imgz, + echoArr, imgArr, + freq, fs, Rnear, Rfar, + rowcount, colcount, + prfid, freqcount + ); + + +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDATBPImage CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ + cudaDeviceSynchronize(); +} + extern "C" void distanceAB(float* Ax, float* Ay, float* Az, float* Bx, float* By, float* Bz, float* R, long len) { // CUDA ˺Ϳijߴ int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С // CUDA ˺ - CUDA_DistanceAB << > > (Ax, Ay, Az, Bx, By, Bz, R, len); + CUDA_DistanceAB << > > (Ax, Ay, Az, Bx, By, Bz, R, len); + +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ + cudaDeviceSynchronize(); } extern "C" void BdistanceAs(float* Ax, float* Ay, float* Az, float Bx, float By, float Bz, float* R, long len) { @@ -487,7 +721,15 @@ extern "C" void BdistanceAs(float* Ax, float* Ay, float* Az, float Bx, float By, int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С // CUDA ˺ - CUDA_B_DistanceA << > > (Ax, Ay, Az, Bx, By, Bz, R, len); + CUDA_B_DistanceA << > > (Ax, Ay, Az, Bx, By, Bz, R, len); + +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ cudaDeviceSynchronize(); } @@ -496,7 +738,15 @@ extern "C" void make_VectorA_B(float sX, float sY, float sZ, float* tX, float* t int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С // CUDA ˺ - CUDA_make_VectorA_B << > > (sX, sY, sZ, tX, tY, tZ, RstX, RstY, RstZ, len); + CUDA_make_VectorA_B << > > (sX, sY, sZ, tX, tY, tZ, RstX, RstY, RstZ, len); + +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ cudaDeviceSynchronize(); } @@ -505,7 +755,15 @@ extern "C" void Norm_Vector(float* Vx, float* Vy, float* Vz, float* R, long len) int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С // CUDA ˺ - CUDA_Norm_Vector << > > (Vx, Vy, Vz, R, len); + CUDA_Norm_Vector << > > (Vx, Vy, Vz, R, len); + +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ cudaDeviceSynchronize(); } @@ -513,7 +771,15 @@ extern "C" void cosAngle_VA_AB(float* Ax, float* Ay, float* Az, float* Bx, float int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С // CUDA ˺ - CUDA_cosAngle_VA_AB << > > (Ax, Ay, Az, Bx, By, Bz, anglecos, len); + CUDA_cosAngle_VA_AB << > > (Ax, Ay, Az, Bx, By, Bz, anglecos, len); + +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ cudaDeviceSynchronize(); } @@ -528,25 +794,76 @@ extern "C" void SatelliteAntDirectNormal(float* RstX, float* RstY, float* RstZ, int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С // CUDA ˺ - CUDA_SatelliteAntDirectNormal << > > (RstX, RstY, RstZ, + CUDA_SatelliteAntDirectNormal << > > (RstX, RstY, RstZ, antXaxisX, antXaxisY, antXaxisZ, antYaxisX, antYaxisY, antYaxisZ, antZaxisX, antZaxisY, antZaxisZ, antDirectX, antDirectY, antDirectZ, thetaAnt, phiAnt , len); + +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ cudaDeviceSynchronize(); } +extern "C" void AntPatternInterpGain(float* anttheta, float* antphi, float* gain, + float* antpattern, float starttheta, float startphi, float dtheta, float dphi, int thetapoints, int phipoints, long len) { + int blockSize = 256; // ÿ߳ + int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С + //printf("\nCUDA_RTPC_SiglePRF blockSize:%d ,numBlock:%d\n", blockSize, numBlocks); + + CUDA_AntPatternInterpGain << > > ( anttheta,antphi, gain, + antpattern, + starttheta, startphi, dtheta, dphi, thetapoints, phipoints, + len); +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ + cudaDeviceSynchronize(); +} + extern "C" void CUDARTPCPRF(float antPx, long len) { int blockSize = 256; // ÿ߳ int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С printf("\nCUDA_RTPC_SiglePRF blockSize:%d ,numBlock:%d\n", blockSize, numBlocks); - CUDA_Test_HelloWorld << > > (antPx, len); + CUDA_Test_HelloWorld << > > (antPx, len); +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ + cudaDeviceSynchronize(); +} +extern "C" void calculationEcho(float* sigma0, float* TransAnt, float* ReciveAnt, + float* localangle, float* R, float* slopeangle, + float nearRange, float Fs, float pt, float lamda, long FreqIDmax, + cuComplex* echoAmp, long* FreqID, + long len) +{ + int blockSize = 256; // ÿ߳ + int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С + // CUDA ˺ + CUDA_calculationEcho << > > (sigma0, TransAnt, ReciveAnt, + localangle, R, slopeangle, + nearRange, Fs, pt, lamda, FreqIDmax, + echoAmp, FreqID, + len); #ifdef __CUDADEBUG__ cudaError_t err = cudaGetLastError(); if (err != cudaSuccess) { @@ -610,7 +927,25 @@ CUDA_RTPC << > > ( } - +extern "C" void CUDAInterpSigma( + long* demcls,float* sigmaAmp, float* localanglearr,long len, + CUDASigmaParam* sigma0Paramslist, long sigmaparamslistlen) {// ر-sigmaֵӦ-ulaby + int blockSize = 256; // ÿ߳ + int numBlocks = (len + blockSize - 1) / blockSize; // pixelcount С + // CUDA ˺ + CUDA_InterpSigma << > > ( + demcls, sigmaAmp, localanglearr, len, + sigma0Paramslist, sigmaparamslistlen + ); +#ifdef __CUDADEBUG__ + cudaError_t err = cudaGetLastError(); + if (err != cudaSuccess) { + printf("CUDA_RTPC_SiglePRF CUDA Error: %s\n", cudaGetErrorString(err)); + // Possibly: exit(-1) if program cannot continue.... + } +#endif // __CUDADEBUG__ + cudaDeviceSynchronize(); +} #endif diff --git a/GPUTool.cuh b/GPUTool.cuh index dd19e48..5d0ad17 100644 --- a/GPUTool.cuh +++ b/GPUTool.cuh @@ -58,6 +58,9 @@ extern "C" void make_VectorA_B(float sX, float sY, float sZ, float* tX, float* t extern "C" void Norm_Vector(float* Vx, float* Vy, float* Vz, float* R, long member); extern "C" void cosAngle_VA_AB(float* Ax, float* Ay, float* Az, float* Bx, float* By, float* Bz, float* anglecos, long len); extern "C" void SatelliteAntDirectNormal(float* RstX, float* RstY, float* RstZ, float antXaxisX, float antXaxisY, float antXaxisZ, float antYaxisX, float antYaxisY, float antYaxisZ, float antZaxisX, float antZaxisY, float antZaxisZ, float antDirectX, float antDirectY, float antDirectZ, float* thetaAnt, float* phiAnt, long len); + +extern "C" void AntPatternInterpGain(float* anttheta, float* antphi, float* gain, float* antpattern, float starttheta, float startphi, float dtheta, float dphi, int thetapoints, int phipoints,long len); + extern "C" void CUDA_RTPC_SiglePRF( float antPx, float antPy, float antPZ, float antXaxisX, float antXaxisY, float antXaxisZ, @@ -75,22 +78,41 @@ extern "C" void CUDA_RTPC_SiglePRF( ); extern "C" void CUDARTPCPRF(float antPx, long len); - - - extern "C" void CUDATestHelloWorld(float a, long len); + +extern "C" void CUDATBPImage( + float* antPx, + float* antPy, + float* antPz, + float* imgx, + float* imgy, + float* imgz, + cuComplex* echoArr, + cuComplex* imgArr, + float freq, float fs, float Rnear, float Rfar, + long rowcount, long colcount, + long prfid, long freqcount +); + + +extern "C" void calculationEcho(float* sigma0, float* TransAnt, float* ReciveAnt, + float* localangle, float* R, float* slopeangle, + float nearRange, float Fs, float pt, float lamda, long FreqIDmax, + cuComplex* echoAmp, long* FreqID, + long len); + + +extern "C" void CUDAInterpSigma( + long* demcls, float* sigmaAmp, float* localanglearr, long len, + CUDASigmaParam* sigma0Paramslist, long sigmaparamslistlen); + #endif #endif - - - - - /** * diff --git a/ImageOperatorBase.cpp b/ImageOperatorBase.cpp index 45156ee..fac1fdd 100644 --- a/ImageOperatorBase.cpp +++ b/ImageOperatorBase.cpp @@ -819,8 +819,6 @@ void gdalImage::saveImage(Eigen::MatrixXd data, int start_row = 0, int start_col } - - int datarows = data.rows(); int datacols = data.cols(); @@ -1174,7 +1172,7 @@ RasterExtend gdalImage::getExtend() } gdalImage CreategdalImage(const QString& img_path, int height, int width, int band_num, - Eigen::MatrixXd gt, QString projection, bool need_gt, bool overwrite) + Eigen::MatrixXd gt, QString projection, bool need_gt, bool overwrite, bool isEnvi) { if(exists_test(img_path.toUtf8().constData())) { if(overwrite) { @@ -1187,11 +1185,21 @@ gdalImage CreategdalImage(const QString& img_path, int height, int width, int ba } GDALAllRegister(); CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // 注锟斤拷锟绞斤拷锟斤拷锟斤拷锟?1锟?7 - GDALDriver* poDriver = GetGDALDriverManager()->GetDriverByName("GTiff"); + GDALDriver* poDriver = nullptr; + if (isEnvi) { + poDriver = GetGDALDriverManager()->GetDriverByName("ENVI"); + } + else { + poDriver = GetGDALDriverManager()->GetDriverByName("GTiff"); + } + + GDALDataset* poDstDS = poDriver->Create(img_path.toUtf8().constData(), width, height, band_num, GDT_Float32, NULL); // 锟斤拷锟斤拷锟斤拷 if(need_gt) { - poDstDS->SetProjection(projection.toUtf8().constData()); + if (!projection.isEmpty()) { + poDstDS->SetProjection(projection.toUtf8().constData()); + } double gt_ptr[6] = { 0 }; for(int i = 0; i < gt.rows(); i++) { for(int j = 0; j < gt.cols(); j++) { @@ -1932,6 +1940,18 @@ ErrorCode MergeRasterInGeoCoding(QVector imgdslist, gdalImage resulti return ErrorCode::SUCCESS; } +bool saveEigenMatrixXd2Bin(Eigen::MatrixXd data, QString dataStrPath) +{ + + Eigen::MatrixXd gt = Eigen::MatrixXd::Zero(2, 3); + + gdalImage img=CreategdalImage(dataStrPath, data.rows(), data.cols(), 1, gt, "", false, false,true); + + img.saveImage(data, 0,0,1); + + return true; +} + gdalImageComplex::gdalImageComplex(const QString& raster_path) { omp_lock_t lock; @@ -1942,7 +1962,7 @@ gdalImageComplex::gdalImageComplex(const QString& raster_path) GDALAllRegister(); CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen( - raster_path.toUtf8().constData(), GA_ReadOnly)); // 锟斤拷只斤拷式锟斤拷取斤拷影锟斤拷 + raster_path.toUtf8().constData(), GA_ReadOnly)); this->width = rasterDataset->GetRasterXSize(); this->height = rasterDataset->GetRasterYSize(); this->band_num = rasterDataset->GetRasterCount(); diff --git a/ImageOperatorBase.h b/ImageOperatorBase.h index 3e2d33a..c26ad1d 100644 --- a/ImageOperatorBase.h +++ b/ImageOperatorBase.h @@ -226,7 +226,7 @@ public: }; // 创建影像 -gdalImage CreategdalImage(const QString& img_path, int height, int width, int band_num, Eigen::MatrixXd gt, QString projection, bool need_gt = true, bool overwrite = false); +gdalImage CreategdalImage(const QString& img_path, int height, int width, int band_num, Eigen::MatrixXd gt, QString projection, bool need_gt = true, bool overwrite = false, bool isEnvi = false); gdalImage CreategdalImage(const QString& img_path, int height, int width, int band_num, Eigen::MatrixXd gt, long espgcode, GDALDataType eType=GDT_Float32, bool need_gt = true, bool overwrite = false,bool isENVI=false); gdalImageComplex CreategdalImageComplex(const QString& img_path, int height, int width, int band_num, Eigen::MatrixXd gt, QString projection, bool need_gt = true, bool overwrite = false); @@ -268,12 +268,16 @@ ErrorCode MergeRasterProcess(QVector filepath, QString outfileptah, QSt ErrorCode MergeRasterInGeoCoding(QVector inimgs, gdalImage resultimg,gdalImage maskimg, ShowProessAbstract* dia = nullptr); +// 保存矩阵转换为envi文件,默认数据格式为double +bool saveEigenMatrixXd2Bin(Eigen::MatrixXd data, QString dataStrPath); + + + template std::shared_ptr readDataArr(gdalImage& imgds, int start_row, int start_col, int rows_count, int cols_count, int band_ids, GDALREADARRCOPYMETHOD method) { std::shared_ptr result = nullptr; - omp_lock_t lock; omp_init_lock(&lock); omp_set_lock(&lock); @@ -303,7 +307,6 @@ std::shared_ptr readDataArr(gdalImage& imgds, int start_row, int start_col, i } } - delete[] temp; } else if (gdal_datatype == GDT_UInt16) { @@ -416,40 +419,50 @@ std::shared_ptr readDataArr(gdalImage& imgds, int start_row, int start_col, i } delete[] temp; } - else if (gdal_datatype == GDT_CFloat32) { - float* temp = new float[rows_count * cols_count*2]; - demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count, rows_count, gdal_datatype, 0, 0); + //else if (gdal_datatype == GDT_CFloat32) { + // if (std::is_same>::value || std::is_same>::value) { + // float* temp = new float[rows_count * cols_count * 2]; + // demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count, rows_count, gdal_datatype, 0, 0); - result = std::shared_ptr(new T[rows_count * cols_count], delArrPtr); - if (method == GDALREADARRCOPYMETHOD::MEMCPYMETHOD) { - std::memcpy(result.get(), temp, rows_count * cols_count); - } - else if (method == GDALREADARRCOPYMETHOD::VARIABLEMETHOD) { - long count = rows_count * cols_count; - for (long i = 0; i < count; i++) { - result.get()[i] = std::complex(temp[i * 2 ], - temp[i * 2 + 1]); - } - } - delete[] temp; - } - else if (gdal_datatype == GDT_CFloat64) { - double* temp = new double[rows_count * cols_count*2]; - demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count, rows_count, gdal_datatype, 0, 0); + // result = std::shared_ptr(new T[rows_count * cols_count], delArrPtr); + // if (method == GDALREADARRCOPYMETHOD::MEMCPYMETHOD) { + // std::memcpy(result.get(), temp, rows_count * cols_count); + // } + // else if (method == GDALREADARRCOPYMETHOD::VARIABLEMETHOD) { + // long count = rows_count * cols_count; + // for (long i = 0; i < count; i++) { + // result.get()[i] = T(temp[i * 2], + // temp[i * 2 + 1]); + // } + // } + // delete[] temp; + // } + // else { + // result = nullptr; + // } + //} + //else if (gdal_datatype == GDT_CFloat64 ) { + // if (std::is_same>::value || std::is_same>::value) { + // double* temp = new double[rows_count * cols_count * 2]; + // demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count, rows_count, gdal_datatype, 0, 0); - result = std::shared_ptr(new T[rows_count * cols_count], delArrPtr); - if (method == GDALREADARRCOPYMETHOD::MEMCPYMETHOD) { - std::memcpy(result.get(), temp, rows_count * cols_count); - } - else if (method == GDALREADARRCOPYMETHOD::VARIABLEMETHOD) { - long count = rows_count * cols_count; - for (long i = 0; i < count; i++) { - result.get()[i] = std::complex(temp[i * 2], - temp[i * 2 + 1]); - } - } - delete[] temp; - } + // result = std::shared_ptr(new T[rows_count * cols_count], delArrPtr); + // if (method == GDALREADARRCOPYMETHOD::MEMCPYMETHOD) { + // std::memcpy(result.get(), temp, rows_count * cols_count); + // } + // else if (method == GDALREADARRCOPYMETHOD::VARIABLEMETHOD) { + // long count = rows_count * cols_count; + // for (long i = 0; i < count; i++) { + // result.get()[i] = T(temp[i * 2], + // temp[i * 2 + 1]); + // } + // } + // delete[] temp; + // } + // else { + // result = nullptr; + // } + //} else { } GDALClose((GDALDatasetH)rasterDataset); @@ -459,6 +472,78 @@ std::shared_ptr readDataArr(gdalImage& imgds, int start_row, int start_col, i return result; } +template +std::shared_ptr readDataArrComplex(gdalImageComplex& imgds, int start_row, int start_col, int rows_count, int cols_count, int band_ids, GDALREADARRCOPYMETHOD method) +{ + std::shared_ptr result = nullptr; + + omp_lock_t lock; + omp_init_lock(&lock); + omp_set_lock(&lock); + GDALAllRegister(); + CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); + GDALDataset* rasterDataset = (GDALDataset*)(GDALOpen(imgds.img_path.toUtf8().constData(), GA_ReadOnly)); // 锟斤拷只斤拷式锟斤拷取斤拷影锟斤拷 + + GDALDataType gdal_datatype = rasterDataset->GetRasterBand(1)->GetRasterDataType(); + GDALRasterBand* demBand = rasterDataset->GetRasterBand(band_ids); + + rows_count = start_row + rows_count <= imgds.height ? rows_count : imgds.height - start_row; + cols_count = start_col + cols_count <= imgds.width ? cols_count : imgds.width - start_col; + + //Eigen::MatrixXd datamatrix(rows_count, cols_count); + + if (gdal_datatype == GDT_CFloat32) { + if (std::is_same>::value || std::is_same>::value) { + float* temp = new float[rows_count * cols_count * 2]; + demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count, rows_count, gdal_datatype, 0, 0); + + result = std::shared_ptr(new T[rows_count * cols_count], delArrPtr); + if (method == GDALREADARRCOPYMETHOD::MEMCPYMETHOD) { + std::memcpy(result.get(), temp, rows_count * cols_count); + } + else if (method == GDALREADARRCOPYMETHOD::VARIABLEMETHOD) { + long count = rows_count * cols_count; + for (long i = 0; i < count; i++) { + result.get()[i] = T(temp[i * 2], + temp[i * 2 + 1]); + } + } + delete[] temp; + } + else { + result = nullptr; + } + } + else if (gdal_datatype == GDT_CFloat64) { + if (std::is_same>::value || std::is_same>::value) { + double* temp = new double[rows_count * cols_count * 2]; + demBand->RasterIO(GF_Read, start_col, start_row, cols_count, rows_count, temp, cols_count, rows_count, gdal_datatype, 0, 0); + + result = std::shared_ptr(new T[rows_count * cols_count], delArrPtr); + if (method == GDALREADARRCOPYMETHOD::MEMCPYMETHOD) { + std::memcpy(result.get(), temp, rows_count * cols_count); + } + else if (method == GDALREADARRCOPYMETHOD::VARIABLEMETHOD) { + long count = rows_count * cols_count; + for (long i = 0; i < count; i++) { + result.get()[i] = T(temp[i * 2], + temp[i * 2 + 1]); + } + } + delete[] temp; + } + else { + result = nullptr; + } + } + else { + } + GDALClose((GDALDatasetH)rasterDataset); + omp_unset_lock(&lock); // 锟酵放伙拷斤拷 + omp_destroy_lock(&lock); // 劫伙拷斤拷 + // GDALDestroy(); // or, DllMain at DLL_PROCESS_DETACH + return result; +} //--------------------- 图像分块 ------------------------------