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

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2006 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 0.9.5, packaged on February, 2006.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_mesh2.cpp implementation of the GLC_Mesh2 class.

#include <QtDebug>
#include <assert.h>
#include "glc_mesh2.h"

//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////
GLC_Mesh2::GLC_Mesh2(const GLfloat *pColor)
:GLC_Geometry("Mesh", pColor)
, m_NumberOfFaces(0)
{

}

GLC_Mesh2::GLC_Mesh2(const GLC_Mesh2 &meshToCopy)
: GLC_Geometry(meshToCopy.GetName(), meshToCopy.GetfRGBA())
, m_CoordinateHash(meshToCopy.m_CoordinateHash)
, m_CoordinateIndex(meshToCopy.m_CoordinateIndex)
, m_MaterialHash(meshToCopy.m_MaterialHash)
, m_MaterialIndex(meshToCopy.m_MaterialIndex)
, m_NormalHash(meshToCopy.m_NormalHash)
, m_NormalIndex(meshToCopy.m_NormalIndex)
, m_TextCoordinateHash(meshToCopy.m_TextCoordinateHash)
, m_TextureIndex(meshToCopy.m_TextureIndex)

, m_NumberOfFaces(meshToCopy.m_NumberOfFaces)
{
	SetMaterial(meshToCopy.GetMaterial());
	SetMatrix(meshToCopy.GetMatrix());

}

GLC_Mesh2::~GLC_Mesh2(void)
{
	m_CoordinateHash.clear();
	m_CoordinateIndex.clear();

	m_NormalHash.clear();
	m_NormalIndex.clear();

	m_TextCoordinateHash.clear();
	m_TextureIndex.clear();

	m_MaterialHash.clear();
	m_MaterialIndex.clear();
}
/////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

//! Get material from mesh
void GLC_Mesh2::GetOneMaterial(int Index, GLC_Material &Material)
{
	MaterialHash::const_iterator iMaterial= m_MaterialHash.find(Index);
	// Check if the key is find
	assert(iMaterial != m_MaterialHash.end());

	// Retrieve the material
	Material= m_MaterialHash[Index];

}
// return the mesh bounding box
GLC_BoundingBox* GLC_Mesh2::getBoundingBox(void) const
{
	GLC_BoundingBox* pBoundingBox= new GLC_BoundingBox();

	Vector3dHash::const_iterator iEntry= m_CoordinateHash.begin();

    while (iEntry != m_CoordinateHash.constEnd())
    {
        // Combine the vertex with the bounding box
        pBoundingBox->combine(iEntry.value());
        ++iEntry;
    }

	return pBoundingBox;
}

/////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

//! Add material to mesh
void GLC_Mesh2::AddMaterial(int Index, GLC_Material &Material)
{

	// Add or replace the Material to Material hash table
	m_MaterialHash.insert(Index, Material);

}

//! Modify material from mesh
void GLC_Mesh2::ModifyMaterial(int Index, GLC_Material &Material)
{
	//! \todo GLC_Material should have copy constructor
	MaterialHash::const_iterator iMaterial= m_MaterialHash.find(Index);
	// Check if the key is find
	assert(iMaterial != m_MaterialHash.end());

	// Modify the material
	m_MaterialHash.insert(Index, Material);

}

// Add a vertex to mesh
void GLC_Mesh2::AddCoordinate(int Index, GLC_Vector3d Coordinate)
{
	Vector3dHash::const_iterator iVector= m_CoordinateHash.find(Index);
	// Check if the key is already use

	assert(iVector == m_CoordinateHash.end());

	// Add the coordinate to coordinate hash table
	m_CoordinateHash.insert(Index, Coordinate);

}

// Add Normal
void GLC_Mesh2::AddNormal(int Index, GLC_Vector3d Normal)
{
	Vector3dHash::const_iterator iVector= m_NormalHash.find(Index);
	// Check if the key is already use

	assert(iVector == m_NormalHash.end());

	// Add the coordinate to coordinate hash table
	m_NormalHash.insert(Index, Normal);

}

// Add texture coordinate
void GLC_Mesh2::AddTextureCoordinate(int Index, GLC_Vector2d TextureCoordinate)
{
	Vector2dHash::const_iterator iVector= m_TextCoordinateHash.find(Index);

	// Check if the key is already in use
	assert(iVector == m_TextCoordinateHash.end());

	// Add the coordinate to coordinate hash table
	m_TextCoordinateHash.insert(Index, TextureCoordinate);

}

//! Add a face without texture coordinate
void GLC_Mesh2::AddFace(const QVector<int> &Material, const QVector<int> &Coordinate, const QVector<int> &Normal)
{

	AddMaterialIndex(Material);
	AddCoordAndNormIndex(Coordinate, Normal);

	// The testture index should be empty
	//assert(m_TextureIndex.isEmpty());

	// Increment number of faces
	m_NumberOfFaces++;

}

// Add a face with texture coordinate
void GLC_Mesh2::AddFace(const QVector<int> &Material, const QVector<int> &Coordinate, const QVector<int> &Normal,
						const QVector<int> &TextureCoordinate)
{
	AddMaterialIndex(Material);
	AddCoordAndNormIndex(Coordinate, Normal);
	AddTextureIndex(TextureCoordinate);

	// Increment number of faces
	m_NumberOfFaces++;
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Virtual interface for OpenGL Geometry set up.
void GLC_Mesh2::GlDraw()
{
	qDebug() << "GLC_Mesh2::GlDraw ENTER";

	// If the mesh is empty there is noting to do
	if (m_CoordinateIndex.isEmpty()) return;

	// Index face separator
	const int separator= -1;

	int CurrentMaterialIndex= -1;
	bool IsNewFace= true;

	for(int i=0; i < m_CoordinateIndex.size(); ++i)
	{
		if (m_CoordinateIndex.at(i) == separator)
		{
			assert((i != 0) && (!IsNewFace));	// the first index couldn't be a separator
			// End of current face
			glEnd();
			// At the next round a new face will be create
			IsNewFace=true;
		}
		else
		{
			if (IsNewFace)
			{
				if (CurrentMaterialIndex != m_MaterialIndex.at(i))
				{	// If the material change, make it current
					CurrentMaterialIndex= m_MaterialIndex.at(i);
					//qDebug() << "GLC_Mesh2::GlDraw : CurrentMaterialIndex" << CurrentMaterialIndex;

					MaterialHash::const_iterator iMaterial= m_MaterialHash.find(CurrentMaterialIndex);
					// Check if the key is already use
					if (iMaterial != m_MaterialHash.end())
					{
						if (m_MaterialHash[CurrentMaterialIndex].GetAddRgbaTexture())
						{
							glEnable(GL_TEXTURE_2D);
							//qDebug() << "GLC_Mesh2::GlDraw : Texture enabled";
						}
						else
						{
							glDisable(GL_TEXTURE_2D);
						}
						m_MaterialHash[CurrentMaterialIndex].GlExecute();
					}
					else
					{
						m_pMaterial->GlExecute();
					}
				}
				IsNewFace= false;
				// New polygon creation
				glBegin(GL_POLYGON);
			}
				// Vertex texture coordinate if necessary
				if (i < m_TextureIndex.size())
				{
					glTexCoord2dv(m_TextCoordinateHash[m_TextureIndex.at(i)].Return_dVect());
				}

				// Vertex Normal
				if (i < m_NormalIndex.size())
				{
					glNormal3dv(m_NormalHash[m_NormalIndex.at(i)].Return_dVect());
				}
				else
				{
					qDebug() << "GLC_Mesh2::GlDraw : m_NormalIndex out of bound";
				}

				// Vertex 3D coordinate
				if (i < m_CoordinateIndex.size())
				{
					glVertex3dv(m_CoordinateHash[m_CoordinateIndex.at(i)].Return_dVect());
				}
				else
				{
					qDebug() << "GLC_Mesh2::GlDraw : m_CoordinateIndex out of bound";
				}

		}
	}
}

// Virtual interface for OpenGL Geomtry properties.
void GLC_Mesh2::GlPropGeom()
{
		//! Change the current matrix
		glMultMatrixd(m_MatPos.Return_dMat());

		// Polygons display mode
		glPolygonMode(m_PolyFace, m_PolyMode);

		if (m_IsBlended)
		{
			glEnable(GL_BLEND);
			glDepthMask(GL_FALSE);
		}
		else
		{
			glDisable(GL_BLEND);
		}

		if(!m_pMaterial || (m_PolyMode != GL_FILL))
		{
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_LIGHTING);
			glLineWidth(GetThickness());	// is thikness
			glColor4fv(GetfRGBA());			// is color
		}
		else if (m_pMaterial->GetAddRgbaTexture())
		{
			glEnable(GL_TEXTURE_2D);
			glEnable(GL_LIGHTING);
			m_pMaterial->GlExecute();
		}
		else
		{
			glDisable(GL_TEXTURE_2D);
			glEnable(GL_LIGHTING);
			m_pMaterial->GlExecute();
		}

}

// Add coordinate and normal index of a face
void GLC_Mesh2::AddCoordAndNormIndex(const QVector<int> &Coordinate, const QVector<int> &Normal)
{
	// Number of coordinate to add
	const int size= Coordinate.size();

	// Add Coordinate index of the face
	for (int i= 0; i < size; ++i)
	{
		m_CoordinateIndex.append(Coordinate[i]);
	}
	m_CoordinateIndex.append(-1); // End of the face's coordinate index

	// Add Normal index of the face
	for (int i= 0; i < size; ++i)
	{
		m_NormalIndex.append(Normal[i]);
	}
	m_NormalIndex.append(-1); // End of the face's normal index

	// Check if indexed list have the same size
	assert(m_NormalIndex.size() == m_CoordinateIndex.size());

}

// Add Texture coordinate index of a face
void GLC_Mesh2::AddTextureIndex(const QVector<int> &TextureCoordinate)
{
	for (int i= 0; i < TextureCoordinate.size(); ++i)
	{
		m_TextureIndex.append(TextureCoordinate[i]);
	}
	m_TextureIndex.append(-1); // End of the face's texture coordinate index

}

// Add Material index of a face
void GLC_Mesh2::AddMaterialIndex(const QVector<int> &Material)
{
	for (int i= 0; i < Material.size(); ++i)
	{
		m_MaterialIndex.append(Material[i]);
	}
	m_MaterialIndex.append(-1); // End of the face's material index
}
<commit_msg>Fix bug in method getBoundingBox() (matrix transformation)<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2006 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 0.9.5, packaged on February, 2006.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*****************************************************************************/

//! \file glc_mesh2.cpp implementation of the GLC_Mesh2 class.

#include <QtDebug>
#include <assert.h>
#include "glc_mesh2.h"

//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////
GLC_Mesh2::GLC_Mesh2(const GLfloat *pColor)
:GLC_Geometry("Mesh", pColor)
, m_NumberOfFaces(0)
{

}

