예제 #1
0
int main(int argc, char **argv)
{
    // Initialize ROS
    ros::init(argc, argv, "ic2020_loop");
    ros::NodeHandle n;   

    ros::Subscriber surf_sub = n.subscribe("/vodom/keyframes", 5, keyframeCallback);
    edge_pub = n.advertise<ic2020_toro::newedge>("/loop/edges", 1000);
    loop_notice_pub = n.advertise<ic2020_toro::loopnotice>("/loop/notice", 1000);
	
    // Wait for video streams to be up
    BlockWhileWaitingForVideo();  
	
    cornHelp.Init(newArrival->im);
    
    // Create images
	view_im = cvCreateImage( cvSize(2*newArrival->width, newArrival->height), 8, IPL_PXL_BYTES );
	
	cvNamedWindow("LoopDetect", CV_WINDOW_AUTOSIZE);
	
    // Main loop
    printf("Entering main loop\n");

    int keyframe_done = -1;
    while (ros::ok())
    {
        char c = cvWaitKey(5);
        if (c == 'Q' || c == 'q')
            break;
            
		// Run a RANSAC
		CheckForLoopAndPubQ();
		
        // Get Images
        ros::spinOnce();
        
        // *****************************************
        // Check if we have unprocessed keyframes
        // *****************************************
        if ( keyframes.size() <= keyframe_done + 1)
            continue;       
        keyframe_done = keyframes.size() - 1;
		
		// Detect loop closure
        detectLoopClosure();
		
		// Publish edges for Toro
		publishNewFrame();
    }
	
    return 0;
}
예제 #2
0
int main(int argc, char **argv)
{
    // Initialize ROS
    ros::init(argc, argv, "ic2020_vodom");
    ros::NodeHandle n;   

    ros::Subscriber surf_sub = n.subscribe("/surf/keyframes", 5, optflowCallback);
    ros::Publisher vodom_pub = n.advertise<ic2020_vodom::keyframe>("/vodom/keyframes", 100);    

    // Wait for video streams to be up
    BlockWhileWaitingForVideo();  

    // Create display images
	view_im = cvCreateImage( cvSize(2*newArrival->width, newArrival->height), 8, IPL_PXL_BYTES );

	#ifdef VISUALIZE
	cvNamedWindow("VisualOdom", CV_WINDOW_AUTOSIZE);
	#endif

    // Main loop
    printf("Entering main loop\n");

    while (ros::ok())
    {
        char c = cvWaitKey(5);
        if (c == 'Q' || c == 'q')
            break; 

        // Get Images
        ros::spinOnce();

        // Check if new keyframe is available
        if (newArrival == NULL) { continue; }
        printf ("\33[2J");
        
        // Rotate in new data
        RotateNewArrivalIn();
        
        /**********************************
            Check we have two keyframes
        ***********************************/
        if (kA == 0 || kB == 0) { continue; }
        
        printf("Keyframe A: %i\n", kA->keyframe_num);
        printf("Keyframe B: %i\n", kB->keyframe_num);
        
        // COPY IMAGE DATA TO DOUBLE SIZE IMAGE
        cvSetImageROI( view_im, cvRect(0, 0, kB->im->width, kB->im->height));
        cvCopy( kB->im, view_im );
        cvSetImageROI( view_im, cvRect(kB->im->width, 0, kA->im->width, kA->im->height));
        cvCopy( kA->im, view_im );
        cvResetImageROI( view_im );

        // DRAW RED CIRCLES ON FEATURES
        for (unsigned int i = 0; i < kB->features.size(); i++) {
            cvCircle(view_im, cvPoint(cvRound(kB->features[i].point2D[0]),
                     cvRound(kB->features[i].point2D[1])), 3.0f, colors[0], 2, 8);
        }
        for (unsigned int i = 0; i < kA->features.size(); i++) {
            cvCircle(view_im, cvPoint(cvRound(kA->features[i].point2D[0]) + kB->im->width, 
                     cvRound(kA->features[i].point2D[1])), 3.0f, colors[0], 2, 8);              
        }
        for (unsigned int i = 0; i < kB->numCorn1; i++) {
            cvCircle(view_im, cvPoint(cvRound(kB->corn1[i].point2D[0]),
                     cvRound(kB->corn1[i].point2D[1])), 3.0f, colors[1], 1, 8);
        }
        for (unsigned int i = 0; i < kA->numCorn2; i++) {
            cvCircle(view_im, cvPoint(cvRound(kA->corn2[i].point2D[0]) + kB->im->width, 
                     cvRound(kA->corn2[i].point2D[1])), 3.0f, colors[1], 1, 8);              
        }
        
        /**********************************
          Initial RANSAC w SURF and STCorn
        ***********************************/
        
        // GET SURF PAIRS
        tt = (double)cvGetTickCount();
        std::vector<unsigned int> pairs;
        SURFHelper::findSURFPairs(&kA->descBuffer, &kB->descBuffer, pairs);
        tt = (double)cvGetTickCount() - tt;
        //printf( "SURF Match Time = %gms\n", tt/(cvGetTickFrequency()*1000.));        
        printf( "Found %i SURF Matches \n", pairs.size()/2);
        
        // RANSAC
        std::vector<unsigned int> filtered_surf_pairs;
        std::vector<unsigned int> filtered_corn_pairs;
        tt = (double)cvGetTickCount();
        if (kA->numCorn2 == kB->numCorn1) {
            if (!VisualOdometry::RANSAC6DFast(&kA->features, &kB->features, &pairs, &filtered_surf_pairs,
                                          &kA->corn2[0], &kB->corn1[0], &kB->status[0], kB->numCorn1, &filtered_corn_pairs,
                                          kB->im->width, kB->im->height, 10, 10, 1)) 
            //if (!VisualOdometry::RANSAC6D(&kA->features, &kB->features, &pairs, &filtered_surf_pairs,
            //                              &kA->corn2[0], &kB->corn1[0], &kB->status[0], kB->numCorn1, &filtered_corn_pairs)) 
            //if (!VisualOdometry::RANSAC6DReproj(&kA->features, &kB->features, &pairs, &filtered_surf_pairs))
            {
                printf("RANSAC MATCHES FEATURE # AREN'T EQUAL OR LESS THAN 7 FEATURES \n");
                continue;
            }
        } else {
            printf("WTF KEYFRAME A's FORWARD ST FEATURES != KEYFRAME B's BACK ST FEATURES \n");
        }
        tt = (double)cvGetTickCount() - tt;
        printf( "RANSAC Time = %gms\n", tt/(cvGetTickFrequency()*1000.));        

        // Create index links from B to A
        std::vector<int> revReferenceA;
        for(unsigned int i = 0; i < (unsigned int)kA->features.size(); i++) { revReferenceA.push_back(-1); }
        for(unsigned int i = 0; i < (unsigned int)filtered_surf_pairs.size()/2; i++ )
        {
            int a = filtered_surf_pairs[2*i+0];
            int b = filtered_surf_pairs[2*i+1]; 
            kB->surfMatches[b] = a;
            revReferenceA[a] = b;
        } 
     
        // Remove Useless SURF Features
        std::vector<feature> tfeatures;
        std::vector<surfdesc> tdescBuffer;
        std::vector<int> tsurfMatches;
        for (unsigned int i = 0; i < kA->features.size(); i++) {
            if (revReferenceA[i] >= 0) { // is being matched in the next frame
                tfeatures.push_back(kA->features[i]);
                tdescBuffer.push_back(kA->descBuffer[i]);
                tsurfMatches.push_back(kA->surfMatches[i]);
                kB->surfMatches[revReferenceA[i]] = tfeatures.size() - 1;
            }
            else if (kA->surfMatches[i] >= 0) { // has a match in the previous frame
                tfeatures.push_back(kA->features[i]);
                tdescBuffer.push_back(kA->descBuffer[i]);
                tsurfMatches.push_back(kA->surfMatches[i]);
            }
        }
        kA->features = tfeatures;
        kA->descBuffer = tdescBuffer;
        kA->surfMatches = tsurfMatches;
     
        // CREATE VECTOR OF MATCHES
        std::vector<feature> matchesA2;
        std::vector<feature> matchesB2;
        // ADD IN SURF MATCHES
        for(unsigned int i = 0; i < (unsigned int)filtered_surf_pairs.size()/2; i++ )
        {
            //int a = filtered_surf_pairs[2*i+0];
            int b = filtered_surf_pairs[2*i+1]; 
            int a = kB->surfMatches[b];
            matchesA2.push_back(kA->features[a]);
            matchesB2.push_back(kB->features[b]);
        } 
     
        // ADD IN CORNER MATCHES
        for(unsigned int i = 0; i < kB->numCorn1; i++ )
        {
            if (filtered_corn_pairs[i] > 0) {
                matchesA2.push_back(kA->corn2[i]);
                matchesB2.push_back(kB->corn1[i]);
            } else {
                kB->status[i] = 0;
            }
        }
        
        // Print Green Circles Over RANSAC Points
        for (unsigned int i = 0; i < matchesA2.size(); i++) {
            float lx = matchesB2[i].point2D[0];
            float ly = matchesB2[i].point2D[1];
            float lx2 = matchesA2[i].point2D[0];
            float ly2 = matchesA2[i].point2D[1];
            cvCircle(view_im,cvPoint(cvRound(lx), cvRound(ly)), 3.0f, colors[3], 2, 8);
            cvCircle(view_im, cvPoint(cvRound(lx2) + kA->im->width, cvRound(ly2)), 3.0f, colors[3], 2, 8);  
            cvLine(view_im, cvPoint(cvRound(lx), cvRound(ly)), cvPoint(cvRound(lx2), cvRound(ly2)), colors[3] );
        }

        // Least Squares
        double rdata[9];
        double translation[3];
        
        VisualOdometry::ArunLeastSquares(&matchesA2, &matchesB2, rdata, translation);      
        
        for (unsigned int i = 0; i < 9; i++) { kB->rotation[i] = rdata[i]; }
        for (unsigned int i = 0; i < 3; i++) { kB->translation[i] = translation[i]; }
        
        /*********************
            ICP
        **********************/
        // Setup Images and Contours
        
	/*
        // Call ICP
        double rdata2[9];
        double translation2[3];
        VisualOdometry::ICPKeyframes(kA, kB, rdata, translation, rdata2, translation2);
        for (unsigned int i = 0; i < 9; i++) { kB->rotation[i] = rdata2[i]; }
        for (unsigned int i = 0; i < 3; i++) { kB->translation[i] = translation2[i];}
	*/
        /*********************
            Publish Frame
        **********************/        
        
        // Print Rotation and Translation
        double pitch = atan2(-rdata[6], sqrt(pow(rdata[0],2.0)+pow(rdata[3],2.0)));
        double yaw = atan2(rdata[3]/cos(pitch), rdata[0]/cos(pitch));
        double roll = atan2(rdata[7]/cos(pitch), rdata[8]/cos(pitch));
        printf("pit yaw rol: %f %f %f\n",pitch,yaw,roll);
        printf("translation: %f %f %f\n",translation[0],translation[1],translation[2]); 
        
        /*double pitch2 = atan2(-rdata2[6], sqrt(pow(rdata2[0],2.0)+pow(rdata2[3],2.0)));
        double yaw2 = atan2(rdata2[3]/cos(pitch), rdata2[0]/cos(pitch));
        double roll2 = atan2(rdata2[7]/cos(pitch), rdata2[8]/cos(pitch));
        printf("icp pit yaw rol: %f %f %f\n",pitch2,yaw2,roll2);
        printf("icp translation: %f %f %f\n",translation2[0],translation2[1],translation2[2]); */

        // Publish Point Clouds
        printf("publishing\n");
        kA->PublishKeyframe(&vodom_pub);
        printf("done publishing\n");

	#ifdef VISUALIZE
        // Show stereo image
        cvShowImage("VisualOdom", view_im);
	#endif
    }

    return 0;
}