DAVID4 SDK  1.8.7
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
SimpleMeshComparison.cpp

Shows usage of david::ShapeFusion and david::Measure class.

/// @example SimpleMeshComparison.cpp
///
/// Shows usage of david::ShapeFusion and david::Measure class.
#include "davidSDK/david.h"
#include <math.h>
#include <iostream>
#ifdef _WIN32
#include <conio.h> // required for _getch
#else
#include <curses.h>
#define _getch getch
#endif
namespace examples {
/// Shows usage of david::ShapeFusion and david::Measure class.
///
{
try
{
//=============
// PREPARATION
//=============
// INITIALIZE, CONNECT TO SERVER:
david.Connect();
// IMPORT REFERENCE SCAN:
int idRef = david.fusion().ImportMesh("Reference.obj");
// Best to use absolute paths like "C:/Scans/Reference.obj".
// We assume that the reference part is complete, i.e. contains all surface areas that will be scanned.
// PREPARE SCANNING:
// Select screen.
david.sls().SetScreenID(2);
// II) Select camera based on common name: Select any DAVID cam.
std::vector<std::string> cameraNames = david.sls().GetAvailableCameraNames();
for (size_t i=0; i < cameraNames.size(); ++i)
{
if (cameraNames[i].find("DAVID-CAM") != std::string::npos)
{
david.sls().SelectCamera(cameraNames[i]);
break;
}
}
while (true) // repeat forever (press ESC to stop)
{
printf("\nPress ESC to stop, or any other key to start new measurement\n");
char ch = _getch(); // read one char from keyboard
if (27==ch) break; // breaks if key is ESC
//======
// SCAN
//======
// Scan new part:
int num = david.sls().Scan();
std::cout << "New scan consists of " << num << " 3D points\n";
// Add scan to Shapefusion for further analysis:
int idScan = david.sls().AddScanToShapeFusion();
//===================
// ALIGN AND COMPARE
//===================
// ALIGN SCAN TO REFERENCE:
david.fusion().AlignPairCoarse(idScan, idRef, david::CoarseAlignParams(david::GetMotionInfo_Free())); // first, coarse alignment (free)
david.fusion().AlignPairFine(idScan, idRef, david::FineAlignParams()); // then fine alignment
// COMPUTE DISTANCE VALUES FOR EACH VERTEX:
const double MAX_DIST = 2.0; // maximum for measurement
std::vector<float> distances; // prepare array
david.measure().ComputeSurfaceDistances(distances, idScan, idRef, MAX_DIST);
// "distances" now contains one distance value for each vertex of idScan. You can get those vertices in the same order using david.fusion().GetVertexPositions(...)
//=====================
// SIMPLE DECISION:
// PART IS GOOD OR BAD
//=====================
const float DIST_GOOD = 1.0f; // 1.0 mm --> larger distance is "bad"
const float MAX_ALLOWED_RATIO = 0.05f; // 5 percent bad values allowed
int numBad=0; // count "bad" vertices
for (float dist : distances) // for each distance value
{
if (fabs(dist)>DIST_GOOD) // if absolute value is larger than DIST_GOOD
{
numBad++; // count as bad
}
}
float badRatio = (float)numBad / distances.size(); // relative amount of "bad" vertices
std::cout << badRatio*100 << " percent of vertices are 'bad'\n";
// You could make a more complex analysis here.
if (badRatio <= MAX_ALLOWED_RATIO)
{
std::cout << "==> PART IS GOOD :-)\n";
// Here, make your robot put the part into basket A
// using david.fusion().GetPose(gripPose, idScan) to compute your grip pose
}
else
{
std::cout << "==> PART IS BAD :-(\n";
// Here, make your robot put the part into basket B / trash can
// using david.fusion().GetPose(gripPose, idScan) to compute your grip pose
}
// Delete scan because we don't need it any more:
david.fusion().DeleteMesh(idScan);
}
}
catch (david::Exception& e)
{
e.PrintError();
}
}
} // namespace