GLC_Mesh2::GLC_Mesh2(const GLC_Mesh2 &meshToCopy)
: GLC_Geometry(meshToCopy.GetName(), meshToCopy.GetfRGBA())
, m_CoordinateHash(meshToCopy.m_CoordinateHash)
, m_CoordinateIndex(meshToCopy.m_CoordinateIndex)
, m_MaterialHash(meshToCopy.m_MaterialHash)
, m_MaterialIndex(meshToCopy.m_MaterialIndex)
, m_NormalHash(meshToCopy.m_NormalHash)
, m_NormalIndex(meshToCopy.m_NormalIndex)
, m_TextCoordinateHash(meshToCopy.m_TextCoordinateHash)
, m_TextureIndex(meshToCopy.m_TextureIndex)

, m_NumberOfFaces(meshToCopy.m_NumberOfFaces)
{
	SetMaterial(meshToCopy.GetMaterial());
	SetMatrix(meshToCopy.GetMatrix());

}

GLC_Mesh2::~GLC_Mesh2(void)
{
	m_CoordinateHash.clear();
	m_CoordinateIndex.clear();

	m_NormalHash.clear();
	m_NormalIndex.clear();

	m_TextCoordinateHash.clear();
	m_TextureIndex.clear();

	m_MaterialHash.clear();
	m_MaterialIndex.clear();
}
/////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

//! Get material from mesh
void GLC_Mesh2::GetOneMaterial(int Index, GLC_Material &Material)
{
	MaterialHash::const_iterator iMaterial= m_MaterialHash.find(Index);
	// Check if the key is find
	assert(iMaterial != m_MaterialHash.end());

	// Retrieve the material
	Material= m_MaterialHash[Index];

}
// return the mesh bounding box
GLC_BoundingBox* GLC_Mesh2::getBoundingBox(void) const
{
	GLC_BoundingBox* pBoundingBox= new GLC_BoundingBox();

	Vector3dHash::const_iterator iEntry= m_CoordinateHash.begin();

    while (iEntry != m_CoordinateHash.constEnd())
    {
        // Combine the vertex with the bounding box
        pBoundingBox->combine(iEntry.value());
        ++iEntry;
    }

    pBoundingBox->transform(m_MatPos);
	return pBoundingBox;
}

/////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

//! Add material to mesh
void GLC_Mesh2::AddMaterial(int Index, GLC_Material &Material)
{

	// Add or replace the Material to Material hash table
	m_MaterialHash.insert(Index, Material);

}

//! Modify material from mesh
void GLC_Mesh2::ModifyMaterial(int Index, GLC_Material &Material)
{
	//! \todo GLC_Material should have copy constructor
	MaterialHash::const_iterator iMaterial= m_MaterialHash.find(Index);
	// Check if the key is find
	assert(iMaterial != m_MaterialHash.end());

	// Modify the material
	m_MaterialHash.insert(Index, Material);

}

// Add a vertex to mesh
void GLC_Mesh2::AddCoordinate(int Index, GLC_Vector3d Coordinate)
{
	Vector3dHash::const_iterator iVector= m_CoordinateHash.find(Index);
	// Check if the key is already use

	assert(iVector == m_CoordinateHash.end());

	// Add the coordinate to coordinate hash table
	m_CoordinateHash.insert(Index, Coordinate);

}

// Add Normal
void GLC_Mesh2::AddNormal(int Index, GLC_Vector3d Normal)
{
	Vector3dHash::const_iterator iVector= m_NormalHash.find(Index);
	// Check if the key is already use

	assert(iVector == m_NormalHash.end());

	// Add the coordinate to coordinate hash table
	m_NormalHash.insert(Index, Normal);

}

// Add texture coordinate
void GLC_Mesh2::AddTextureCoordinate(int Index, GLC_Vector2d TextureCoordinate)
{
	Vector2dHash::const_iterator iVector= m_TextCoordinateHash.find(Index);

	// Check if the key is already in use
	assert(iVector == m_TextCoordinateHash.end());

	// Add the coordinate to coordinate hash table
	m_TextCoordinateHash.insert(Index, TextureCoordinate);

}

//! Add a face without texture coordinate
void GLC_Mesh2::AddFace(const QVector<int> &Material, const QVector<int> &Coordinate, const QVector<int> &Normal)
{

	AddMaterialIndex(Material);
	AddCoordAndNormIndex(Coordinate, Normal);

	// The testture index should be empty
	//assert(m_TextureIndex.isEmpty());

	// Increment number of faces
	m_NumberOfFaces++;

}

// Add a face with texture coordinate
void GLC_Mesh2::AddFace(const QVector<int> &Material, const QVector<int> &Coordinate, const QVector<int> &Normal,
						const QVector<int> &TextureCoordinate)
{
	AddMaterialIndex(Material);
	AddCoordAndNormIndex(Coordinate, Normal);
	AddTextureIndex(TextureCoordinate);

	// Increment number of faces
	m_NumberOfFaces++;
}

//////////////////////////////////////////////////////////////////////
// OpenGL Functions
//////////////////////////////////////////////////////////////////////

// Virtual interface for OpenGL Geometry set up.
void GLC_Mesh2::GlDraw()
{
	qDebug() << "GLC_Mesh2::GlDraw ENTER";

	// If the mesh is empty there is noting to do
	if (m_CoordinateIndex.isEmpty()) return;

	// Index face separator
	const int separator= -1;

	int CurrentMaterialIndex= -1;
	bool IsNewFace= true;

	for(int i=0; i < m_CoordinateIndex.size(); ++i)
	{
		if (m_CoordinateIndex.at(i) == separator)
		{
			assert((i != 0) && (!IsNewFace));	// the first index couldn't be a separator
			// End of current face
			glEnd();
			// At the next round a new face will be create
			IsNewFace=true;
		}
		else
		{
			if (IsNewFace)
			{
				if (CurrentMaterialIndex != m_MaterialIndex.at(i))
				{	// If the material change, make it current
					CurrentMaterialIndex= m_MaterialIndex.at(i);
					//qDebug() << "GLC_Mesh2::GlDraw : CurrentMaterialIndex" << CurrentMaterialIndex;

					MaterialHash::const_iterator iMaterial= m_MaterialHash.find(CurrentMaterialIndex);
					// Check if the key is already use
					if (iMaterial != m_MaterialHash.end())
					{
						if (m_MaterialHash[CurrentMaterialIndex].GetAddRgbaTexture())
						{
							glEnable(GL_TEXTURE_2D);
							//qDebug() << "GLC_Mesh2::GlDraw : Texture enabled";
						}
						else
						{
							glDisable(GL_TEXTURE_2D);
						}
						m_MaterialHash[CurrentMaterialIndex].GlExecute();
					}
					else
					{
						m_pMaterial->GlExecute();
					}
				}
				IsNewFace= false;
				// New polygon creation
				glBegin(GL_POLYGON);
			}
				// Vertex texture coordinate if necessary
				if (i < m_TextureIndex.size())
				{
					glTexCoord2dv(m_TextCoordinateHash[m_TextureIndex.at(i)].Return_dVect());
				}

				// Vertex Normal
				if (i < m_NormalIndex.size())
				{
					glNormal3dv(m_NormalHash[m_NormalIndex.at(i)].Return_dVect());
				}
				else
				{
					qDebug() << "GLC_Mesh2::GlDraw : m_NormalIndex out of bound";
				}

				// Vertex 3D coordinate
				if (i < m_CoordinateIndex.size())
				{
					glVertex3dv(m_CoordinateHash[m_CoordinateIndex.at(i)].Return_dVect());
				}
				else
				{
					qDebug() << "GLC_Mesh2::GlDraw : m_CoordinateIndex out of bound";
				}

		}
	}
}

// Virtual interface for OpenGL Geomtry properties.
void GLC_Mesh2::GlPropGeom()
{
		//! Change the current matrix
		glMultMatrixd(m_MatPos.Return_dMat());

		// Polygons display mode
		glPolygonMode(m_PolyFace, m_PolyMode);

		if (m_IsBlended)
		{
			glEnable(GL_BLEND);
			glDepthMask(GL_FALSE);
		}
		else
		{
			glDisable(GL_BLEND);
		}

		if(!m_pMaterial || (m_PolyMode != GL_FILL))
		{
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_LIGHTING);
			glLineWidth(GetThickness());	// is thikness
			glColor4fv(GetfRGBA());			// is color
		}
		else if (m_pMaterial->GetAddRgbaTexture())
		{
			glEnable(GL_TEXTURE_2D);
			glEnable(GL_LIGHTING);
			m_pMaterial->GlExecute();
		}
		else
		{
			glDisable(GL_TEXTURE_2D);
			glEnable(GL_LIGHTING);
			m_pMaterial->GlExecute();
		}

}

// Add coordinate and normal index of a face
void GLC_Mesh2::AddCoordAndNormIndex(const QVector<int> &Coordinate, const QVector<int> &Normal)
{
	// Number of coordinate to add
	const int size= Coordinate.size();

	// Add Coordinate index of the face
	for (int i= 0; i < size; ++i)
	{
		m_CoordinateIndex.append(Coordinate[i]);
	}
	m_CoordinateIndex.append(-1); // End of the face's coordinate index

	// Add Normal index of the face
	for (int i= 0; i < size; ++i)
	{
		m_NormalIndex.append(Normal[i]);
	}
	m_NormalIndex.append(-1); // End of the face's normal index

	// Check if indexed list have the same size
	assert(m_NormalIndex.size() == m_CoordinateIndex.size());

}

// Add Texture coordinate index of a face
void GLC_Mesh2::AddTextureIndex(const QVector<int> &TextureCoordinate)
{
	for (int i= 0; i < TextureCoordinate.size(); ++i)
	{
		m_TextureIndex.append(TextureCoordinate[i]);
	}
	m_TextureIndex.append(-1); // End of the face's texture coordinate index

}

// Add Material index of a face
void GLC_Mesh2::AddMaterialIndex(const QVector<int> &Material)
{
	for (int i= 0; i < Material.size(); ++i)
	{
		m_MaterialIndex.append(Material[i]);
	}
	m_MaterialIndex.append(-1); // End of the face's material index
}
<|endoftext|>


<commit_before>#include "googledataresource.h"

#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>

extern "C" {
#include <gcalendar.h>
#include <gcontact.h>
#include <gcal_status.h>
}

using namespace Akonadi;

googledataResource::googledataResource( const QString &id )
	: ResourceBase( id )
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
						      Settings::self(), QDBusConnection::ExportAdaptors );

	if (!(gcal = gcal_new(GCONTACT)))
		exit(1);
	gcal_set_store_xml(gcal, 1);
}

googledataResource::~googledataResource()
{
	gcal_delete(gcal);
	gcal_cleanup_contacts(&all_contacts);
}

void googledataResource::retrieveCollections()
{
	// TODO: this method is called when Akonadi wants to have all the
	// collections your resource provides.
	// Be sure to set the remote ID and the content MIME types
}

