/**
	 * Handler method for input of perturbed measurement data. All
	 * measurements are collected and will contribute to the finally
	 * generated distribution which will be computed and pushed onward
	 * as soon as the configured amount of trials is reached.
	 *
	 * It is not necessary to trigger the compoent before via the
	 * {@code TriggerInput} input and noisy data may be pushed
	 * asynchronously. However, each push will result in an event to
	 * be issued on the {@code Sync} output.
	 */
    void dataIn( const EventType& e )
    {
		LOG4CPP_TRACE( logger, getName() << " Received perturbed measurement with timestamp " << e.time() );

		if ( m_bStopped ) 
		{
			LOG4CPP_TRACE( logger, getName() << " Covariance estimation has not been triggered yet, ignore measurement" );
			return;
		}
			
		m_counter ++;
		LOG4CPP_TRACE( logger, getName() << " Current counter: " << m_counter << ", go on until: " << m_size );

		// Compute incremental covariance
		typename ResultType::value_type estimate = incrementalEstimate ( *e );

		// Check list size
		if ( m_counter == m_size )
		{
			// push onward final result
			LOG4CPP_DEBUG( logger, getName() << " Terminate and push final result" );
			m_outPortDist.send( ResultType ( e.time(), estimate ) );

			boost::mutex::scoped_lock l( m_mutex );
			m_bStopped = true;

			return;
		}
		
		// If not reached, send next trigger event
		LOG4CPP_TRACE( logger, getName() << " Triggering computation..." );
		m_outPortSync.send( Measurement::Button( Measurement::now(), m_button ) );
	}
    /** integrates an inverse rotation velocity measurement. */
    void receiveInverseRotationVelocity( const Measurement::RotationVelocity& m )
    {
        LOG4CPP_DEBUG( logger, "Received inverse rotation velocity measurement: " << m );
        LOG4CPP_TRACE( logger, "state before: " << m_pKF->getState() << std::endl << m_pKF->getCovariance() );

        m_pKF->addInverseRotationVelocityMeasurement( m );

        checkSend( m.time() );

        LOG4CPP_TRACE( logger, "state after: " << m_pKF->getState() << std::endl << m_pKF->getCovariance() );
    }
    /** Method that returns a predicted measurement. */
    Measurement::ErrorPose sendOut( Measurement::Timestamp t )
    {
        LOG4CPP_DEBUG( logger, "Computing pose for t=" << t );
        LOG4CPP_TRACE( logger, "state: " << m_pKF->getState() << std::endl << m_pKF->getCovariance() );

        return m_pKF->predictPose( t );
    }
	/** Method that returns a predicted measurement. */
	Measurement::Rotation sendOut( Measurement::Timestamp t )
	{
		LOG4CPP_DEBUG( logger, "Computing rotation for t=" << t );
		LOG4CPP_TRACE( logger, "state: " << m_kf.getState() );

		return m_kf.predict( t );
	}
	/** integrates an absolute measurement. */
	void receiveAbsolute( const Measurement::Rotation& m )
	{
		LOG4CPP_DEBUG( logger, "Received absolute measurement: " << m );
		LOG4CPP_TRACE( logger, "state before: " << m_kf.getState() );

		m_kf.addRotationMeasurement( m );

		LOG4CPP_DEBUG( logger, "computed state: " << m_kf.getState() );
    }
	/** integrates an absolute measurement. */
	void receiveVelocity( const Measurement::RotationVelocity& m )
	{
		LOG4CPP_DEBUG( logger, "Received velocity measurement: " << m );
		LOG4CPP_TRACE( logger, "state before: " << m_kf.getState() );

		m_kf.addVelocityMeasurement( m );

		LOG4CPP_DEBUG( logger, "computed state: " << m_kf.getState() );
    }
   /** Method that computes the result for the smoothing. */
	void compute( Measurement::Timestamp t )
	{
		if( !m_init ){
			m_mean = *( m_inPort.get() );
			m_init = true;
		}
		else
			m_mean = (  m_alpha * ( *( m_inPort.get() ) )  ) + ( ( 1. - m_alpha ) * m_mean );
			
		LOG4CPP_TRACE( logger, "exponential smoothing: " << m_mean );
		m_outPort.send( EventType( t, m_mean ) );
	}
	/** Method that computes the result. */
	void compute( Measurement::Timestamp t )
	{
		LOG4CPP_TRACE( logger, "desired list size: " << m_size );

		// Retrieve and store measurement
		m_list.push_back( *m_inPort.get() );

		LOG4CPP_TRACE( logger, "current size: " << m_list.size() );

		if ( m_list.size() < m_size ) 
		{
			if ( isPortPush ( "Input" ) ) 
			{
				LOG4CPP_TRACE( logger, "push input port, wait for more measurements..." );
				return;
			}

			LOG4CPP_TRACE( logger, "pull inport port, retrieve missing measurements..." );
			while ( m_list.size() < m_size )
			{
				LOG4CPP_TRACE( logger, "items in list: " << m_list.size() << ", pulling next measurement" );
				
				m_inPort.pull( t );
				m_list.push_back( *m_inPort.get() );
			};
		}

		LOG4CPP_TRACE( logger, "desired list size reached" );
 		m_outPort.send( Measurement::Measurement< typename std::vector< typename EventType::value_type > >( t, m_list ) );
		m_list.clear();
	}
