// find Differential between the latest sample and the desired point back in history Eigen::VectorXd DistributedDiff::findDifferentialFromLatest(const unsigned long &desired_hist_ut) { assert(desired_hist_ut>0); unsigned long actual_delta_ut; // now we need to find where this sample is back in the stored history state Eigen::VectorXd prev_sample(size); prev_sample.resize(size); prev_sample = searchHistElement(desired_hist_ut, &actual_delta_ut); //double firstval = (*_state_hist.back())(0); //double secondval = (prev_sample)(0); //std::cout << "period used: " << actual_delta_ut << " diff between: " << firstval << " - " << prev_sample << " = " << (firstval - prev_sample(0))/(double)actual_delta_ut*1E6; return (*(_state_hist.back()) - prev_sample) / ((double) actual_delta_ut*1.E-6); }
void FlowClusteringEPG::_compute() { if(!optflow_otl_->pull().prev_pcd_indices_) { edge_otl_.push(NULL); return; } cv::Mat3b img = optflow_otl_->pull().img_; initializeStorage(img.rows * img.cols, 0.10); if(cluster_index_.rows == 0) cluster_index_ = cv::Mat1i(img.size(), -1); const vector<int>& prev_pcd_indices = *optflow_otl_->pull().prev_pcd_indices_; const vector<int>& pcd_indices = *optflow_otl_->pull().pcd_indices_; const KinectCloud& prev_cloud = *index_otl_->pull().previous_pcd_; const KinectCloud& cloud = *index_otl_->pull().current_pcd_; ROS_ASSERT(prev_pcd_indices.size() == pcd_indices.size()); int iter = 0; int max_iter = 500; // TODO: Parameterize. vector<int> prev_sample(3); vector<int> sample(3); vector<bool> active(pcd_indices.size(), true); while(iter < max_iter) { ++iter; sampleFlows(active, prev_pcd_indices, pcd_indices, &prev_sample, &sample); Eigen::Matrix4f transform; pcl::registration::TransformationEstimationSVD<Point, Point> te; te.estimateRigidTransformation(prev_cloud, prev_sample, cloud, sample, transform); // -- See if this transform made any sense at all. size_t num_inliers = 0; for(size_t i = 0; i < sample.size(); ++i) { Vector3f projected = (transform * prev_cloud[prev_sample[i]].getVector4fMap()).head(3); float dist = (projected - cloud[sample[i]].getVector3fMap()).norm(); if(dist < inlier_thresh_) ++num_inliers; } if(num_inliers != 3) continue; // -- Refine the estimate. // -- Get inlier flows. vector<bool> inliers(pcd_indices.size(), false); num_inliers = 0; for(size_t i = 0; i < pcd_indices.size(); ++i) { if(!active[i]) continue; Vector3f projected = (transform * prev_cloud[prev_pcd_indices[i]].getVector4fMap()).head(3); float dist = (projected - cloud[pcd_indices[i]].getVector3fMap()).norm(); if(dist < inlier_thresh_) { inliers[i] = true; active[i] = false; ++num_inliers; } } //cout << "FC: Found cluster with " << num_inliers << " inliers out of " << pcd_indices.size() << endl; // -- Link inliers with edge potentials. clusters_.push_back(vector<int>()); vector<int>& cluster = clusters_.back(); cluster.reserve(num_inliers); size_t id = clusters_.size() - 1; for(size_t i = 0; i < inliers.size(); ++i) { if(!inliers[i]) continue; cluster.push_back(pcd_indices[i]); // Assumes ordered ptcld. // Assumes ordered point cloud. ROS_ASSERT((size_t)img.cols == prev_cloud.width); int y = prev_pcd_indices[i] / img.cols; int x = prev_pcd_indices[i] - y * img.cols; cluster_index_(y, x) = id; } sort(cluster.begin(), cluster.end()); // Make a note if this is the one to ignore. if(num_inliers > max_cluster_size_) { max_cluster_size_ = num_inliers; max_cluster_ = id; } // -- Break if few active flows remaining. int num_active = 0; for(size_t i = 0; i < active.size(); ++i) if(active[i]) ++num_active; if(num_active < 3) break; } //cout << "FC: total clusters = " << clusters_.size() << endl; // -- potentials_ is a sparse matrix, so add links in order. // cluster_index_(y, x) is the id of the cluster this pixel is in. // clusters_[i] is a sorted (ascending) vector of indices into the image. for(int y = 0; y < cluster_index_.rows; ++y) { for(int x = 0; x < cluster_index_.cols; ++x) { int idx0 = y * cluster_index_.cols + x; potentials_.startVec(idx0); if(cluster_index_(y, x) == -1) continue; // Ignore the biggest cluster. if(cluster_index_(y, x) == (int)max_cluster_) continue; // TODO: Gross. const vector<int>& cluster = clusters_[cluster_index_(y, x)]; if(cluster.size() < 5) { for(size_t i = 0; i < cluster.size(); ++i) { int idx1 = cluster[i]; if(i > 0) { ROS_ASSERT(cluster[i] > cluster[i-1]); //cout << "FC: Adding edge between " << idx0 << " and " << idx1 << endl; } if(idx0 != idx1) potentials_.insertBack(idx0, idx1) = 1.0; } } else { for(int i = 0; i < 1; ++i) { int r = rand() % cluster.size(); int idx1 = cluster[r]; //cout << "FC: Adding edge between " << idx0 << " and " << idx1 << endl; if(idx0 != idx1) potentials_.insertBack(idx0, idx1) = 1.0; } } } } potentials_.finalize(); edge_otl_.push(&potentials_); }