RadarKit

所属分类:雷达系统
开发工具:C
文件大小:1329KB
下载次数:1
上传日期:2021-05-15 21:28:23
上 传 者sh-1993
说明:  雷达基础工具包
(Radar Foundation Toolkit)

文件列表:
.vscode (0, 2023-06-13)
.vscode\c_cpp_properties.json (1427, 2023-06-13)
.vscode\tasks.json (836, 2023-06-13)
LICENSE (1077, 2023-06-13)
Makefile (4340, 2023-06-13)
RadarKit.xcodeproj (0, 2023-06-13)
RadarKit.xcodeproj\project.pbxproj (84738, 2023-06-13)
RadarKit.xcodeproj\xcshareddata (0, 2023-06-13)
RadarKit.xcodeproj\xcshareddata\xcschemes (0, 2023-06-13)
RadarKit.xcodeproj\xcshareddata\xcschemes\Product Generator.xcscheme (4290, 2023-06-13)
RadarKit.xcodeproj\xcshareddata\xcschemes\Product Header.xcscheme (3475, 2023-06-13)
RadarKit.xcodeproj\xcshareddata\xcschemes\RadarKit Utility.xcscheme (4933, 2023-06-13)
RadarKit.xcodeproj\xcshareddata\xcschemes\Simple Emulator.xcscheme (2879, 2023-06-13)
__radarkit.xcodeproj (18, 2023-06-13)
blob (0, 2023-06-13)
blob\RKClock.pdf (839225, 2023-06-13)
blob\RadarKit.pdf (96516, 2023-06-13)
blob\RadarKit.png (6422, 2023-06-13)
blob\RadarKitAnnotated.png (35928, 2023-06-13)
blob\RadarKitAnnotated.svg (3479, 2023-06-13)
entitlements (0, 2023-06-13)
entitlements\common.entitlements (258, 2023-06-13)
headers (0, 2023-06-13)
headers\RadarKit.h (13515, 2023-06-13)
headers\RadarKit (0, 2023-06-13)
headers\RadarKit\RKCalibrator.h (349, 2023-06-13)
headers\RadarKit\RKClient.h (5121, 2023-06-13)
headers\RadarKit\RKClock.h (2875, 2023-06-13)
headers\RadarKit\RKCommandCenter.h (6662, 2023-06-13)
headers\RadarKit\RKConfig.h (600, 2023-06-13)
headers\RadarKit\RKDSP.h (2655, 2023-06-13)
headers\RadarKit\RKFileHeader.h (488, 2023-06-13)
headers\RadarKit\RKFileManager.h (5853, 2023-06-13)
headers\RadarKit\RKFoundation.h (11790, 2023-06-13)
headers\RadarKit\RKHealthEngine.h (1717, 2023-06-13)
headers\RadarKit\RKHealthLogger.h (1817, 2023-06-13)
... ...