void PoseErrorVisualization::receiveError( const Ubitrack::Measurement::ErrorPose& error )
{
	LOG4CPP_DEBUG( logger, "Received error pose" );
	LOG4CPP_TRACE( logger, *error );

	boost::mutex::scoped_lock l( m_poseLock );

	// rotate the position covariance into the target coordinate frame
	Matrix< double, 3, 3 > j( ~error->rotation() );
	Matrix< double, 3, 3 > tmp( ublas::prod( j, ublas::subrange( error->covariance(), 0, 3, 0, 3 ) ) );
	Matrix< double, 3, 3 > posError( ublas::prod( tmp, ublas::trans( j ) ) );

	LOG4CPP_TRACE( logger, "Position error: " << std::endl << posError );
	m_posEllipsoid.setCovariance( posError );

	// x rotation error
	rotErrorJacobian( j, m_rotXEllipsoid.position() );
	noalias( tmp ) = ublas::prod( j, ublas::subrange( error->covariance(), 3, 6, 3, 6 ) );
	noalias( posError ) = ublas::prod( tmp, ublas::trans( j ) );

	LOG4CPP_TRACE( logger, "X rotation error: " << std::endl << posError );
	m_rotXEllipsoid.setCovariance( posError );

	// y rotation error
	rotErrorJacobian( j, m_rotYEllipsoid.position() );
	noalias( tmp ) = ublas::prod( j, ublas::subrange( error->covariance(), 3, 6, 3, 6 ) );
	noalias( posError ) = ublas::prod( tmp, ublas::trans( j ) );

	LOG4CPP_TRACE( logger, "Y rotation error: " << std::endl << posError );
	m_rotYEllipsoid.setCovariance( posError );

	// z rotation error
	rotErrorJacobian( j, m_rotZEllipsoid.position() );
	noalias( tmp ) = ublas::prod( j, ublas::subrange( error->covariance(), 3, 6, 3, 6 ) );
	noalias( posError ) = ublas::prod( tmp, ublas::trans( j ) );

	LOG4CPP_TRACE( logger, "Z rotation error: " << std::endl << posError );
	m_rotZEllipsoid.setCovariance( posError );
}
/** render the object */
void Projection::draw( Measurement::Timestamp& time, int parity )
{
	// use projection in stereo mode only if correct eye
	if ( ( m_stereoEye == stereoEyeRight && parity == 1 ) || ( m_stereoEye == stereoEyeLeft && parity == 0 ) )
		return;
		
	if ( m_pPull && m_pPull->isConnected())
		inputIn( m_pPull->get(time), 0);

	LOG4CPP_TRACE( logger, "Updating projection matrix to:" << std::endl << m_projection );
	glMatrixMode( GL_PROJECTION );
	glLoadMatrixd( m_projection.content() );
	glMatrixMode( GL_MODELVIEW );
}
Beispiel #11
0
void globFiles( const std::string& directory, const std::string & patternString, std::list< boost::filesystem::path >& files, bool globDirectories)
{
	boost::filesystem::path testPath( directory );
	if ( boost::filesystem::is_directory( testPath ) && boost::filesystem::exists( testPath ) )
	{
		boost::regex ext( patternString.c_str() );

		// iterate directory
		boost::filesystem::directory_iterator dirEnd;
		for ( boost::filesystem::directory_iterator it( testPath ); it != dirEnd; it++ )
		{
#ifdef BOOST_FILESYSTEM_I18N
			boost::filesystem::path p( it->path() );
#else
			boost::filesystem::path p( *it );
#endif
			// check for files with suitable extension
			if ( boost::filesystem::exists( p ) && ! boost::filesystem::is_directory( p ) && boost::regex_match( p.filename().string(), ext ) )
			{
				LOG4CPP_TRACE( logger, "Adding file " << p << " to list" );

				files.push_back( p );
			}
			// glob directories, if desired
			else if ( globDirectories && boost::filesystem::exists( p ) && boost::filesystem::is_directory( p ) )
			{
				files.push_back( p );
			}
		}

		// sort, since directory iteration is not ordered on some file systems
		files.sort();

		LOG4CPP_DEBUG( logger, "Sorted list of files" );		
		for ( std::list< boost::filesystem::path >::iterator iter = files.begin(); iter != files.end(); iter ++ )
		{
			LOG4CPP_DEBUG( logger, *iter );		
		}
	}
	else if ( boost::filesystem::exists( testPath ) ) {
		files.push_back( testPath );
	}
	else {
		UBITRACK_THROW( "Invalid path specified" );
	}

	if ( files.size() == 0 ) {
		UBITRACK_THROW( "No suitable files found at the specified location" );	
	}
}
	/**
	 * UTQL component constructor.
	 *
	 * @param sName Unique name of the component.
	 * @param subgraph UTQL subgraph
	 */
	RingBuffer( const std::string& sName, boost::shared_ptr< Graph::UTQLSubgraph > cfg )
		: Dataflow::TriggerComponent( sName, cfg )
		, m_inPort( "Input", *this )
		, m_outPort( "Output", *this )
		, m_size( 0 ) // number of elements
		, m_position_buffer( 0 )
	{
		m_list.clear();
		if( cfg->m_DataflowAttributes.hasAttribute( "size" ) )
		{
			cfg->m_DataflowAttributes.getAttributeData( "size", m_size );
			m_list.reserve( m_size );
			LOG4CPP_TRACE( logger, "desired list size: " << m_size );
		}
	}
