<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2008-02-25 17:27:17 +0100 (Mo, 25 Feb 2008) $
Version:   $Revision: 7837 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkStandardFileLocations.h"
#include "mitkDicomSeriesReader.h"
#include "mitkTestingMacros.h"
#include "mitkImageStatisticsCalculator.h"
#include "mitkPlanarPolygon.h"

#include "mitkDicomSeriesReader.h"
#include <itkGDCMSeriesFileNames.h>

//#include <QtCore>

/**
 * \brief Test class for mitkImageStatisticsCalculator
 *
 * This test covers:
 * - instantiation of an ImageStatisticsCalculator class
 * - correctness of statistics when using PlanarFigures for masking
 */
class mitkImageStatisticsCalculatorTestClass
{

public:

  struct testCase
  {
    int id;
    mitk::PlanarFigure::Pointer figure;
    double mean;
    double sd;
  };

// calculate statistics for the given image and planarpolygon
static const mitk::ImageStatisticsCalculator::Statistics TestStatistics( mitk::Image::Pointer image, mitk::PlanarFigure::Pointer polygon )
{
  mitk::ImageStatisticsCalculator::Pointer statisticsCalculator = mitk::ImageStatisticsCalculator::New();
  statisticsCalculator->SetImage( image );
  statisticsCalculator->SetMaskingModeToPlanarFigure();
  statisticsCalculator->SetPlanarFigure( polygon );

  statisticsCalculator->ComputeStatistics();

  return statisticsCalculator->GetStatistics();
}

// returns a vector of defined test-cases
static std::vector<testCase> InitializeTestCases( mitk::Geometry2D::Pointer geom )
{
  std::vector<testCase> testCases;

  {
    /*****************************
    * one whole white pixel
    * -> mean of 255 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 10.5 ; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 10.5; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 255.0;
    test.sd = 0.0;

    testCases.push_back( test );
  }

  {
    /*****************************
    * half pixel in x-direction (white)
    * -> mean of 255 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 10.0 ; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 10.0; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 255.0;
    test.sd = 0.0;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (white) + half pixel (gray) in x-direction
    * -> mean of 191.5 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 191.5;
    test.sd = 89.8025;

    testCases.push_back( test );
  }

  {
    /*****************************
    * quarter pixel (black) + whole pixel (white) + half pixel (gray) in x-direction
    * -> mean of 191.5 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.25; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.25; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 191.5;
    test.sd = 89.8025;

    testCases.push_back( test );
  }

  {
    /*****************************
    * half pixel (black) + whole pixel (white) + half pixel (gray) in x-direction
    * -> mean of 127.67 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.0; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.0; pnt3[1] = 4.0;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.0;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 127.67;
    test.sd = 127.5;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (gray)
    * -> mean of 128 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
    figure2->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
    figure2->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 11.5;
    figure2->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 11.5;
    figure2->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
    figure2->SetControlPoint( 3, pnt4, true );
    figure2->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure2;
    test.mean = 128.0;
    test.sd = 0.0;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (gray) + half pixel (white) in y-direction
    * -> mean of 191.5 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
    figure2->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
    figure2->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 12.0;
    figure2->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 12.0;
    figure2->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
    figure2->SetControlPoint( 3, pnt4, true );
    figure2->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure2;
    test.mean = 191.5;
    test.sd = 89.8025;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (gray) + whole pixel (white) + whole pixel (black) in y-direction
    * -> mean of 127.67 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
    figure2->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
    figure2->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 13.5;
    figure2->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 13.5;
    figure2->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
    figure2->SetControlPoint( 3, pnt4, true );
    figure2->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure2;
    test.mean = 127.67;
    test.sd = 127.5;

    testCases.push_back( test );
  }

  return testCases;
}

// loads the test image
static mitk::Image::Pointer GetTestImage()
{
  mitk::StandardFileLocations::Pointer locator = mitk::StandardFileLocations::GetInstance();

  const std::string filename = locator->FindFile("testimage.dcm", "Modules\\MitkExt\\Testing\\Data");
  if (filename.empty())
  {
    MITK_ERROR << "Could not find test file";
    return NULL;
  }
  else
  {
    MITK_INFO << "Found testimage.dcm";
  }

  itk::FilenamesContainer file;
  file.push_back( filename );

  mitk::DicomSeriesReader* reader = new mitk::DicomSeriesReader;

  mitk::DataNode::Pointer node = reader->LoadDicomSeries( file, false, false );
  mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );

  return image;
}

};

int mitkImageStatisticsCalculatorTest(int argc, char* argv[])
{
  // always start with this!
  MITK_TEST_BEGIN("mitkImageStatisticsCalculatorTest")

  //QCoreApplication app(argc, argv);

  mitk::Image::Pointer image = mitkImageStatisticsCalculatorTestClass::GetTestImage();
  MITK_TEST_CONDITION_REQUIRED( image.IsNotNull(), "Loading test image" );

  mitk::Geometry2D::Pointer geom = image->GetSlicedGeometry()->GetGeometry2D(0);

  std::vector<mitkImageStatisticsCalculatorTestClass::testCase> allTestCases = mitkImageStatisticsCalculatorTestClass::InitializeTestCases( geom );
  for ( int i=0; i<allTestCases.size(); i++ )
  {
    mitkImageStatisticsCalculatorTestClass::testCase test = allTestCases[i];

    const mitk::ImageStatisticsCalculator::Statistics stats = mitkImageStatisticsCalculatorTestClass::TestStatistics( image, test.figure );

    MITK_TEST_CONDITION( int(stats.Mean) == int(test.mean),
      "Calculated mean grayvalue '"<< stats.Mean <<"'  is equal to the desired value '"
      << test.mean <<"' for testcase #" << test.id );

    MITK_TEST_CONDITION( int(stats.Sigma) == int(test.sd),
      "Calculated grayvalue sd '"<< stats.Sigma <<"'  is equal to the desired value '"
      << test.sd <<"' for testcase #" << test.id );

    //MITK_TEST_CONDITION( int(stats.Sigma) == int(test.sd),
    //  qPrintable( QString("Calculated grayvalue sd '%1'  is equal to the desired value '%2' for testcase #%3")
    //  .arg(stats.Sigma).arg( test.sd ).arg( test.id ) ) );

  }

  MITK_TEST_END()
}

<commit_msg>fixing failing test, seems like path was falsely formatted for linux<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Language:  C++
Date:      $Date: 2008-02-25 17:27:17 +0100 (Mo, 25 Feb 2008) $
Version:   $Revision: 7837 $

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkStandardFileLocations.h"
#include "mitkDicomSeriesReader.h"
#include "mitkTestingMacros.h"
#include "mitkImageStatisticsCalculator.h"
#include "mitkPlanarPolygon.h"

#include "mitkDicomSeriesReader.h"
#include <itkGDCMSeriesFileNames.h>

//#include <QtCore>

/**
 * \brief Test class for mitkImageStatisticsCalculator
 *
 * This test covers:
 * - instantiation of an ImageStatisticsCalculator class
 * - correctness of statistics when using PlanarFigures for masking
 */
class mitkImageStatisticsCalculatorTestClass
{

public:

  struct testCase
  {
    int id;
    mitk::PlanarFigure::Pointer figure;
    double mean;
    double sd;
  };

// calculate statistics for the given image and planarpolygon
static const mitk::ImageStatisticsCalculator::Statistics TestStatistics( mitk::Image::Pointer image, mitk::PlanarFigure::Pointer polygon )
{
  mitk::ImageStatisticsCalculator::Pointer statisticsCalculator = mitk::ImageStatisticsCalculator::New();
  statisticsCalculator->SetImage( image );
  statisticsCalculator->SetMaskingModeToPlanarFigure();
  statisticsCalculator->SetPlanarFigure( polygon );

  statisticsCalculator->ComputeStatistics();

  return statisticsCalculator->GetStatistics();
}

// returns a vector of defined test-cases
static std::vector<testCase> InitializeTestCases( mitk::Geometry2D::Pointer geom )
{
  std::vector<testCase> testCases;

  {
    /*****************************
    * one whole white pixel
    * -> mean of 255 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 10.5 ; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 10.5; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 255.0;
    test.sd = 0.0;

    testCases.push_back( test );
  }

  {
    /*****************************
    * half pixel in x-direction (white)
    * -> mean of 255 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 10.0 ; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 10.0; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 255.0;
    test.sd = 0.0;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (white) + half pixel (gray) in x-direction
    * -> mean of 191.5 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.5; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.5; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 191.5;
    test.sd = 89.8025;

    testCases.push_back( test );
  }

  {
    /*****************************
    * quarter pixel (black) + whole pixel (white) + half pixel (gray) in x-direction
    * -> mean of 191.5 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.25; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.25; pnt3[1] = 4.5;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.5;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 191.5;
    test.sd = 89.8025;

    testCases.push_back( test );
  }

  {
    /*****************************
    * half pixel (black) + whole pixel (white) + half pixel (gray) in x-direction
    * -> mean of 127.67 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure1 = mitk::PlanarPolygon::New();
    figure1->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.0; pnt1[1] = 3.5;
    figure1->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 9.0; pnt2[1] = 3.5;
    figure1->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 9.0; pnt3[1] = 4.0;
    figure1->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 11.0; pnt4[1] = 4.0;
    figure1->SetControlPoint( 3, pnt4, true );
    figure1->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure1;
    test.mean = 127.67;
    test.sd = 127.5;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (gray)
    * -> mean of 128 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
    figure2->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
    figure2->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 11.5;
    figure2->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 11.5;
    figure2->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
    figure2->SetControlPoint( 3, pnt4, true );
    figure2->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure2;
    test.mean = 128.0;
    test.sd = 0.0;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (gray) + half pixel (white) in y-direction
    * -> mean of 191.5 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
    figure2->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
    figure2->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 12.0;
    figure2->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 12.0;
    figure2->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
    figure2->SetControlPoint( 3, pnt4, true );
    figure2->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure2;
    test.mean = 191.5;
    test.sd = 89.8025;

    testCases.push_back( test );
  }

  {
    /*****************************
    * whole pixel (gray) + whole pixel (white) + whole pixel (black) in y-direction
    * -> mean of 127.67 expected
    ******************************/
    mitk::PlanarPolygon::Pointer figure2 = mitk::PlanarPolygon::New();
    figure2->SetGeometry2D( geom );
    mitk::Point2D pnt1; pnt1[0] = 11.5; pnt1[1] = 10.5;
    figure2->PlaceFigure( pnt1 );

    mitk::Point2D pnt2; pnt2[0] = 11.5; pnt2[1] = 13.5;
    figure2->SetControlPoint( 1, pnt2, true );
    mitk::Point2D pnt3; pnt3[0] = 12.5; pnt3[1] = 13.5;
    figure2->SetControlPoint( 2, pnt3, true );
    mitk::Point2D pnt4; pnt4[0] = 12.5; pnt4[1] = 10.5;
    figure2->SetControlPoint( 3, pnt4, true );
    figure2->GetPolyLine(0);

    testCase test;
    test.id = testCases.size();
    test.figure = figure2;
    test.mean = 127.67;
    test.sd = 127.5;

    testCases.push_back( test );
  }

  return testCases;
}

// loads the test image
static mitk::Image::Pointer GetTestImage()
{
  mitk::StandardFileLocations::Pointer locator = mitk::StandardFileLocations::GetInstance();

  const std::string filename = locator->FindFile("testimage.dcm", "Modules/MitkExt/Testing/Data");
  if (filename.empty())
  {
    MITK_ERROR << "Could not find test file";
    return NULL;
  }
  else
  {
    MITK_INFO << "Found testimage.dcm";
  }

  itk::FilenamesContainer file;
  file.push_back( filename );

  mitk::DicomSeriesReader* reader = new mitk::DicomSeriesReader;

  mitk::DataNode::Pointer node = reader->LoadDicomSeries( file, false, false );
  mitk::Image::Pointer image = dynamic_cast<mitk::Image*>( node->GetData() );

  return image;
}

};

int mitkImageStatisticsCalculatorTest(int argc, char* argv[])
{
  // always start with this!
  MITK_TEST_BEGIN("mitkImageStatisticsCalculatorTest")

  //QCoreApplication app(argc, argv);

  mitk::Image::Pointer image = mitkImageStatisticsCalculatorTestClass::GetTestImage();
  MITK_TEST_CONDITION_REQUIRED( image.IsNotNull(), "Loading test image" );

  mitk::Geometry2D::Pointer geom = image->GetSlicedGeometry()->GetGeometry2D(0);

  std::vector<mitkImageStatisticsCalculatorTestClass::testCase> allTestCases = mitkImageStatisticsCalculatorTestClass::InitializeTestCases( geom );
  for ( int i=0; i<allTestCases.size(); i++ )
  {
    mitkImageStatisticsCalculatorTestClass::testCase test = allTestCases[i];

    const mitk::ImageStatisticsCalculator::Statistics stats = mitkImageStatisticsCalculatorTestClass::TestStatistics( image, test.figure );

    MITK_TEST_CONDITION( int(stats.Mean) == int(test.mean),
      "Calculated mean grayvalue '"<< stats.Mean <<"'  is equal to the desired value '"
      << test.mean <<"' for testcase #" << test.id );

    MITK_TEST_CONDITION( int(stats.Sigma) == int(test.sd),
      "Calculated grayvalue sd '"<< stats.Sigma <<"'  is equal to the desired value '"
      << test.sd <<"' for testcase #" << test.id );

    //MITK_TEST_CONDITION( int(stats.Sigma) == int(test.sd),
    //  qPrintable( QString("Calculated grayvalue sd '%1'  is equal to the desired value '%2' for testcase #%3")
    //  .arg(stats.Sigma).arg( test.sd ).arg( test.id ) ) );

  }

  MITK_TEST_END()
}

<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2010 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <BRepAdaptor_Surface.hxx>
# include <BRepAlgoAPI_Common.hxx>
# include <BRepAlgoAPI_Cut.hxx>
# include <BRepAlgoAPI_Section.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepGProp_Face.hxx>
# include <BRepPrimAPI_MakeHalfSpace.hxx>
# include <gp_Pln.hxx>
# include <Precision.hxx>
# include <ShapeFix_Wire.hxx>
# include <ShapeAnalysis_FreeBounds.hxx>
# include <TopExp.hxx>
# include <TopExp_Explorer.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
# include <TopTools_HSequenceOfShape.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Wire.hxx>
#endif

#include "CrossSection.h"

using namespace Part;

CrossSection::CrossSection(double a, double b, double c, const TopoDS_Shape& s)
  : a(a), b(b), c(c), s(s)
{
}

std::list<TopoDS_Wire> CrossSection::slice(double d) const
{
    std::list<TopoDS_Wire> wires;
    // Fixes: 0001228: Cross section of Torus in Part Workbench fails or give wrong results
    // Fixes: 0001137: Incomplete slices when using Part.slice on a torus
    TopExp_Explorer xp;
    for (xp.Init(s, TopAbs_SOLID); xp.More(); xp.Next()) {
        sliceSolid(d, xp.Current(), wires);
    }
    for (xp.Init(s, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next()) {
        sliceNonSolid(d, xp.Current(), wires);
    }
    for (xp.Init(s, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next()) {
        sliceNonSolid(d, xp.Current(), wires);
    }

    return wires;
}

void CrossSection::sliceNonSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
{
    BRepAlgoAPI_Section cs(shape, gp_Pln(a,b,c,-d));
    if (cs.IsDone()) {
        std::list<TopoDS_Edge> edges;
        TopExp_Explorer xp;
        for (xp.Init(cs.Shape(), TopAbs_EDGE); xp.More(); xp.Next())
            edges.push_back(TopoDS::Edge(xp.Current()));
        connectEdges(edges, wires);
    }
}

void CrossSection::sliceSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
{
#if 0
    gp_Pln slicePlane(a,b,c,-d);
    BRepBuilderAPI_MakeFace mkFace(slicePlane);
    TopoDS_Face face = mkFace.Face();
    BRepAlgoAPI_Common mkInt(shape, face);

    if (mkInt.IsDone()) {
        // sort and repair the wires
        TopTools_IndexedMapOfShape mapOfWires;
        TopExp::MapShapes(mkInt.Shape(), TopAbs_WIRE, mapOfWires);
        connectWires(mapOfWires, wires);
    }
#else
    gp_Pln slicePlane(a,b,c,-d);
    BRepBuilderAPI_MakeFace mkFace(slicePlane);
    TopoDS_Face face = mkFace.Face();
    BRepPrimAPI_MakeHalfSpace mkSolid(face, gp_Pnt(0,0,d-1));
    TopoDS_Solid solid = mkSolid.Solid();
    BRepAlgoAPI_Cut mkCut(shape, solid);

    if (mkCut.IsDone()) {
        TopTools_IndexedMapOfShape mapOfFaces;
        TopExp::MapShapes(mkCut.Shape(), TopAbs_FACE, mapOfFaces);
        for (int i=1; i<=mapOfFaces.Extent(); i++) {
            const TopoDS_Face& face = TopoDS::Face(mapOfFaces.FindKey(i));
            BRepAdaptor_Surface adapt(face);
            if (adapt.GetType() == GeomAbs_Plane) {
                gp_Pln plane = adapt.Plane();
                if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion()) &&
                    plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
                    // sort and repair the wires
                    TopTools_IndexedMapOfShape mapOfWires;
                    TopExp::MapShapes(face, TopAbs_WIRE, mapOfWires);
                    connectWires(mapOfWires, wires);
                }
            }
        }
    }
#endif
}

void CrossSection::connectEdges (const std::list<TopoDS_Edge>& edges, std::list<TopoDS_Wire>& wires) const
{
    // FIXME: Use ShapeAnalysis_FreeBounds::ConnectEdgesToWires() as an alternative
    std::list<TopoDS_Edge> edge_list = edges;
    while (edge_list.size() > 0) {
        BRepBuilderAPI_MakeWire mkWire;
        // add and erase first edge
        mkWire.Add(edge_list.front());
        edge_list.erase(edge_list.begin());

        TopoDS_Wire new_wire = mkWire.Wire();  // current new wire

        // try to connect each edge to the wire, the wire is complete if no more egdes are connectible
        bool found = false;
        do {
            found = false;
            for (std::list<TopoDS_Edge>::iterator pE = edge_list.begin(); pE != edge_list.end();++pE) {
                mkWire.Add(*pE);
                if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire) {
                    // edge added ==> remove it from list
                    found = true;
                    edge_list.erase(pE);
                    new_wire = mkWire.Wire();
                    break;
                }
            }
        }
        while (found);

        // Fix any topological issues of the wire
        ShapeFix_Wire aFix;
        aFix.SetPrecision(Precision::Confusion());
        aFix.Load(new_wire);
        aFix.FixReorder();
        aFix.FixConnected();
        aFix.FixClosed();
        wires.push_back(aFix.Wire());
    }
}

void CrossSection::connectWires (const TopTools_IndexedMapOfShape& wireMap, std::list<TopoDS_Wire>& wires) const
{
    Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
    for (int i=1; i<=wireMap.Extent(); i++) {
        const TopoDS_Shape& wire = wireMap.FindKey(i);
        hWires->Append(wire);
    }

    Handle(TopTools_HSequenceOfShape) hSorted = new TopTools_HSequenceOfShape();
    ShapeAnalysis_FreeBounds::ConnectWiresToWires(hWires, Precision::Confusion(), false, hSorted);

    for (int i=1; i<=hSorted->Length(); i++) {
        const TopoDS_Wire& new_wire = TopoDS::Wire(hSorted->Value(i));
        // Fix any topological issues of the wire
        ShapeFix_Wire aFix;
        aFix.SetPrecision(Precision::Confusion());
        aFix.Load(new_wire);
        aFix.FixReorder();
        aFix.FixConnected();
        aFix.FixClosed();
        wires.push_back(aFix.Wire());
    }
}
<commit_msg>0001228: Cross section of Torus in Part Workbench fails or give wrong results<commit_after>/***************************************************************************
 *   Copyright (c) 2010 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <BRepAdaptor_Surface.hxx>
# include <BRepAlgoAPI_Common.hxx>
# include <BRepAlgoAPI_Cut.hxx>
# include <BRepAlgoAPI_Section.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepBuilderAPI_MakeWire.hxx>
# include <BRepGProp_Face.hxx>
# include <BRepPrimAPI_MakeHalfSpace.hxx>
# include <gp_Pln.hxx>
# include <Precision.hxx>
# include <ShapeFix_Wire.hxx>
# include <ShapeAnalysis_FreeBounds.hxx>
# include <TopExp.hxx>
# include <TopExp_Explorer.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
# include <TopTools_HSequenceOfShape.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Edge.hxx>
# include <TopoDS_Wire.hxx>
#endif

#include "CrossSection.h"

using namespace Part;

CrossSection::CrossSection(double a, double b, double c, const TopoDS_Shape& s)
  : a(a), b(b), c(c), s(s)
{
}

std::list<TopoDS_Wire> CrossSection::slice(double d) const
{
    std::list<TopoDS_Wire> wires;
    // Fixes: 0001228: Cross section of Torus in Part Workbench fails or give wrong results
    // Fixes: 0001137: Incomplete slices when using Part.slice on a torus
    TopExp_Explorer xp;
    for (xp.Init(s, TopAbs_SOLID); xp.More(); xp.Next()) {
        sliceSolid(d, xp.Current(), wires);
    }
    for (xp.Init(s, TopAbs_SHELL, TopAbs_SOLID); xp.More(); xp.Next()) {
        sliceNonSolid(d, xp.Current(), wires);
    }
    for (xp.Init(s, TopAbs_FACE, TopAbs_SHELL); xp.More(); xp.Next()) {
        sliceNonSolid(d, xp.Current(), wires);
    }

    return wires;
}

void CrossSection::sliceNonSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
{
    BRepAlgoAPI_Section cs(shape, gp_Pln(a,b,c,-d));
    if (cs.IsDone()) {
        std::list<TopoDS_Edge> edges;
        TopExp_Explorer xp;
        for (xp.Init(cs.Shape(), TopAbs_EDGE); xp.More(); xp.Next())
            edges.push_back(TopoDS::Edge(xp.Current()));
        connectEdges(edges, wires);
    }
}

void CrossSection::sliceSolid(double d, const TopoDS_Shape& shape, std::list<TopoDS_Wire>& wires) const
{
#if 0
    gp_Pln slicePlane(a,b,c,-d);
    BRepBuilderAPI_MakeFace mkFace(slicePlane);
    TopoDS_Face face = mkFace.Face();
    BRepAlgoAPI_Common mkInt(shape, face);

    if (mkInt.IsDone()) {
        // sort and repair the wires
        TopTools_IndexedMapOfShape mapOfWires;
        TopExp::MapShapes(mkInt.Shape(), TopAbs_WIRE, mapOfWires);
        connectWires(mapOfWires, wires);
    }
#else
    gp_Pln slicePlane(a,b,c,-d);
    BRepBuilderAPI_MakeFace mkFace(slicePlane);
    TopoDS_Face face = mkFace.Face();

    // Make sure to choose a point that does not lie on the plane (fixes #0001228)
    gp_Vec tempVector(a,b,c);
    tempVector.Normalize();//just in case.
    tempVector *= (d+1.0);
    gp_Pnt refPoint(0.0d, 0.0d, 0.0d);
    refPoint.Translate(tempVector);

    BRepPrimAPI_MakeHalfSpace mkSolid(face, refPoint);
    TopoDS_Solid solid = mkSolid.Solid();
    BRepAlgoAPI_Cut mkCut(shape, solid);

    if (mkCut.IsDone()) {
        TopTools_IndexedMapOfShape mapOfFaces;
        TopExp::MapShapes(mkCut.Shape(), TopAbs_FACE, mapOfFaces);
        for (int i=1; i<=mapOfFaces.Extent(); i++) {
            const TopoDS_Face& face = TopoDS::Face(mapOfFaces.FindKey(i));
            BRepAdaptor_Surface adapt(face);
            if (adapt.GetType() == GeomAbs_Plane) {
                gp_Pln plane = adapt.Plane();
                if (plane.Axis().IsParallel(slicePlane.Axis(), Precision::Confusion()) &&
                    plane.Distance(slicePlane.Location()) < Precision::Confusion()) {
                    // sort and repair the wires
                    TopTools_IndexedMapOfShape mapOfWires;
                    TopExp::MapShapes(face, TopAbs_WIRE, mapOfWires);
                    connectWires(mapOfWires, wires);
                }
            }
        }
    }
#endif
}

void CrossSection::connectEdges (const std::list<TopoDS_Edge>& edges, std::list<TopoDS_Wire>& wires) const
{
    // FIXME: Use ShapeAnalysis_FreeBounds::ConnectEdgesToWires() as an alternative
    std::list<TopoDS_Edge> edge_list = edges;
    while (edge_list.size() > 0) {
        BRepBuilderAPI_MakeWire mkWire;
        // add and erase first edge
        mkWire.Add(edge_list.front());
        edge_list.erase(edge_list.begin());

        TopoDS_Wire new_wire = mkWire.Wire();  // current new wire

        // try to connect each edge to the wire, the wire is complete if no more egdes are connectible
        bool found = false;
        do {
            found = false;
            for (std::list<TopoDS_Edge>::iterator pE = edge_list.begin(); pE != edge_list.end();++pE) {
                mkWire.Add(*pE);
                if (mkWire.Error() != BRepBuilderAPI_DisconnectedWire) {
                    // edge added ==> remove it from list
                    found = true;
                    edge_list.erase(pE);
                    new_wire = mkWire.Wire();
                    break;
                }
            }
        }
        while (found);

        // Fix any topological issues of the wire
        ShapeFix_Wire aFix;
        aFix.SetPrecision(Precision::Confusion());
        aFix.Load(new_wire);
        aFix.FixReorder();
        aFix.FixConnected();
        aFix.FixClosed();
        wires.push_back(aFix.Wire());
    }
}

void CrossSection::connectWires (const TopTools_IndexedMapOfShape& wireMap, std::list<TopoDS_Wire>& wires) const
{
    Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();
    for (int i=1; i<=wireMap.Extent(); i++) {
        const TopoDS_Shape& wire = wireMap.FindKey(i);
        hWires->Append(wire);
    }

    Handle(TopTools_HSequenceOfShape) hSorted = new TopTools_HSequenceOfShape();
    ShapeAnalysis_FreeBounds::ConnectWiresToWires(hWires, Precision::Confusion(), false, hSorted);

    for (int i=1; i<=hSorted->Length(); i++) {
        const TopoDS_Wire& new_wire = TopoDS::Wire(hSorted->Value(i));
        // Fix any topological issues of the wire
        ShapeFix_Wire aFix;
        aFix.SetPrecision(Precision::Confusion());
        aFix.Load(new_wire);
        aFix.FixReorder();
        aFix.FixConnected();
        aFix.FixClosed();
        wires.push_back(aFix.Wire());
    }
}
<|endoftext|>


<commit_before>
#include "odrive_main.h"

Encoder::Encoder(const EncoderHardwareConfig_t& hw_config,
                Config_t& config) :
        hw_config_(hw_config),
        config_(config)
{
    // Calculate encoder pll gains
    // This calculation is currently identical to the PLL in SensorlessEstimator
    float pll_bandwidth = 1000.0f;  // [rad/s]
    pll_kp_ = 2.0f * pll_bandwidth;

    // Critically damped
    pll_ki_ = 0.25f * (pll_kp_ * pll_kp_);

    if (config.pre_calibrated && (config.mode == Encoder::MODE_HALL)) {
        offset_ = config.offset;
        is_ready_ = true;
    }
}

static void enc_index_cb_wrapper(void* ctx) {
    reinterpret_cast<Encoder*>(ctx)->enc_index_cb();
}

void Encoder::setup() {
    HAL_TIM_Encoder_Start(hw_config_.timer, TIM_CHANNEL_ALL);
    GPIO_subscribe(hw_config_.index_port, hw_config_.index_pin, GPIO_NOPULL,
            enc_index_cb_wrapper, this);
}

void Encoder::set_error(Encoder::Error_t error) {
    error_ |= error;
    axis_->error_ |= Axis::ERROR_MOTOR_FAILED;
}

bool Encoder::do_checks(){
    return error_ == ERROR_NONE;
}

//--------------------
// Hardware Dependent
//--------------------

// Triggered when an encoder passes over the "Index" pin
// TODO: only arm index edge interrupt when we know encoder has powered up
// TODO: disable interrupt once we found the index
void Encoder::enc_index_cb() {
    if (config_.use_index && !index_found_) {
        set_circular_count(0);
        if (config_.pre_calibrated) {
            offset_ = config_.offset;
            is_ready_ = true;
        }
        index_found_ = true;
    }
}

// Function that sets the current encoder count to a desired 32-bit value.
void Encoder::set_linear_count(int32_t count) {
    // Disable interrupts to make a critical section to avoid race condition
    uint32_t prim = __get_PRIMASK();
    __disable_irq();

    // Update states
    shadow_count_ = count;
    pos_estimate_ = (float)count;
    //Write hardware last
    hw_config_.timer->Instance->CNT = count;

    __set_PRIMASK(prim);
}

// Function that sets the CPR circular tracking encoder count to a desired 32-bit value.
// Note that this will get mod'ed down to [0, cpr)
void Encoder::set_circular_count(int32_t count) {
    // Disable interrupts to make a critical section to avoid race condition
    uint32_t prim = __get_PRIMASK();
    __disable_irq();

    // Offset and state must be shifted by the same amount
    offset_ += count - count_in_cpr_;
    offset_ = mod(offset_, config_.cpr);
    // Update states
    count_in_cpr_ = mod(count, config_.cpr);
    pos_cpr_ = (float)count_in_cpr_;

    __set_PRIMASK(prim);
}

// @brief Slowly turns the motor in one direction until the
// encoder index is found.
// TODO: Do the scan with current, not voltage!
bool Encoder::run_index_search() {
    float voltage_magnitude;
    if (axis_->motor_.config_.motor_type == MOTOR_TYPE_HIGH_CURRENT)
        voltage_magnitude = axis_->motor_.config_.calibration_current * axis_->motor_.config_.phase_resistance;
    else if (axis_->motor_.config_.motor_type == MOTOR_TYPE_GIMBAL)
        voltage_magnitude = axis_->motor_.config_.calibration_current;
    else
        return false;

    float omega = (float)(axis_->motor_.config_.direction) * config_.idx_search_speed;

    index_found_ = false;
    float phase = 0.0f;
    axis_->run_control_loop([&](){
        phase = wrap_pm_pi(phase + omega * current_meas_period);

        float v_alpha = voltage_magnitude * arm_cos_f32(phase);
        float v_beta = voltage_magnitude * arm_sin_f32(phase);
        if (!axis_->motor_.enqueue_voltage_timings(v_alpha, v_beta))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_IDX_SEARCH);

        // continue until the index is found
        return !index_found_;
    });
    return true;
}

// @brief Turns the motor in one direction for a bit and then in the other
// direction in order to find the offset between the electrical phase 0
// and the encoder state 0.
// TODO: Do the scan with current, not voltage!
bool Encoder::run_offset_calibration() {
    static const float start_lock_duration = 1.0f;
    static const float scan_omega = 4.0f * M_PI;
    static const float scan_distance = 16.0f * M_PI;
    static const int num_steps = scan_distance / scan_omega * current_meas_hz;

    // Temporarily disable index search so it doesn't mess
    // with the offset calibration
    bool old_use_index = config_.use_index;
    config_.use_index = false;

    float voltage_magnitude;
    if (axis_->motor_.config_.motor_type == MOTOR_TYPE_HIGH_CURRENT)
        voltage_magnitude = axis_->motor_.config_.calibration_current * axis_->motor_.config_.phase_resistance;
    else if (axis_->motor_.config_.motor_type == MOTOR_TYPE_GIMBAL)
        voltage_magnitude = axis_->motor_.config_.calibration_current;
    else
        return false;

    // go to motor zero phase for start_lock_duration to get ready to scan
    int i = 0;
    axis_->run_control_loop([&](){
        if (!axis_->motor_.enqueue_voltage_timings(voltage_magnitude, 0.0f))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_ENC_CALIB);
        return ++i < start_lock_duration * current_meas_hz;
    });
    if (axis_->error_ != Axis::ERROR_NONE)
        return false;

    int32_t init_enc_val = shadow_count_;
    int64_t encvaluesum = 0;

    // scan forward
    i = 0;
    axis_->run_control_loop([&](){
        float phase = wrap_pm_pi(scan_distance * (float)i / (float)num_steps - scan_distance / 2.0f);
        float v_alpha = voltage_magnitude * arm_cos_f32(phase);
        float v_beta = voltage_magnitude * arm_sin_f32(phase);
        if (!axis_->motor_.enqueue_voltage_timings(v_alpha, v_beta))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_ENC_CALIB);

        encvaluesum += shadow_count_;

        return ++i < num_steps;
    });
    if (axis_->error_ != Axis::ERROR_NONE)
        return false;

    //TODO avoid recomputing elec_rad_per_enc every time
    float elec_rad_per_enc = axis_->motor_.config_.pole_pairs * 2 * M_PI * (1.0f / (float)(config_.cpr));
    float expected_encoder_delta = scan_distance / elec_rad_per_enc;
    float actual_encoder_delta_abs = fabsf(shadow_count_-init_enc_val);
    if(fabsf(actual_encoder_delta_abs - expected_encoder_delta)/expected_encoder_delta > config_.calib_range)
    {
        set_error(ERROR_CPR_OUT_OF_RANGE);
        return false;
    }
    // check direction
    if (shadow_count_ > init_enc_val + 8) {
        // motor same dir as encoder
        axis_->motor_.config_.direction = 1;
    } else if (shadow_count_ < init_enc_val - 8) {
        // motor opposite dir as encoder
        axis_->motor_.config_.direction = -1;
    } else {
        // Encoder response error
        set_error(ERROR_RESPONSE);
        return false;
    }

    // scan backwards
    i = 0;
    axis_->run_control_loop([&](){
        float phase = wrap_pm_pi(-scan_distance * (float)i / (float)num_steps + scan_distance / 2.0f);
        float v_alpha = voltage_magnitude * arm_cos_f32(phase);
        float v_beta = voltage_magnitude * arm_sin_f32(phase);
        if (!axis_->motor_.enqueue_voltage_timings(v_alpha, v_beta))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_ENC_CALIB);

        encvaluesum += shadow_count_;

        return ++i < num_steps;
    });
    if (axis_->error_ != Axis::ERROR_NONE)
        return false;

    offset_ = encvaluesum / (num_steps * 2);
    config_.offset = offset_;
    int32_t residual = encvaluesum - ((int64_t)offset_ * (int64_t)(num_steps * 2));
    config_.offset_float = (float)residual / (float)(num_steps * 2);
    is_ready_ = true;
    config_.use_index = old_use_index;
    return true;
}

static bool decode_hall(uint8_t hall_state, int32_t* hall_cnt) {
    switch (hall_state) {
        case 0b001: *hall_cnt = 0; return true;
        case 0b011: *hall_cnt = 1; return true;
        case 0b010: *hall_cnt = 2; return true;
        case 0b110: *hall_cnt = 3; return true;
        case 0b100: *hall_cnt = 4; return true;
        case 0b101: *hall_cnt = 5; return true;
        default: return false;
    }
}

bool Encoder::update() {
    // Check that we don't get problems with discrete time approximation
    if (!(current_meas_period * pll_kp_ < 1.0f)) {
        set_error(ERROR_UNSTABLE_GAIN);
        return false;
    }

    // update internal encoder state.
    int32_t delta_enc = 0;
    switch (config_.mode) {
        case MODE_INCREMENTAL: {
            //TODO: use count_in_cpr_ instead as shadow_count_ can overflow
            //or use 64 bit
            int16_t delta_enc_16 = (int16_t)hw_config_.timer->Instance->CNT - (int16_t)shadow_count_;
            delta_enc = (int32_t)delta_enc_16; //sign extend
        } break;

        case MODE_HALL: {
            int32_t hall_cnt;
            if (decode_hall(hall_state_, &hall_cnt)) {
                delta_enc = hall_cnt - count_in_cpr_;
                delta_enc = mod(delta_enc, 6);
                if (delta_enc > 3)
                    delta_enc -= 6;
            } else {
                set_error(ERROR_ILLEGAL_HALL_STATE);
                return false;
            }
        } break;

        default: {
           set_error(ERROR_UNSUPPORTED_ENCODER_MODE);
           return false;
        } break;
    }

    shadow_count_ += delta_enc;
    count_in_cpr_ += delta_enc;
    count_in_cpr_ = mod(count_in_cpr_, config_.cpr);

    //// run encoder count interpolation
    int32_t corrected_enc = count_in_cpr_ - offset_;
    // reset interpolation if encoder edge comes
    if (delta_enc > 0) {
        interpolation_ = 0.0f;
    } else if (delta_enc < 0) {
        interpolation_ = 1.0f;
    } else {
        // Interpolate (predict) between encoder counts using pll_vel,
        interpolation_ += current_meas_period * pll_vel_;
        // don't allow interpolation indicated position outside of [enc, enc+1)
        if (interpolation_ > 1.0f) interpolation_ = 1.0f;
        if (interpolation_ < 0.0f) interpolation_ = 0.0f;
    }
    float interpolated_enc = corrected_enc + interpolation_;

    //// compute electrical phase
    //TODO avoid recomputing elec_rad_per_enc every time
    float elec_rad_per_enc = axis_->motor_.config_.pole_pairs * 2 * M_PI * (1.0f / (float)(config_.cpr));
    float ph = elec_rad_per_enc * (interpolated_enc - config_.offset_float);
    // ph = fmodf(ph, 2*M_PI);
    phase_ = wrap_pm_pi(ph);

    //// run pll (for now pll is in units of encoder counts)
    // Predict current pos
    pos_estimate_ += current_meas_period * pll_vel_;
    pos_cpr_      += current_meas_period * pll_vel_;
    // discrete phase detector
    float delta_pos     = (float)(shadow_count_ - (int32_t)floorf(pos_estimate_));
    float delta_pos_cpr = (float)(count_in_cpr_ - (int32_t)floorf(pos_cpr_));
    delta_pos_cpr = wrap_pm(delta_pos_cpr, 0.5f * (float)(config_.cpr));
    // pll feedback
    pos_estimate_ += current_meas_period * pll_kp_ * delta_pos;
    pos_cpr_      += current_meas_period * pll_kp_ * delta_pos_cpr;
    pos_cpr_ = fmodf_pos(pos_cpr_, (float)(config_.cpr));
    pll_vel_      += current_meas_period * pll_ki_ * delta_pos_cpr;
    if (fabsf(pll_vel_) < 0.5f * current_meas_period * pll_ki_)
        pll_vel_ = 0.0f; //align delta-sigma on zero to prevent jitter

    return true;
}
<commit_msg>center-align hall interpolation float offset<commit_after>
#include "odrive_main.h"

Encoder::Encoder(const EncoderHardwareConfig_t& hw_config,
                Config_t& config) :
        hw_config_(hw_config),
        config_(config)
{
    // Calculate encoder pll gains
    // This calculation is currently identical to the PLL in SensorlessEstimator
    float pll_bandwidth = 1000.0f;  // [rad/s]
    pll_kp_ = 2.0f * pll_bandwidth;

    // Critically damped
    pll_ki_ = 0.25f * (pll_kp_ * pll_kp_);

    if (config.pre_calibrated && (config.mode == Encoder::MODE_HALL)) {
        offset_ = config.offset;
        is_ready_ = true;
    }
}

static void enc_index_cb_wrapper(void* ctx) {
    reinterpret_cast<Encoder*>(ctx)->enc_index_cb();
}

void Encoder::setup() {
    HAL_TIM_Encoder_Start(hw_config_.timer, TIM_CHANNEL_ALL);
    GPIO_subscribe(hw_config_.index_port, hw_config_.index_pin, GPIO_NOPULL,
            enc_index_cb_wrapper, this);
}

void Encoder::set_error(Encoder::Error_t error) {
    error_ |= error;
    axis_->error_ |= Axis::ERROR_MOTOR_FAILED;
}

bool Encoder::do_checks(){
    return error_ == ERROR_NONE;
}

//--------------------
// Hardware Dependent
//--------------------

// Triggered when an encoder passes over the "Index" pin
// TODO: only arm index edge interrupt when we know encoder has powered up
// TODO: disable interrupt once we found the index
void Encoder::enc_index_cb() {
    if (config_.use_index && !index_found_) {
        set_circular_count(0);
        if (config_.pre_calibrated) {
            offset_ = config_.offset;
            is_ready_ = true;
        }
        index_found_ = true;
    }
}

// Function that sets the current encoder count to a desired 32-bit value.
void Encoder::set_linear_count(int32_t count) {
    // Disable interrupts to make a critical section to avoid race condition
    uint32_t prim = __get_PRIMASK();
    __disable_irq();

    // Update states
    shadow_count_ = count;
    pos_estimate_ = (float)count;
    //Write hardware last
    hw_config_.timer->Instance->CNT = count;

    __set_PRIMASK(prim);
}

// Function that sets the CPR circular tracking encoder count to a desired 32-bit value.
// Note that this will get mod'ed down to [0, cpr)
void Encoder::set_circular_count(int32_t count) {
    // Disable interrupts to make a critical section to avoid race condition
    uint32_t prim = __get_PRIMASK();
    __disable_irq();

    // Offset and state must be shifted by the same amount
    offset_ += count - count_in_cpr_;
    offset_ = mod(offset_, config_.cpr);
    // Update states
    count_in_cpr_ = mod(count, config_.cpr);
    pos_cpr_ = (float)count_in_cpr_;

    __set_PRIMASK(prim);
}

// @brief Slowly turns the motor in one direction until the
// encoder index is found.
// TODO: Do the scan with current, not voltage!
bool Encoder::run_index_search() {
    float voltage_magnitude;
    if (axis_->motor_.config_.motor_type == MOTOR_TYPE_HIGH_CURRENT)
        voltage_magnitude = axis_->motor_.config_.calibration_current * axis_->motor_.config_.phase_resistance;
    else if (axis_->motor_.config_.motor_type == MOTOR_TYPE_GIMBAL)
        voltage_magnitude = axis_->motor_.config_.calibration_current;
    else
        return false;

    float omega = (float)(axis_->motor_.config_.direction) * config_.idx_search_speed;

    index_found_ = false;
    float phase = 0.0f;
    axis_->run_control_loop([&](){
        phase = wrap_pm_pi(phase + omega * current_meas_period);

        float v_alpha = voltage_magnitude * arm_cos_f32(phase);
        float v_beta = voltage_magnitude * arm_sin_f32(phase);
        if (!axis_->motor_.enqueue_voltage_timings(v_alpha, v_beta))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_IDX_SEARCH);

        // continue until the index is found
        return !index_found_;
    });
    return true;
}

// @brief Turns the motor in one direction for a bit and then in the other
// direction in order to find the offset between the electrical phase 0
// and the encoder state 0.
// TODO: Do the scan with current, not voltage!
bool Encoder::run_offset_calibration() {
    static const float start_lock_duration = 1.0f;
    static const float scan_omega = 4.0f * M_PI;
    static const float scan_distance = 16.0f * M_PI;
    static const int num_steps = scan_distance / scan_omega * current_meas_hz;

    // Temporarily disable index search so it doesn't mess
    // with the offset calibration
    bool old_use_index = config_.use_index;
    config_.use_index = false;

    float voltage_magnitude;
    if (axis_->motor_.config_.motor_type == MOTOR_TYPE_HIGH_CURRENT)
        voltage_magnitude = axis_->motor_.config_.calibration_current * axis_->motor_.config_.phase_resistance;
    else if (axis_->motor_.config_.motor_type == MOTOR_TYPE_GIMBAL)
        voltage_magnitude = axis_->motor_.config_.calibration_current;
    else
        return false;

    // go to motor zero phase for start_lock_duration to get ready to scan
    int i = 0;
    axis_->run_control_loop([&](){
        if (!axis_->motor_.enqueue_voltage_timings(voltage_magnitude, 0.0f))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_ENC_CALIB);
        return ++i < start_lock_duration * current_meas_hz;
    });
    if (axis_->error_ != Axis::ERROR_NONE)
        return false;

    int32_t init_enc_val = shadow_count_;
    int64_t encvaluesum = 0;

    // scan forward
    i = 0;
    axis_->run_control_loop([&](){
        float phase = wrap_pm_pi(scan_distance * (float)i / (float)num_steps - scan_distance / 2.0f);
        float v_alpha = voltage_magnitude * arm_cos_f32(phase);
        float v_beta = voltage_magnitude * arm_sin_f32(phase);
        if (!axis_->motor_.enqueue_voltage_timings(v_alpha, v_beta))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_ENC_CALIB);

        encvaluesum += shadow_count_;

        return ++i < num_steps;
    });
    if (axis_->error_ != Axis::ERROR_NONE)
        return false;

    //TODO avoid recomputing elec_rad_per_enc every time
    float elec_rad_per_enc = axis_->motor_.config_.pole_pairs * 2 * M_PI * (1.0f / (float)(config_.cpr));
    float expected_encoder_delta = scan_distance / elec_rad_per_enc;
    float actual_encoder_delta_abs = fabsf(shadow_count_-init_enc_val);
    if(fabsf(actual_encoder_delta_abs - expected_encoder_delta)/expected_encoder_delta > config_.calib_range)
    {
        set_error(ERROR_CPR_OUT_OF_RANGE);
        return false;
    }
    // check direction
    if (shadow_count_ > init_enc_val + 8) {
        // motor same dir as encoder
        axis_->motor_.config_.direction = 1;
    } else if (shadow_count_ < init_enc_val - 8) {
        // motor opposite dir as encoder
        axis_->motor_.config_.direction = -1;
    } else {
        // Encoder response error
        set_error(ERROR_RESPONSE);
        return false;
    }

    // scan backwards
    i = 0;
    axis_->run_control_loop([&](){
        float phase = wrap_pm_pi(-scan_distance * (float)i / (float)num_steps + scan_distance / 2.0f);
        float v_alpha = voltage_magnitude * arm_cos_f32(phase);
        float v_beta = voltage_magnitude * arm_sin_f32(phase);
        if (!axis_->motor_.enqueue_voltage_timings(v_alpha, v_beta))
            return false; // error set inside enqueue_voltage_timings
        axis_->motor_.log_timing(Motor::TIMING_LOG_ENC_CALIB);

        encvaluesum += shadow_count_;

        return ++i < num_steps;
    });
    if (axis_->error_ != Axis::ERROR_NONE)
        return false;

    offset_ = encvaluesum / (num_steps * 2);
    config_.offset = offset_;
    int32_t residual = encvaluesum - ((int64_t)offset_ * (int64_t)(num_steps * 2));
    config_.offset_float = (float)residual / (float)(num_steps * 2) + 0.5f; // add 0.5 to center-align state to phase
    is_ready_ = true;
    config_.use_index = old_use_index;
    return true;
}

static bool decode_hall(uint8_t hall_state, int32_t* hall_cnt) {
    switch (hall_state) {
        case 0b001: *hall_cnt = 0; return true;
        case 0b011: *hall_cnt = 1; return true;
        case 0b010: *hall_cnt = 2; return true;
        case 0b110: *hall_cnt = 3; return true;
        case 0b100: *hall_cnt = 4; return true;
        case 0b101: *hall_cnt = 5; return true;
        default: return false;
    }
}

bool Encoder::update() {
    // Check that we don't get problems with discrete time approximation
    if (!(current_meas_period * pll_kp_ < 1.0f)) {
        set_error(ERROR_UNSTABLE_GAIN);
        return false;
    }

    // update internal encoder state.
    int32_t delta_enc = 0;
    switch (config_.mode) {
        case MODE_INCREMENTAL: {
            //TODO: use count_in_cpr_ instead as shadow_count_ can overflow
            //or use 64 bit
            int16_t delta_enc_16 = (int16_t)hw_config_.timer->Instance->CNT - (int16_t)shadow_count_;
            delta_enc = (int32_t)delta_enc_16; //sign extend
        } break;

        case MODE_HALL: {
            int32_t hall_cnt;
            if (decode_hall(hall_state_, &hall_cnt)) {
                delta_enc = hall_cnt - count_in_cpr_;
                delta_enc = mod(delta_enc, 6);
                if (delta_enc > 3)
                    delta_enc -= 6;
            } else {
                set_error(ERROR_ILLEGAL_HALL_STATE);
                return false;
            }
        } break;

        default: {
           set_error(ERROR_UNSUPPORTED_ENCODER_MODE);
           return false;
        } break;
    }

    shadow_count_ += delta_enc;
    count_in_cpr_ += delta_enc;
    count_in_cpr_ = mod(count_in_cpr_, config_.cpr);

    //// run pll (for now pll is in units of encoder counts)
    // Predict current pos
    pos_estimate_ += current_meas_period * pll_vel_;
    pos_cpr_      += current_meas_period * pll_vel_;
    // discrete phase detector
    float delta_pos     = (float)(shadow_count_ - (int32_t)floorf(pos_estimate_));
    float delta_pos_cpr = (float)(count_in_cpr_ - (int32_t)floorf(pos_cpr_));
    delta_pos_cpr = wrap_pm(delta_pos_cpr, 0.5f * (float)(config_.cpr));
    // pll feedback
    pos_estimate_ += current_meas_period * pll_kp_ * delta_pos;
    pos_cpr_      += current_meas_period * pll_kp_ * delta_pos_cpr;
    pos_cpr_ = fmodf_pos(pos_cpr_, (float)(config_.cpr));
    pll_vel_      += current_meas_period * pll_ki_ * delta_pos_cpr;
    bool snap_to_zero_vel = false;
    if (fabsf(pll_vel_) < 0.5f * current_meas_period * pll_ki_) {
        pll_vel_ = 0.0f; //align delta-sigma on zero to prevent jitter
        snap_to_zero_vel = true;
    }

    //// run encoder count interpolation
    int32_t corrected_enc = count_in_cpr_ - offset_;
    // if we are stopped, make sure we don't randomly drift
    if (snap_to_zero_vel) {
        interpolation_ = 0.5f;
    // reset interpolation if encoder edge comes
    } else if (delta_enc > 0) {
        interpolation_ = 0.0f;
    } else if (delta_enc < 0) {
        interpolation_ = 1.0f;
    } else {
        // Interpolate (predict) between encoder counts using pll_vel,
        interpolation_ += current_meas_period * pll_vel_;
        // don't allow interpolation indicated position outside of [enc, enc+1)
        if (interpolation_ > 1.0f) interpolation_ = 1.0f;
        if (interpolation_ < 0.0f) interpolation_ = 0.0f;
    }
    float interpolated_enc = corrected_enc + interpolation_;

    //// compute electrical phase
    //TODO avoid recomputing elec_rad_per_enc every time
    float elec_rad_per_enc = axis_->motor_.config_.pole_pairs * 2 * M_PI * (1.0f / (float)(config_.cpr));
    float ph = elec_rad_per_enc * (interpolated_enc - config_.offset_float);
    // ph = fmodf(ph, 2*M_PI);
    phase_ = wrap_pm_pi(ph);

    return true;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// This file is part of Swift2D.                                              //
//                                                                            //
// Copyright: (c) 2011-2014 Simon Schneegans & Felix Lauer                    //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

// includes  -------------------------------------------------------------------
#include <swift2d/network/NetworkObjectBase.hpp>

#include <swift2d/utils/Logger.hpp>

#include <raknet/RakPeerInterface.h>
#include <raknet/GetTime.h>

namespace swift {

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::WriteAllocationID(RakNet::Connection_RM3 *con, RakNet::BitStream* stream) const {
  stream->Write(get_type());
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3ConstructionState NetworkObjectBase::QueryConstruction(RakNet::Connection_RM3 *con, RakNet::ReplicaManager3 *replicaManager3) {
  return QueryConstruction_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

bool NetworkObjectBase::QueryRemoteConstruction(RakNet::Connection_RM3 *con) {
  return QueryRemoteConstruction_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::SerializeConstruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  vd_serializer_.AddRemoteSystemVariableHistory(con->GetRakNetGUID());

  for (auto& member: distributed_members_) {
    member.serialize(stream);
  }
}

////////////////////////////////////////////////////////////////////////////////

bool NetworkObjectBase::DeserializeConstruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  for (auto& member: distributed_members_) {
    member.deserialize(stream);
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::SerializeDestruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  vd_serializer_.RemoveRemoteSystemVariableHistory(con->GetRakNetGUID());

  for (auto& member: distributed_members_) {
    member.serialize(stream);
  }
}

////////////////////////////////////////////////////////////////////////////////

bool NetworkObjectBase::DeserializeDestruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  for (auto& member: distributed_members_) {
    member.deserialize(stream);
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3ActionOnPopConnection NetworkObjectBase::QueryActionOnPopConnection(RakNet::Connection_RM3 *con) const {
  return QueryActionOnPopConnection_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::DeallocReplica(RakNet::Connection_RM3 *con) {
  on_remote_delete();
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3QuerySerializationResult NetworkObjectBase::QuerySerialization(RakNet::Connection_RM3 *con) {
  return QuerySerialization_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3SerializationResult NetworkObjectBase::Serialize(RakNet::SerializeParameters *serializeParameters) {

  RakNet::VariableDeltaSerializer::SerializationContext ctx;

  serializeParameters->pro[0].reliability=RELIABLE_ORDERED;
  vd_serializer_.BeginIdenticalSerialize(
    &ctx,
    serializeParameters->whenLastSerialized==0,
    &serializeParameters->outputBitstream[0]
  );
  for (auto& member: distributed_members_) {
    member.serialize(&ctx, &vd_serializer_);
  }
  vd_serializer_.EndSerialize(&ctx);

  return RakNet::RM3SR_SERIALIZED_ALWAYS_IDENTICALLY;
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::Deserialize(RakNet::DeserializeParameters *deserializeParameters) {
  RakNet::VariableDeltaSerializer::DeserializationContext ctx;

  vd_serializer_.BeginDeserialize(&ctx, &deserializeParameters->serializationBitstream[0]);
  for (auto& member: distributed_members_) {
    member.deserialize(&ctx, &vd_serializer_);
  }
  vd_serializer_.EndDeserialize(&ctx);
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::OnUserReplicaPreSerializeTick(void) {
  vd_serializer_.OnPreSerializeTick();
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::distribute_member(SerializableReference const& value) {
  distributed_members_.push_back(value);
}

////////////////////////////////////////////////////////////////////////////////

}
<commit_msg>added some output<commit_after>////////////////////////////////////////////////////////////////////////////////
//                                                                            //
// This file is part of Swift2D.                                              //
//                                                                            //
// Copyright: (c) 2011-2014 Simon Schneegans & Felix Lauer                    //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////

// includes  -------------------------------------------------------------------
#include <swift2d/network/NetworkObjectBase.hpp>

#include <swift2d/utils/Logger.hpp>

#include <raknet/RakPeerInterface.h>
#include <raknet/GetTime.h>

namespace swift {

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::WriteAllocationID(RakNet::Connection_RM3 *con, RakNet::BitStream* stream) const {
  stream->Write(get_type());
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3ConstructionState NetworkObjectBase::QueryConstruction(RakNet::Connection_RM3 *con, RakNet::ReplicaManager3 *replicaManager3) {
  return QueryConstruction_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

bool NetworkObjectBase::QueryRemoteConstruction(RakNet::Connection_RM3 *con) {
  return QueryRemoteConstruction_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::SerializeConstruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  vd_serializer_.AddRemoteSystemVariableHistory(con->GetRakNetGUID());

  std::cout << "SerializeConstruction Begin" << std::endl;
  for (auto& member: distributed_members_) {
    std::cout << "membaa" << std::endl;
    member.serialize(stream);
  }
  std::cout << "SerializeConstruction End" << std::endl;
}

////////////////////////////////////////////////////////////////////////////////

bool NetworkObjectBase::DeserializeConstruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  std::cout << "DeserializeConstruction Begin" << std::endl;
  for (auto& member: distributed_members_) {
    std::cout << "membaa" << std::endl;
    member.deserialize(stream);
  }

  std::cout << "DeserializeConstruction End" << std::endl;

  return true;
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::SerializeDestruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  vd_serializer_.RemoveRemoteSystemVariableHistory(con->GetRakNetGUID());

  for (auto& member: distributed_members_) {
    member.serialize(stream);
  }
}

////////////////////////////////////////////////////////////////////////////////

bool NetworkObjectBase::DeserializeDestruction(RakNet::BitStream* stream, RakNet::Connection_RM3 *con) {
  for (auto& member: distributed_members_) {
    member.deserialize(stream);
  }

  return true;
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3ActionOnPopConnection NetworkObjectBase::QueryActionOnPopConnection(RakNet::Connection_RM3 *con) const {
  return QueryActionOnPopConnection_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::DeallocReplica(RakNet::Connection_RM3 *con) {
  on_remote_delete();
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3QuerySerializationResult NetworkObjectBase::QuerySerialization(RakNet::Connection_RM3 *con) {
  return QuerySerialization_PeerToPeer(con);
}

////////////////////////////////////////////////////////////////////////////////

RakNet::RM3SerializationResult NetworkObjectBase::Serialize(RakNet::SerializeParameters *serializeParameters) {

  RakNet::VariableDeltaSerializer::SerializationContext ctx;

  serializeParameters->pro[0].reliability=RELIABLE_ORDERED;
  vd_serializer_.BeginIdenticalSerialize(
    &ctx,
    serializeParameters->whenLastSerialized==0,
    &serializeParameters->outputBitstream[0]
  );
  for (auto& member: distributed_members_) {
    member.serialize(&ctx, &vd_serializer_);
  }
  vd_serializer_.EndSerialize(&ctx);

  return RakNet::RM3SR_SERIALIZED_ALWAYS_IDENTICALLY;
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::Deserialize(RakNet::DeserializeParameters *deserializeParameters) {
  RakNet::VariableDeltaSerializer::DeserializationContext ctx;

  vd_serializer_.BeginDeserialize(&ctx, &deserializeParameters->serializationBitstream[0]);
  for (auto& member: distributed_members_) {
    member.deserialize(&ctx, &vd_serializer_);
  }
  vd_serializer_.EndDeserialize(&ctx);
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::OnUserReplicaPreSerializeTick(void) {
  vd_serializer_.OnPreSerializeTick();
}

////////////////////////////////////////////////////////////////////////////////

void NetworkObjectBase::distribute_member(SerializableReference const& value) {
  distributed_members_.push_back(value);
}

////////////////////////////////////////////////////////////////////////////////

}
<|endoftext|>


<commit_before>#ifndef __NETWORKMESSAGEJOINACCEPT_H
#define __NETWORKMESSAGEJOINACCEPT_H

#include <string>
#include <sstream>
#include <deque>
#include "NetworkMessage.hpp"
#include "../Player.hpp"
#include "../PlayerList.hpp"
#include "../Map.hpp"

namespace NetworkMessage{

	class JoinAccept : public NetworkMessage{

		public:
			//methods
			JoinAccept(
				PlayerList *playerList,
				unsigned int mapHeight,
				unsigned int mapWidth,
				time_t seed
			);
			~JoinAccept();

			PlayerList *getPlayerList();
			unsigned int getMapHeight();
			unsigned int getMapWidth();
			time_t getSeed();

		private:
			//methods
			//arguments
			PlayerList mPlayerList;
			unsigned int mMapHeight;
			unsigned int mMapWidth;
			time_t mSeed;

	};

};

#endif //__NETWORKMESSAGEJOINACCEPT_H
<commit_msg>removed unnecessary 'Player.hpp' include<commit_after>#ifndef __NETWORKMESSAGEJOINACCEPT_H
#define __NETWORKMESSAGEJOINACCEPT_H

#include <string>
#include <sstream>
#include <deque>
#include "NetworkMessage.hpp"
#include "../PlayerList.hpp"
#include "../Map.hpp"

namespace NetworkMessage{

	class JoinAccept : public NetworkMessage{

		public:
			//methods
			JoinAccept(
				PlayerList *playerList,
				unsigned int mapHeight,
				unsigned int mapWidth,
				time_t seed
			);
			~JoinAccept();

			PlayerList *getPlayerList();
			unsigned int getMapHeight();
			unsigned int getMapWidth();
			time_t getSeed();

		private:
			//methods
			//arguments
			PlayerList mPlayerList;
			unsigned int mMapHeight;
			unsigned int mMapWidth;
			time_t mSeed;

	};

};

#endif //__NETWORKMESSAGEJOINACCEPT_H
<|endoftext|>


<commit_before>/** @file
 *
 * @ingroup dspSoundFileLib
 *
 * @brief Tests for the #TTSoundfileLoader class
 *
 * @details Tests the core functions of the TTSoundfileLoader class in order to ensure that things are working after a build. It also demostrate how to make calls to common methods within the class.@n
 * IMPORTANT NOTE: Because POSIX filepaths will be specific to your system, it is important to change the TESTFILE definitions in this file to match a local absolute address. The related TEST definitions should also be set to match the attribution of the file which can be obtained via your sound file editor of choice.
 *
 * @authors Nathan Wolek
 *
 * @copyright Copyright © 2013 by Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSoundfileLoader.h"
#include "TTUnitTest.h"

/*
 #define TESTFILE "/Users/nathanwolek/Desktop/geese_clip.aif"
 #define TESTNUMCHANNELS 2
 #define TESTSAMPLERATE 44100
 #define TESTDURATIONINSAMPLES 88202
 #define TESTDURATIONINSECONDS 2.00004535
 #define TESTTITLE ""
 #define TESTARTIST ""
 #define TESTDATE ""
 #define TESTANNOTATION ""
 */

/* */
 #define TESTFILE "/Volumes/Storage/Audio/200604femf15/pitched/ding_b2.aiff"
#define TESTNUMCHANNELS 1
#define TESTSAMPLERATE 44100
#define TESTDURATIONINSAMPLES 39493
#define TESTDURATIONINSECONDS 0.89553288
#define TESTTITLE ""
#define TESTARTIST ""
#define TESTDATE ""
#define TESTANNOTATION ""
/* */

/*
 #define TESTFILE "/Volumes/Storage/Audio/200604femf15/ambience/street.aiff"
 #define TESTNUMCHANNELS 1
 #define TESTSAMPLERATE 44100
 #define TESTDURATIONINSAMPLES 4750848
 #define TESTDURATIONINSECONDS 107.728980
 #define TESTTITLE "UF Street"
 #define TESTARTIST "MPG"
 #define TESTDATE "2006"
 #define TESTANNOTATION ""
 */

TTErr TTSoundfileLoader::test(TTValue& returnedTestInfo)
{
    int errorCount = 0;
    int testAssertionCount = 0;

    {

		TTTestLog("\n");
		TTTestLog("Testing TTSoundfileLoader Basics...");

		TTSoundfileLoaderPtr soundfile_loader = NULL;
        TTErr err;

        // TEST 0: instantiate the object to a pointer
        TTBoolean result0 = { TTObjectBaseInstantiate("soundfile.loader", (TTObjectBasePtr*)&soundfile_loader, kTTValNONE) == kTTErrNone};

		TTTestAssertion("instantiates successfully",
						result0,
						testAssertionCount,
						errorCount);

    }

    return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo);
}
<commit_msg>adding test of setTargetMatrix()<commit_after>/** @file
 *
 * @ingroup dspSoundFileLib
 *
 * @brief Tests for the #TTSoundfileLoader class
 *
 * @details Tests the core functions of the TTSoundfileLoader class in order to ensure that things are working after a build. It also demostrate how to make calls to common methods within the class.@n
 * IMPORTANT NOTE: Because POSIX filepaths will be specific to your system, it is important to change the TESTFILE definitions in this file to match a local absolute address. The related TEST definitions should also be set to match the attribution of the file which can be obtained via your sound file editor of choice.
 *
 * @authors Nathan Wolek
 *
 * @copyright Copyright © 2013 by Nathan Wolek @n
 * This code is licensed under the terms of the "New BSD License" @n
 * http://creativecommons.org/licenses/BSD/
 */

#include "TTSoundfileLoader.h"
#include "TTUnitTest.h"

/*
 #define TESTFILE "/Users/nathanwolek/Desktop/geese_clip.aif"
 #define TESTNUMCHANNELS 2
 #define TESTSAMPLERATE 44100
 #define TESTDURATIONINSAMPLES 88202
 #define TESTDURATIONINSECONDS 2.00004535
 #define TESTTITLE ""
 #define TESTARTIST ""
 #define TESTDATE ""
 #define TESTANNOTATION ""
 */

/* */
 #define TESTFILE "/Volumes/Storage/Audio/200604femf15/pitched/ding_b2.aiff"
#define TESTNUMCHANNELS 1
#define TESTSAMPLERATE 44100
#define TESTDURATIONINSAMPLES 39493
#define TESTDURATIONINSECONDS 0.89553288
#define TESTTITLE ""
#define TESTARTIST ""
#define TESTDATE ""
#define TESTANNOTATION ""
/* */

/*
 #define TESTFILE "/Volumes/Storage/Audio/200604femf15/ambience/street.aiff"
 #define TESTNUMCHANNELS 1
 #define TESTSAMPLERATE 44100
 #define TESTDURATIONINSAMPLES 4750848
 #define TESTDURATIONINSECONDS 107.728980
 #define TESTTITLE "UF Street"
 #define TESTARTIST "MPG"
 #define TESTDATE "2006"
 #define TESTANNOTATION ""
 */

TTErr TTSoundfileLoader::test(TTValue& returnedTestInfo)
{
    int errorCount = 0;
    int testAssertionCount = 0;

    {

		TTTestLog("\n");
		TTTestLog("Testing TTSoundfileLoader Basics...");

		TTSoundfileLoaderPtr testSoundfileLoader = NULL;
        TTMatrixPtr testTargetMatrix = NULL;
        TTErr err;

        // TEST 0: instantiate the object to a pointer
        TTBoolean result0 = { TTObjectBaseInstantiate("soundfile.loader", (TTObjectBasePtr*)&testSoundfileLoader, kTTValNONE) == kTTErrNone};

		TTTestAssertion("instantiates successfully",
						result0,
						testAssertionCount,
						errorCount);

        // TEST 2: instantiate a TTSampleMatrix and set is as the target
        TTBoolean result2 = { TTObjectBaseInstantiate("samplematrix", (TTObjectBasePtr*)&testTargetMatrix, kTTValNONE) == kTTErrNone};

        TTBoolean result2b = { testSoundfileLoader->setTargetMatrix(testTargetMatrix) == kTTErrNone };

        TTTestAssertion("sets target matrix successfully",
						result0,
						testAssertionCount,
						errorCount);

    }

    return TTTestFinish(testAssertionCount, errorCount, returnedTestInfo);
}
<|endoftext|>


<commit_before>// @(#) $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTAgentUtil.cxx
    @author Matthias Richter
    @date
    @brief  Agent of the libAliHLTUtil library
*/

#include <cassert>
#include "AliHLTAgentUtil.h"
#include "AliHLTConfiguration.h"
#include "AliHLTOUTHandlerChain.h"

// header files of library components
#include "AliHLTDataGenerator.h"
#include "AliHLTRawReaderPublisherComponent.h"
#include "AliHLTLoaderPublisherComponent.h"
#include "AliHLTRootFileStreamerComponent.h"
#include "AliHLTRootFileWriterComponent.h"
#include "AliHLTRootFilePublisherComponent.h"
#include "AliHLTRootSchemaEvolutionComponent.h"
//#include "AliHLTMCGeneratorComponent.h"
#include "AliHLTESDMCEventPublisherComponent.h"
#include "AliHLTFileWriter.h"
#include "AliHLTFilePublisher.h"
#include "AliHLTBlockFilterComponent.h"
#include "AliHLTMonitoringRelay.h"
#include "AliHLTEsdCollectorComponent.h"
#include "AliHLTReadoutListDumpComponent.h"
#include "AliHLTOUTPublisherComponent.h"
#include "AliHLTCompStatCollector.h"

/** global instance for agent registration */
AliHLTAgentUtil gAliHLTAgentUtil;

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTAgentUtil)

AliHLTAgentUtil::AliHLTAgentUtil()
  : AliHLTModuleAgent("Util")
  , fCompStatDataHandler(NULL)
  , fStreamerInfoDataHandler(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTAgentUtil::~AliHLTAgentUtil()
{
  // see header file for class documentation
}

int AliHLTAgentUtil::CreateConfigurations(AliHLTConfigurationHandler* handler,
					  AliRawReader* /*rawReader*/,
					  AliRunLoader* /*runloader*/) const
{
  // see header file for class documentation
  if (!handler) return 0;

  /////////////////////////////////////////////////////////////////////////////////////
  //
  // a kChain HLTOUT configuration for processing of {'COMPSTAT':'PRIV'} data blocks
  // produces a TTree object of the component statistics and writes it to disc

  // publisher component
  handler->CreateConfiguration("UTIL-hltout-compstat-publisher", "AliHLTOUTPublisher"   , NULL, "-disable-component-stat");

  // collector configuration
  handler->CreateConfiguration("UTIL-compstat-converter", "StatisticsCollector", "UTIL-hltout-compstat-publisher", "-disable-component-stat -arraysize 10000");

  // writer configuration
  handler->CreateConfiguration("UTIL-compstat-writer", "ROOTFileWriter", "UTIL-compstat-converter", "-datafile HLT.statistics.root -concatenate-events -overwrite");

  return 0;
}

const char* AliHLTAgentUtil::GetReconstructionChains(AliRawReader* /*rawReader*/,
						     AliRunLoader* /*runloader*/) const
{
  // see header file for class documentation
  return NULL;
}

const char* AliHLTAgentUtil::GetRequiredComponentLibraries() const
{
  // see header file for class documentation
  return NULL;
}

int AliHLTAgentUtil::RegisterComponents(AliHLTComponentHandler* pHandler) const
{
  // see header file for class documentation
  assert(pHandler);
  if (!pHandler) return -EINVAL;
  pHandler->AddComponent(new AliHLTDataGenerator);
  pHandler->AddComponent(new AliHLTRawReaderPublisherComponent);
  pHandler->AddComponent(new AliHLTLoaderPublisherComponent);
  pHandler->AddComponent(new AliHLTRootFileStreamerComponent);
  pHandler->AddComponent(new AliHLTRootFileWriterComponent);
  pHandler->AddComponent(new AliHLTRootFilePublisherComponent);
  pHandler->AddComponent(new AliHLTRootSchemaEvolutionComponent);
  //  pHandler->AddComponent(new AliHLTMCGeneratorComponent);
  pHandler->AddComponent(new AliHLTESDMCEventPublisherComponent);
  pHandler->AddComponent(new AliHLTFileWriter);
  pHandler->AddComponent(new AliHLTFilePublisher);
  pHandler->AddComponent(new AliHLTBlockFilterComponent);
  pHandler->AddComponent(new AliHLTMonitoringRelay);
  pHandler->AddComponent(new AliHLTEsdCollectorComponent);
  pHandler->AddComponent(new AliHLTReadoutListDumpComponent);
  pHandler->AddComponent(new AliHLTOUTPublisherComponent);
  pHandler->AddComponent(new AliHLTCompStatCollector);
  return 0;
}

int AliHLTAgentUtil::GetHandlerDescription(AliHLTComponentDataType dt,
					   AliHLTUInt32_t /*spec*/,
					   AliHLTOUTHandlerDesc& desc) const
{
  // see header file for class documentation

  // handler for the component statistics data blocks {'COMPSTAT':'PRIV'}
  if (dt==kAliHLTDataTypeComponentStatistics ||
      dt==kAliHLTDataTypeComponentTable) {
      desc=AliHLTOUTHandlerDesc(kChain, dt, GetModuleId());
      return 1;
  }

  // handler for the component statistics data blocks {'ROOTSTRI':'HLT '}
  if (dt==kAliHLTDataTypeStreamerInfo) {
      desc=AliHLTOUTHandlerDesc(kProprietary, dt, GetModuleId());
      return 1;
  }
  return 0;
}

AliHLTOUTHandler* AliHLTAgentUtil::GetOutputHandler(AliHLTComponentDataType dt,
						   AliHLTUInt32_t /*spec*/)
{
  // see header file for class documentation

  // handler for the component statistics data blocks {'COMPSTAT':'PRIV'}
  if (dt==kAliHLTDataTypeComponentStatistics ||
      dt==kAliHLTDataTypeComponentTable) {
    if (fCompStatDataHandler==NULL)
      fCompStatDataHandler=new AliHLTOUTHandlerChain("chains=UTIL-compstat-writer");
    return fCompStatDataHandler;
  }

  // handler for the component statistics data blocks {'ROOTSTRI':'HLT '}
  if (dt==kAliHLTDataTypeStreamerInfo) {
    if (fStreamerInfoDataHandler==NULL)
      fStreamerInfoDataHandler=new AliHLTStreamerInfoHandler;
    return fStreamerInfoDataHandler;
  }

  return NULL;
}

int AliHLTAgentUtil::DeleteOutputHandler(AliHLTOUTHandler* pInstance)
{
  // see header file for class documentation
  if (pInstance==NULL) return -EINVAL;

  if (pInstance==fCompStatDataHandler) {
    delete fCompStatDataHandler;
    fCompStatDataHandler=NULL;
  }

  if (pInstance==fStreamerInfoDataHandler) {
    delete fStreamerInfoDataHandler;
    fStreamerInfoDataHandler=NULL;
  }
  return 0;
}
<commit_msg>removing unnecessary include file<commit_after>// $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTAgentUtil.cxx
    @author Matthias Richter
    @date
    @brief  Agent of the libAliHLTUtil library
*/

#include <cassert>
#include "AliHLTAgentUtil.h"
#include "AliHLTOUTHandlerChain.h"

// header files of library components
#include "AliHLTDataGenerator.h"
#include "AliHLTRawReaderPublisherComponent.h"
#include "AliHLTLoaderPublisherComponent.h"
#include "AliHLTRootFileStreamerComponent.h"
#include "AliHLTRootFileWriterComponent.h"
#include "AliHLTRootFilePublisherComponent.h"
#include "AliHLTRootSchemaEvolutionComponent.h"
//#include "AliHLTMCGeneratorComponent.h"
#include "AliHLTESDMCEventPublisherComponent.h"
#include "AliHLTFileWriter.h"
#include "AliHLTFilePublisher.h"
#include "AliHLTBlockFilterComponent.h"
#include "AliHLTMonitoringRelay.h"
#include "AliHLTEsdCollectorComponent.h"
#include "AliHLTReadoutListDumpComponent.h"
#include "AliHLTOUTPublisherComponent.h"
#include "AliHLTCompStatCollector.h"

/** global instance for agent registration */
AliHLTAgentUtil gAliHLTAgentUtil;

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTAgentUtil)

AliHLTAgentUtil::AliHLTAgentUtil()
  : AliHLTModuleAgent("Util")
  , fCompStatDataHandler(NULL)
  , fStreamerInfoDataHandler(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTAgentUtil::~AliHLTAgentUtil()
{
  // see header file for class documentation
}

int AliHLTAgentUtil::CreateConfigurations(AliHLTConfigurationHandler* handler,
					  AliRawReader* /*rawReader*/,
					  AliRunLoader* /*runloader*/) const
{
  // see header file for class documentation
  if (!handler) return 0;

  /////////////////////////////////////////////////////////////////////////////////////
  //
  // a kChain HLTOUT configuration for processing of {'COMPSTAT':'PRIV'} data blocks
  // produces a TTree object of the component statistics and writes it to disc

  // publisher component
  handler->CreateConfiguration("UTIL-hltout-compstat-publisher", "AliHLTOUTPublisher"   , NULL, "-disable-component-stat");

  // collector configuration
  handler->CreateConfiguration("UTIL-compstat-converter", "StatisticsCollector", "UTIL-hltout-compstat-publisher", "-disable-component-stat -arraysize 10000");

  // writer configuration
  handler->CreateConfiguration("UTIL-compstat-writer", "ROOTFileWriter", "UTIL-compstat-converter", "-datafile HLT.statistics.root -concatenate-events -overwrite");

  return 0;
}

const char* AliHLTAgentUtil::GetReconstructionChains(AliRawReader* /*rawReader*/,
						     AliRunLoader* /*runloader*/) const
{
  // see header file for class documentation
  return NULL;
}

const char* AliHLTAgentUtil::GetRequiredComponentLibraries() const
{
  // see header file for class documentation
  return NULL;
}

int AliHLTAgentUtil::RegisterComponents(AliHLTComponentHandler* pHandler) const
{
  // see header file for class documentation
  assert(pHandler);
  if (!pHandler) return -EINVAL;
  pHandler->AddComponent(new AliHLTDataGenerator);
  pHandler->AddComponent(new AliHLTRawReaderPublisherComponent);
  pHandler->AddComponent(new AliHLTLoaderPublisherComponent);
  pHandler->AddComponent(new AliHLTRootFileStreamerComponent);
  pHandler->AddComponent(new AliHLTRootFileWriterComponent);
  pHandler->AddComponent(new AliHLTRootFilePublisherComponent);
  pHandler->AddComponent(new AliHLTRootSchemaEvolutionComponent);
  //  pHandler->AddComponent(new AliHLTMCGeneratorComponent);
  pHandler->AddComponent(new AliHLTESDMCEventPublisherComponent);
  pHandler->AddComponent(new AliHLTFileWriter);
  pHandler->AddComponent(new AliHLTFilePublisher);
  pHandler->AddComponent(new AliHLTBlockFilterComponent);
  pHandler->AddComponent(new AliHLTMonitoringRelay);
  pHandler->AddComponent(new AliHLTEsdCollectorComponent);
  pHandler->AddComponent(new AliHLTReadoutListDumpComponent);
  pHandler->AddComponent(new AliHLTOUTPublisherComponent);
  pHandler->AddComponent(new AliHLTCompStatCollector);
  return 0;
}

int AliHLTAgentUtil::GetHandlerDescription(AliHLTComponentDataType dt,
					   AliHLTUInt32_t /*spec*/,
					   AliHLTOUTHandlerDesc& desc) const
{
  // see header file for class documentation

  // handler for the component statistics data blocks {'COMPSTAT':'PRIV'}
  if (dt==kAliHLTDataTypeComponentStatistics ||
      dt==kAliHLTDataTypeComponentTable) {
      desc=AliHLTOUTHandlerDesc(kChain, dt, GetModuleId());
      return 1;
  }

  // handler for the component statistics data blocks {'ROOTSTRI':'HLT '}
  if (dt==kAliHLTDataTypeStreamerInfo) {
      desc=AliHLTOUTHandlerDesc(kProprietary, dt, GetModuleId());
      return 1;
  }
  return 0;
}

AliHLTOUTHandler* AliHLTAgentUtil::GetOutputHandler(AliHLTComponentDataType dt,
						   AliHLTUInt32_t /*spec*/)
{
  // see header file for class documentation

  // handler for the component statistics data blocks {'COMPSTAT':'PRIV'}
  if (dt==kAliHLTDataTypeComponentStatistics ||
      dt==kAliHLTDataTypeComponentTable) {
    if (fCompStatDataHandler==NULL)
      fCompStatDataHandler=new AliHLTOUTHandlerChain("chains=UTIL-compstat-writer");
    return fCompStatDataHandler;
  }

  // handler for the component statistics data blocks {'ROOTSTRI':'HLT '}
  if (dt==kAliHLTDataTypeStreamerInfo) {
    if (fStreamerInfoDataHandler==NULL)
      fStreamerInfoDataHandler=new AliHLTStreamerInfoHandler;
    return fStreamerInfoDataHandler;
  }

  return NULL;
}

int AliHLTAgentUtil::DeleteOutputHandler(AliHLTOUTHandler* pInstance)
{
  // see header file for class documentation
  if (pInstance==NULL) return -EINVAL;

  if (pInstance==fCompStatDataHandler) {
    delete fCompStatDataHandler;
    fCompStatDataHandler=NULL;
  }

  if (pInstance==fStreamerInfoDataHandler) {
    delete fStreamerInfoDataHandler;
    fStreamerInfoDataHandler=NULL;
  }
  return 0;
}
<|endoftext|>