# RadarKit First of all, many thanks for your interest in the framework! :smile: :thumbsup: :punch: The RadarKit framework is a straight C framework. This is a library toolkit that abstracts various components of a radar signal processor. Mainly, the real-time operations of data collection, data fusion, transportation through network, and rudimentary processing from raw I/Q data to _base moment_ products. The main goal is to let developers only worry about implementing the interface between a _digital transceiver_, a _pedestal_, and a generic _health relay_. The RadarKit framework combines all of these information, generates radar products, provides live data and display streams, and redirects the control commands to the hardware. ## System Requirements - Processors capable of SSE, SSE2, SSE3 - Optional: AVX, AVX-256, AVX-512 ## Getting the Project Follow these steps to get the project 1. Clone a git project using one of the following commands in Terminal: ```shell git clone https://github.com/ouradar/radarkit.git ``` or ```shell git clone https://git.arrc.ou.edu/radar/radarkit.git ``` 2. Get the required packages, which can either be installed through one of the package managers or compiled from source, which I would recommend for the FFTW library since it can take advantage of SSE, SSE2, AVX and AVX-2 accelerations (see 5). - [FFTW] - [NetCDF] - [OpenSSL] ##### Debian / Ubuntu ```shell apt-get install libfftw3-dev libnetcdf-dev libssl-dev ``` ##### CentOS 7 ```shell yum install epel-release yum install fftw-devel netcdf-devel ssl-devel ``` ##### macOS I use [Homebrew] as my package manager for macOS. I highly recommend it. ```shell brew install fftw netcdf openssl ``` ##### Special Notes About NetCDF shared library Some operating systems require the following line in your shell profile for the netcdf shared library to be found. ```shell export LD_LIBRARY_PATH=/usr/local/lib ``` 3. Compile and install the framework. ```shell make sudo make install ``` 4. Try the test program to simulate a Level-1 system. ```shell rkutil -vs1 ``` 5. (Some Linux) Add the following line to /etc/sysctl.conf (CentOS 7) ``` net.ipv4.ping_group_range = 0 0 ``` or (CentOS 6 / Ubuntu 18) ``` net.ipv4.ping_group_range = 0 2147483***7 ``` 6. (Optional) Compile [FFTW] from source ```shell ./configure --enable-single --enable-sse --enable-sse2 --enable-avx --enable-avx2 --enable-shared make sudo make install ``` [fftw]: http://www.fftw.org [netcdf]: http://www.unidata.ucar.edu/software/netcdf [homebrew]: http://brew.sh ## Basic Usage on a Radar Host 1. Initialize an `RKRadar` object (although RadarKit is not an objective implementation but it is easier to think this way). Supply the necessary _tranceiver_ routines and _pedestal_ routines. The _health relay_ is omitted here for simplicity. ```c #include int main() { RKRadar *radar = RKInit(); RKSetTransceiver(radar, userInput, transceiverInit, transceiverExec, transceiverFree); RKSetPedestal(radar, userInput, pedestalInit, pedestalExec, pedestalFree); RKGoLive(radar); RKWaitWhileActive(radar); RKFree(radar); } ``` 2. By design, the data acquired through hardware, e.g., I/Q samples, is delivered to the RadarKit framework through functions provided in ``, and a small number of functions in `` and ``. The functions listed under these headers are about the only functions you should be concerned with. The design is intended to abstract the majority of common signal processing and low-level house-keeping tasks. As you accumulate more experiences, feel free to explore other parts of the framework. Feedback and suggestions for improvements are always welcome. ![Figure](https://github.com/OURadar/RadarKit/blob/master/blob/RadarKitAnnotated.png) 3. Set up **digital transceiver** _init_, _exec_ and _free_ routines. The _init_ routine must launch a separate run-loop so that the _init_ routine returns a user-defined pointer (of a struct) immediately. The run-loop routine receives I/Q data, actively request a vacant slot through `RKGetVacantPulse()`, fills in the slot with proper data and then declare the pulse to have data using `RKSetPulseHasData()`. ```c typedef struct user_transceiver_struct { // Your variables int x; int y; int z; bool active; // Recommend keeping a reference to the supplied radar RKRadar *radar; // For this example, we will keep the thread reference here pthread tid; } UserTransceiverStruct; RKTransceiver transceiverInit(RKRadar *radar, void *userInput) { // Allocate your own resources, define your structure somewhere else UserTransceiverStruct *resource = (UserTransceiverStruct *)malloc(sizeof(UserTransceiverStruct)); // Be sure to save a reference to the radar resource->radar = radar; resource->active = true; // Create your run loop as a separate thread so you can return immediately pthread_create(&resource->tid, NULL, transceiverRunLoop, resource); return (RKTransceiver)resource; } int transceiverExec(RKTransceiver yourTransceiver, const char *command, char *feedback) { // Type cast the first input as your transceiver UserTransceiverStruct *resource = (UserTransceiverStruct *)yourTransceiver; // Now you can recover the radar reference you provided in init routine. RKRadar *radar = resource->radar; // Execute commands stored in const char *command if (!strcmp(command, "disconnect")) { // The exec function should response to 'disconnect' and stop the run loop resource->active = false; pthread_join(resource->tidRunLoop, NULL); sprintf(feedback, "ACK. Pedestal stopped." RKEOL); } else if (!strcmp(command, "a") { // Perform task "a" print("Hello World.\n"); // Provide text feedback to char *feedback; Starts with "ACK" for acknowledge. Ends with RKEOL. sprintf(feedback, "ACK. Command executed." RKEOL); } else { // Return something even if you cannot do something sprintf(feedback, "NAK. Command not understood." RKEOL); return 1; } return 0; } int transceiverFree(RKTransceiver yourTransceiver) { // Free up resources free(yourTransceiver); return RKResultSuccess; } void *transceiverRunLoop(void *in) { // Type cast the input to something you defined earlier UserTransceiverStruct *resource = (UserTransceiverStruct *)in; // Now you can recover the radar reference you provided in init routine. RKRadar *radar = resource->radar; // Some internal variables. It would be best if this is a clean reference from an FPGA or something similar uint***_t tic = 0; // Here is the busy run loop while (radar->state & RKRadarStateLive) { RKPulse *pulse = RKGetVacantPulse(radar); pulse->header.t = tic++; // Required. Some kind of clean reference directly proportional to time pulse->header.gateCount = 1000; // Required. The number of range gates. Must be < gateCapacity (RKRadarDesc) pulse->header.gateCount = 500; // Required. pulse->header.gateSizeMeters = 30.0f; // Required. // Go through both polarizations for (int p = 0; p < 2; p++) { // Get a data pointer to the 16-bit data RKInt16C *X = RKGetInt16CDataFromPulse(pulse, p); // Go through all range gates and fill in the samples for (int g = 0; g < 1000; g++) { // Copy the I/Q samples from hardware interface X->i = 0; X->q = 1; X++; } } RKSetPulseHasData(radar, pulse); } return 0; } ``` 4. Set up **pedestal** _init_, _exec_ and _free_ routines. The _init_ routine must launch a separate run-loop so that the _init_ routine returns a user-defined pointer (of a struct) immediately. The run-loop routine receives position data, actively request a vacant slot through `RKGetVacantPosition()`, fills in the slot with proper data and then declare the pulse to have data using `RKSetPositionReady()`. ```c typedef struct user_pedestal_struct { // Your variables int x; int y; int z; bool active; // Recommend keeping a reference to the supplied radar RKRadar *radar; // For this example, we will keep the thread reference here pthread tid; } UserPedestalStruct; RKPedestal pedestalInit(RKRadar *radar, void *userInput) { // Allocate your own resources, define your structure somewhere else UserPedestalStruct *resource = (UserPedestalStruct *)malloc(sizeof(UserPedestalStruct)); // Be sure to save a reference to the radar resource->radar = radar; resource->active = true; // Create your run loop as a separate thread so you can return immediately pthread_create(&resource->tid, NULL, pedestalRunLoop, resource); return (RKPedestal)resource; } int pedestalExec(RKPedestal yourPedestal, const char *command, char *feedback) { // Type cast the first input as your pedestal UserPedestalStruct *resource = (UserPedestalStruct *)yourPedestal; // Now you can recover the radar reference you provided in init routine. RKRadar *radar = resource->radar; // Execute commands stored in const char *command if (!strcmp(command, "disconnect")) { // The exec function should response to 'disconnect' and stop the run loop resource->active = false; pthread_join(resource->tidRunLoop, NULL); sprintf(feedback, "ACK. Pedestal stopped." RKEOL); } else if (!strcmp(command, "a") { // Perform task "a" print("Hello World.\n"); // Provide text feedback to char *feedback; Starts with "ACK" for acknowledge. Ends with RKEOL. sprintf(feedback, "ACK. Command executed." RKEOL); } else { // Return something even if you cannot do something sprintf(feedback, "NAK. Command not understood." RKEOL); return 2; } return 0; } int pedestalFree(RKPedestal yourPedestal) { // Free up resources free(yourPedestal); return 0; } int pedestalRunLoop(void *in) { // Type cast the input to something you defined earlier UserPedestalStruct *resource = (UserPedestalStruct *)in; // Now you can recover the radar reference you provided in init routine. RKRadar *radar = resource->radar; // Some internal variables. It would be best if this is a clean reference from an FPGA or something similar uint***_t tic = 0; // Here is the busy run loop while (resource->active) { RKPosition *position = RKGetVacantPosition(radar); // Copy the position from hardware interface position->t = tic++; // Required. A clean reference that is directional proportional to sampling time position->azimuthDegrees = 1.0; // Required. position->elevationDegrees = 0.5; // Required. position->azimuthVelocityDegreesPerSecond = 25.0f; // Optional. position->elevationVelocityDegreesPerSecond = 0.0f; // Optional. position->flag = RKPositionFlagScanActive | RKPositionFlagAzimuthEnabled | RKPositionFlagElevationEnabled; // Required. RKSetPositionReady(radar, position); } return 0; } ``` 5. (Optional) Set up _health relay_ initialization and run-loop routines just like the previous two examples. 6. Build the program and link to the RadarKit framework. Note that the required packages should be applied too. ```shell gcc -o program program.c -lradarkit -lfftw3f -lnetcdf ``` This example is extremely simple. The actual radar will be more complex but this short example illustrates the simplicity of using RadarKit to abstract all the DSP and non-hardware related tasks. # Design Philosophy The three major hardware components of a radar: (i) a **digital transceiver**, (ii) a **pedestal**, and (iii) a **health relay** (_auxiliary controller_) are not tightly coupled with the RadarKit framework. Only a set of protocol functions are defined so that the RadarKit framework can be interfaced with other libraries, which are usually specific to the hardware and/or vendor design. It is the user responsibility to implement the appropriate interface routines to bridge the data transport and control commands. There are three functions needed for each hardware: _init_, _exec_ and _free_, which are routines to allocate an object--akin to an object in object-oriented programming, althought RadarKit is a straight C framework, interact with the object and deallocate the object, respectively. The _exec_ routine has the form of accepting text command and producing text feedback. Some keywords for the command are already defined in the framework so user should not use them. They are intercepted prior to passing down to the _exec_ routine. Detailed usage on these functions will be discussed in detail later. ![Figure](https://github.com/OURadar/RadarKit/blob/master/blob/RadarKit.png) The **digital transceiver** is the hardware that requires high-speed data throughput. RadarKit is designed so that redudant memory copy is minimized. That is, a pointer to the memory space for a payload will be provided upon request. User defined routines fill in the data, typically through a copy mechanism through DMA to transport the I/Q data from a transceiver memory to the host memory, which is initialized and managed by RadarKit. The fundamental form is signed 16-bit I and Q, which is a part of the `RKPulse` definition in the framework. The **pedestal** is the hardware that is usually low speed, typically on the orders of 10 KBps, about 100 samples per second. A RadarKit position structure `RKPosition` is defined in the framework. If the interface software [pedzy] is used, which is a light-weight pedestal controller, RadarKit can readily ingest position data through a network connection. Otherwise, an `RKPedestalPedzy` replacement can be implemented to provide same functionality. In this case, the user is also free to define a new position type. The RadarKit framework does not restrict this definition. The **health relay** is the hardware that is also low speed, typically on the orders of 1 KBps. This is also the hardware that can be called an _auxiliary controller_, where everything else is interfaced through this relay and the health information is routinely probed through this controller. A RadarKit health structure `RKHealth` is defined in the framework. Multiple health node can be implemented. They provide health information using JSON strings through TCP/IP socket connections. If the interface software [tweeta] or [tweeto] is used, RadarKit can readily ingest auxiliary hardware health data through a TCP/IP network connection. Otherwise, an `RKHealthRelayTweeta` replacement can be implemented to provide same functionality. The RadarKit framework does not restrict this definition. Base radar moments are generated on a ray-by-ray basis. Each ray is of type `RKRay`. Once a sweep is complete, a Level-II data file in NetCDF format will be generated. Live streams and can be view through a desktop application [iRadar]. [pedzy]: https://git.arrc.ou.edu/cheo4524/pedzy [tweeta]: https://git.arrc.ou.edu/dstarchman/tweeta [tweeto]: https://git.arrc.ou.edu/cheo4524/tweeto.git [iradar]: https://arrc.ou.edu/tools [openssl]: https://www.openssl.org [radarhub]: https://git.arrc.ou.edu/radar/RadarHub.git # Radar Struct This is about the only structure you need to worry about. A radar structure represents an object-like structure where everything is encapsulated. ### Life Cycle These are functions that allocate and deallocate a radar struct. ```c RKRadar *RKInitWithDesc(RKRadarDesc); RKRadar *RKInitLean(void); // For a lean system, PX-1000 like RKRadar *RKInitMean(void); // For a medium system, RaXPol like RKRadar *RKInitFull(void); // For a high-performance system, PX-10,000 like RKRadar *RKInit(void); // Everything based on default settings, in between mean & lean int RKFree(RKRadar *radar); ``` ### Properties Hardware hooks are provided to communicate with a digital transceiver, a positioner and various sensors. They must obey the protocol to implement three important functions: _init_, _exec_ and _free_ routines. These functions will be called to start the hardware routine, execute text form commands that will be passed down the master controller, and to deallocate the resources properly upon exit, respectively. ```c // Set the transceiver. Pass in function pointers: init, exec and free int RKSetTransceiver(RKRadar *, void *initInput, RKTransceiver initRoutine(RKRadar *, void *), int execRoutine(RKTransceiver, const char *, char *), int freeRoutine(RKTransceiver)); // Set the pedestal. Pass in function pointers: init, exec and free int RKSetPedestal(RKRadar *, void *initInput, RKPedestal initRoutine(RKRadar *, void *), int execRoutine(RKPedestal, const char *, char *), int freeRoutine(RKPedestal)); // Set the health relay. Pass in function pointers: init, exec and free int RKSetHealthRelay(RKRadar *, void *initInput, RKHealthRelay initRoutine(RKRadar *, void *), int execRoutine(RKHealthRelay, const char *, char *), int freeRoutine(RKHealthRelay)); // These can only be set before the radar goes live int RKSetProcessingCoreCounts(RKRadar *, const unsigned int pulseCores, const unsigned int rayCores); // Some states of the radar int RKSetVerbosity(RKRadar *, const int); int RKSetVerbosityUsingArray(RKRadar *, const uint8_t *); int RKSetDataPath(RKRadar *, const char *); int RKSetDataUsageLimit(RKRadar *, const size_t limit); int RKSetRecordingLevel(RKRadar *, const int); // Waveform routines RKWaveform *RKWaveformInitAsImpulse(void); RKWaveform *RKWaveformInitFromFile(const char *filename); RKWaveform *RKWaveformInitAsLinearFrequencyModulation(const double fs, const double fc, const double pulsewidth, const double bandwidth); RKWaveform *RKWaveformInitAsFrequencyHops(const double fs, const double fc, const double pulsewidth, const double bandwidth, const int count); void RKWaveformOnes(RKWaveform *); void RKWaveformHops(RKWaveform *, const double fs, const double fc, const double bandwidth); void RKWaveformLinearFrequencyModulation(RKWaveform *, const double fs, const double fc, const double pulsewidth, const double bandwidth); void RKWaveformDecimate(RKWaveform *, const int); void RKWaveformConjuate(RKWaveform *); void RKWaveformDownConvert(RKWaveform *); void RKWaveformWrite(RKWaveform *, c ... ...

近期下载者

相关文件


收藏者