Beispiel #13
0
SimpleFacade::SimpleFacade( const char* sComponentPath ) throw()
	: m_pPrivate( 0 )
	, m_sError( 0 )
{
	try
	{
		m_pPrivate = new SimpleFacadePrivate( sComponentPath );
		LOG4CPP_TRACE( logger, "SimpleFacadePrivate created successfully" );
	}
	catch ( const Ubitrack::Util::Exception& e )
	{
		LOG4CPP_ERROR( logger, "Caught exception constructing SimpleFacade: " << e );
		setError( e.what() );
	}
}
Math::ErrorVector< double, 3 > CovarianceEstimation< Measurement::Position, Measurement::ErrorPosition >::incrementalEstimate( Math::Vector< double, 3 >& posNew )
{
	ublas::vector_range< typename Math::Vector< double >::base_type > posMean ( mean, ublas::range( 0, 3 ) );
	ublas::matrix_range< typename Math::Matrix< double, 0, 0 >::base_type > outProd3 ( outProd, ublas::range ( 0, 3 ), ublas::range ( 0, 3 ) );

 	// Running mean value of position random variable
 	posMean = ( ( ((double)m_counter - 1) / (double)m_counter ) * posMean ) + ( ( 1 / (double)m_counter ) * posNew );

	// Running outer product of position random variable (not yet normalized by number of measurements)
 	outProd3 = outProd3 + ublas::outer_prod( posNew, posNew );

 	// Compute covariance matrix
 	if ( m_counter == 1 ) 
 	{
 		LOG4CPP_TRACE( logger, "Not enough data to compute covariance matrix" );
 		return Math::ErrorVector< double, 3 >();
 	}

 	Math::ErrorVector< double, 3 > ev ( posMean, outProd3 / ((double)m_counter) - ublas::outer_prod ( posMean, posMean ) );

	LOG4CPP_TRACE( logger, "Running (empirical) mean / covariance: " << std::endl << ev );

 	return ev;
}
	/**
	 * UTQL component constructor.
	 *
	 * @param sName Unique name of the component.
	 * @param subgraph UTQL subgraph
	 */
	WindowedAggregator( const std::string& sName, boost::shared_ptr< Graph::UTQLSubgraph > cfg )
		: Dataflow::TriggerComponent( sName, cfg )
		, m_inPort( "Input", *this )
		, m_outPort( "Output", *this )
		, m_time( 0.0 ) // duration in nanoseconds
	{
		m_mList.clear();
		m_tList.clear();
		if( cfg->m_DataflowAttributes.hasAttribute( "time" ) )
		{
			cfg->m_DataflowAttributes.getAttributeData( "time", m_time );
			LOG4CPP_TRACE( logger, "desired list duration[ms] : " << m_time );
			m_time *= 1e+06; //ms to ns
		}
	}