void googledataResource::retrieveItems( const Akonadi::Collection &collection )
{
	Q_UNUSED( collection );

	Item::List items;
	int result;

	/* Downloading the contacts can be slow and it is blocking. Will
	 * it mess up with akonadi?
	 */
	if ((result = gcal_get_contacts(gcal, &all_contacts)))
		exit(1);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_contacts.length; ++i) {

		Item item(QLatin1String("what_is_the_mime_type?"));
		gcal_contact_t contact = gcal_contact_element(&all_contacts, i);
		item.setRemoteId(gcal_contact_get_id(contact));
	}

	itemsRetrieved(items);
}

bool googledataResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED( parts );
	const QString entry_id = item.remoteId();
	QString temp;
	/* I assume that here I can report the atom::entry data?
	 */
	Item newItem(item);
	gcal_contact_t contact;
	KABC::Addressee addressee;
	KABC::PhoneNumber number;

	/*
	 * And another question, are the requests in the same sequence that
	 * I informed in 'retrieveItems'? For while, I try to locate the entry...
	 */
	for (size_t i = 0; i < all_contacts.length; ++i) {
		contact = gcal_contact_element(&all_contacts, i);
		if (entry_id == gcal_contact_get_id(contact)) {
			/* name */
			temp = gcal_contact_get_title(contact);
			addressee.setNameFromString(temp);

			/* email */
			temp = gcal_contact_get_email(contact);
			addressee.insertEmail(temp, true);

			/* edit url: required to do edit/delete */
			temp = gcal_contact_get_url(contact);
			addressee.setUid(temp);

			/* TODO: add ETag/etc  on libgcal */

			newItem.setPayload<KABC::Addressee>(addressee);
			return true;
		}

	}

	return false;
}

void googledataResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void googledataResource::configure( WId windowId )
{
	Q_UNUSED( windowId );

	/* TODO:
	 * what kind of dialog to collect google acount username + password ?
	 */
	synchronize();
}

void googledataResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED( item );
	Q_UNUSED( collection );

	// TODO: this method is called when somebody else, e.g. a client application,
	// has created an item in a collection managed by your resource.

	// NOTE: There is an equivalent method for collections, but it isn't part
	// of this template code to keep it simple
}

void googledataResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED( item );
	Q_UNUSED( parts );

	// TODO: this method is called when somebody else, e.g. a client application,
	// has changed an item managed by your resource.

	// NOTE: There is an equivalent method for collections, but it isn't part
	// of this template code to keep it simple
}

void googledataResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED( item );

	// TODO: this method is called when somebody else, e.g. a client application,
	// has deleted an item managed by your resource.

	// NOTE: There is an equivalent method for collections, but it isn't part
	// of this template code to keep it simple
}

AKONADI_RESOURCE_MAIN( googledataResource )

#include "googledataresource.moc"
<commit_msg>Removing outdated comment.<commit_after>#include "googledataresource.h"

#include "settings.h"
#include "settingsadaptor.h"

#include <QtDBus/QDBusConnection>
#include <kabc/addressee.h>
#include <kabc/phonenumber.h>

extern "C" {
#include <gcalendar.h>
#include <gcontact.h>
#include <gcal_status.h>
}

using namespace Akonadi;

googledataResource::googledataResource( const QString &id )
	: ResourceBase( id )
{
	new SettingsAdaptor( Settings::self() );
	QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
						      Settings::self(), QDBusConnection::ExportAdaptors );

	if (!(gcal = gcal_new(GCONTACT)))
		exit(1);
	gcal_set_store_xml(gcal, 1);
}

googledataResource::~googledataResource()
{
	gcal_delete(gcal);
	gcal_cleanup_contacts(&all_contacts);
}

void googledataResource::retrieveCollections()
{
	// TODO: this method is called when Akonadi wants to have all the
	// collections your resource provides.
	// Be sure to set the remote ID and the content MIME types
}

void googledataResource::retrieveItems( const Akonadi::Collection &collection )
{
	Q_UNUSED( collection );

	Item::List items;
	int result;

	/* Downloading the contacts can be slow and it is blocking. Will
	 * it mess up with akonadi?
	 */
	if ((result = gcal_get_contacts(gcal, &all_contacts)))
		exit(1);

	/* Each google entry has a unique ID and edit_url */
	for (size_t i = 0; i < all_contacts.length; ++i) {

		Item item(QLatin1String("what_is_the_mime_type?"));
		gcal_contact_t contact = gcal_contact_element(&all_contacts, i);
		item.setRemoteId(gcal_contact_get_id(contact));
	}

	itemsRetrieved(items);
}

bool googledataResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED( parts );
	const QString entry_id = item.remoteId();
	QString temp;
	Item newItem(item);
	gcal_contact_t contact;
	KABC::Addressee addressee;
	KABC::PhoneNumber number;

	/*
	 * And another question, are the requests in the same sequence that
	 * I informed in 'retrieveItems'? For while, I try to locate the entry...
	 */
	for (size_t i = 0; i < all_contacts.length; ++i) {
		contact = gcal_contact_element(&all_contacts, i);
		if (entry_id == gcal_contact_get_id(contact)) {
			/* name */
			temp = gcal_contact_get_title(contact);
			addressee.setNameFromString(temp);

			/* email */
			temp = gcal_contact_get_email(contact);
			addressee.insertEmail(temp, true);

			/* edit url: required to do edit/delete */
			temp = gcal_contact_get_url(contact);
			addressee.setUid(temp);

			/* TODO: add ETag/etc  on libgcal */

			newItem.setPayload<KABC::Addressee>(addressee);
			return true;
		}

	}

	return false;
}

void googledataResource::aboutToQuit()
{
	// TODO: any cleanup you need to do while there is still an active
	// event loop. The resource will terminate after this method returns
}

void googledataResource::configure( WId windowId )
{
	Q_UNUSED( windowId );

	/* TODO:
	 * what kind of dialog to collect google acount username + password ?
	 */
	synchronize();
}

void googledataResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collection &collection )
{
	Q_UNUSED( item );
	Q_UNUSED( collection );

	// TODO: this method is called when somebody else, e.g. a client application,
	// has created an item in a collection managed by your resource.

	// NOTE: There is an equivalent method for collections, but it isn't part
	// of this template code to keep it simple
}

void googledataResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts )
{
	Q_UNUSED( item );
	Q_UNUSED( parts );

	// TODO: this method is called when somebody else, e.g. a client application,
	// has changed an item managed by your resource.

	// NOTE: There is an equivalent method for collections, but it isn't part
	// of this template code to keep it simple
}

void googledataResource::itemRemoved( const Akonadi::Item &item )
{
	Q_UNUSED( item );

	// TODO: this method is called when somebody else, e.g. a client application,
	// has deleted an item managed by your resource.

	// NOTE: There is an equivalent method for collections, but it isn't part
	// of this template code to keep it simple
}

AKONADI_RESOURCE_MAIN( googledataResource )

#include "googledataresource.moc"
<|endoftext|>


<commit_before>/*
 * file:   {{fun.name}}.cpp
 * author: A trusty code generator
 * date:   {{time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())}}
 *
 * This file was autogenerated, do not modify.
 * See LICENCE for full modification and redistribution details.
 * Copyright {{time.strftime("%Y", time.localtime())}} The OpenCV Foundation
 */
#include "mex.h"
#include "bridge.hpp"
#include <vector>
{% block includes %}
{% endblock %}

/*
 * {{ fun.name }}
 * Gateway routine
 *   nlhs - number of return arguments
 *   plhs - pointers to return arguments
 *   nrhs - number of input arguments
 *   prhs - pointers to input arguments
 */
void mexFunction(int nlhs, mxArray* plhs[],
                 int nrhs, const mxArray* prhs[]) {

  {% block argcheck %}
  {% endblock %}

  {% block prebridge %}
  {% endblock %}

  // parse the inputs and outputs

  {% block postbridge %}
  {% endblock %}

  // call the opencv function
  // [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn);
  {{fun.name}}();
  {% block fcall %}
  {% endblock %}

  {% block postfun %}
  {% endblock %}

  {% block cleanup %}
  {% endblock %}
}
<commit_msg>Improved exception handling in function template<commit_after>/*
 * file:   {{fun.name}}.cpp
 * author: A trusty code generator
 * date:   {{time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())}}
 *
 * This file was autogenerated, do not modify.
 * See LICENCE for full modification and redistribution details.
 * Copyright {{time.strftime("%Y", time.localtime())}} The OpenCV Foundation
 */
#include "mex.h"
#include "bridge.hpp"
#include <vector>
{% block includes %}
{% endblock %}

/*
 * {{ fun.name }}
 * Gateway routine
 *   nlhs - number of return arguments
 *   plhs - pointers to return arguments
 *   nrhs - number of input arguments
 *   prhs - pointers to input arguments
 */
