From b7782a061e7614a1c2361224cd47da326759755e Mon Sep 17 00:00:00 2001 From: CZC-123 <2315228186@qq.com> Date: Fri, 22 Sep 2023 21:47:27 +0800 Subject: [PATCH] finish SORT --- algorithm/mot/sv_mot.cpp | 290 ++++++++++++++++++++++----------------- include/sv_mot.h | 7 +- models-converting.sh | 41 ++++++ models-downloading.sh | 107 +++++++++++++++ 4 files changed, 321 insertions(+), 124 deletions(-) create mode 100755 models-converting.sh create mode 100755 models-downloading.sh diff --git a/algorithm/mot/sv_mot.cpp b/algorithm/mot/sv_mot.cpp index 4e26283..7496f8f 100644 --- a/algorithm/mot/sv_mot.cpp +++ b/algorithm/mot/sv_mot.cpp @@ -1,6 +1,8 @@ #include "sv_mot.h" #include #include +#include +#include #include "gason.h" #include "sv_util.h" @@ -116,11 +118,11 @@ KalmanFilter::KalmanFilter() this->_F = MatrixXd::Identity(8, 8); for (int i=0; i<4; i++) { - this->_F(i,i+4) = 1; + this->_F(i,i+4) = 1.; //1 } this->_H = MatrixXd::Identity(4, 8); - this->_std_weight_position = 1. / 20; - this->_std_weight_vel = 1. / 160; + this->_std_weight_position = 1. / 20; //1./20 + this->_std_weight_vel = 1. / 160; //1./160 } KalmanFilter::~KalmanFilter() @@ -130,7 +132,9 @@ KalmanFilter::~KalmanFilter() pair, Matrix > KalmanFilter::initiate(Vector4d &bbox) { Matrix mean; - mean << bbox(0), bbox(1), bbox(2) / bbox(3), bbox(3), 0, 0, 0, 0; + Matrix zero_vector; + zero_vector.setZero(); + mean << bbox(0), bbox(1), (double)bbox(2) / (double)bbox(3), bbox(3), zero_vector; VectorXd stds(8); stds << 2 * this->_std_weight_position * mean(3), 2 * this->_std_weight_position * mean(3), 0.01, 2 * this->_std_weight_position * mean(3), \ 10 * this->_std_weight_vel * mean(3), 10 * this->_std_weight_vel * mean(3), 1e-5, 10 * this->_std_weight_vel * mean(3); @@ -142,31 +146,43 @@ pair, Matrix > KalmanFilter::initiate(Vector4 pair, Matrix > KalmanFilter::update(Matrix mean, Matrix covariances, sv::Box &box) { - MatrixXd R; - Vector4d stds; - - stds << this->_std_weight_position * mean(3), this->_std_weight_position * mean(3), 0.1, this->_std_weight_position * mean(3); - MatrixXd squared = stds.array().square(); - R = squared.asDiagonal(); - MatrixXd S = this->_H * covariances * this->_H.transpose() + R; - - MatrixXd Kalman_gain = covariances * this->_H.transpose() * S.inverse(); VectorXd measurement(4); - measurement << box.x1, box.y1, (box.x2-box.x1) / (box.y2-box.y1), box.y2-box.y1; - Matrix new_mean = mean + Kalman_gain * (measurement - this->_H * mean); - Matrix new_covariances = (MatrixXd::Identity(8, 8) - Kalman_gain * this->_H) * covariances; - return make_pair(new_mean, new_covariances); + double a = (double)(box.x2-box.x1) / (double)(box.y2-box.y1); + measurement << box.x1+(box.x2-box.x1)/2, box.y1+(box.y2-box.y1)/2, a, box.y2-box.y1; + pair, Matrix > projected = project(mean, covariances); + Matrix projected_mean = projected.first; + Matrix projected_cov = projected.second; + + Eigen::LLT chol_factor(projected_cov); + MatrixXd Kalman_gain = (chol_factor.solve((covariances * this->_H.transpose()).transpose())).transpose(); + + VectorXd innovation = measurement - projected_mean; + Matrix new_mean = mean + Kalman_gain *innovation; + Matrix new_covariances = covariances - Kalman_gain * projected_cov * Kalman_gain.transpose(); + + return make_pair(new_mean, new_covariances); } +pair, Matrix > KalmanFilter::project(Matrix mean, Matrix covariances) +{ + VectorXd stds(4); + stds << this->_std_weight_position * mean(3), this->_std_weight_position * mean(3), 0.1, this->_std_weight_position * mean(3); + MatrixXd squared = stds.array().square(); + MatrixXd R = squared.asDiagonal(); + + Matrix pro_mean = this->_H * mean; + Matrix pro_covariances = this->_H * covariances * this->_H.transpose() + R; + return make_pair(pro_mean, pro_covariances); +} pair, Matrix > KalmanFilter::predict(Matrix mean, Matrix covariances) { VectorXd stds(8); - stds << this->_std_weight_position * mean(3), this->_std_weight_position * mean(3), 0.01, this->_std_weight_position * mean(3), \ - this->_std_weight_vel * mean(3), this->_std_weight_vel * mean(3), 1e-5, this->_std_weight_vel * mean(3); + stds << this->_std_weight_position * mean(3), this->_std_weight_position * mean(3), 1e-2, this->_std_weight_position * mean(3), \ + this->_std_weight_vel * mean(3), this->_std_weight_vel * mean(3), 1e-5, this->_std_weight_vel * mean(3); // a = 0.01 MatrixXd squared = stds.array().square(); MatrixXd Q = squared.asDiagonal(); Matrix pre_mean = this->_F * mean; - Matrix pre_cov = this->_F * covariances * this->_F.transpose() + Q; + Matrix pre_cov = this->_F * covariances * this->_F.transpose()+Q;//+Q return make_pair(pre_mean, pre_cov); } @@ -178,7 +194,7 @@ SORT::~SORT() void SORT::update(TargetsInFrame& tgts) { sv::KalmanFilter kf; - if (! this->_tracklets.size()) + if (! this->_tracklets.size() || tgts.targets.size() == 0) { Vector4d bbox; for (int i=0; i_next_tracklet_id; - // cout << tracklet.id << endl; tgts.targets[i].tracked_id = this->_next_tracklet_id; tgts.targets[i].has_tid = true; - tracklet.bbox << box.x1, box.y1, box.x2-box.x1, box.y2-box.y1; // x,y,w,h + tracklet.bbox << box.x1+(box.x2-box.x1)/2, box.y1+(box.y2-box.y1)/2, box.x2-box.x1, box.y2-box.y1; // x,y,w,h; center(x,y) + tracklet.age = 0; tracklet.hits = 1; tracklet.misses = 0; tracklet.frame_id = tgts.frame_id; + tracklet.category_id = tgts.targets[i].category_id; tracklet.tentative = true; + // initate the motion pair, Matrix > motion = kf.initiate(tracklet.bbox); tracklet.mean = motion.first; tracklet.covariance = motion.second; - + this->_tracklets.push_back(tracklet); } } else { + cout<<"frame id:"< match_det; - match_det.fill(-1); + vector match_det(tgts.targets.size(), -1); // predict the next state of each tracklet for (auto& tracklet : this->_tracklets) { @@ -226,8 +244,6 @@ void SORT::update(TargetsInFrame& tgts) } // Match the detections to the existing tracklets - // cout << "the num of targets: " << tgts.targets.size() << endl; - // cout << "the num of tracklets: " << this->_tracklets.size() << endl; vector > iouMatrix(this->_tracklets.size(), vector (tgts.targets.size(), 0)); for (int i=0; i_tracklets.size(); i++) { @@ -238,6 +254,7 @@ void SORT::update(TargetsInFrame& tgts) iouMatrix[i][j] = this->_iou(this->_tracklets[i], box); } } + vector > matches = this->_hungarian(iouMatrix); for (auto& match : matches) { @@ -245,50 +262,58 @@ void SORT::update(TargetsInFrame& tgts) int detectionIndex = match.second; if (trackletIndex >= 0 && detectionIndex >= 0) { - if (iouMatrix[match.first][match.second] >= _iou_threshold) // iou_thrshold + if (iouMatrix[match.first][match.second] <= 1-_iou_threshold) // iou_thrshold { sv::Box box; tgts.targets[detectionIndex].getBox(box); this->_tracklets[trackletIndex].age = 0; this->_tracklets[trackletIndex].hits++; this->_tracklets[trackletIndex].frame_id = tgts.frame_id; - this->_tracklets[trackletIndex].bbox << box.x1, box.y1, box.x2-box.x1, box.y2-box.y1; - - auto[mean, covariance] = kf.update(this->_tracklets[trackletIndex].mean, this->_tracklets[trackletIndex].covariance, box); - this->_tracklets[trackletIndex].mean = mean; - this->_tracklets[trackletIndex].covariance = covariance; - + this->_tracklets[trackletIndex].bbox << box.x1+(box.x2-box.x1)/2, box.y1+(box.y2-box.y1)/2, box.x2-box.x1, box.y2-box.y1; tgts.targets[detectionIndex].tracked_id = this->_tracklets[trackletIndex].id; - match_det[detectionIndex] = detectionIndex; + match_det[detectionIndex] = trackletIndex; } } } - // create new tracklets for unmatched detections + std::vector > ().swap(iouMatrix); for (int i=0; i_next_tracklet_id; - tracklet.bbox << box.x1, box.y1, box.x2-box.x1, box.y2-box.y1; - + tracklet.bbox << box.x1+(box.x2-box.x1)/2, (double)(box.y1+(box.y2-box.y1)/2), box.x2-box.x1, box.y2-box.y1; tracklet.age = 0; tracklet.hits = 1; tracklet.misses = 0; tracklet.frame_id = tgts.frame_id; + tracklet.category_id = tgts.targets[i].category_id; tracklet.tentative = true; - auto[new_mean, new_covariance] = kf.initiate(tracklet.bbox); - tracklet.mean = new_mean; - tracklet.covariance = new_covariance; - + pair, Matrix > new_motion = kf.initiate(tracklet.bbox); + tracklet.mean = new_motion.first; + tracklet.covariance = new_motion.second; + tgts.targets[i].tracked_id = this->_next_tracklet_id; tgts.targets[i].has_tid = true; this->_tracklets.push_back(tracklet); } + else + { + sv::Box box; + int track_id = match_det[i]; + tgts.targets[i].getBox(box); + pair, Matrix > updated = kf.update(this->_tracklets[track_id].mean, this->_tracklets[track_id].covariance, box); + this->_tracklets[track_id].mean = updated.first; + this->_tracklets[track_id].covariance = updated.second; + } } + + //sift tracklets for (auto& tracklet : this->_tracklets) { if (tracklet.hits >= _min_hits) @@ -312,15 +337,16 @@ vector SORT::getTracklets() const double SORT::_iou(Tracklet& tracklet, sv::Box& box) { - double trackletX1 = tracklet.bbox(0); - double trackletY1 = tracklet.bbox(1); - double trackletX2 = tracklet.bbox(0) + tracklet.bbox(2); - double trackletY2 = tracklet.bbox(1) + tracklet.bbox(3); - + double trackletX1 = tracklet.bbox(0)-tracklet.bbox(2)/2; + double trackletY1 = tracklet.bbox(1)-tracklet.bbox(3)/2; + double trackletX2 = tracklet.bbox(0) + tracklet.bbox(2)/2; + double trackletY2 = tracklet.bbox(1) + tracklet.bbox(3)/2; + double detectionX1 = box.x1; double detectionY1 = box.y1; double detectionX2 = box.x2; double detectionY2 = box.y2; + double intersectionX1 = max(trackletX1, detectionX1); double intersectionY1 = max(trackletY1, detectionY1); double intersectionX2 = min(trackletX2, detectionX2); @@ -339,19 +365,55 @@ double SORT::_iou(Tracklet& tracklet, sv::Box& box) return iou; } +// Function to find the minimum element in a vector +double SORT::_findMin(const std::vector& vec) { + double minVal = std::numeric_limits::max(); + for (double val : vec) { + if (val < minVal) { + minVal = val; + } + } + return minVal; +} + +// Function to subtract the minimum value from each row of the cost matrix +void SORT::_subtractMinFromRows(std::vector>& costMatrix) { + for (auto& row : costMatrix) { + double minVal = _findMin(row); + for (double& val : row) { + val -= minVal; + } + } +} + +// Function to subtract the minimum value from each column of the cost matrix +void SORT::_subtractMinFromCols(std::vector>& costMatrix) { + for (size_t col = 0; col < costMatrix[0].size(); ++col) { + double minVal = std::numeric_limits::max(); + for (size_t row = 0; row < costMatrix.size(); ++row) { + if (costMatrix[row][col] < minVal) { + minVal = costMatrix[row][col]; + } + } + for (size_t row = 0; row < costMatrix.size(); ++row) { + costMatrix[row][col] -= minVal; + } + } +} + +// Function to find a matching using the Hungarian algorithm vector > SORT::_hungarian(vector > costMatrix) { - int numRows = costMatrix.size(); - int numCols = costMatrix[0].size(); + size_t numRows = costMatrix.size(); + size_t numCols = costMatrix[0].size(); + //transpose the matrix if necessary const bool transposed = numCols > numRows; - // transpose the matrix if necessary - if (transposed) - { - vector > transposedMatrix(numCols, vector(numRows)); - for (int i=0; i> transposedMatrix(numCols, vector(numRows)); + for (int i = 0; i < numRows; i++) { - for (int j=0; j > SORT::_hungarian(vector > costMatrix) costMatrix = transposedMatrix; swap(numRows, numCols); } - vectorrowMin(numRows, numeric_limits::infinity()); - vectorcolMin(numCols, numeric_limits::infinity()); - vectorrowMatch(numRows, -1); - vectorcolMatch(numCols, -1); - vector > matches; - // step1: Subtract the row minimums from each row - for (int i=0; i visited(numCols, false); - this->_augment(costMatrix, i, rowMatch, colMatch, visited); - } - // step4: calculate the matches - matches.clear(); - for (int j=0; j >& costMatrix, int row, vector& rowMatch, vector& colMatch, vector& visited) -{ - int numCols = costMatrix[0].size(); - for (int j=0; j_augment(costMatrix, colMatch[j], rowMatch, colMatch, visited)) - { - rowMatch[row] = j; - colMatch[j] = row; - return true; + // Create a square cost matrix by padding with zeros if necessary + std::vector> squareMatrix(maxDim, std::vector(maxDim, 0.0)); + for (size_t row = 0; row < numRows; ++row) { + for (size_t col = 0; col < numCols; ++col) { + squareMatrix[row][col] = costMatrix[row][col]; + } + } + + // Subtract the minimum value from each row and column + _subtractMinFromRows(squareMatrix); + _subtractMinFromCols(squareMatrix); + + // Initialize the assignment vectors with -1 values + std::vector rowAssignment(maxDim, -1); + std::vector colAssignment(maxDim, -1); + + // Perform the matching + for (size_t row = 0; row < maxDim; ++row) { + std::vector visitedCols(maxDim, false); + for (size_t col = 0; col < maxDim; ++col) { + if (squareMatrix[row][col] == 0 && colAssignment[col] == -1) { + rowAssignment[row] = col; + colAssignment[col] = row; + break; } } } - return false; -} - - + + // Convert the assignment vectors to pair format + std::vector> assignmentPairs; + for (size_t row = 0; row < numRows; ++row) { + int col = rowAssignment[row]; + //if (col != -1) { + // assignmentPairs.emplace_back(row, col); + // } + if (col != -1) { + if (col >= numCols) { + col = -1; + } + assignmentPairs.emplace_back(row, col); + } + } + if (transposed) { + for (auto& assignment : assignmentPairs) + { + swap(assignment.first, assignment.second); + } + } + return assignmentPairs; + } } diff --git a/include/sv_mot.h b/include/sv_mot.h index 9ed81df..4fbac61 100644 --- a/include/sv_mot.h +++ b/include/sv_mot.h @@ -56,6 +56,7 @@ public: int hits; int misses; int frame_id = 0; + int category_id; bool tentative; std::vector features; Eigen::Matrix mean; @@ -70,6 +71,7 @@ public: std::pair, Eigen::Matrix > initiate(Eigen::Vector4d &bbox); std::pair, Eigen::Matrix > update(Eigen::Matrix mean, Eigen::Matrix covariances, Box &box); std::pair, Eigen::Matrix > predict(Eigen::Matrix mean, Eigen::Matrix covariances); + std::pair, Eigen::Matrix > project(Eigen::Matrix mean, Eigen::Matrix covariances); private: Eigen::Matrix _F; Eigen::Matrix _H; @@ -88,7 +90,10 @@ public: private: double _iou(Tracklet &tracklet, Box &box); std::vector> _hungarian(std::vector> costMatrix); - bool _augment(const std::vector>& costMatrix, int row, std::vector& rowMatch, std::vector& colMatch, std::vector& visited); + double _findMin(const std::vector& vec); + void _subtractMinFromRows(std::vector>& costMatrix); + void _subtractMinFromCols(std::vector>& costMatrix); + //bool _augment(const std::vector>& costMatrix, int row, std::vector& rowMatch, std::vector& colMatch, std::vector& visited); double _iou_threshold; int _max_age; diff --git a/models-converting.sh b/models-converting.sh new file mode 100755 index 0000000..6e08d2b --- /dev/null +++ b/models-converting.sh @@ -0,0 +1,41 @@ +#!/bin/bash -e +export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH + +root_dir=${HOME}"/SpireCV/models" + + +coco_model1="COCO-yolov5s.wts" +coco_model2="COCO-yolov5s6.wts" +coco_model3="COCO-yolov5s-seg.wts" +coco_model1_fn=${root_dir}/${coco_model1} +coco_model2_fn=${root_dir}/${coco_model2} +coco_model3_fn=${root_dir}/${coco_model3} + +drone_model1="Drone-yolov5s-ap935-v230302.wts" +drone_model2="Drone-yolov5s6-ap949-v230302.wts" +drone_model1_fn=${root_dir}/${drone_model1} +drone_model2_fn=${root_dir}/${drone_model2} + +personcar_model1="PersonCar-yolov5s-ap606-v230306.wts" +personcar_model2="PersonCar-yolov5s6-ap702-v230306.wts" +personcar_model1_fn=${root_dir}/${personcar_model1} +personcar_model2_fn=${root_dir}/${personcar_model2} + +landing_model1="LandingMarker-resnet34-v230228.onnx" +landing_model1_fn=${root_dir}/${landing_model1} + +SpireCVDet -s ${coco_model1_fn} ${root_dir}/COCO.engine 80 s +SpireCVDet -s ${coco_model2_fn} ${root_dir}/COCO_HD.engine 80 s6 +SpireCVSeg -s ${coco_model3_fn} ${root_dir}/COCO_SEG.engine 80 s + +SpireCVDet -s ${drone_model1_fn} ${root_dir}/Drone.engine 1 s +SpireCVDet -s ${drone_model2_fn} ${root_dir}/Drone_HD.engine 1 s6 + +SpireCVDet -s ${personcar_model1_fn} ${root_dir}/PersonCar.engine 8 s +SpireCVDet -s ${personcar_model2_fn} ${root_dir}/PersonCar_HD.engine 8 s6 + +cd /usr/src/tensorrt/bin/ +./trtexec --explicitBatch --onnx=${landing_model1_fn} --saveEngine=${root_dir}/LandingMarker.engine --fp16 + +echo "export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH" >> ~/.bashrc + diff --git a/models-downloading.sh b/models-downloading.sh new file mode 100755 index 0000000..f884534 --- /dev/null +++ b/models-downloading.sh @@ -0,0 +1,107 @@ +#!/bin/bash -e + +root_dir=${HOME}"/SpireCV/models" +root_server="https://download.amovlab.com/model" + +sv_params1=${HOME}"/SpireCV/sv_algorithm_params.json" +sv_params2=${HOME}"/SpireCV/sv_algorithm_params_coco_640.json" +sv_params3=${HOME}"/SpireCV/sv_algorithm_params_coco_1280.json" +camera_params1=${HOME}"/SpireCV/calib_webcam_640x480.yaml" +camera_params2=${HOME}"/SpireCV/calib_webcam_1280x720.yaml" + +coco_model1="COCO-yolov5s.wts" +coco_model2="COCO-yolov5s6.wts" +coco_model3="COCO-yolov5s-seg.wts" +coco_model1_fn=${root_dir}/${coco_model1} +coco_model2_fn=${root_dir}/${coco_model2} +coco_model3_fn=${root_dir}/${coco_model3} + +drone_model1="Drone-yolov5s-ap935-v230302.wts" +drone_model2="Drone-yolov5s6-ap949-v230302.wts" +drone_model1_fn=${root_dir}/${drone_model1} +drone_model2_fn=${root_dir}/${drone_model2} + +personcar_model1="PersonCar-yolov5s-ap606-v230306.wts" +personcar_model2="PersonCar-yolov5s6-ap702-v230306.wts" +personcar_model1_fn=${root_dir}/${personcar_model1} +personcar_model2_fn=${root_dir}/${personcar_model2} + +track_model1="dasiamrpn_model.onnx" +track_model2="dasiamrpn_kernel_cls1.onnx" +track_model3="dasiamrpn_kernel_r1.onnx" +track_model4="nanotrack_backbone_sim.onnx" +track_model5="nanotrack_head_sim.onnx" +track_model1_fn=${root_dir}/${track_model1} +track_model2_fn=${root_dir}/${track_model2} +track_model3_fn=${root_dir}/${track_model3} +track_model4_fn=${root_dir}/${track_model4} +track_model5_fn=${root_dir}/${track_model5} + +landing_model1="LandingMarker-resnet34-v230228.onnx" +landing_model1_fn=${root_dir}/${landing_model1} + + +if [ ! -d ${root_dir} ]; then + echo -e "\033[32m[INFO]: ${root_dir} not exist, creating it ... \033[0m" + mkdir -p ${root_dir} +fi + +if [ ! -f ${sv_params1} ]; then + echo -e "\033[32m[INFO]: ${sv_params1} not exist, downloading ... \033[0m" + wget -O ${sv_params1} ${root_server}/install/a-params/sv_algorithm_params.json +fi +if [ ! -f ${sv_params2} ]; then + echo -e "\033[32m[INFO]: ${sv_params2} not exist, downloading ... \033[0m" + wget -O ${sv_params2} ${root_server}/install/a-params/sv_algorithm_params_coco_640.json +fi +if [ ! -f ${sv_params3} ]; then + echo -e "\033[32m[INFO]: ${sv_params3} not exist, downloading ... \033[0m" + wget -O ${sv_params3} ${root_server}/install/a-params/sv_algorithm_params_coco_1280.json +fi + +if [ ! -f ${camera_params1} ]; then + echo -e "\033[32m[INFO]: ${camera_params1} not exist, downloading ... \033[0m" + wget -O ${camera_params1} ${root_server}/install/c-params/calib_webcam_640x480.yaml +fi +if [ ! -f ${camera_params2} ]; then + echo -e "\033[32m[INFO]: ${camera_params2} not exist, downloading ... \033[0m" + wget -O ${camera_params2} ${root_server}/install/c-params/calib_webcam_1280x720.yaml +fi + +if [ ! -f ${coco_model1_fn} ]; then + echo -e "\033[32m[INFO]: ${coco_model1_fn} not exist, downloading ... \033[0m" + wget -O ${coco_model1_fn} ${root_server}/install/${coco_model1} + wget -O ${coco_model2_fn} ${root_server}/install/${coco_model2} + wget -O ${coco_model3_fn} ${root_server}/install/${coco_model3} +fi + +if [ ! -f ${drone_model1_fn} ]; then + echo -e "\033[32m[INFO]: ${drone_model1_fn} not exist, downloading ... \033[0m" + wget -O ${drone_model1_fn} ${root_server}/install/${drone_model1} + wget -O ${drone_model2_fn} ${root_server}/install/${drone_model2} +fi + +if [ ! -f ${personcar_model1_fn} ]; then + echo -e "\033[32m[INFO]: ${personcar_model1_fn} not exist, downloading ... \033[0m" + wget -O ${personcar_model1_fn} ${root_server}/install/${personcar_model1} + wget -O ${personcar_model2_fn} ${root_server}/install/${personcar_model2} +fi + +if [ ! -f ${track_model1_fn} ]; then + echo -e "\033[32m[INFO]: ${track_model1_fn} not exist, downloading ... \033[0m" + wget -O ${track_model1_fn} ${root_server}/${track_model1} + wget -O ${track_model2_fn} ${root_server}/${track_model2} + wget -O ${track_model3_fn} ${root_server}/${track_model3} +fi + +if [ ! -f ${track_model4_fn} ]; then + echo -e "\033[32m[INFO]: ${track_model4_fn} not exist, downloading ... \033[0m" + wget -O ${track_model4_fn} ${root_server}/${track_model4} + wget -O ${track_model5_fn} ${root_server}/${track_model5} +fi + +if [ ! -f ${landing_model1_fn} ]; then + echo -e "\033[32m[INFO]: ${landing_model1_fn} not exist, downloading ... \033[0m" + wget -O ${landing_model1_fn} ${root_server}/install/${landing_model1} +fi +