void Undistortion::initMap( int width, int height, int origin )
{
	// skip if already initialized with same values
	if ( m_pMapX && m_pMapX->width == width && m_pMapX->height == height )
		return;
		
	LOG4CPP_INFO( logger, "Creating undistortion map" );
	LOG4CPP_DEBUG( logger, "coeffs=" << m_coeffs );
	LOG4CPP_DEBUG( logger, "intrinsic=" << m_intrinsics );
	
	// copy ublas to OpenCV parameters
	CvMat* pCvCoeffs = cvCreateMat( 1, 8, CV_32FC1 );
	for ( unsigned i = 0; i < 8; i++ )
		pCvCoeffs->data.fl[ i ] = static_cast< float >( m_coeffs( i ) );
		
	CvMat* pCvIntrinsics = cvCreateMat( 3, 3, CV_32FC1 );
	for ( unsigned i = 0; i < 3; i++ )
		for ( unsigned j = 0; j < 3; j++ )
			cvmSet( pCvIntrinsics, i, j, m_intrinsics( i, j ) );
	
	// compensate for left-handed OpenCV coordinate frame
	for ( unsigned i = 0; i < 3; i++ )
		cvmSet( pCvIntrinsics, i, 2, cvmGet( pCvIntrinsics, i, 2 ) * -1 );
	
	// compensate if origin==0
	if ( !origin )
	{
		cvmSet( pCvIntrinsics, 1, 2, height - 1 - cvmGet( pCvIntrinsics,  1, 2 ) );
		cvmSet( pCvCoeffs, 0, 2, cvmGet( pCvCoeffs, 0, 2 ) * -1 );
	}

	// initialize the distortion map
	// create map images
	m_pMapX.reset( new Image( width, height, 1, IPL_DEPTH_32F ) );
	m_pMapY.reset( new Image( width, height, 1, IPL_DEPTH_32F ) );
	
	cvInitUndistortMap( pCvIntrinsics, pCvCoeffs, *m_pMapX, *m_pMapY );
	
	LOG4CPP_TRACE( logger, "origin=" << origin );
	Math::Vector< double, 2 > startPixel( *reinterpret_cast< float* >( m_pMapX->imageData ), *reinterpret_cast< float* >( m_pMapY->imageData ) );
	LOG4CPP_DEBUG( logger, "first pixel (0, 0) mapped from " << startPixel );
		
	// release data
	cvReleaseMat( &pCvCoeffs );
	cvReleaseMat( &pCvIntrinsics );
}	
	/** Method that computes the result. */
	void compute( Measurement::Timestamp t )
	{
		//add newest elements to queues
		m_mList.push_back( *m_inPort.get() );
		m_tList.push_back( t );
		
		//delete oldest elements from queues
		while( ( m_tList.front() + m_time ) < t )
		{
			m_mList.pop_front();
			m_tList.pop_front();
		}	

		//copy all elements from queue to vector
		std::vector< typename EventType::value_type > output;
		output.reserve( m_mList.size() );
		output.assign( m_mList.begin(), m_mList.end() );
		LOG4CPP_TRACE( logger, "items in queue: " << m_mList.size() );
 		m_outPort.send( Measurement::Measurement< typename std::vector< typename EventType::value_type > >( t, output ) );
	}
	/** Method that computes the result. */
	void compute( Measurement::Timestamp t )
	{
		
		if( m_list.size() < m_list.capacity() )
		{
			m_list.push_back( *m_inPort.get() );
			if( m_list.size() < m_list.capacity())
			{
				LOG4CPP_TRACE( logger, "Ring Buffer not yet full, reached " << m_list.size() << " of " << m_list.capacity() << " measurements." );
				UBITRACK_THROW( "Ring buffer not full. need to add more measurements." );
				return;
			}
			m_outPort.send( Measurement::Measurement< typename std::vector< typename EventType::value_type > >( t, m_list ) );
			return;
		}
		
		m_list[ m_position_buffer++ ] = *m_inPort.get();
		m_position_buffer = m_position_buffer % m_size;
 		m_outPort.send( Measurement::Measurement< typename std::vector< typename EventType::value_type > >( t, m_list ) );
	}
