diff --git a/README.md b/README.md
index d9be781..9eba1cd 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,11 @@
-
-
+
+
-This repository contains the TrackDLO Robot Operating System (ROS) package. The TrackDLO ROS package is an implementation of our paper *TrackDLO: Tracking Deformable Linear Objects Under Occlusion with Motion Coherence* (under review) by Jingyi Xiang, Holly Dinkel, Harry Zhao, Naixiang Gao, Brian Coltin, Trey Smith, and Timothy Bretl. The TrackDLO algorithm is implemented in C++.
+## TrackDLO: Tracking Deformable Linear Objects Under Occlusion with Motion Coherence
+**IEEE Robotics and Automation Letters (IEEE Xplore: https://ieeexplore.ieee.org/document/10214157)**
+
+This repository contains the TrackDLO Robot Operating System (ROS) package. The TrackDLO ROS package is an implementation of our paper, *TrackDLO: Tracking Deformable Linear Objects Under Occlusion with Motion Coherence*, by Jingyi Xiang, Holly Dinkel, Harry Zhao, Naixiang Gao, Brian Coltin, Trey Smith, and Timothy Bretl. The TrackDLO algorithm is implemented in C++.
@@ -19,14 +22,17 @@ See the [requirements and run instructions](https://github.com/RMDLO/trackdlo/bl
To learn more about TrackDLO, watch our [supplementary video](https://www.youtube.com/watch?v=MxqNJsen5eg&t) and read our [supplemental documentation](https://github.com/RMDLO/trackdlo/blob/master/docs/LEARN_MORE.md).
-## Bibtex:
+## Bibtex
```bash
-@inproceedings{xiang2023trackdlo,
- title={TrackDLO: Tracking Deformable Linear Objects Under Occlusion with Motion Coherence},
+@ARTICLE{10214157,
author={Xiang, Jingyi and Dinkel, Holly and Zhao, Harry and Gao, Naixiang and Coltin, Brian and Smith, Trey and Bretl, Timothy},
- booktitle={IEEE Robotics and Automation: Letters},
- pages={1--8},
+ journal={IEEE Robotics and Automation Letters},
+ title={TrackDLO: Tracking Deformable Linear Objects Under Occlusion with Motion Coherence},
year={2023},
+ volume={},
+ number={},
+ pages={1-8},
+ doi={10.1109/LRA.2023.3303710}
}
```
\ No newline at end of file
diff --git a/launch/trackdlo.launch b/launch/trackdlo.launch
index afab431..d8dc402 100644
--- a/launch/trackdlo.launch
+++ b/launch/trackdlo.launch
@@ -9,18 +9,10 @@
-
+
-
-
-
-
-
-
-
@@ -32,24 +24,12 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
@@ -62,23 +42,22 @@
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
diff --git a/trackdlo/include/trackdlo.h b/trackdlo/include/trackdlo.h
index 281ca50..4d0e13e 100644
--- a/trackdlo/include/trackdlo.h
+++ b/trackdlo/include/trackdlo.h
@@ -58,19 +58,17 @@ class trackdlo
trackdlo(int num_of_nodes);
// fancy constructor
trackdlo(int num_of_nodes,
- double visibility_threshold,
- double beta,
- double lambda,
- double alpha,
- double gamma,
- double k_vis,
- double mu,
- int max_iter,
- const double tol,
- bool include_lle,
- bool use_geodesic,
- bool use_prev_sigma2,
- int kernel);
+ double visibility_threshold,
+ double beta,
+ double lambda,
+ double alpha,
+ double k_vis,
+ double mu,
+ int max_iter,
+ double tol,
+ double beta_pre_proc,
+ double lambda_pre_proc,
+ double lle_weight);
double get_sigma2();
MatrixXd get_tracking_result();
@@ -80,27 +78,23 @@ class trackdlo
void initialize_nodes (MatrixXd Y_init);
void set_sigma2 (double sigma2);
- bool cpd_lle (MatrixXd X,
+ bool cpd_lle (MatrixXd X_orig,
MatrixXd& Y,
double& sigma2,
double beta,
double lambda,
- double gamma,
+ double lle_weight,
double mu,
int max_iter = 30,
- double tol = 0.00001,
+ double tol = 0.0001,
bool include_lle = true,
- bool use_geodesic = false,
- bool use_prev_sigma2 = false,
- bool use_ecpd = false,
std::vector correspondence_priors = {},
double alpha = 0,
- int kernel = 3,
std::vector visible_nodes = {},
double k_vis = 0,
double visibility_threshold = 0.01);
- void tracking_step (MatrixXd X,
+ void tracking_step (MatrixXd X_orig,
std::vector visible_nodes,
std::vector visible_nodes_extended,
MatrixXd proj_matrix,
@@ -112,17 +106,16 @@ class trackdlo
MatrixXd guide_nodes_;
double sigma2_;
double beta_;
+ double beta_pre_proc_;
double lambda_;
+ double lambda_pre_proc_;
double alpha_;
- double lle_weight_;
double k_vis_;
double mu_;
int max_iter_;
double tol_;
- bool include_lle_;
- bool use_geodesic_;
- bool use_prev_sigma2_;
- int kernel_;
+ double lle_weight_;
+
std::vector geodesic_coord_;
std::vector correspondence_priors_;
double visibility_threshold_;
diff --git a/trackdlo/src/trackdlo.cpp b/trackdlo/src/trackdlo.cpp
index 0d139ab..70717a5 100644
--- a/trackdlo/src/trackdlo.cpp
+++ b/trackdlo/src/trackdlo.cpp
@@ -12,18 +12,16 @@ trackdlo::trackdlo(int num_of_nodes) {
Y_ = MatrixXd::Zero(num_of_nodes, 3);
guide_nodes_ = Y_.replicate(1, 1);
sigma2_ = 0.0;
- beta_ = 1.0;
+ beta_ = 5.0;
+ beta_pre_proc_ = 3.0;
lambda_ = 1.0;
+ lambda_pre_proc_ = 1.0;
alpha_ = 0.0;
lle_weight_ = 1.0;
k_vis_ = 0.0;
mu_ = 0.05;
max_iter_ = 50;
tol_ = 0.00001;
- include_lle_ = true;
- use_geodesic_ = true;
- use_prev_sigma2_ = true;
- kernel_ = 1;
geodesic_coord_ = {};
correspondence_priors_ = {};
visibility_threshold_ = 0.02;
@@ -34,32 +32,28 @@ trackdlo::trackdlo(int num_of_nodes,
double beta,
double lambda,
double alpha,
- double lle_weight,
double k_vis,
double mu,
int max_iter,
double tol,
- bool include_lle,
- bool use_geodesic,
- bool use_prev_sigma2,
- int kernel)
+ double beta_pre_proc,
+ double lambda_pre_proc,
+ double lle_weight)
{
Y_ = MatrixXd::Zero(num_of_nodes, 3);
visibility_threshold_ = visibility_threshold;
guide_nodes_ = Y_.replicate(1, 1);
sigma2_ = 0.0;
beta_ = beta;
+ beta_pre_proc_ = beta_pre_proc;
lambda_ = lambda;
+ lambda_pre_proc_ = lambda_pre_proc;
alpha_ = alpha;
lle_weight_ = lle_weight;
k_vis_ = k_vis;
mu_ = mu;
max_iter_ = max_iter;
tol_ = tol;
- include_lle_ = include_lle;
- use_geodesic_ = use_geodesic;
- use_prev_sigma2_ = use_prev_sigma2;
- kernel_ = kernel;
geodesic_coord_ = {};
correspondence_priors_ = {};
}
@@ -164,7 +158,7 @@ MatrixXd trackdlo::calc_LLE_weights (int k, MatrixXd X) {
return W;
}
-bool trackdlo::cpd_lle (MatrixXd X,
+bool trackdlo::cpd_lle (MatrixXd X_orig,
MatrixXd& Y,
double& sigma2,
double beta,
@@ -174,23 +168,34 @@ bool trackdlo::cpd_lle (MatrixXd X,
int max_iter,
double tol,
bool include_lle,
- bool use_geodesic,
- bool use_prev_sigma2,
- bool use_ecpd,
std::vector correspondence_priors,
double alpha,
- int kernel,
std::vector visible_nodes,
double k_vis,
double visibility_threshold)
{
+ // prune X
+ MatrixXd X_temp = MatrixXd::Zero(X_orig.rows(), 3);
+ int valid_pt_counter = 0;
+ for (int i = 0; i < X_orig.rows(); i ++) {
+ // find shortest distance between this point and any node
+ double shortest_dist = 100000;
+ for (int j = 0; j < Y.rows(); j ++) {
+ double dist = (Y.row(j) - X_orig.row(i)).norm();
+ if (dist < shortest_dist) {
+ shortest_dist = dist;
+ }
+ }
+ // require a point to be sufficiently close to the node set to be valid
+ if (shortest_dist < 0.1) {
+ X_temp.row(valid_pt_counter) = X_orig.row(i);
+ valid_pt_counter += 1;
+ }
+ }
+ MatrixXd X = X_temp.topRows(valid_pt_counter);
bool converged = true;
- if (correspondence_priors.size() == 0) {
- use_ecpd = false;
- }
-
int M = Y.rows();
int N = X.rows();
int D = 3;
@@ -211,65 +216,29 @@ bool trackdlo::cpd_lle (MatrixXd X,
std::vector converted_node_coord = {0.0}; // this is not squared
MatrixXd G = MatrixXd::Zero(M, M);
- if (!use_geodesic) {
- if (kernel == 3) {
- G = (-diff_yy / (2 * beta * beta)).array().exp();
- }
- else if (kernel == 0) {
- G = (-diff_yy_sqrt / (2 * beta * beta)).array().exp();
- }
- else if (kernel == 1) {
- // G = 1/(2*beta * 2*beta) * (-sqrt(2)*diff_yy_sqrt/beta).array().exp() * (2*diff_yy_sqrt.array() + sqrt(2)*beta);
- G = 1/(2 * pow(beta, 2)) * (-2 *diff_yy_sqrt/beta).array().exp() * (2*diff_yy_sqrt.array() + sqrt(2)*beta);
- }
- else if (kernel == 2) {
- // G = 27 * 1/(72 * pow(beta, 3)) * (-sqrt(3)*diff_yy_sqrt/beta).array().exp() * (sqrt(3)*beta*beta + 3*beta*diff_yy_sqrt.array() + sqrt(3)*diff_yy.array());
- G = 3/(16 * pow(beta, 3)) * (-sqrt(6)*diff_yy_sqrt/beta).array().exp() * (2*sqrt(6)*diff_yy.array() + 6*beta*diff_yy_sqrt.array() + sqrt(6) * pow(beta, 2));
- }
- else { // default to gaussian
- G = (-diff_yy / (2 * beta * beta)).array().exp();
- }
+ double cur_sum = 0;
+ for (int i = 0; i < M-1; i ++) {
+ cur_sum += pt2pt_dis(Y_0.row(i+1), Y_0.row(i));
+ converted_node_coord.push_back(cur_sum);
}
- else {
- double cur_sum = 0;
- for (int i = 0; i < M-1; i ++) {
- cur_sum += pt2pt_dis(Y_0.row(i+1), Y_0.row(i));
- converted_node_coord.push_back(cur_sum);
- }
- for (int i = 0; i < converted_node_coord.size(); i ++) {
- for (int j = 0; j < converted_node_coord.size(); j ++) {
- converted_node_dis_sq(i, j) = pow(converted_node_coord[i] - converted_node_coord[j], 2);
- converted_node_dis(i, j) = abs(converted_node_coord[i] - converted_node_coord[j]);
- }
- }
-
- if (kernel == 3) {
- G = (-converted_node_dis_sq / (2 * beta * beta)).array().exp();
- }
- else if (kernel == 0) {
- G = (-converted_node_dis / (2 * beta * beta)).array().exp();
- }
- else if (kernel == 1) {
- G = 1/(2*beta * 2*beta) * (-sqrt(2)*converted_node_dis/beta).array().exp() * (sqrt(2)*converted_node_dis.array() + beta);
- }
- else if (kernel == 2) {
- G = 27 * 1/(72 * pow(beta, 3)) * (-sqrt(3)*converted_node_dis/beta).array().exp() * (sqrt(3)*beta*beta + 3*beta*converted_node_dis.array() + sqrt(3)*converted_node_dis_sq.array());
- }
- else { // default to gaussian
- G = (-converted_node_dis_sq / (2 * beta * beta)).array().exp();
+ for (int i = 0; i < converted_node_coord.size(); i ++) {
+ for (int j = 0; j < converted_node_coord.size(); j ++) {
+ converted_node_dis_sq(i, j) = pow(converted_node_coord[i] - converted_node_coord[j], 2);
+ converted_node_dis(i, j) = abs(converted_node_coord[i] - converted_node_coord[j]);
}
}
+ // kernel matrix
+ G = 1/(2*beta * 2*beta) * (-sqrt(2)*converted_node_dis/beta).array().exp() * (2*converted_node_dis.array() + sqrt(2)*beta);
+
// get the LLE matrix
MatrixXd L = calc_LLE_weights(6, Y_0);
MatrixXd H = (MatrixXd::Identity(M, M) - L).transpose() * (MatrixXd::Identity(M, M) - L);
- // construct R and J
- MatrixXd priors = MatrixXd::Zero(correspondence_priors.size(), 3);
+ // construct J
MatrixXd J = MatrixXd::Zero(M, M);
MatrixXd Y_extended = Y_0.replicate(1, 1);
- MatrixXd G_masked = MatrixXd::Zero(M, M);
if (correspondence_priors.size() != 0) {
int num_of_correspondence_priors = correspondence_priors.size();
@@ -280,10 +249,8 @@ bool trackdlo::cpd_lle (MatrixXd X,
temp(0, 1) = correspondence_priors[i](0, 2);
temp(0, 2) = correspondence_priors[i](0, 3);
- priors.row(i) = temp;
J.row(index) = MatrixXd::Identity(M, M).row(index);
Y_extended.row(index) = temp;
- G_masked.row(index) = G.row(index);
// // enforce boundaries
// if (i == 0 || i == num_of_correspondence_priors-1) {
@@ -301,7 +268,7 @@ bool trackdlo::cpd_lle (MatrixXd X,
}
// initialize sigma2
- if (!use_prev_sigma2 || sigma2 == 0) {
+ if (sigma2 == 0) {
sigma2 = diff_xy.sum() / static_cast(D * M * N);
}
@@ -333,64 +300,59 @@ bool trackdlo::cpd_lle (MatrixXd X,
double c = pow((2 * M_PI * sigma2), static_cast(D)/2) * mu / (1 - mu) * static_cast(M)/N;
P = P.array().rowwise() / (P.colwise().sum().array() + c);
- if (use_geodesic) {
- std::vector max_p_nodes(P.cols(), 0);
- MatrixXd pts_dis_sq_geodesic = MatrixXd::Zero(M, N);
+ // P matrix calculation based on geodesic distance
+ std::vector max_p_nodes(P.cols(), 0);
+ MatrixXd pts_dis_sq_geodesic = MatrixXd::Zero(M, N);
- // loop through all points
- for (int i = 0; i < N; i ++) {
-
- P.col(i).maxCoeff(&max_p_nodes[i]);
- int max_p_node = max_p_nodes[i];
+ // loop through all points
+ for (int i = 0; i < N; i ++) {
+
+ P.col(i).maxCoeff(&max_p_nodes[i]);
+ int max_p_node = max_p_nodes[i];
- int potential_2nd_max_p_node_1 = max_p_node - 1;
- if (potential_2nd_max_p_node_1 == -1) {
- potential_2nd_max_p_node_1 = 2;
- }
+ int potential_2nd_max_p_node_1 = max_p_node - 1;
+ if (potential_2nd_max_p_node_1 == -1) {
+ potential_2nd_max_p_node_1 = 2;
+ }
- int potential_2nd_max_p_node_2 = max_p_node + 1;
- if (potential_2nd_max_p_node_2 == M) {
- potential_2nd_max_p_node_2 = M - 3;
- }
+ int potential_2nd_max_p_node_2 = max_p_node + 1;
+ if (potential_2nd_max_p_node_2 == M) {
+ potential_2nd_max_p_node_2 = M - 3;
+ }
- int next_max_p_node;
- if (pt2pt_dis(Y.row(potential_2nd_max_p_node_1), X.row(i)) < pt2pt_dis(Y.row(potential_2nd_max_p_node_2), X.row(i))) {
- next_max_p_node = potential_2nd_max_p_node_1;
- }
- else {
- next_max_p_node = potential_2nd_max_p_node_2;
- }
+ int next_max_p_node;
+ if (pt2pt_dis(Y.row(potential_2nd_max_p_node_1), X.row(i)) < pt2pt_dis(Y.row(potential_2nd_max_p_node_2), X.row(i))) {
+ next_max_p_node = potential_2nd_max_p_node_1;
+ }
+ else {
+ next_max_p_node = potential_2nd_max_p_node_2;
+ }
- // fill the current column of pts_dis_sq_geodesic
- pts_dis_sq_geodesic(max_p_node, i) = pt2pt_dis_sq(Y.row(max_p_node), X.row(i));
- pts_dis_sq_geodesic(next_max_p_node, i) = pt2pt_dis_sq(Y.row(next_max_p_node), X.row(i));
+ // fill the current column of pts_dis_sq_geodesic
+ pts_dis_sq_geodesic(max_p_node, i) = pt2pt_dis_sq(Y.row(max_p_node), X.row(i));
+ pts_dis_sq_geodesic(next_max_p_node, i) = pt2pt_dis_sq(Y.row(next_max_p_node), X.row(i));
- if (max_p_node < next_max_p_node) {
- for (int j = 0; j < max_p_node; j ++) {
- pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[max_p_node]) + pt2pt_dis(Y.row(max_p_node), X.row(i)), 2);
- }
- for (int j = next_max_p_node; j < M; j ++) {
- pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[next_max_p_node]) + pt2pt_dis(Y.row(next_max_p_node), X.row(i)), 2);
- }
+ if (max_p_node < next_max_p_node) {
+ for (int j = 0; j < max_p_node; j ++) {
+ pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[max_p_node]) + pt2pt_dis(Y.row(max_p_node), X.row(i)), 2);
}
- else {
- for (int j = 0; j < next_max_p_node; j ++) {
- pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[next_max_p_node]) + pt2pt_dis(Y.row(next_max_p_node), X.row(i)), 2);
- }
- for (int j = max_p_node; j < M; j ++) {
- pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[max_p_node]) + pt2pt_dis(Y.row(max_p_node), X.row(i)), 2);
- }
+ for (int j = next_max_p_node; j < M; j ++) {
+ pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[next_max_p_node]) + pt2pt_dis(Y.row(next_max_p_node), X.row(i)), 2);
+ }
+ }
+ else {
+ for (int j = 0; j < next_max_p_node; j ++) {
+ pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[next_max_p_node]) + pt2pt_dis(Y.row(next_max_p_node), X.row(i)), 2);
+ }
+ for (int j = max_p_node; j < M; j ++) {
+ pts_dis_sq_geodesic(j, i) = pow(abs(converted_node_coord[j] - converted_node_coord[max_p_node]) + pt2pt_dis(Y.row(max_p_node), X.row(i)), 2);
}
}
-
- // update P
- P = (-0.5 * pts_dis_sq_geodesic / sigma2).array().exp();
- // P = P.array().rowwise() / (P.colwise().sum().array() + c);
- }
- else {
- P = P_stored.replicate(1, 1);
}
+ // update P
+ P = (-0.5 * pts_dis_sq_geodesic / sigma2).array().exp();
+
// modified membership probability (adapted from cdcpd)
if (visible_nodes.size() != Y.rows() && !visible_nodes.empty() && k_vis != 0) {
@@ -420,11 +382,8 @@ bool trackdlo::cpd_lle (MatrixXd X,
P = P.array().rowwise() / (P.colwise().sum().array() + c);
}
- // test code when not using pvis
- // P = P.array().rowwise() / (P.colwise().sum().array() + c);
- // std::cout << P.colwise().sum() << std::endl;
- MatrixXd Pt1 = P.colwise().sum(); // this should have shape (N,) or (1, N)
+ MatrixXd Pt1 = P.colwise().sum();
MatrixXd P1 = P.rowwise().sum();
double Np = P1.sum();
MatrixXd PX = P * X;
@@ -433,7 +392,7 @@ bool trackdlo::cpd_lle (MatrixXd X,
MatrixXd A_matrix;
MatrixXd B_matrix;
if (include_lle) {
- if (use_ecpd) {
+ if (correspondence_priors.size() != 0) {
A_matrix = P1.asDiagonal()*G + lambda*sigma2 * MatrixXd::Identity(M, M) + sigma2*lle_weight * H*G + alpha*J*G;
B_matrix = PX - P1.asDiagonal()*Y_0 - sigma2*lle_weight * H*Y_0 + alpha*(Y_extended - Y_0);
}
@@ -443,7 +402,7 @@ bool trackdlo::cpd_lle (MatrixXd X,
}
}
else {
- if (use_ecpd) {
+ if (correspondence_priors.size() != 0) {
A_matrix = P1.asDiagonal() * G + lambda * sigma2 * MatrixXd::Identity(M, M) + alpha*J*G;
B_matrix = PX - P1.asDiagonal() * Y_0 + alpha*(Y_extended - Y_0);
}
@@ -655,7 +614,7 @@ std::vector trackdlo::traverse_euclidean (std::vector geodesic
int seg_dist_it = 0;
MatrixXd cur_center = guide_nodes.row(0);
- // basically pure pursuit lol
+ // basically pure pursuit
while (last_found_index+1 <= consecutive_visible_nodes.size()-1 && seg_dist_it+1 <= geodesic_coord.size()-1) {
double look_ahead_dist = fabs(geodesic_coord[seg_dist_it+1] - geodesic_coord[seg_dist_it]);
bool found_intersection = false;
@@ -730,7 +689,7 @@ std::vector trackdlo::traverse_euclidean (std::vector geodesic
int seg_dist_it = geodesic_coord.size()-1;
MatrixXd cur_center = guide_nodes.row(guide_nodes.rows()-1);
- // basically pure pursuit lol
+ // basically pure pursuit
while (last_found_index-1 >= (guide_nodes.rows() - consecutive_visible_nodes.size()) && seg_dist_it-1 >= 0) {
double look_ahead_dist = fabs(geodesic_coord[seg_dist_it] - geodesic_coord[seg_dist_it-1]);
@@ -808,7 +767,7 @@ std::vector trackdlo::traverse_euclidean (std::vector geodesic
int seg_dist_it = visible_nodes[alignment_node_idx];
MatrixXd cur_center = guide_nodes.row(alignment_node_idx);
- // basically pure pursuit lol
+ // basically pure pursuit
while (last_found_index+1 <= alignment_node_idx+consecutive_visible_nodes_2.size()-1 && seg_dist_it+1 <= geodesic_coord.size()-1) {
double look_ahead_dist = fabs(geodesic_coord[seg_dist_it+1] - geodesic_coord[seg_dist_it]);
bool found_intersection = false;
@@ -879,7 +838,7 @@ std::vector trackdlo::traverse_euclidean (std::vector geodesic
seg_dist_it = visible_nodes[alignment_node_idx];
cur_center = guide_nodes.row(alignment_node_idx);
- // basically pure pursuit lol
+ // basically pure pursuit
while (last_found_index-1 >= alignment_node_idx-consecutive_visible_nodes_1.size() && seg_dist_it-1 >= 0) {
double look_ahead_dist = fabs(geodesic_coord[seg_dist_it] - geodesic_coord[seg_dist_it-1]);
bool found_intersection = false;
@@ -938,7 +897,7 @@ std::vector trackdlo::traverse_euclidean (std::vector geodesic
return node_pairs;
}
-void trackdlo::tracking_step (MatrixXd X,
+void trackdlo::tracking_step (MatrixXd X_orig,
std::vector visible_nodes,
std::vector visible_nodes_extended,
MatrixXd proj_matrix,
@@ -964,8 +923,8 @@ void trackdlo::tracking_step (MatrixXd X,
// determine DLO state: heading visible, tail visible, both visible, or both occluded
// priors_vec should be the final output; priors_vec[i] = {index, x, y, z}
double sigma2_pre_proc = sigma2_;
- cpd_lle(X, guide_nodes_, sigma2_pre_proc, 3, 1, lle_weight_, mu_, 50, tol_, true, true, true, false, {}, 0, 1);
- // cpd_lle(X, guide_nodes_, sigma2_pre_proc, 1, 1, 1, mu_, 50, tol_, true, true, true);
+ // pre-processing registration
+ cpd_lle(X_orig, guide_nodes_, sigma2_pre_proc, beta_pre_proc_, lambda_pre_proc_, lle_weight_, mu_, max_iter_, tol_, true);
if (visible_nodes_extended.size() == Y_.rows()) {
if (visible_nodes.size() == visible_nodes_extended.size()) {
@@ -975,11 +934,9 @@ void trackdlo::tracking_step (MatrixXd X,
ROS_INFO("Minor occlusion");
}
- // get priors vec
+ // remap visible node locations
std::vector priors_vec_1 = traverse_euclidean(geodesic_coord_, guide_nodes_, visible_nodes_extended, 0);
std::vector priors_vec_2 = traverse_euclidean(geodesic_coord_, guide_nodes_, visible_nodes_extended, 1);
- // std::vector priors_vec_1 = traverse_geodesic(geodesic_coord, guide_nodes, visible_nodes, 0);
- // std::vector priors_vec_2 = traverse_geodesic(geodesic_coord, guide_nodes, visible_nodes, 1);
// priors vec 2 goes from last index -> first index
std::reverse(priors_vec_2.begin(), priors_vec_2.end());
@@ -1038,5 +995,5 @@ void trackdlo::tracking_step (MatrixXd X,
}
// include_lle == false because we have no space to discuss it in the paper
- cpd_lle (X, Y_, sigma2_, beta_, lambda_, lle_weight_, mu_, max_iter_, tol_, include_lle_, use_geodesic_, use_prev_sigma2_, true, correspondence_priors_, alpha_, kernel_, visible_nodes_extended, k_vis_, visibility_threshold_);
+ cpd_lle (X_orig, Y_, sigma2_, beta_, lambda_, lle_weight_, mu_, max_iter_, tol_, false, correspondence_priors_, alpha_, visible_nodes_extended, k_vis_, visibility_threshold_);
}
\ No newline at end of file
diff --git a/trackdlo/src/trackdlo_node.cpp b/trackdlo/src/trackdlo_node.cpp
index 7de3149..f2d2626 100644
--- a/trackdlo/src/trackdlo_node.cpp
+++ b/trackdlo/src/trackdlo_node.cpp
@@ -26,24 +26,20 @@ Mat occlusion_mask;
bool updated_opencv_mask = false;
MatrixXd proj_matrix(3, 4);
-double total_len = 0;
-
bool multi_color_dlo;
-bool gltp;
double visibility_threshold;
int dlo_pixel_width;
double beta;
+double beta_pre_proc;
double lambda;
+double lambda_pre_proc;
double alpha;
double lle_weight;
double mu;
int max_iter;
double tol;
double k_vis;
-bool include_lle;
-bool use_geodesic;
-bool use_prev_sigma2;
-int kernel;
+double d_vis;
double downsample_leaf_size;
std::string camera_info_topic;
@@ -132,7 +128,7 @@ sensor_msgs::ImagePtr Callback(const sensor_msgs::ImageConstPtr& image_msg, cons
if (!initialized) {
if (received_init_nodes && received_proj_matrix) {
- tracker = trackdlo(init_nodes.rows(), visibility_threshold, beta, lambda, alpha, lle_weight, k_vis, mu, max_iter, tol, include_lle, use_geodesic, use_prev_sigma2, kernel);
+ tracker = trackdlo(init_nodes.rows(), visibility_threshold, beta, lambda, alpha, k_vis, mu, max_iter, tol, beta_pre_proc, lambda_pre_proc, lle_weight);
sigma2 = 0.001;
@@ -260,8 +256,6 @@ sensor_msgs::ImagePtr Callback(const sensor_msgs::ImageConstPtr& image_msg, cons
// for each point in X, determine its shortest distance to Y
std::map shortest_node_pt_dists;
std::vector shortest_pt_node_dists(X.rows(), 100000.0);
- MatrixXd X_temp = MatrixXd::Zero(X.rows(), 3);
- int valid_pt_counter = 0;
for (int m = 0; m < Y.rows(); m ++) {
int closest_pt_idx = 0;
double shortest_dist = 100000;
@@ -278,24 +272,10 @@ sensor_msgs::ImagePtr Callback(const sensor_msgs::ImageConstPtr& image_msg, cons
if (dist < shortest_pt_node_dists[n]) {
shortest_pt_node_dists[n] = dist;
}
- // count valid point in the last iteration
- if (m == Y.rows()-1) {
- // assumption: DLO movement between frames is small
- // get rid of points too far away from the node point set Y^{t-1}
- // this is necessary because exp(-dist/sigma2) can become too small to represent in MatrixXd
- // if a point x_n in X is too far away from all nodes, all entries in row n of P will be zero,
- // even if they technically aren't all zeros
- if (shortest_pt_node_dists[n] < 0.05) {
- X_temp.row(valid_pt_counter) = X.row(n);
- valid_pt_counter += 1;
- }
- }
}
shortest_node_pt_dists.insert(std::pair(m, shortest_dist));
}
- MatrixXd X_pruned = X_temp.topRows(valid_pt_counter);
-
// for current nodes and edges in Y, sort them based on how far away they are from the camera
std::vector averaged_node_camera_dists = {};
std::vector indices_vec = {};
@@ -355,14 +335,11 @@ sensor_msgs::ImagePtr Callback(const sensor_msgs::ImageConstPtr& image_msg, cons
}
// add edges for checking overlap with upcoming nodes
- cv::line(projected_edges, cv::Point(col_1, row_1), cv::Point(col_2, row_2), cv::Scalar(255, 255, 255), dlo_pixel_width);
- }
-
- // obtain self-occluded nodes
- for (int i = 0; i < Y.rows(); i ++) {
- if (std::find(not_self_occluded_nodes.begin(), not_self_occluded_nodes.end(), i) == not_self_occluded_nodes.end()) {
- self_occluded_nodes.push_back(i);
- }
+ double x1 = col_1;
+ double y1 = row_1;
+ double x2 = col_2;
+ double y2 = row_2;
+ cv::line(projected_edges, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 255, 255), dlo_pixel_width);
}
// sort visible nodes to preserve the original connectivity
@@ -373,8 +350,8 @@ sensor_msgs::ImagePtr Callback(const sensor_msgs::ImageConstPtr& image_msg, cons
std::vector visible_nodes_extended = {};
for (int i = 0; i < visible_nodes.size()-1; i ++) {
visible_nodes_extended.push_back(visible_nodes[i]);
- // extend two nodes
- if (visible_nodes[i+1] - visible_nodes[i] <= 3) {
+ // extend visible nodes
+ if (fabs(converted_node_coord[visible_nodes[i+1]] - converted_node_coord[visible_nodes[i]]) <= d_vis) {
for (int j = 1; j < visible_nodes[i+1] - visible_nodes[i]; j ++) {
visible_nodes_extended.push_back(visible_nodes[i] + j);
}
@@ -385,15 +362,11 @@ sensor_msgs::ImagePtr Callback(const sensor_msgs::ImageConstPtr& image_msg, cons
// store Y_0 for post processing
MatrixXd Y_0 = Y.replicate(1, 1);
- if (!gltp) {
- tracker.tracking_step(X_pruned, visible_nodes, visible_nodes_extended, proj_matrix, mask.rows, mask.cols);
- Y = tracker.get_tracking_result();
- guide_nodes = tracker.get_guide_nodes();
- priors = tracker.get_correspondence_pairs();
- }
- else {
- tracker.cpd_lle(X_pruned, Y, sigma2, 1, 1, 1, mu, 50, tol, true, false, true);
- }
+ // step tracker
+ tracker.tracking_step(X, visible_nodes, visible_nodes_extended, proj_matrix, mask.rows, mask.cols);
+ Y = tracker.get_tracking_result();
+ guide_nodes = tracker.get_guide_nodes();
+ priors = tracker.get_correspondence_pairs();
// log time
time_diff = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - cur_time).count() / 1000.0;
@@ -566,20 +539,18 @@ int main(int argc, char **argv) {
nh.getParam("/trackdlo/beta", beta);
nh.getParam("/trackdlo/lambda", lambda);
nh.getParam("/trackdlo/alpha", alpha);
- nh.getParam("/trackdlo/lle_weight", lle_weight);
nh.getParam("/trackdlo/mu", mu);
nh.getParam("/trackdlo/max_iter", max_iter);
nh.getParam("/trackdlo/tol", tol);
nh.getParam("/trackdlo/k_vis", k_vis);
- nh.getParam("/trackdlo/include_lle", include_lle);
- nh.getParam("/trackdlo/use_geodesic", use_geodesic);
- nh.getParam("/trackdlo/use_prev_sigma2", use_prev_sigma2);
- nh.getParam("/trackdlo/kernel", kernel);
-
- nh.getParam("/trackdlo/multi_color_dlo", multi_color_dlo);
- nh.getParam("/trackdlo/gltp", gltp);
+ nh.getParam("/trackdlo/d_vis", d_vis);
nh.getParam("/trackdlo/visibility_threshold", visibility_threshold);
nh.getParam("/trackdlo/dlo_pixel_width", dlo_pixel_width);
+ nh.getParam("/trackdlo/beta_pre_proc", beta_pre_proc);
+ nh.getParam("/trackdlo/lambda_pre_proc", lambda_pre_proc);
+ nh.getParam("/trackdlo/lle_weight", lle_weight);
+
+ nh.getParam("/trackdlo/multi_color_dlo", multi_color_dlo);
nh.getParam("/trackdlo/downsample_leaf_size", downsample_leaf_size);
nh.getParam("/trackdlo/camera_info_topic", camera_info_topic);