void mexFunction(int nlhs, mxArray* plhs[],
                 int nrhs, const mxArray* prhs[]) {

  {% block argcheck %}
  {% endblock %}

  {% block prebridge %}
  {% endblock %}

  // parse the inputs and outputs

  {% block postbridge %}
  {% endblock %}

  // call the opencv function
  // [out =] namespace.fun(src1, ..., srcn, dst1, ..., dstn, opt1, ..., optn);
  try {
    {{fun.name}}();
  } catch(...) {
    mexErrMsgTxt("Uncaught exception occurred in {{fun.name}}");
  }
  {% block fcall %}
  {% endblock %}

  {% block postfun %}
  {% endblock %}

  {% block cleanup %}
  {% endblock %}
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/container/obstacles/obstacles_container.h"

#include <utility>
#include <unordered_set>

#include "modules/prediction/common/feature_output.h"
#include "modules/prediction/common/junction_analyzer.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_system_gflags.h"
#include "modules/prediction/container/obstacles/obstacle_clusters.h"

namespace apollo {
namespace prediction {

using apollo::perception::PerceptionObstacle;
using apollo::perception::PerceptionObstacles;

ObstaclesContainer::ObstaclesContainer()
    : obstacles_(FLAGS_max_num_obstacles),
      id_mapping_(FLAGS_max_num_obstacles) {}

// This is called by Perception module at every frame to insert all
// detected obstacles.
void ObstaclesContainer::Insert(const ::google::protobuf::Message& message) {
  // Clean up the history and get the PerceptionObstacles
  curr_frame_predictable_obstacle_ids_.clear();
  curr_frame_id_mapping_.clear();
  PerceptionObstacles perception_obstacles;
  perception_obstacles.CopyFrom(
      dynamic_cast<const PerceptionObstacles&>(message));

  // Get the new timestamp and update it in the class
  // - If it's more than 10sec later than the most recent one, clear the
  //   obstacle history.
  // - If it's not a valid time (earlier than history), continue.
  // - Also consider the offline_mode case.

  double timestamp = 0.0;
  if (perception_obstacles.has_header() &&
      perception_obstacles.header().has_timestamp_sec()) {
    timestamp = perception_obstacles.header().timestamp_sec();
  }
  if (std::fabs(timestamp - timestamp_) > FLAGS_replay_timestamp_gap) {
    obstacles_.Clear();
    ADEBUG << "Replay mode is enabled.";
  } else if (timestamp <= timestamp_) {
    AERROR << "Invalid timestamp curr [" << timestamp << "] v.s. prev ["
           << timestamp_ << "].";
    return;
  }
  if (FLAGS_prediction_offline_mode) {
    if (std::fabs(timestamp - timestamp_) > FLAGS_replay_timestamp_gap ||
        FeatureOutput::Size() > FLAGS_max_num_dump_feature) {
      FeatureOutput::Write();
    }
  }
  timestamp_ = timestamp;
  ADEBUG << "Current timestamp is [" << timestamp_ << "]";

  // Prediction tracking adaptation
  if (FLAGS_enable_tracking_adaptation) {
    BuildCurrentFrameIdMapping(perception_obstacles);
  }

  // Set up the ObstacleClusters:
  // 1. Initialize ObstacleClusters
  ObstacleClusters::Init();
  // 2. Insert the Obstacles one by one
  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    ADEBUG << "Perception obstacle [" << perception_obstacle.id() << "] "
           << "was detected";
    InsertPerceptionObstacle(perception_obstacle, timestamp_);
    ADEBUG << "Perception obstacle [" << perception_obstacle.id() << "] "
           << "was inserted";
  }
  // 3. Sort the Obstacles
  ObstacleClusters::SortObstacles();
  // 4. Deduct the NearbyObstacles info. from the sorted Obstacles
  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    if (IsPredictable(perception_obstacle)) {
      continue;
    }
    Obstacle* obstacle_ptr = GetObstacle(perception_obstacle.id());
    if (obstacle_ptr == nullptr) {
      continue;
    }
    obstacle_ptr->SetNearbyObstacles();
  }
}

Obstacle* ObstaclesContainer::GetObstacle(const int id) {
  return obstacles_.GetSilently(id);
}

const std::vector<int>&
ObstaclesContainer::GetCurrentFramePredictableObstacleIds() const {
  return curr_frame_predictable_obstacle_ids_;
}

void ObstaclesContainer::Clear() {
  obstacles_.Clear();
  id_mapping_.Clear();
  timestamp_ = -1.0;
}

void ObstaclesContainer::InsertPerceptionObstacle(
    const PerceptionObstacle& perception_obstacle, const double timestamp) {
  // Sanity checks.
  int prediction_id = perception_obstacle.id();
  if (curr_frame_id_mapping_.find(prediction_id) !=
      curr_frame_id_mapping_.end()) {
    prediction_id = curr_frame_id_mapping_[prediction_id];
    if (prediction_id != perception_obstacle.id()) {
      ADEBUG << "Obstacle have got AdaptTracking, with perception_id: "
             << perception_obstacle.id()
             << ", and prediction_id: " << prediction_id;
    }
  }
  if (prediction_id < -1) {
    AERROR << "Invalid ID [" << prediction_id << "]";
    return;
  }
  if (!IsPredictable(perception_obstacle)) {
    ADEBUG << "Perception obstacle [" << prediction_id
           << "] is not predictable.";
    return;
  }

  // Insert the obstacle and also update the LRUCache.
  curr_frame_predictable_obstacle_ids_.push_back(prediction_id);
  Obstacle* obstacle_ptr = obstacles_.Get(prediction_id);
  if (obstacle_ptr != nullptr) {
    obstacle_ptr->Insert(perception_obstacle, timestamp, prediction_id);
    ADEBUG << "Refresh obstacle [" << prediction_id << "]";
  } else {
    Obstacle obstacle;
    obstacle.Insert(perception_obstacle, timestamp, prediction_id);
    obstacles_.Put(prediction_id, std::move(obstacle));
    ADEBUG << "Insert obstacle [" << prediction_id << "]";
  }
}

void ObstaclesContainer::InsertFeatureProto(const Feature& feature) {
  if (!feature.has_id()) {
    AERROR << "Invalid feature, no ID found.";
    return;
  }
  int id = feature.id();
  Obstacle* obstacle_ptr = obstacles_.Get(id);
  if (obstacle_ptr != nullptr) {
    obstacle_ptr->InsertFeature(feature);
  } else {
    Obstacle obstacle;
    obstacle.InsertFeature(feature);
    obstacles_.Put(id, std::move(obstacle));
  }
}

void ObstaclesContainer::BuildCurrentFrameIdMapping(
    const PerceptionObstacles& perception_obstacles) {
  // Go through every obstacle in the current frame, after some
  // sanity checks, build current_frame_id_mapping for every obstacle

  std::unordered_set<int> seen_perception_ids;
  // Loop all precept_id and find those in obstacles_LRU
  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    int perception_id = perception_obstacle.id();
    if (GetObstacle(perception_id) != nullptr) {
      seen_perception_ids.insert(perception_id);
    }
  }

  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    int perception_id = perception_obstacle.id();
    curr_frame_id_mapping_[perception_id] = perception_id;
    if (seen_perception_ids.find(perception_id) != seen_perception_ids.end()) {
      // find this perception_id in LRUCache, treat it as a tracked obstacle
      continue;
    }
    std::unordered_set<int> seen_prediction_ids;
    int prediction_id = 0;
    if (id_mapping_.GetCopy(perception_id, &prediction_id)) {
      if (seen_perception_ids.find(prediction_id) ==
          seen_perception_ids.end()) {
        // find this perception_id in LRUMapping, map it to a tracked obstacle
        curr_frame_id_mapping_[perception_id] = prediction_id;
        seen_prediction_ids.insert(prediction_id);
      }
    } else {  // process adaption
      common::util::Node<int, Obstacle>* curr = obstacles_.First();
      while (curr != nullptr) {
        int obs_id = curr->key;
        curr = curr->next;
        if (seen_perception_ids.find(obs_id) != seen_perception_ids.end() ||
            seen_prediction_ids.find(obs_id) != seen_prediction_ids.end()) {
          // this obs_id has already been processed
          continue;
        }
        Obstacle* obstacle_ptr = obstacles_.GetSilently(obs_id);
        if (obstacle_ptr == nullptr) {
          AERROR << "Obstacle id [" << obs_id << "] with empty obstacle_ptr.";
          break;
        }
        if (timestamp_ - obstacle_ptr->timestamp() > FLAGS_max_tracking_time) {
          ADEBUG << "Obstacle already reach time threshold.";
          break;
        }
        if (AdaptTracking(perception_obstacle, obstacle_ptr)) {
          id_mapping_.Put(perception_id, obs_id);
          curr_frame_id_mapping_[perception_id] = obs_id;
          break;
        }
      }
    }
  }
}

void ObstaclesContainer::BuildLaneGraph() {
  // Go through every obstacle in the current frame, after some
  // sanity checks, build lane graph for non-junction cases.
  for (const int id : curr_frame_predictable_obstacle_ids_) {
    Obstacle* obstacle_ptr = obstacles_.GetSilently(id);
    if (obstacle_ptr == nullptr) {
      AERROR << "Null obstacle found.";
      continue;
    }
    if (obstacle_ptr->ToIgnore()) {
      ADEBUG << "Ignore obstacle [" << obstacle_ptr->id() << "]";
      continue;
    }
    obstacle_ptr->BuildLaneGraph();
  }
}

void ObstaclesContainer::BuildJunctionFeature() {
  // Go through every obstacle in the current frame, after some
  // sanit checks, build junction features for those that are in junction.
  for (const int id : curr_frame_predictable_obstacle_ids_) {
    Obstacle* obstacle_ptr = obstacles_.GetSilently(id);
    if (obstacle_ptr == nullptr) {
      AERROR << "Null obstacle found.";
      continue;
    }
    if (obstacle_ptr->ToIgnore()) {
      ADEBUG << "Ignore obstacle [" << obstacle_ptr->id() << "]";
      continue;
    }
    const std::string& junction_id = JunctionAnalyzer::GetJunctionId();
    if (obstacle_ptr->IsInJunction(junction_id)) {
      ADEBUG << "Build junction feature for obstacle [" << obstacle_ptr->id()
            << "] in junction [" << junction_id << "]";
      obstacle_ptr->BuildJunctionFeature();
    }
  }
}

bool ObstaclesContainer::AdaptTracking(
    const PerceptionObstacle& perception_obstacle, Obstacle* obstacle_ptr) {
  if (!perception_obstacle.has_type() ||
      perception_obstacle.type() != obstacle_ptr->type()) {
    // different obstacle type, can't be same obstacle
    return false;
  }
  // test perception_obstacle position with possible obstacle position
  if (perception_obstacle.has_position() &&
      perception_obstacle.position().has_x() &&
      perception_obstacle.position().has_y()) {
    double obs_x = obstacle_ptr->latest_feature().position().x() + (timestamp_ -
                   obstacle_ptr->latest_feature().timestamp()) *
                   obstacle_ptr->latest_feature().raw_velocity().x();
    double obs_y = obstacle_ptr->latest_feature().position().y() + (timestamp_ -
                   obstacle_ptr->latest_feature().timestamp()) *
                   obstacle_ptr->latest_feature().raw_velocity().y();
    double dist = std::hypot(perception_obstacle.position().x() - obs_x,
                             perception_obstacle.position().y() - obs_y);
    if (dist < FLAGS_max_tracking_dist) {
      return true;
    }
  }
  return false;
}

bool ObstaclesContainer::IsPredictable(
    const PerceptionObstacle& perception_obstacle) {
  if (!perception_obstacle.has_type() ||
      perception_obstacle.type() == PerceptionObstacle::UNKNOWN_UNMOVABLE) {
    return false;
  }
  return true;
}

}  // namespace prediction
}  // namespace apollo
<commit_msg>Prediction: treat latitude and longitude dist in TrackingAdaptation<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/container/obstacles/obstacles_container.h"

#include <utility>
#include <unordered_set>

#include "modules/prediction/common/feature_output.h"
#include "modules/prediction/common/junction_analyzer.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_system_gflags.h"
#include "modules/prediction/container/obstacles/obstacle_clusters.h"

namespace apollo {
namespace prediction {

using apollo::perception::PerceptionObstacle;
using apollo::perception::PerceptionObstacles;

ObstaclesContainer::ObstaclesContainer()
    : obstacles_(FLAGS_max_num_obstacles),
      id_mapping_(FLAGS_max_num_obstacles) {}

// This is called by Perception module at every frame to insert all
// detected obstacles.
void ObstaclesContainer::Insert(const ::google::protobuf::Message& message) {
  // Clean up the history and get the PerceptionObstacles
  curr_frame_predictable_obstacle_ids_.clear();
  curr_frame_id_mapping_.clear();
  PerceptionObstacles perception_obstacles;
  perception_obstacles.CopyFrom(
      dynamic_cast<const PerceptionObstacles&>(message));

  // Get the new timestamp and update it in the class
  // - If it's more than 10sec later than the most recent one, clear the
  //   obstacle history.
  // - If it's not a valid time (earlier than history), continue.
  // - Also consider the offline_mode case.

  double timestamp = 0.0;
  if (perception_obstacles.has_header() &&
      perception_obstacles.header().has_timestamp_sec()) {
    timestamp = perception_obstacles.header().timestamp_sec();
  }
  if (std::fabs(timestamp - timestamp_) > FLAGS_replay_timestamp_gap) {
    obstacles_.Clear();
    ADEBUG << "Replay mode is enabled.";
  } else if (timestamp <= timestamp_) {
    AERROR << "Invalid timestamp curr [" << timestamp << "] v.s. prev ["
           << timestamp_ << "].";
    return;
  }
  if (FLAGS_prediction_offline_mode) {
    if (std::fabs(timestamp - timestamp_) > FLAGS_replay_timestamp_gap ||
        FeatureOutput::Size() > FLAGS_max_num_dump_feature) {
      FeatureOutput::Write();
    }
  }
  timestamp_ = timestamp;
  ADEBUG << "Current timestamp is [" << timestamp_ << "]";

  // Prediction tracking adaptation
  if (FLAGS_enable_tracking_adaptation) {
    BuildCurrentFrameIdMapping(perception_obstacles);
  }

  // Set up the ObstacleClusters:
  // 1. Initialize ObstacleClusters
  ObstacleClusters::Init();
  // 2. Insert the Obstacles one by one
  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    ADEBUG << "Perception obstacle [" << perception_obstacle.id() << "] "
           << "was detected";
    InsertPerceptionObstacle(perception_obstacle, timestamp_);
    ADEBUG << "Perception obstacle [" << perception_obstacle.id() << "] "
           << "was inserted";
  }
  // 3. Sort the Obstacles
  ObstacleClusters::SortObstacles();
  // 4. Deduct the NearbyObstacles info. from the sorted Obstacles
  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    if (IsPredictable(perception_obstacle)) {
      continue;
    }
    Obstacle* obstacle_ptr = GetObstacle(perception_obstacle.id());
    if (obstacle_ptr == nullptr) {
      continue;
    }
    obstacle_ptr->SetNearbyObstacles();
  }
}

Obstacle* ObstaclesContainer::GetObstacle(const int id) {
  return obstacles_.GetSilently(id);
}

const std::vector<int>&
ObstaclesContainer::GetCurrentFramePredictableObstacleIds() const {
  return curr_frame_predictable_obstacle_ids_;
}

void ObstaclesContainer::Clear() {
  obstacles_.Clear();
  id_mapping_.Clear();
  timestamp_ = -1.0;
}

void ObstaclesContainer::InsertPerceptionObstacle(
    const PerceptionObstacle& perception_obstacle, const double timestamp) {
  // Sanity checks.
  int prediction_id = perception_obstacle.id();
  if (curr_frame_id_mapping_.find(prediction_id) !=
      curr_frame_id_mapping_.end()) {
    prediction_id = curr_frame_id_mapping_[prediction_id];
    if (prediction_id != perception_obstacle.id()) {
      ADEBUG << "Obstacle have got AdaptTracking, with perception_id: "
             << perception_obstacle.id()
             << ", and prediction_id: " << prediction_id;
    }
  }
  if (prediction_id < -1) {
    AERROR << "Invalid ID [" << prediction_id << "]";
    return;
  }
  if (!IsPredictable(perception_obstacle)) {
    ADEBUG << "Perception obstacle [" << prediction_id
           << "] is not predictable.";
    return;
  }

  // Insert the obstacle and also update the LRUCache.
  curr_frame_predictable_obstacle_ids_.push_back(prediction_id);
  Obstacle* obstacle_ptr = obstacles_.Get(prediction_id);
  if (obstacle_ptr != nullptr) {
    obstacle_ptr->Insert(perception_obstacle, timestamp, prediction_id);
    ADEBUG << "Refresh obstacle [" << prediction_id << "]";
  } else {
    Obstacle obstacle;
    obstacle.Insert(perception_obstacle, timestamp, prediction_id);
    obstacles_.Put(prediction_id, std::move(obstacle));
    ADEBUG << "Insert obstacle [" << prediction_id << "]";
  }
}

void ObstaclesContainer::InsertFeatureProto(const Feature& feature) {
  if (!feature.has_id()) {
    AERROR << "Invalid feature, no ID found.";
    return;
  }
  int id = feature.id();
  Obstacle* obstacle_ptr = obstacles_.Get(id);
  if (obstacle_ptr != nullptr) {
    obstacle_ptr->InsertFeature(feature);
  } else {
    Obstacle obstacle;
    obstacle.InsertFeature(feature);
    obstacles_.Put(id, std::move(obstacle));
  }
}

void ObstaclesContainer::BuildCurrentFrameIdMapping(
    const PerceptionObstacles& perception_obstacles) {
  // Go through every obstacle in the current frame, after some
  // sanity checks, build current_frame_id_mapping for every obstacle

  std::unordered_set<int> seen_perception_ids;
  // Loop all precept_id and find those in obstacles_LRU
  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    int perception_id = perception_obstacle.id();
    if (GetObstacle(perception_id) != nullptr) {
      seen_perception_ids.insert(perception_id);
    }
  }

  for (const PerceptionObstacle& perception_obstacle :
       perception_obstacles.perception_obstacle()) {
    int perception_id = perception_obstacle.id();
    curr_frame_id_mapping_[perception_id] = perception_id;
    if (seen_perception_ids.find(perception_id) != seen_perception_ids.end()) {
      // find this perception_id in LRUCache, treat it as a tracked obstacle
      continue;
    }
    std::unordered_set<int> seen_prediction_ids;
    int prediction_id = 0;
    if (id_mapping_.GetCopy(perception_id, &prediction_id)) {
      if (seen_perception_ids.find(prediction_id) ==
          seen_perception_ids.end()) {
        // find this perception_id in LRUMapping, map it to a tracked obstacle
        curr_frame_id_mapping_[perception_id] = prediction_id;
        seen_prediction_ids.insert(prediction_id);
      }
    } else {  // process adaption
      common::util::Node<int, Obstacle>* curr = obstacles_.First();
      while (curr != nullptr) {
        int obs_id = curr->key;
        curr = curr->next;
        if (obs_id < 0 ||
            seen_perception_ids.find(obs_id) != seen_perception_ids.end() ||
            seen_prediction_ids.find(obs_id) != seen_prediction_ids.end()) {
          // this obs_id has already been processed
          continue;
        }
        Obstacle* obstacle_ptr = obstacles_.GetSilently(obs_id);
        if (obstacle_ptr == nullptr) {
          AERROR << "Obstacle id [" << obs_id << "] with empty obstacle_ptr.";
          break;
        }
        if (timestamp_ - obstacle_ptr->timestamp() > FLAGS_max_tracking_time) {
          ADEBUG << "Obstacle already reach time threshold.";
          break;
        }
        if (AdaptTracking(perception_obstacle, obstacle_ptr)) {
          id_mapping_.Put(perception_id, obs_id);
          curr_frame_id_mapping_[perception_id] = obs_id;
          break;
        }
      }
    }
  }
}

void ObstaclesContainer::BuildLaneGraph() {
  // Go through every obstacle in the current frame, after some
  // sanity checks, build lane graph for non-junction cases.
  for (const int id : curr_frame_predictable_obstacle_ids_) {
    Obstacle* obstacle_ptr = obstacles_.GetSilently(id);
    if (obstacle_ptr == nullptr) {
      AERROR << "Null obstacle found.";
      continue;
    }
    if (obstacle_ptr->ToIgnore()) {
      ADEBUG << "Ignore obstacle [" << obstacle_ptr->id() << "]";
      continue;
    }
    obstacle_ptr->BuildLaneGraph();
  }
}

void ObstaclesContainer::BuildJunctionFeature() {
  // Go through every obstacle in the current frame, after some
  // sanit checks, build junction features for those that are in junction.
  for (const int id : curr_frame_predictable_obstacle_ids_) {
    Obstacle* obstacle_ptr = obstacles_.GetSilently(id);
    if (obstacle_ptr == nullptr) {
      AERROR << "Null obstacle found.";
      continue;
    }
    if (obstacle_ptr->ToIgnore()) {
      ADEBUG << "Ignore obstacle [" << obstacle_ptr->id() << "]";
      continue;
    }
    const std::string& junction_id = JunctionAnalyzer::GetJunctionId();
    if (obstacle_ptr->IsInJunction(junction_id)) {
      ADEBUG << "Build junction feature for obstacle [" << obstacle_ptr->id()
            << "] in junction [" << junction_id << "]";
      obstacle_ptr->BuildJunctionFeature();
    }
  }
}

bool ObstaclesContainer::AdaptTracking(
    const PerceptionObstacle& perception_obstacle, Obstacle* obstacle_ptr) {
  if (!perception_obstacle.has_type() ||
      perception_obstacle.type() != obstacle_ptr->type()) {
    // different obstacle type, can't be same obstacle
    return false;
  }
  // test perception_obstacle position with possible obstacle position
  if (perception_obstacle.has_position() &&
      perception_obstacle.position().has_x() &&
      perception_obstacle.position().has_y()) {
    double obs_x = obstacle_ptr->latest_feature().position().x() + (timestamp_ -
                   obstacle_ptr->latest_feature().timestamp()) *
                   obstacle_ptr->latest_feature().raw_velocity().x();
    double obs_y = obstacle_ptr->latest_feature().position().y() + (timestamp_ -
                   obstacle_ptr->latest_feature().timestamp()) *
                   obstacle_ptr->latest_feature().raw_velocity().y();
    double v_heading = std::atan2(
        obstacle_ptr->latest_feature().raw_velocity().y(),
        obstacle_ptr->latest_feature().raw_velocity().x());
    double dist_x = perception_obstacle.position().x() - obs_x;
    double dist_y = perception_obstacle.position().y() - obs_y;
    double dist = std::hypot(dist_x, dist_y);
    double angle = std::atan2(dist_y, dist_x) - v_heading;
    if (std::abs(dist * std::cos(angle)) < FLAGS_max_tracking_dist &&
        std::abs(dist * std::sin(angle)) < FLAGS_max_tracking_dist / 3) {
      return true;
    }
  }
  return false;
}

bool ObstaclesContainer::IsPredictable(
    const PerceptionObstacle& perception_obstacle) {
  if (!perception_obstacle.has_type() ||
      perception_obstacle.type() == PerceptionObstacle::UNKNOWN_UNMOVABLE) {
    return false;
  }
  return true;
}

}  // namespace prediction
}  // namespace apollo
<|endoftext|>


<commit_before>/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Jochen Thaeder <thaeder@kip.uni-heidelberg.de>        *
 *                  Sebastian Bablok                                      *
 *                  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   AliHLTCalibrationProcessor.cxx
 * @author Jochen Thaeder, Sebastian Bablok
 * @date
 * @brief  Base class of HLT calibration components.  */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#if __GNUC__ >= 3
using namespace std;
#endif

#include "AliHLTCalibrationProcessor.h"
#include "AliHLTMemoryFile.h"

#include <cstdlib>
#include <cerrno>
#include <string.h>
#include <TObjString.h>
#include <TFile.h>

ClassImp(AliHLTCalibrationProcessor);

const AliHLTUInt32_t AliHLTCalibrationProcessor::fgkFXSProtocolHeaderSize = 204;
const AliHLTUInt32_t AliHLTCalibrationProcessor::fgkFXSProtocolHeaderVersion = 1;

/*
 * ################ Constructor / Destructor ####################
 */

AliHLTCalibrationProcessor::AliHLTCalibrationProcessor() :
  fEventModulo(0),
  fUseCorruptEvents(kFALSE),
  fEventCounter(0),
  fDDLNumber(),
  fDummy(0) {

  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

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

/*
 * ######################## InitCalibration #####################
 */

Int_t AliHLTCalibrationProcessor::DoInit( int argc, const char** argv ) {
  // see header file for class documentation

  Int_t iResult = 0;
  TString argument = "";
  TString parameter = "";
  Int_t bMissingParam=0;

  for ( Int_t ii=0; ii<argc && iResult>=0; ii++ ) {
    argument = argv[ii];

    if ( argument.IsNull() ) continue;

    // -eventmodulo
    if ( argument.CompareTo("-eventmodulo") == 0 ) {
      if ( ( bMissingParam=( ++ii >= argc ) ) ) break;
      parameter = argv[ii];
      parameter.Remove(TString::kLeading, ' '); // remove all blanks
      if (parameter.IsDigit()) {
	fEventModulo = parameter.Atoi();
	HLTInfo("EventModulo is set to %d.", fEventModulo);
      }
      else {
	HLTError("Cannot convert EventModulo specifier '%s'.", argv[ii]);
	iResult = -EINVAL;
	break;
      }
    }
    // -usecorruptevents
    else if ( argument.CompareTo( "-usecorruptevents" ) == 0 ) {
      HLTInfo( "Passing through of corrupted events enabled." );
      fUseCorruptEvents = kTRUE;
    }
    // not known by calibration processor
    else {
      if ( ( iResult = ScanArgument( argc-ii, &argv[ii] ) ) == -EINVAL ) {
	HLTError( "unknown argument %s", argument.Data() );
	break;
      }
      else if ( iResult == -EPROTO ) {
	bMissingParam = 1;
	break;
      }
      else if ( iResult >= 0 ) {
	ii += iResult;
	iResult = 0;
      }
    }
  }

  if ( bMissingParam ) {
    HLTError( "missing parameter for argument %s", argument.Data() );
    iResult = -EPROTO;
  }

  if ( iResult >= 0 ) {
    iResult = InitCalibration();
  }

  return iResult;
}

Int_t AliHLTCalibrationProcessor::InitCalibration() {
  // see header file for class documentation

  // fDummy is just touched here to avoid coding convention violation RC11.
  // The function can not be declared  const since it is just the default implementation,
  // overloaded virtual function might not be const.
  fDummy = 0;

  return 0;
}

Int_t AliHLTCalibrationProcessor::ScanArgument(int argc, const char** argv) {
  // see header file for class documentation

  // there are no other arguments than the standard ones
  if ( argc == 0 && argv == NULL) {
    // this is just to get rid of the warning "unused parameter"
  }

  // fDummy is just touched here to avoid coding convention violation RC11.
  // The function can not be declared  const since it is just the default implementation,
  // overloaded virtual function might not be const.
  fDummy = 0;

  return -EINVAL;
}

/*
 * ######################## DeinitCalibration #####################
 */

Int_t AliHLTCalibrationProcessor::DoDeinit() {
  // see header file for class documentation

  int iResult = DeinitCalibration();

  return iResult;
}

Int_t AliHLTCalibrationProcessor::DeinitCalibration() {
  // see header file for class documentation

  // fDummy is just touched here to avoid coding convention violation RC11.
  // The function can not be declared  const since it is just the default implementation,
  // overloaded virtual function might not be const.
  fDummy = 0;

  return 0;
}

/*
 * ######################## DoEvent #####################
 */

Int_t AliHLTCalibrationProcessor::DoEvent( const AliHLTComponentEventData& evtData,
	       const AliHLTComponentBlockData* blocks,
	       AliHLTComponentTriggerData& trigData,
	       AliHLTUInt8_t* outputPtr,
	       AliHLTUInt32_t& size,
	       vector<AliHLTComponentBlockData>& outputBlocks )
{
  // see header file for class documentation

  Int_t iResult = 0;
  const AliHLTComponentBlockData* iter = NULL;

  const AliHLTComponentBlockData* blkSOR = NULL;
  const AliHLTComponentBlockData* blkEOR = NULL;
  const AliHLTComponentBlockData* blkDDL = NULL;

  HLTInfo( "Event ID: %lu", evtData.fEventID );

  // ---------------  START OF RUN -----------------
  blkSOR = GetFirstInputBlock( kAliHLTDataTypeSOR );

  // ----------------  END OF RUN ------------------
  blkEOR = GetFirstInputBlock( kAliHLTDataTypeEOR );

  // --------------  GET DDLNumber -----------------
  blkDDL = GetFirstInputBlock( kAliHLTDataTypeDDL );

  if ( blkDDL ) {
    HLTInfo("DDLLIST block received, size: %u", iter->fSize );
    //AliHLTEventDDL ddlList = ( AliHLTEventDDL* ) iter->fPtr;
  }

  // ------------ decide which event type ----------

  // - if event Type is not SOR or EOR -> process data
  if ( ! blkEOR  && !blkSOR ) {
    iResult = ProcessCalibration( evtData, blocks, trigData, outputPtr, size, outputBlocks );
    fEventCounter++;
  }

  // - if event Type is EOR or event modulo is set -> ship data to FXS
  // - use event modulo ship data also during the run
  if ( ( fEventModulo > 0 && fEventCounter == fEventModulo ) || blkEOR ){
    HLTDebug ( "Ship Data to FXS!" );
    iResult = ShipDataToFXS( evtData, blocks, trigData, outputPtr, size, outputBlocks );
    fEventCounter = 0;
  }

  return iResult;
}

/*
 * ######################## ProcessCalibration #####################
 */

Int_t AliHLTCalibrationProcessor::ProcessCalibration( const AliHLTComponentEventData& evtData,
						      const AliHLTComponentBlockData* /*blocks*/,
						      AliHLTComponentTriggerData& trigData,
						      AliHLTUInt8_t* /*outputPtr*/,
						      AliHLTUInt32_t& /*size*/,
						      vector<AliHLTComponentBlockData>& /*outputBlocks*/ ) {
  // see header file for class documentation

  // we just forward to the high level method, all other parameters already
  // have been stored internally
  return ProcessCalibration( evtData, trigData );
}

Int_t AliHLTCalibrationProcessor::ProcessCalibration( const AliHLTComponentEventData& /*evtData*/,
						      AliHLTComponentTriggerData& /*trigData*/) {
  // see header file for class documentation

  HLTFatal( "no processing method implemented" );
  return -ENOSYS;
}

/*
 * ######################## ShipDataToFXS #####################
 */

Int_t AliHLTCalibrationProcessor::ShipDataToFXS( const AliHLTComponentEventData& evtData,
						 const AliHLTComponentBlockData* /*blocks*/,
						 AliHLTComponentTriggerData& trigData,
						 AliHLTUInt8_t* /*outputPtr*/,
						 AliHLTUInt32_t& /*size*/,
						 vector<AliHLTComponentBlockData>& /*outputBlocks*/ ) {
  // see header file for class documentation

  // we just forward to the high level method, all other parameters already
  // have been stored internally
  return ShipDataToFXS( evtData, trigData );
}

Int_t AliHLTCalibrationProcessor::ShipDataToFXS( const AliHLTComponentEventData& /*evtData*/,
						 AliHLTComponentTriggerData& /*trigData*/) {
  // see header file for class documentation

  HLTFatal( "no processing method implemented" );
  return -ENOSYS;
}

/*
 * ######################## CreateFXSHeader #####################
 */

Int_t AliHLTCalibrationProcessor::CreateFXSHeader( AliHLTFXSHeader &pHeader, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {
  // see header file for class documentation

  Int_t iResult = 0;

  AliHLTUInt32_t runNumber = GetRunNo();         //  debug : 2176;

  HLTDebug( "RunNumber = %d", runNumber );

  /* STILL TO BE DONE .. but interface fixed   */

  //  if ( pDDLNumber  != "" ) {
  char ddltmp[5] = "4444";
  strncpy ( fDDLNumber, ddltmp, gkAliHLTFXSHeaderfDDLNumberSize );
  //}
  //else {
  //strncpy ( fDDLNumber, pDDLNumber, gkAliHLTFXSHeaderfDDLNumberSize );
  //}

  fDDLNumber[gkAliHLTFXSHeaderfDDLNumberSize] = 0;

  // -- Fill Header

  // Fill header version
  pHeader.fHeaderVersion = AliHLTCalibrationProcessor::fgkFXSProtocolHeaderVersion;

  // Fill run number
  pHeader.fRunNumber = runNumber;

  // Fill origin
  HLTDebug( "FXS Header Detector  size max %i - actual %i .",gkAliHLTFXSHeaderfOriginSize, strlen( pDetector ) );
  strncpy ( pHeader.fOrigin, pDetector, gkAliHLTFXSHeaderfOriginSize ) ;

  // To take care if fileIDs which are longer than gkAliHLTFXSHeaderfOriginSize, write one 0 is cheaper than an if.
  pHeader.fOrigin[gkAliHLTFXSHeaderfOriginSize] = 0;

  // Fill file ID
  HLTInfo( "FXS Header FileID size max %i - actual %i .",gkAliHLTFXSHeaderfFileIDSize, strlen( pFileID ) );
  strncpy ( pHeader.fFileID, pFileID, gkAliHLTFXSHeaderfFileIDSize ) ;

  // To take care if fileIDs which are longer than gkAliHLTFXSHeaderfFileIDSize, write one 0 is cheaper than an if.
  pHeader.fFileID[gkAliHLTFXSHeaderfFileIDSize] = 0;

  // Fill DDL number
  HLTInfo( "FXS Header DDLNumber size max %i - actual %i .", gkAliHLTFXSHeaderfDDLNumberSize, strlen( pDDLNumber ) );
  strncpy ( pHeader.fDDLNumber, fDDLNumber, gkAliHLTFXSHeaderfDDLNumberSize) ;

  // To take care if DDLNumber which are longer than gkAliHLTFXSHeaderfDDLNumberSize, write one 0 is cheaper than an if.
  pHeader.fDDLNumber[gkAliHLTFXSHeaderfDDLNumberSize] = 0;

  return iResult;
}  // Int_t AliHLTCalibrationProcessor::CreateFXSHeader( AliHLTXSHeader &pHeader, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {

/*
 * ######################## PushToFXS #####################
 */

Int_t AliHLTCalibrationProcessor::PushToFXS(TObject* pObject, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {
  // see header file for class documentation

  Int_t iResult = 0;

  AliHLTFXSHeader pHeader;

  CreateFXSHeader( pHeader, pDetector, pFileID, pDDLNumber );

  if ( pObject ) {

    AliHLTMemoryFile* pMemFile = CreateMemoryFile( kAliHLTDataTypeFXSCalib, kAliHLTVoidDataSpec );
    if ( pMemFile ) {

      iResult = pMemFile->WriteHeaderBuffer( (const char*) &pHeader, AliHLTCalibrationProcessor::fgkFXSProtocolHeaderSize );

      if ( iResult ) {
	HLTError( "Buffer size to small - for header!" );
      }
      else {
	iResult = Write( pMemFile, pObject );
	if ( !iResult ) {
	  HLTError( "Buffer size to small - for data!" );
	}
	else {
	  iResult = CloseMemoryFile( pMemFile );
	}
      }
    }
    else {
      iResult = -ENOMEM;
    }
  }
  else {
    iResult=-EINVAL;
  }

  return iResult;

} // Int_t AliHLTCalibrationProcessor::PushToFXS(TObject* pObject, const char* detector, const char* pFileID, const char* pDDLNumber ) {

Int_t AliHLTCalibrationProcessor::PushToFXS( void* pBuffer, int iSize, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {
  // see header file for class documentation

  Int_t iResult = 0;

  AliHLTFXSHeader pHeader;

  CreateFXSHeader( pHeader, pDetector, pFileID, pDDLNumber );

  iResult = PushBack( pBuffer, iSize, kAliHLTDataTypeFXSCalib, kAliHLTVoidDataSpec, (void*) (&pHeader), AliHLTCalibrationProcessor::fgkFXSProtocolHeaderSize );

  return iResult;

} // Int_t AliHLTCalibrationProcessor::PushToFXS(void* pBuffer, int iSize, const char* pDdetector, const char* pFileID, const char* pDDLNumber = "") {

<commit_msg>bugfix: crash when receiving a DDL List block<commit_after>/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Jochen Thaeder <thaeder@kip.uni-heidelberg.de>        *
 *                  Sebastian Bablok                                      *
 *                  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   AliHLTCalibrationProcessor.cxx
 * @author Jochen Thaeder, Sebastian Bablok
 * @date
 * @brief  Base class of HLT calibration components.  */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#if __GNUC__ >= 3
using namespace std;
#endif

#include "AliHLTCalibrationProcessor.h"
#include "AliHLTMemoryFile.h"

#include <cstdlib>
#include <cerrno>
#include <string.h>
#include <TObjString.h>
#include <TFile.h>

ClassImp(AliHLTCalibrationProcessor);

const AliHLTUInt32_t AliHLTCalibrationProcessor::fgkFXSProtocolHeaderSize = 204;
const AliHLTUInt32_t AliHLTCalibrationProcessor::fgkFXSProtocolHeaderVersion = 1;

/*
 * ################ Constructor / Destructor ####################
 */

AliHLTCalibrationProcessor::AliHLTCalibrationProcessor() :
  fEventModulo(0),
  fUseCorruptEvents(kFALSE),
  fEventCounter(0),
  fDDLNumber(),
  fDummy(0) {

  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

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

/*
 * ######################## InitCalibration #####################
 */

Int_t AliHLTCalibrationProcessor::DoInit( int argc, const char** argv ) {
  // see header file for class documentation

  Int_t iResult = 0;
  TString argument = "";
  TString parameter = "";
  Int_t bMissingParam=0;

  for ( Int_t ii=0; ii<argc && iResult>=0; ii++ ) {
    argument = argv[ii];

    if ( argument.IsNull() ) continue;

    // -eventmodulo
    if ( argument.CompareTo("-eventmodulo") == 0 ) {
      if ( ( bMissingParam=( ++ii >= argc ) ) ) break;
      parameter = argv[ii];
      parameter.Remove(TString::kLeading, ' '); // remove all blanks
      if (parameter.IsDigit()) {
	fEventModulo = parameter.Atoi();
	HLTInfo("EventModulo is set to %d.", fEventModulo);
      }
      else {
	HLTError("Cannot convert EventModulo specifier '%s'.", argv[ii]);
	iResult = -EINVAL;
	break;
      }
    }
    // -usecorruptevents
    else if ( argument.CompareTo( "-usecorruptevents" ) == 0 ) {
      HLTInfo( "Passing through of corrupted events enabled." );
      fUseCorruptEvents = kTRUE;
    }
    // not known by calibration processor
    else {
      if ( ( iResult = ScanArgument( argc-ii, &argv[ii] ) ) == -EINVAL ) {
	HLTError( "unknown argument %s", argument.Data() );
	break;
      }
      else if ( iResult == -EPROTO ) {
	bMissingParam = 1;
	break;
      }
      else if ( iResult >= 0 ) {
	ii += iResult;
	iResult = 0;
      }
    }
  }

  if ( bMissingParam ) {
    HLTError( "missing parameter for argument %s", argument.Data() );
    iResult = -EPROTO;
  }

  if ( iResult >= 0 ) {
    iResult = InitCalibration();
  }

  return iResult;
}

Int_t AliHLTCalibrationProcessor::InitCalibration() {
  // see header file for class documentation

  // fDummy is just touched here to avoid coding convention violation RC11.
  // The function can not be declared  const since it is just the default implementation,
  // overloaded virtual function might not be const.
  fDummy = 0;

  return 0;
}

Int_t AliHLTCalibrationProcessor::ScanArgument(int argc, const char** argv) {
  // see header file for class documentation

  // there are no other arguments than the standard ones
  if ( argc == 0 && argv == NULL) {
    // this is just to get rid of the warning "unused parameter"
  }

  // fDummy is just touched here to avoid coding convention violation RC11.
  // The function can not be declared  const since it is just the default implementation,
  // overloaded virtual function might not be const.
  fDummy = 0;

  return -EINVAL;
}

/*
 * ######################## DeinitCalibration #####################
 */

Int_t AliHLTCalibrationProcessor::DoDeinit() {
  // see header file for class documentation

  int iResult = DeinitCalibration();

  return iResult;
}

Int_t AliHLTCalibrationProcessor::DeinitCalibration() {
  // see header file for class documentation

  // fDummy is just touched here to avoid coding convention violation RC11.
  // The function can not be declared  const since it is just the default implementation,
  // overloaded virtual function might not be const.
  fDummy = 0;

  return 0;
}

/*
 * ######################## DoEvent #####################
 */

Int_t AliHLTCalibrationProcessor::DoEvent( const AliHLTComponentEventData& evtData,
	       const AliHLTComponentBlockData* blocks,
	       AliHLTComponentTriggerData& trigData,
	       AliHLTUInt8_t* outputPtr,
	       AliHLTUInt32_t& size,
	       vector<AliHLTComponentBlockData>& outputBlocks )
{
  // see header file for class documentation

  Int_t iResult = 0;

  const AliHLTComponentBlockData* blkSOR = NULL;
  const AliHLTComponentBlockData* blkEOR = NULL;
  const AliHLTComponentBlockData* blkDDL = NULL;

  HLTInfo( "Event ID: %lu", evtData.fEventID );

  // ---------------  START OF RUN -----------------
  blkSOR = GetFirstInputBlock( kAliHLTDataTypeSOR );

  // ----------------  END OF RUN ------------------
  blkEOR = GetFirstInputBlock( kAliHLTDataTypeEOR );

  // --------------  GET DDLNumber -----------------
  blkDDL = GetFirstInputBlock( kAliHLTDataTypeDDL );

  if ( blkDDL ) {
    HLTInfo("DDLLIST block received, size: %u", blkDDL->fSize );
    //AliHLTEventDDL ddlList = ( AliHLTEventDDL* ) iter->fPtr;
  }

  // ------------ decide which event type ----------

  // - if event Type is not SOR or EOR -> process data
  if ( ! blkEOR  && !blkSOR ) {
    iResult = ProcessCalibration( evtData, blocks, trigData, outputPtr, size, outputBlocks );
    fEventCounter++;
  }

  // - if event Type is EOR or event modulo is set -> ship data to FXS
  // - use event modulo ship data also during the run
  if ( ( fEventModulo > 0 && fEventCounter == fEventModulo ) || blkEOR ){
    HLTDebug ( "Ship Data to FXS!" );
    iResult = ShipDataToFXS( evtData, blocks, trigData, outputPtr, size, outputBlocks );
    fEventCounter = 0;
  }

  return iResult;
}

/*
 * ######################## ProcessCalibration #####################
 */

Int_t AliHLTCalibrationProcessor::ProcessCalibration( const AliHLTComponentEventData& evtData,
						      const AliHLTComponentBlockData* /*blocks*/,
						      AliHLTComponentTriggerData& trigData,
						      AliHLTUInt8_t* /*outputPtr*/,
						      AliHLTUInt32_t& /*size*/,
						      vector<AliHLTComponentBlockData>& /*outputBlocks*/ ) {
  // see header file for class documentation

  // we just forward to the high level method, all other parameters already
  // have been stored internally
  return ProcessCalibration( evtData, trigData );
}

Int_t AliHLTCalibrationProcessor::ProcessCalibration( const AliHLTComponentEventData& /*evtData*/,
						      AliHLTComponentTriggerData& /*trigData*/) {
  // see header file for class documentation

  HLTFatal( "no processing method implemented" );
  return -ENOSYS;
}

/*
 * ######################## ShipDataToFXS #####################
 */

Int_t AliHLTCalibrationProcessor::ShipDataToFXS( const AliHLTComponentEventData& evtData,
						 const AliHLTComponentBlockData* /*blocks*/,
						 AliHLTComponentTriggerData& trigData,
						 AliHLTUInt8_t* /*outputPtr*/,
						 AliHLTUInt32_t& /*size*/,
						 vector<AliHLTComponentBlockData>& /*outputBlocks*/ ) {
  // see header file for class documentation

  // we just forward to the high level method, all other parameters already
  // have been stored internally
  return ShipDataToFXS( evtData, trigData );
}

Int_t AliHLTCalibrationProcessor::ShipDataToFXS( const AliHLTComponentEventData& /*evtData*/,
						 AliHLTComponentTriggerData& /*trigData*/) {
  // see header file for class documentation

  HLTFatal( "no processing method implemented" );
  return -ENOSYS;
}

/*
 * ######################## CreateFXSHeader #####################
 */

Int_t AliHLTCalibrationProcessor::CreateFXSHeader( AliHLTFXSHeader &pHeader, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {
  // see header file for class documentation

  Int_t iResult = 0;

  AliHLTUInt32_t runNumber = GetRunNo();         //  debug : 2176;

  HLTDebug( "RunNumber = %d", runNumber );

  /* STILL TO BE DONE .. but interface fixed   */

  //  if ( pDDLNumber  != "" ) {
  char ddltmp[5] = "4444";
  strncpy ( fDDLNumber, ddltmp, gkAliHLTFXSHeaderfDDLNumberSize );
  //}
  //else {
  //strncpy ( fDDLNumber, pDDLNumber, gkAliHLTFXSHeaderfDDLNumberSize );
  //}

  fDDLNumber[gkAliHLTFXSHeaderfDDLNumberSize] = 0;

  // -- Fill Header

  // Fill header version
  pHeader.fHeaderVersion = AliHLTCalibrationProcessor::fgkFXSProtocolHeaderVersion;

  // Fill run number
  pHeader.fRunNumber = runNumber;

  // Fill origin
  HLTDebug( "FXS Header Detector  size max %i - actual %i .",gkAliHLTFXSHeaderfOriginSize, strlen( pDetector ) );
  strncpy ( pHeader.fOrigin, pDetector, gkAliHLTFXSHeaderfOriginSize ) ;

  // To take care if fileIDs which are longer than gkAliHLTFXSHeaderfOriginSize, write one 0 is cheaper than an if.
  pHeader.fOrigin[gkAliHLTFXSHeaderfOriginSize] = 0;

  // Fill file ID
  HLTInfo( "FXS Header FileID size max %i - actual %i .",gkAliHLTFXSHeaderfFileIDSize, strlen( pFileID ) );
  strncpy ( pHeader.fFileID, pFileID, gkAliHLTFXSHeaderfFileIDSize ) ;

  // To take care if fileIDs which are longer than gkAliHLTFXSHeaderfFileIDSize, write one 0 is cheaper than an if.
  pHeader.fFileID[gkAliHLTFXSHeaderfFileIDSize] = 0;

  // Fill DDL number
  HLTInfo( "FXS Header DDLNumber size max %i - actual %i .", gkAliHLTFXSHeaderfDDLNumberSize, strlen( pDDLNumber ) );
  strncpy ( pHeader.fDDLNumber, fDDLNumber, gkAliHLTFXSHeaderfDDLNumberSize) ;

  // To take care if DDLNumber which are longer than gkAliHLTFXSHeaderfDDLNumberSize, write one 0 is cheaper than an if.
  pHeader.fDDLNumber[gkAliHLTFXSHeaderfDDLNumberSize] = 0;

  return iResult;
}  // Int_t AliHLTCalibrationProcessor::CreateFXSHeader( AliHLTXSHeader &pHeader, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {

/*
 * ######################## PushToFXS #####################
 */

Int_t AliHLTCalibrationProcessor::PushToFXS(TObject* pObject, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {
  // see header file for class documentation

  Int_t iResult = 0;

  AliHLTFXSHeader pHeader;

  CreateFXSHeader( pHeader, pDetector, pFileID, pDDLNumber );

  if ( pObject ) {

    AliHLTMemoryFile* pMemFile = CreateMemoryFile( kAliHLTDataTypeFXSCalib, kAliHLTVoidDataSpec );
    if ( pMemFile ) {

      iResult = pMemFile->WriteHeaderBuffer( (const char*) &pHeader, AliHLTCalibrationProcessor::fgkFXSProtocolHeaderSize );

      if ( iResult ) {
	HLTError( "Buffer size to small - for header!" );
      }
      else {
	iResult = Write( pMemFile, pObject );
	if ( !iResult ) {
	  HLTError( "Buffer size to small - for data!" );
	}
	else {
	  iResult = CloseMemoryFile( pMemFile );
	}
      }
    }
    else {
      iResult = -ENOMEM;
    }
  }
  else {
    iResult=-EINVAL;
  }

  return iResult;

} // Int_t AliHLTCalibrationProcessor::PushToFXS(TObject* pObject, const char* detector, const char* pFileID, const char* pDDLNumber ) {

Int_t AliHLTCalibrationProcessor::PushToFXS( void* pBuffer, int iSize, const char* pDetector, const char* pFileID, const char* pDDLNumber ) {
  // see header file for class documentation

  Int_t iResult = 0;

  AliHLTFXSHeader pHeader;

  CreateFXSHeader( pHeader, pDetector, pFileID, pDDLNumber );

  iResult = PushBack( pBuffer, iSize, kAliHLTDataTypeFXSCalib, kAliHLTVoidDataSpec, (void*) (&pHeader), AliHLTCalibrationProcessor::fgkFXSProtocolHeaderSize );

  return iResult;

} // Int_t AliHLTCalibrationProcessor::PushToFXS(void* pBuffer, int iSize, const char* pDdetector, const char* pFileID, const char* pDDLNumber = "") {

<|endoftext|>


<commit_before>// Copyright Paul Dardeau, SwampBits LLC 2014
// BSD License

#include <exception>

#include "ThreadPoolWorker.h"
#include "ThreadPoolQueue.h"
#include "ThreadingFactory.h"
#include "Thread.h"
#include "BasicException.h"
#include "Logger.h"

//******************************************************************************

ThreadPoolWorker::ThreadPoolWorker(ThreadingFactory* threadingFactory,
                                   ThreadPoolQueue& queue,
                                   int workerId) noexcept :
   m_threadingFactory(threadingFactory),
   m_workerThread(nullptr),
   m_poolQueue(queue),
   m_workerId(workerId),
   m_isRunning(false)
{
   Logger::logInstanceCreate("ThreadPoolWorker");
}

//******************************************************************************

ThreadPoolWorker::~ThreadPoolWorker() noexcept
{
   Logger::logInstanceDestroy("ThreadPoolWorker");

   if (m_workerThread) {
      delete m_workerThread;
   }
}

//******************************************************************************

void ThreadPoolWorker::start() noexcept
{
   if (!m_workerThread) {
      m_workerThread = m_threadingFactory->createThread(this);
      m_workerThread->setPoolWorkerStatus(true);
      m_workerThread->setWorkerId(std::to_string(m_workerId));
   }

   m_isRunning = true;
   m_workerThread->start();
}

//******************************************************************************

void ThreadPoolWorker::stop() noexcept
{
   m_isRunning = false;
}

//******************************************************************************

void ThreadPoolWorker::run() noexcept
{
   while (m_isRunning) {
      if (Logger::isLogging(Logger::LogLevel::Debug)) {
         char message[128];
         std::snprintf(message, 128, "poolQueue taking request on thread %d", m_workerId);
         Logger::debug(std::string(message));
      }

      Runnable* runnable = m_poolQueue.takeRequest();
      if (runnable) {
	      // has our thread been notified to shut down?
	      if (!m_workerThread->isAlive()) {
		      // put the request back on the front of the queue
				m_isRunning = false;
				continue;
	      } else {
            try
            {
               runnable->run();
            }
            catch (const BasicException& be)
            {
               Logger::error("run method of runnable threw exception: " + be.whatString());
            }
            catch (const std::exception& e)
            {
               Logger::error("run method of runnable threw exception: " + std::string(e.what()));
            }
            catch (...)
            {
               Logger::error("run method of runnable threw exception");
            }

            if (Logger::isLogging(Logger::LogLevel::Debug)) {
               char message[128];
               std::snprintf(message, 128, "ending processing request on thread %d", m_workerId);
               Logger::debug(std::string(message));
            }

            if (runnable->isAutoDelete()) {
               try
               {
                  delete runnable;
               }
               catch( ... )
               {
               }
            }

         }
      }
   }
}

//******************************************************************************

<commit_msg>updated thread pool worker to stamp the runnable so that we can know who ran it<commit_after>// Copyright Paul Dardeau, SwampBits LLC 2014
// BSD License

#include <exception>

#include "ThreadPoolWorker.h"
#include "ThreadPoolQueue.h"
#include "ThreadingFactory.h"
#include "Thread.h"
#include "BasicException.h"
#include "Logger.h"

//******************************************************************************

ThreadPoolWorker::ThreadPoolWorker(ThreadingFactory* threadingFactory,
                                   ThreadPoolQueue& queue,
                                   int workerId) noexcept :
   m_threadingFactory(threadingFactory),
   m_workerThread(nullptr),
   m_poolQueue(queue),
   m_workerId(workerId),
   m_isRunning(false)
{
   Logger::logInstanceCreate("ThreadPoolWorker");
}

//******************************************************************************

ThreadPoolWorker::~ThreadPoolWorker() noexcept
{
   Logger::logInstanceDestroy("ThreadPoolWorker");

   if (m_workerThread) {
      delete m_workerThread;
   }
}

//******************************************************************************

void ThreadPoolWorker::start() noexcept
{
   if (!m_workerThread) {
      m_workerThread = m_threadingFactory->createThread(this);
      m_workerThread->setPoolWorkerStatus(true);
      m_workerThread->setWorkerId(std::to_string(m_workerId));
   }

   m_isRunning = true;
   m_workerThread->start();
}

//******************************************************************************

void ThreadPoolWorker::stop() noexcept
{
   m_isRunning = false;
}

//******************************************************************************

void ThreadPoolWorker::run() noexcept
{
   while (m_isRunning) {
      if (Logger::isLogging(Logger::LogLevel::Debug)) {
         char message[128];
         std::snprintf(message, 128, "poolQueue taking request on thread %d", m_workerId);
         Logger::debug(std::string(message));
      }

      Runnable* runnable = m_poolQueue.takeRequest();
      if (runnable) {
	      // has our thread been notified to shut down?
	      if (!m_workerThread->isAlive()) {
		      // put the request back on the front of the queue
				m_isRunning = false;
				continue;
	      } else {

            // mark it
            runnable->setRunByThreadId(m_workerId);
            runnable->setRunByThreadWorkerId(m_workerThread->getWorkerId());

            try
            {
               runnable->run();
            }
            catch (const BasicException& be)
            {
               Logger::error("run method of runnable threw exception: " + be.whatString());
            }
            catch (const std::exception& e)
            {
               Logger::error("run method of runnable threw exception: " + std::string(e.what()));
            }
            catch (...)
            {
               Logger::error("run method of runnable threw exception");
            }

            if (Logger::isLogging(Logger::LogLevel::Debug)) {
               char message[128];
               std::snprintf(message, 128, "ending processing request on thread %d", m_workerId);
               Logger::debug(std::string(message));
            }

            if (runnable->isAutoDelete()) {
               try
               {
                  delete runnable;
               }
               catch( ... )
               {
               }
            }

         }
      }
   }
}

//******************************************************************************

<|endoftext|>