Math::ErrorPose CovarianceEstimation< Measurement::Pose, Measurement::ErrorPose >::incrementalEstimate( Math::Pose& poseNew )
{
	ublas::vector_range< typename Math::Vector< double >::base_type > posMean( mean, ublas::range( 0, 3 ) );
	ublas::vector_range< typename Math::Vector< double >::base_type > rotMean( mean, ublas::range( 3, 7 ) );

	LOG4CPP_TRACE ( logger, "Update pose event: " << poseNew );

	// The order is tx, ty, tz, qx, qy, qz, qw.
	Math::Vector< double > poseNewVec( 7 );
	poseNew.toVector( poseNewVec );
	ublas::vector_range< typename Math::Vector< double >::base_type > posNew( poseNewVec, ublas::range( 0, 3 ) );
	ublas::vector_range< typename Math::Vector< double >::base_type > rotNew( poseNewVec, ublas::range( 3, 7 ) );

	// Take care of quaternion ambiguity
 	if ( ublas::inner_prod( rotNew, rotMean ) < 0 )
 		rotNew *= -1;

	// Update running mean value
	mean = ( ( ((double)m_counter - 1) / (double)m_counter ) * mean ) + ( ( 1 / (double)m_counter ) * poseNewVec );

	// Running outer product of pose random variable (not yet normalized by number of measurements)
	outProd = outProd + ublas::outer_prod( poseNewVec, poseNewVec );

	/*
	 * Use inverted mean value to transform the additive 7x7
	 * covariance to the 6x6 multiplicative format The conversion is
	 * conducted according to the following formulas:
	 * 
	 * q_m = q_0 * ( q_id + q_e )
	 * 
	 * where q_id is the identity quaternion and q_e is a quaternion
	 * with expectation ((0,0,0),0) and a covariance covering only the
	 * imaginary part. Together ( q_id + q_e ) represent a small
	 * quaternion ((e_rx, e_ry, e_rz), 1). If mean and covariance of
	 * the quaternion are estimated according to the usual formulas,
	 * however, one gets the following instead:
	 * 
	 * q_m = q_0 + q'_e
	 * 
	 * Together with the first formula, this yields
	 * 
	 * q_0 * ( q_id + q_e ) = q_0 + q'_e
	 * ( q_id + q_e )       = ~q_0 * q_0 + ~q_0 * q'_e
	 * q_e                  = q_id + ~q_0 * q'_e - q_id
	 * q_e                  = ~q_0 * q'_e
	 *
	 * Thus, one has to rotate the distribution by ~q_0. The variance
	 * of the real part can then be discarded, it should be ~0.
	 */

	Math::Vector< double, 7 > invMean;
	(~(Math::Pose::fromVector( mean ) ) ).toVector( invMean );
	Math::ErrorVector< double, 7 > ev ( invMean, outProd / ( (double)m_counter ) - ublas::outer_prod ( mean, mean ) );
	Math::ErrorPose invEp = Math::ErrorPose::fromAdditiveErrorVector( ev );
	
	// We created the error pose from the inverted mean value above, to obtain the transformed 6x6 covariance
	// Now, we recreate the error pose with the computed mean value.
	Math::ErrorPose ep( Math::Pose::fromVector( mean ), invEp.covariance() );

	LOG4CPP_TRACE( logger, "Running (empirical) mean / covariance: " << std::endl << ep );

	// For debug purposes, compute positional and angular error...
	Math::Matrix< double, 6, 6 > covar = ep.covariance();
	double posRms = sqrt ( covar (0,0) + covar (1,1) + covar (2,2) );
	LOG4CPP_INFO( logger, "RMS positional error [mm]: " << posRms );
	Math::Vector< double, 3 > axis;
	axis (0) = sqrt ( covar (3,3) );
	axis (1) = sqrt ( covar (4,4) );
	axis (2) = sqrt ( covar (5,5) );
	double norm = norm_2 (axis);
	double phi = asin ( norm ) * 2;
	phi = phi * 180 / boost::math::constants::pi<double>();
	LOG4CPP_INFO( logger, "Standard deviation of rotational error [deg]: " << phi );
	
	return ep;
}