mirror of
https://github.com/30hours/blah2.git
synced 2024-11-18 12:33:58 +00:00
Add skeleton for tracker, commented out, do not use
This commit is contained in:
parent
99f09eb5f8
commit
97b34ff3d8
11 changed files with 649 additions and 17 deletions
|
@ -27,11 +27,13 @@ add_executable(blah2
|
|||
${PROJECT_SOURCE_DIR}/process/detection/CfarDetector1D.cpp
|
||||
${PROJECT_SOURCE_DIR}/process/detection/Centroid.cpp
|
||||
${PROJECT_SOURCE_DIR}/process/detection/Interpolate.cpp
|
||||
${PROJECT_SOURCE_DIR}/process/tracker/Tracker.cpp
|
||||
${PROJECT_SOURCE_DIR}/process/spectrum/SpectrumAnalyser.cpp
|
||||
${PROJECT_SOURCE_DIR}/process/meta/HammingNumber.cpp
|
||||
${PROJECT_SOURCE_DIR}/data/IqData.cpp
|
||||
${PROJECT_SOURCE_DIR}/data/Map.cpp
|
||||
${PROJECT_SOURCE_DIR}/data/Detection.cpp
|
||||
${PROJECT_SOURCE_DIR}/data/Track.cpp
|
||||
${PROJECT_SOURCE_DIR}/data/meta/Timing.cpp
|
||||
)
|
||||
|
||||
|
@ -74,6 +76,7 @@ include_directories("${PROJECT_SOURCE_DIR}/capture/rspduo/")
|
|||
include_directories("${PROJECT_SOURCE_DIR}/process/ambiguity/")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/process/clutter/")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/process/detection/")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/process/tracker/")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/process/spectrum/")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/process/meta/")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/data/")
|
||||
|
|
|
@ -12,6 +12,7 @@ const PORT = 3000;
|
|||
const HOST = '0.0.0.0';
|
||||
var map = '';
|
||||
var detection = '';
|
||||
var track = '';
|
||||
var timestamp = '';
|
||||
var timing = '';
|
||||
var iqdata = '';
|
||||
|
@ -37,6 +38,9 @@ app.get('/api/map', (req, res) => {
|
|||
app.get('/api/detection', (req, res) => {
|
||||
res.send(detection);
|
||||
});
|
||||
app.get('/api/tracker', (req, res) => {
|
||||
res.send(track);
|
||||
});
|
||||
app.get('/api/timestamp', (req, res) => {
|
||||
res.send(timestamp);
|
||||
});
|
||||
|
@ -108,6 +112,23 @@ const server_detection = net.createServer((socket)=>{
|
|||
});
|
||||
server_detection.listen(3002);
|
||||
|
||||
// tcp listener tracker
|
||||
const server_tracker = net.createServer((socket)=>{
|
||||
socket.write("Hello From Server!")
|
||||
socket.on("data",(msg)=>{
|
||||
data = data + msg.toString();
|
||||
if (data.slice(-1) === "}")
|
||||
{
|
||||
track = data;
|
||||
data = '';
|
||||
}
|
||||
});
|
||||
socket.on("close",()=>{
|
||||
console.log("Connection closed.");
|
||||
})
|
||||
});
|
||||
server_tracker.listen(3003);
|
||||
|
||||
// tcp listener timestamp
|
||||
const server_timestamp = net.createServer((socket)=>{
|
||||
socket.write("Hello From Server!")
|
||||
|
|
|
@ -27,6 +27,13 @@ process:
|
|||
minDelay: 5
|
||||
minDoppler: 15
|
||||
nCentroid: 10
|
||||
tracker:
|
||||
initiate:
|
||||
M: 3
|
||||
N: 5
|
||||
maxAcc: 10
|
||||
delete: 10
|
||||
smooth: "none"
|
||||
|
||||
network:
|
||||
ip: 0.0.0.0
|
||||
|
@ -34,10 +41,21 @@ network:
|
|||
api: 3000
|
||||
map: 3001
|
||||
detection: 3002
|
||||
track: 3003
|
||||
timestamp: 4000
|
||||
timing: 4001
|
||||
iqdata: 4002
|
||||
|
||||
truth:
|
||||
asdb:
|
||||
enabled: false
|
||||
ip: 0.0.0.0
|
||||
port: 30000
|
||||
ais:
|
||||
enabled: false
|
||||
ip: 0.0.0.0
|
||||
port: 30001
|
||||
|
||||
save:
|
||||
iq: true
|
||||
map: false
|
||||
|
|
|
@ -14,12 +14,12 @@ process:
|
|||
overlap: 0
|
||||
ambiguity:
|
||||
delayMin: -10
|
||||
delayMax: 300
|
||||
dopplerMin: -250
|
||||
dopplerMax: 250
|
||||
delayMax: 400
|
||||
dopplerMin: -200
|
||||
dopplerMax: 200
|
||||
clutter:
|
||||
delayMin: -10
|
||||
delayMax: 300
|
||||
delayMax: 400
|
||||
detection:
|
||||
pfa: 0.00001
|
||||
nGuard: 2
|
||||
|
@ -27,6 +27,13 @@ process:
|
|||
minDelay: 5
|
||||
minDoppler: 15
|
||||
nCentroid: 6
|
||||
tracker:
|
||||
initiate:
|
||||
M: 3
|
||||
N: 5
|
||||
maxAcc: 10
|
||||
delete: 10
|
||||
smooth: "none"
|
||||
|
||||
network:
|
||||
ip: 0.0.0.0
|
||||
|
@ -34,10 +41,21 @@ network:
|
|||
api: 3000
|
||||
map: 3001
|
||||
detection: 3002
|
||||
track: 3003
|
||||
timestamp: 4000
|
||||
timing: 4001
|
||||
iqdata: 4002
|
||||
|
||||
truth:
|
||||
asdb:
|
||||
enabled: false
|
||||
ip: 0.0.0.0
|
||||
port: 30000
|
||||
ais:
|
||||
enabled: false
|
||||
ip: 0.0.0.0
|
||||
port: 30001
|
||||
|
||||
save:
|
||||
iq: true
|
||||
map: false
|
||||
|
|
|
@ -10,9 +10,11 @@
|
|||
#include <Ambiguity.h>
|
||||
#include <WienerHopf.h>
|
||||
#include <CfarDetector1D.h>
|
||||
#include <Tracker.h>
|
||||
#include <IqData.h>
|
||||
#include <Map.h>
|
||||
#include <Detection.h>
|
||||
#include <Track.h>
|
||||
#include <Centroid.h>
|
||||
#include <Interpolate.h>
|
||||
#include <Timing.h>
|
||||
|
@ -89,11 +91,10 @@ int main(int argc, char **argv)
|
|||
IqData *x = new IqData(nSamples);
|
||||
IqData *y = new IqData(nSamples);
|
||||
Map<std::complex<double>> *map;
|
||||
Map<double> *mapdb;
|
||||
std::string mapJson, detectionJson;
|
||||
Detection *detection;
|
||||
Detection *detection1;
|
||||
Detection *detection2;
|
||||
Track *track;
|
||||
|
||||
// setup fftw multithread
|
||||
if (fftw_init_threads() == 0)
|
||||
|
@ -104,10 +105,12 @@ int main(int argc, char **argv)
|
|||
fftw_plan_with_nthreads(4);
|
||||
|
||||
// setup socket
|
||||
uint16_t port_map, port_detection, port_timestamp, port_timing, port_iqdata;
|
||||
uint16_t port_map, port_detection, port_timestamp,
|
||||
port_timing, port_iqdata, port_track;
|
||||
std::string ip;
|
||||
tree["network"]["ports"]["map"] >> port_map;
|
||||
tree["network"]["ports"]["detection"] >> port_detection;
|
||||
tree["network"]["ports"]["track"] >> port_track;
|
||||
tree["network"]["ports"]["timestamp"] >> port_timestamp;
|
||||
tree["network"]["ports"]["timing"] >> port_timing;
|
||||
tree["network"]["ports"]["iqdata"] >> port_iqdata;
|
||||
|
@ -115,11 +118,13 @@ int main(int argc, char **argv)
|
|||
asio::io_service io_service;
|
||||
asio::ip::tcp::socket socket_map(io_service);
|
||||
asio::ip::tcp::socket socket_detection(io_service);
|
||||
asio::ip::tcp::socket socket_track(io_service);
|
||||
asio::ip::tcp::socket socket_timestamp(io_service);
|
||||
asio::ip::tcp::socket socket_timing(io_service);
|
||||
asio::ip::tcp::socket socket_iqdata(io_service);
|
||||
asio::ip::tcp::endpoint endpoint_map;
|
||||
asio::ip::tcp::endpoint endpoint_detection;
|
||||
asio::ip::tcp::endpoint endpoint_track;
|
||||
asio::ip::tcp::endpoint endpoint_timestamp;
|
||||
asio::ip::tcp::endpoint endpoint_timing;
|
||||
asio::ip::tcp::endpoint endpoint_iqdata;
|
||||
|
@ -127,6 +132,8 @@ int main(int argc, char **argv)
|
|||
asio::ip::address::from_string(ip), port_map);
|
||||
endpoint_detection = asio::ip::tcp::endpoint(
|
||||
asio::ip::address::from_string(ip), port_detection);
|
||||
endpoint_track = asio::ip::tcp::endpoint(
|
||||
asio::ip::address::from_string(ip), port_track);
|
||||
endpoint_timestamp = asio::ip::tcp::endpoint(
|
||||
asio::ip::address::from_string(ip), port_timestamp);
|
||||
endpoint_timing = asio::ip::tcp::endpoint(
|
||||
|
@ -135,6 +142,7 @@ int main(int argc, char **argv)
|
|||
asio::ip::address::from_string(ip), port_iqdata);
|
||||
socket_map.connect(endpoint_map);
|
||||
socket_detection.connect(endpoint_detection);
|
||||
socket_track.connect(endpoint_track);
|
||||
socket_timestamp.connect(endpoint_timestamp);
|
||||
socket_timing.connect(endpoint_timing);
|
||||
socket_iqdata.connect(endpoint_iqdata);
|
||||
|
@ -175,6 +183,16 @@ int main(int argc, char **argv)
|
|||
tree["process"]["detection"]["nCentroid"] >> nCentroid;
|
||||
Centroid *centroid = new Centroid(nCentroid, nCentroid, 1/tCpi);
|
||||
|
||||
// setup process tracker
|
||||
uint8_t m, n, nDelete;
|
||||
double maxAcc;
|
||||
std::string smooth;
|
||||
tree["process"]["tracker"]["initiate"]["M"] >> m;
|
||||
tree["process"]["tracker"]["initiate"]["N"] >> n;
|
||||
tree["process"]["tracker"]["delete"] >> nDelete;
|
||||
tree["process"]["tracker"]["initiate"]["maxAcc"] >> maxAcc;
|
||||
Tracker *tracker = new Tracker(m, n, nDelete, tCpi, maxAcc);
|
||||
|
||||
// setup process spectrum analyser
|
||||
double spectrumBandwidth = 2000;
|
||||
SpectrumAnalyser *spectrumAnalyser = new SpectrumAnalyser(nSamples, spectrumBandwidth);
|
||||
|
@ -204,8 +222,8 @@ int main(int argc, char **argv)
|
|||
std::string jsonTiming;
|
||||
std::vector<uint64_t> time;
|
||||
|
||||
// setup output signal
|
||||
std::string jsonIqData;
|
||||
// setup output json
|
||||
std::string mapJson, detectionJson, jsonTracker, jsonIqData;
|
||||
|
||||
// run process
|
||||
std::thread t2([&]{
|
||||
|
@ -249,6 +267,10 @@ int main(int argc, char **argv)
|
|||
detection = interpolate->process(detection2, map);
|
||||
timing_helper(timing_name, timing_time, time, "detector");
|
||||
|
||||
// tracker process
|
||||
// track = tracker->process(detection, time[0]/1000);
|
||||
// timing_helper(timing_name, timing_time, time, "tracker");
|
||||
|
||||
// output IqData meta data
|
||||
jsonIqData = x->to_json(time[0]/1000);
|
||||
for (int i = 0; i < (jsonIqData.size() + MTU - 1) / MTU; i++)
|
||||
|
@ -269,7 +291,6 @@ int main(int argc, char **argv)
|
|||
subdata = mapJson.substr(i * MTU, MTU);
|
||||
socket_map.write_some(asio::buffer(subdata, subdata.size()), err);
|
||||
}
|
||||
|
||||
// output detection data
|
||||
detectionJson = detection->to_json(time[0]/1000);
|
||||
detectionJson = detection->delay_bin_to_km(detectionJson, fs);
|
||||
|
@ -282,6 +303,14 @@ int main(int argc, char **argv)
|
|||
delete detection1;
|
||||
delete detection2;
|
||||
|
||||
// output tracker data
|
||||
// jsonTracker = track->to_json(time[0]/1000);
|
||||
// for (int i = 0; i < (jsonTracker.size() + MTU - 1) / MTU; i++)
|
||||
// {
|
||||
// subdata = jsonTracker.substr(i * MTU, MTU);
|
||||
// socket_track.write_some(asio::buffer(subdata, subdata.size()), err);
|
||||
// }
|
||||
|
||||
// output radar data timer
|
||||
timing_helper(timing_name, timing_time, time, "output_radar_data");
|
||||
|
||||
|
|
|
@ -16,6 +16,13 @@ Detection::Detection(std::vector<double> _delay, std::vector<double> _doppler, s
|
|||
snr = _snr;
|
||||
}
|
||||
|
||||
Detection::Detection(double _delay, double _doppler, double _snr)
|
||||
{
|
||||
delay.push_back(_delay);
|
||||
doppler.push_back(_doppler);
|
||||
snr.push_back(_snr);
|
||||
}
|
||||
|
||||
std::vector<double> Detection::get_delay()
|
||||
{
|
||||
return delay;
|
||||
|
|
|
@ -29,6 +29,12 @@ public:
|
|||
/// @return The object.
|
||||
Detection(std::vector<double> delay, std::vector<double> doppler, std::vector<double> snr);
|
||||
|
||||
/// @brief Constructor for single detection.
|
||||
/// @param delay Detection in delay (bins).
|
||||
/// @param doppler Detection in Doppler (Hz).
|
||||
/// @return The object.
|
||||
Detection(double delay, double doppler, double snr);
|
||||
|
||||
/// @brief Get detections in delay.
|
||||
/// @return Detections in delay (bins).
|
||||
std::vector<double> get_delay();
|
||||
|
@ -46,6 +52,7 @@ public:
|
|||
size_t get_nDetections();
|
||||
|
||||
/// @brief Generate JSON of the detections and metadata.
|
||||
/// @param timestamp Current time (POSIX ms).
|
||||
/// @return JSON string.
|
||||
std::string to_json(uint64_t timestamp);
|
||||
|
||||
|
|
163
src/data/Track.cpp
Normal file
163
src/data/Track.cpp
Normal file
|
@ -0,0 +1,163 @@
|
|||
#include "Track.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/writer.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
#include "rapidjson/filewritestream.h"
|
||||
|
||||
const uint64_t Track::MAX_INDEX = 65535;
|
||||
const std::string Track::STATE_ACTIVE = "ACTIVE";
|
||||
const std::string Track::STATE_TENTATIVE = "TENTATIVE";
|
||||
const std::string Track::STATE_COASTING = "COASTING";
|
||||
|
||||
// constructor
|
||||
Track::Track()
|
||||
{
|
||||
iNext = 0;
|
||||
}
|
||||
|
||||
Track::~Track()
|
||||
{
|
||||
}
|
||||
|
||||
std::string Track::uint2hex(uint64_t number)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << std::setw(4) << std::setfill('0') << std::uppercase << std::hex << number;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
void Track::set_state(uint64_t index, std::string _state)
|
||||
{
|
||||
state.at(index) = _state;
|
||||
}
|
||||
|
||||
void Track::set_current(uint64_t index, Detection smoothed)
|
||||
{
|
||||
current.at(index) = smoothed;
|
||||
associated.at(index).push_back(smoothed);
|
||||
}
|
||||
|
||||
void Track::set_acceleration(uint64_t index, double _acceleration)
|
||||
{
|
||||
acceleration.at(index) = _acceleration;
|
||||
}
|
||||
|
||||
void Track::set_nInactive(uint64_t index, uint64_t n)
|
||||
{
|
||||
nInactive.at(index) = n;
|
||||
}
|
||||
|
||||
uint64_t Track::get_nActive()
|
||||
{
|
||||
uint64_t n = 0;
|
||||
for (size_t i = 0; i < id.size(); i++)
|
||||
{
|
||||
if (state.at(i) == STATE_ACTIVE)
|
||||
{
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
uint64_t Track::get_nTentative()
|
||||
{
|
||||
uint64_t n = 0;
|
||||
for (size_t i = 0; i < id.size(); i++)
|
||||
{
|
||||
if (state.at(i) == STATE_TENTATIVE)
|
||||
{
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
uint64_t Track::get_n()
|
||||
{
|
||||
return id.size();
|
||||
}
|
||||
|
||||
Detection Track::get_current(uint64_t index)
|
||||
{
|
||||
return current.at(index);
|
||||
}
|
||||
|
||||
double Track::get_acceleration(uint64_t index)
|
||||
{
|
||||
return acceleration.at(index);
|
||||
}
|
||||
|
||||
std::string Track::get_state(uint64_t index)
|
||||
{
|
||||
return state.at(index);
|
||||
}
|
||||
|
||||
uint64_t Track::get_nInactive(uint64_t index)
|
||||
{
|
||||
return nInactive.at(index);
|
||||
}
|
||||
|
||||
uint64_t Track::add(Detection initial)
|
||||
{
|
||||
id.push_back(uint2hex(iNext));
|
||||
state.push_back(STATE_TENTATIVE);
|
||||
current.push_back(initial);
|
||||
acceleration.push_back(0);
|
||||
std::vector<Detection> _associated;
|
||||
_associated.push_back(initial);
|
||||
associated.push_back(_associated);
|
||||
nInactive.push_back(0);
|
||||
iNext++;
|
||||
if (iNext >= MAX_INDEX)
|
||||
{
|
||||
iNext = 0;
|
||||
}
|
||||
return id.size()-1;
|
||||
}
|
||||
|
||||
void Track::remove(uint64_t index)
|
||||
{
|
||||
id.erase(id.begin() + index);
|
||||
state.erase(state.begin() + index);
|
||||
current.erase(current.begin() + index);
|
||||
acceleration.erase(acceleration.begin() + index);
|
||||
associated.erase(associated.begin() + index);
|
||||
}
|
||||
|
||||
std::string Track::to_json(uint64_t timestamp)
|
||||
{
|
||||
rapidjson::Document document;
|
||||
document.SetObject();
|
||||
rapidjson::Document::AllocatorType &allocator = document.GetAllocator();
|
||||
|
||||
// store array for non-tentative tracks
|
||||
rapidjson::Value arrayId(rapidjson::kArrayType);
|
||||
rapidjson::Value value;
|
||||
for (int i = 0; i < get_n(); i++)
|
||||
{
|
||||
if (state.at(i) != STATE_TENTATIVE)
|
||||
{
|
||||
value = rapidjson::StringRef(id.at(i).c_str());
|
||||
arrayId.PushBack(value, allocator);
|
||||
}
|
||||
}
|
||||
|
||||
document.AddMember("timestamp", timestamp, allocator);
|
||||
document.AddMember("n", get_n(), allocator);
|
||||
document.AddMember("nActive", get_nActive(), allocator);
|
||||
document.AddMember("nTentative", get_nTentative(), allocator);
|
||||
document.AddMember("id", arrayId, allocator);
|
||||
|
||||
rapidjson::StringBuffer strbuf;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(strbuf);
|
||||
writer.SetMaxDecimalPlaces(2);
|
||||
document.Accept(writer);
|
||||
|
||||
return strbuf.GetString();
|
||||
}
|
154
src/data/Track.h
Normal file
154
src/data/Track.h
Normal file
|
@ -0,0 +1,154 @@
|
|||
/// @file Track.h
|
||||
/// @class Track
|
||||
/// @brief A class to store track data.
|
||||
/// @details The ID is 4 digit hexadecimal with 16^4 = 65536 combinations.
|
||||
/// @details The state can be TENTATIVE, ACTIVE or COASTING.
|
||||
/// @details Associated detections use null detections when no updates.
|
||||
/// @author 30hours
|
||||
|
||||
#ifndef TRACK_H
|
||||
#define TRACK_H
|
||||
|
||||
#include <Detection.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
class Track
|
||||
{
|
||||
private:
|
||||
/// @brief Track ID (4 digit alpha-numeric).
|
||||
//std::unique_ptr<std::vector<std::string>> id;
|
||||
std::vector<std::string> id;
|
||||
|
||||
/// @brief Current state (see VALID_STATE).
|
||||
std::vector<std::string> state;
|
||||
|
||||
/// @brief Curent track position.
|
||||
std::vector<Detection> current;
|
||||
|
||||
/// @brief Current acceleration (Hz/s).
|
||||
std::vector<double> acceleration;
|
||||
|
||||
/// @brief Associated detections in track.
|
||||
std::vector<std::vector<Detection>> associated;
|
||||
|
||||
/// @brief Number of updates the track has been tentative/coasting.
|
||||
/// @details Forms criteria for track deletion.
|
||||
std::vector<uint64_t> nInactive;
|
||||
|
||||
/// @brief Next valid track index.
|
||||
uint64_t iNext;
|
||||
|
||||
/// @brief Maximum integer index to wrap around.
|
||||
static const uint64_t MAX_INDEX;
|
||||
|
||||
/// @brief String for state ACTIVE.
|
||||
static const std::string STATE_ACTIVE;
|
||||
|
||||
/// @brief String for state TENTATIVE.
|
||||
static const std::string STATE_TENTATIVE;
|
||||
|
||||
/// @brief String for state COASTING.
|
||||
static const std::string STATE_COASTING;
|
||||
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
/// @return The object.
|
||||
Track();
|
||||
|
||||
/// @brief Destructor.
|
||||
/// @return Void.
|
||||
~Track();
|
||||
|
||||
/// @brief Convert an unsigned int to hexadecimal.
|
||||
/// @details Max number is 16^4 = 65536 before wrap around.
|
||||
/// @param number Number to convert to hexadecimal.
|
||||
/// @return hex Hexadecimal number.
|
||||
std::string uint2hex(uint64_t number);
|
||||
|
||||
/// @brief Set the state of a track.
|
||||
/// @param index Index of track to change.
|
||||
/// @param state Updated state.
|
||||
/// @return Void.
|
||||
void set_state(uint64_t index, std::string state);
|
||||
|
||||
/// @brief Set the current track position.
|
||||
/// @details Use to update smoothed current position.
|
||||
/// @param index Index of track to change.
|
||||
/// @param smoothed Updated state.
|
||||
/// @return Void.
|
||||
void set_current(uint64_t index, Detection smoothed);
|
||||
|
||||
/// @brief Set the current acceleration.
|
||||
/// @param index Index of track to change.
|
||||
/// @param acceleration Updated acceleration.
|
||||
/// @return Void.
|
||||
void set_acceleration(uint64_t index, double acceleration);
|
||||
|
||||
/// @brief Set the current inactivity.
|
||||
/// @param index Index of track to change.
|
||||
/// @param n Updated inactivity index.
|
||||
/// @return Void.
|
||||
void set_nInactive(uint64_t index, uint64_t n);
|
||||
|
||||
/// @brief Get number of active tracks.
|
||||
/// @return Number of active tracks.
|
||||
uint64_t get_nActive();
|
||||
|
||||
/// @brief Get number of tentative tracks.
|
||||
/// @return Number of tentative tracks.
|
||||
uint64_t get_nTentative();
|
||||
|
||||
/// @brief Get number of total tracks.
|
||||
/// @return Number of total tracks.
|
||||
uint64_t get_n();
|
||||
|
||||
/// @brief Get current track position for track index.
|
||||
/// @return Current detection.
|
||||
Detection get_current(uint64_t index);
|
||||
|
||||
/// @brief Get current acceleration for track index.
|
||||
/// @return Current acceleration (Hz/s).
|
||||
double get_acceleration(uint64_t index);
|
||||
|
||||
/// @brief Get current state for track index.
|
||||
/// @return Current state.
|
||||
std::string get_state(uint64_t index);
|
||||
|
||||
/// @brief Get number of updates track has been tentative/coasting.
|
||||
/// @return Number of updates track has been tentative/coasting.
|
||||
uint64_t get_nInactive(uint64_t index);
|
||||
|
||||
/// @brief Update an associated detection.
|
||||
/// @param index Index of track to change.
|
||||
/// @param update New associated detection.
|
||||
/// @return Void.
|
||||
void update(uint64_t index, Detection update);
|
||||
|
||||
/// @brief Add track to the track set.
|
||||
/// @param initial Initial Detection.
|
||||
/// @details ID is incremented automatically.
|
||||
/// @details Initial state is always TENTATIVE.
|
||||
/// @return Index of last track.
|
||||
uint64_t add(Detection initial);
|
||||
|
||||
/// @brief Remove track based on index.
|
||||
/// @param index Index of track to remove.
|
||||
/// @return Void.
|
||||
void remove(uint64_t index);
|
||||
|
||||
/// @brief Generate JSON of the map and metadata.
|
||||
/// @param timestamp Current time (POSIX ms).
|
||||
/// @return JSON string.
|
||||
std::string to_json(uint64_t timestamp);
|
||||
|
||||
/// @brief Append the map to a save file.
|
||||
/// @param json JSON string of map and metadata.
|
||||
/// @param path Path of file to save.
|
||||
/// @return True is save is successful.
|
||||
bool save(std::string json, std::string path);
|
||||
};
|
||||
|
||||
#endif
|
135
src/process/tracker/Tracker.cpp
Normal file
135
src/process/tracker/Tracker.cpp
Normal file
|
@ -0,0 +1,135 @@
|
|||
#include "Tracker.h"
|
||||
#include <iostream>
|
||||
|
||||
// constructor
|
||||
Tracker::Tracker(uint32_t _m, uint32_t _n, uint32_t _nDelete, double _cpi, double _maxAccInit)
|
||||
{
|
||||
m = _m;
|
||||
n = _n;
|
||||
nDelete = _nDelete;
|
||||
cpi = _cpi;
|
||||
maxAccInit = _maxAccInit;
|
||||
timestamp = 0;
|
||||
|
||||
double resolutionAcc = 1 * (1/(cpi*cpi));
|
||||
uint16_t nAcc = (int)maxAccInit/resolutionAcc;
|
||||
for (int i = 0; i < 2*nAcc+1; i++)
|
||||
{
|
||||
accInit.push_back(resolutionAcc*(i-nAcc));
|
||||
}
|
||||
|
||||
Track track{};
|
||||
}
|
||||
|
||||
Tracker::~Tracker()
|
||||
{
|
||||
}
|
||||
|
||||
Track *Tracker::process(Detection *detection, uint64_t currentTime)
|
||||
{
|
||||
timestamp = currentTime;
|
||||
doNotInitiate.clear();
|
||||
for (size_t i = 0; i < detection->get_nDetections(); i++)
|
||||
{
|
||||
doNotInitiate.push_back(false);
|
||||
}
|
||||
|
||||
if (track.get_n() > 0)
|
||||
{
|
||||
update(detection, timestamp);
|
||||
}
|
||||
initiate(detection);
|
||||
|
||||
return &track;
|
||||
}
|
||||
|
||||
void Tracker::update(Detection *detection, uint64_t current)
|
||||
{
|
||||
std::vector<double> delay = detection->get_delay();
|
||||
std::vector<double> doppler = detection->get_doppler();
|
||||
std::vector<double> snr = detection->get_snr();
|
||||
|
||||
// init
|
||||
double delayPredict, dopplerPredict;
|
||||
double acc;
|
||||
uint32_t nRemove = 0;
|
||||
std::string state;
|
||||
|
||||
// get time between detections
|
||||
double T = (double) current - timestamp;
|
||||
|
||||
// loop over each track
|
||||
for (int i = 0; i < track.get_n(); i++)
|
||||
{
|
||||
// predict next position
|
||||
Detection detectionCurrent = track.get_current(i);
|
||||
double delayTrack = detectionCurrent.get_delay().front();
|
||||
double dopplerTrack = detectionCurrent.get_doppler().front();
|
||||
acc = track.get_acceleration(i);
|
||||
delayPredict = delayTrack+(1/(2*3.14))*(dopplerTrack+0.5*acc*T*T);
|
||||
dopplerPredict = dopplerTrack+acc*T;
|
||||
Detection prediction(delayPredict, dopplerPredict, 0);
|
||||
|
||||
// loop over detections to associate
|
||||
for (size_t j = 0; j < detection->get_nDetections(); j++)
|
||||
{
|
||||
// associate detections
|
||||
if (delay[j] > delayPredict-1 &&
|
||||
delay[j] < delayPredict+1 &&
|
||||
doppler[j] > dopplerPredict-(2/cpi) &&
|
||||
doppler[j] < dopplerPredict+(2/cpi))
|
||||
{
|
||||
Detection associated(delay[j], doppler[j], snr[j]);
|
||||
track.set_current(i, associated);
|
||||
state = "ACTIVE";
|
||||
track.set_state(i, state);
|
||||
track.set_acceleration(i, (doppler[j]-dopplerTrack)/T);
|
||||
track.set_nInactive(i, 0);
|
||||
doNotInitiate[j] = true;
|
||||
break;
|
||||
// todo: check for track promotion
|
||||
}
|
||||
}
|
||||
|
||||
// update state if no detections associated
|
||||
track.set_current(i, prediction);
|
||||
if (track.get_state(i) == "ACTIVE")
|
||||
{
|
||||
state = "COASTING";
|
||||
track.set_state(i, state);
|
||||
}
|
||||
track.set_nInactive(i, track.get_nInactive(i)+1);
|
||||
|
||||
// remove if tentative or coasting too long
|
||||
if (track.get_nInactive(i) > nDelete)
|
||||
{
|
||||
track.remove(i+nRemove);
|
||||
nRemove++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Tracker::initiate(Detection *detection)
|
||||
{
|
||||
std::vector<double> delay = detection->get_delay();
|
||||
std::vector<double> doppler = detection->get_doppler();
|
||||
std::vector<double> snr = detection->get_snr();
|
||||
uint64_t index;
|
||||
|
||||
// loop over new detections
|
||||
for (size_t i = 0; i < detection->get_nDetections(); i++)
|
||||
{
|
||||
// skip if detection used in update
|
||||
if (doNotInitiate.at(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// add tentative detection for each acc
|
||||
for (size_t j = 0; j < accInit.size(); j++)
|
||||
{
|
||||
Detection detectionCurrent(delay[i], doppler[i], snr[i]);
|
||||
index = track.add(detectionCurrent);
|
||||
track.set_acceleration(index, accInit[j]);
|
||||
}
|
||||
}
|
||||
}
|
77
src/process/tracker/Tracker.h
Normal file
77
src/process/tracker/Tracker.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/// @file Tracker.h
|
||||
/// @class Tracker
|
||||
/// @brief A class to implement a bistatic tracker.
|
||||
/// @details Key functions are update, initiate, smooth and remove.
|
||||
/// @details Update before initiate to avoid duplicate tracks.
|
||||
/// @author 30hours
|
||||
/// @todo Add smoothing capability.
|
||||
/// @todo Fix units up.
|
||||
|
||||
#ifndef TRACKER_H
|
||||
#define TRACKER_H
|
||||
|
||||
#include <Detection.h>
|
||||
#include <Track.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class Tracker
|
||||
{
|
||||
private:
|
||||
/// @brief Track initiation constant for M of N detections.
|
||||
uint32_t m;
|
||||
|
||||
/// @brief Track initiation constant for M of N detections.
|
||||
uint32_t n;
|
||||
|
||||
/// @brief Number of missed predictions to delete a tentative track.
|
||||
uint32_t nDelete;
|
||||
|
||||
/// @brief True CPI time for acceleration resolution(s).
|
||||
double cpi;
|
||||
|
||||
/// @brief Maximum acceleration to initiate track (Hz/s).
|
||||
double maxAccInit;
|
||||
|
||||
/// @brief Acceleration values to initiate track (Hz/s).
|
||||
std::vector<double> accInit;
|
||||
|
||||
/// @brief Index of detections already updated.
|
||||
std::vector<bool> doNotInitiate;
|
||||
|
||||
/// @brief POSIX timestamp of last update (ms).
|
||||
uint64_t timestamp;
|
||||
|
||||
/// @brief Track data.
|
||||
Track track;
|
||||
|
||||
public:
|
||||
/// @brief Constructor.
|
||||
/// @param delayMin Minimum clutter filter delay (bins).
|
||||
/// @param delayMax Maximum clutter filter delay (bins).
|
||||
/// @param nSamples Number of samples per CPI.
|
||||
/// @return The object.
|
||||
Tracker(uint32_t m, uint32_t n, uint32_t nDelete, double cpi, double maxAccInit);
|
||||
|
||||
/// @brief Destructor.
|
||||
/// @return Void.
|
||||
~Tracker();
|
||||
|
||||
/// @brief Run through key functions of tracker.
|
||||
/// @param detection Detection data for last CPI.
|
||||
/// @param timestamp POSIX timestamp (ms).
|
||||
/// @return Pointer to track data.
|
||||
Track *process(Detection *detection, uint64_t timestamp);
|
||||
|
||||
/// @brief Update tracks by associating detections.
|
||||
/// @param detection Detection data for last CPI.
|
||||
/// @param timestamp POSIX timestamp (ms).
|
||||
/// @return Void.
|
||||
void update(Detection *detection, uint64_t timestamp);
|
||||
|
||||
/// @brief Initiate new tentative tracks from detections.
|
||||
/// @param detection Detection data for last CPI.
|
||||
/// @return Void.
|
||||
void initiate(Detection *detection);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue