⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mavisclient.cpp

📁 机器人程序
💻 CPP
字号:
// mavisclient.c - by Robin Hewitt, 2004-2005
// http://www.robinhewitt.com/mavis
// This is free software. See license at the bottom
// of this file for details.
//

//////////////////////////////////////////////////////////////
// A dll for communicating with Mavis. Uses the API in
// maviscomm.h.
//
// The API, including exported function interfaces, is in
// maviscomm.h

// special project settings:
//    C/C++, category=preprocessor, added ../../include to the additional
//    include directories.
//
//    added post-build command: copy Debug\mavisclient.dll ..\..\bin

#define __MAVISCLIENT_IMPL
#define USE_OPENCVINTERFACE

#include <windows.h>
#include <stdio.h>
#include "MVLib.h"
#include "maviscomm.h"


// internal name - to kill any waiting threads when
// the dll is unloaded
#define INTERRUPT_EVENT_NAME  "mavis_client_interrupt_event"


// internal methods
BOOL linkToMavis();
void detachFromMavis();
int  sendCtl();
int  getObjLoc(ObjLoc_t * pObjLoc, long waitTime);
void getResult(void * pData, int nBytes);


// file-level data
static CtlData_t   ctlData;
static FrameSize_t g_frameSize = {0};

static HANDLE  hResultEvent      = NULL;
static HANDLE  hResultMutex      = NULL;
static HANDLE  hResultMem        = NULL;
static LPVOID  resultAdd         = NULL;

static HANDLE  hMavisCtlEvent = NULL;
static HANDLE  hCtlMutex      = NULL;
static HANDLE  hCtlMem        = NULL;
static LPVOID  CtlAdd         = NULL;

static HANDLE  hInterruptEvent = NULL;


//set up a shared variable to track number of
//attached instances
#pragma data_seg(".shared")
	int instCount = 0;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")



BOOL WINAPI DllMain(
	HINSTANCE hinstDLL,    // DLL module handle
    DWORD fdwReason,       // reason called
    LPVOID lpvReserved     // reserved
) {

	switch (fdwReason)
	{

		case DLL_PROCESS_ATTACH:
			if(instCount)
			{
				fprintf(stderr, "Mavis already in use - dll initialization aborted\n");
				return FALSE;
			}
			else
			{
				++instCount;
				return linkToMavis();
			}

		case DLL_THREAD_ATTACH:
			break;

		case DLL_THREAD_DETACH:
			break;

		case DLL_PROCESS_DETACH:
			detachFromMavis();
			--instCount;
			break;

		default:
			break;
	}

	return TRUE;
	UNREFERENCED_PARAMETER(hinstDLL);
	UNREFERENCED_PARAMETER(lpvReserved);
}

BOOL linkToMavis()
{

	//open event handles
	hResultEvent = OpenEvent(
		SYNCHRONIZE|EVENT_MODIFY_STATE,
		FALSE,
		TEXT(RESULT_EVENT_NAME)
	);
	hMavisCtlEvent = OpenEvent(
		SYNCHRONIZE|EVENT_MODIFY_STATE,
		FALSE,
		TEXT(CTL_EVENT_NAME)
	);

	if(NULL == hResultEvent || NULL==hMavisCtlEvent) goto error;


	//open mutex handles
	hResultMutex = OpenMutex(
		SYNCHRONIZE|MUTEX_MODIFY_STATE,
		FALSE,
		RESULT_MUTEX_NAME
	);
	hCtlMutex = OpenMutex(
		SYNCHRONIZE|MUTEX_MODIFY_STATE,
		FALSE,
		CTL_MUTEX_NAME
	);


	//open and map shared memory
	hResultMem = OpenFileMapping(
		FILE_MAP_READ,
		FALSE,
		TEXT(RESULT_MEM_NAME)
	);
	resultAdd = MapViewOfFile(
		hResultMem,           //region to be mapped
		FILE_MAP_READ,        //access mode
		0,                    //high-order 32 bits of file offset
		0,                    //low-order 32 bits of file offset
		0                     //map the entire region
	);
	if(NULL==hResultMem || NULL==resultAdd) goto error;

	hCtlMem = OpenFileMapping(
		FILE_MAP_WRITE,
		FALSE,
		TEXT(CTL_MEM_NAME)
	);
	CtlAdd = MapViewOfFile(
		hCtlMem,              //region to be mapped
		FILE_MAP_WRITE,       //access mode
		0,                    //high-order 32 bits of file offset
		0,                    //low-order 32 bits of file offset
		0                     //map the entire region
	);
	if(NULL==hCtlMem || NULL==CtlAdd) goto error;


	// create the internal interrupt event
	hInterruptEvent = CreateEvent(
		NULL,					//use default security attributes
		FALSE,                  //event will be auto reset
		FALSE,                  //initial state is non-signalled
		TEXT(INTERRUPT_EVENT_NAME)
	);
	if(NULL==hInterruptEvent) goto error;

	return TRUE;

error:
	fprintf(stderr, "Can't connect to Mavis - dll initialization aborted\n");
	detachFromMavis();

	fprintf(stderr, "Failed to initialize %s\n",
		(!hResultEvent)?    "hResultEvent" :
		(!hMavisCtlEvent)?  "hMavisCtlEvent" :
		(!hResultMutex)?    "hResultMutex" :
		(!hCtlMutex)?       "hCtlMutex" :
		(!hResultMem)?      "hResultMem" :
		(!resultAdd)?       "resultAdd" :
		(!hCtlMem)?         "hCtlMem" :
		(!CtlAdd)?          "CtlAdd" :
		(!hInterruptEvent)? "hInterruptEvent" :
		"-- unknown initialization failure");
	return FALSE;
}

void detachFromMavis()
{
	//signal an internal interrupt in case
	//an attached thread is waiting
	SetEvent(hInterruptEvent);


	//close event handles
	if(hResultEvent)    CloseHandle(hResultEvent);
	if(hMavisCtlEvent)  CloseHandle(hMavisCtlEvent);
	if(hInterruptEvent) CloseHandle(hInterruptEvent);

	hResultEvent = hMavisCtlEvent = hInterruptEvent = NULL;


	//close mutex handles
	if(hResultMutex) CloseHandle(hResultMutex);
	if(hCtlMutex)    CloseHandle(hCtlMutex);

	hResultMutex = hCtlMutex = NULL;


	//release shared memory resources
	if(resultAdd)  UnmapViewOfFile(resultAdd);
	if(hResultMem) CloseHandle(hResultMem);
	hResultMem = resultAdd = NULL;

	if(CtlAdd)  UnmapViewOfFile(CtlAdd);
	if(hCtlMem) CloseHandle(hCtlMem);
	hCtlMem = CtlAdd = NULL;

	return;
}


int lookOnce(int objId, ObjLoc_t * pObjLoc)
{
	int ret = 0;

	//check for valid object id
	//if(objId < 3 || objId > 5) return -1; //todo: validate objId from database

	//write control data, use mutex to synchronize access
	ctlData.objId = objId;
	ctlData.ctlCode = LOOK_ONCE;
	sendCtl();

	//get result
	ret = getObjLoc(pObjLoc, INFINITE);

	return ret;
}



int getNextObj(int objId, ObjLoc_t * pObjLoc)
{
	int ret = 0;

	//write control data, use mutex to synchronize access
	ctlData.objId = objId;
	ctlData.ctlCode = GET_NEXT_OBJ;
	sendCtl();

	//get result
	ret = getObjLoc(pObjLoc, INFINITE);

	return ret;
}


int startLookUntilSighted(int objId, ObjLoc_t * pObjLoc, DWORD millisec)
{
	int ret = 0;
	HANDLE lpHandleArray[2];
	DWORD waitTerm;

	memset(pObjLoc, 0, sizeof(ObjLoc_t));

	lpHandleArray[0] = hResultEvent;
	lpHandleArray[1] = hInterruptEvent;

	//write control data, use mutex to synchronize access
	ctlData.objId = objId;
	ctlData.ctlCode = LOOK_UNTIL_SIGHTED;
	sendCtl();


	waitTerm = WaitForMultipleObjects(
	  2,              // number of handles in the handle array
	  lpHandleArray,  // pointer to the object-handle array
	  FALSE,          // wait type is to wait for any (but not for all)
	  millisec        // time-out interval in milliseconds
	);

	if(WAIT_OBJECT_0 == waitTerm)
	{
		// The first event, hResultEvent, was signalled,
		// so get the result data.
		WaitForSingleObject(hResultMutex, INFINITE);
		memcpy( pObjLoc, resultAdd, sizeof(ObjLoc_t) );
		ReleaseMutex(hResultMutex);
	}


	return ret;
}

int stopLookUntilSighted()
{

	int ret = 0;

	// Send Pause (null) command to Mavis
	ctlData.objId = INVALID_OBJ_ID;
	ctlData.ctlCode = PAUSE;
	sendCtl();

	SetEvent(hInterruptEvent);

	return ret;
}

int startRawFeed()
{
	// send command to Mavis
	ctlData.ctlCode = FWD_RAW_FRAMES;
	sendCtl();

	return 0;
}

int stopRawFeed()
{
	// Send Pause (null) command to Mavis
	ctlData.ctlCode = PAUSE;
	sendCtl();

	return 0;
}

int nextFrame()
{
	// Send NextFrame command to Mavis
	ctlData.ctlCode = NEXT_FRAME;
	sendCtl();

	return 0;
}

int sendCtl()
{

	// write control data, using mutex to synchronize access
	WaitForSingleObject(hCtlMutex, INFINITE);
	memcpy( CtlAdd, &ctlData, sizeof(CtlData_t) );
	ReleaseMutex(hCtlMutex);

	SetEvent(hMavisCtlEvent);

	return 0;
}

int getObjLoc(ObjLoc_t * pObjLoc, long waitTime)
{
	//wait up to waitTime for a new resultset to become avail
	if( WAIT_TIMEOUT == WaitForSingleObject(hResultEvent, waitTime) )
		return -1; //wait timed out, so return with unchanged data

	//update data, use mutex to synchronize access
	WaitForSingleObject(hResultMutex, INFINITE);
	memcpy( pObjLoc, resultAdd, sizeof(ObjLoc_t) );
	ReleaseMutex(hResultMutex);

	return 0;
}



// Functions for locating horizontal lines in 3D
//
int locateHLines(int d, HLineOrder_t ordering, HLineMetadata_t * pHLineMetadata)
{
	//write control data, use mutex to synchronize access
	ctlData.d = d;
	ctlData.ordering = ordering;
	ctlData.ctlCode = LOCATE_H_LINES;
	sendCtl();

	//wait for the result
	if( WAIT_TIMEOUT == WaitForSingleObject(hResultEvent, INFINITE) )
		return -1; //wait timed out, so return with unchanged data

	//get result
	WaitForSingleObject(hResultMutex, INFINITE);
	memcpy( pHLineMetadata, resultAdd, sizeof(HLineMetadata_t) );
	ReleaseMutex(hResultMutex);

	return 0;
}


int nextLine(HLine_t * pHLine)
{
	NextHLine_t nextHLine;

	//write control data, use mutex to synchronize access
	ctlData.ctlCode = NEXT_H_LINE;
	sendCtl();

	//wait for the result
	if( WAIT_TIMEOUT == WaitForSingleObject(hResultEvent, INFINITE) )
		return -1; //wait timed out, so return with unchanged data

	//get result
	WaitForSingleObject(hResultMutex, INFINITE);
	memcpy( &nextHLine, resultAdd, sizeof(NextHLine_t) );
	ReleaseMutex(hResultMutex);

	// copy mavis data to output
	memcpy( pHLine, &(nextHLine.hLine), sizeof(HLine_t) );

	return nextHLine.nRemaining;
}


// Frame-forwarding functions
getFrameSize(FrameSize_t * pFrameSize)
{
	// send the command
	ctlData.ctlCode = GET_FRAME_SIZE;
	sendCtl();
	getResult((void *)pFrameSize, sizeof(FrameSize_t));

	// store this to use when retrieving frame buffer
	g_frameSize = *pFrameSize;

	return 0;
}

int getFrame(BYTE * buf, int nBytes)
{
	if( !g_frameSize.nBufSize )
		getFrameSize( &g_frameSize );

	if(nBytes < g_frameSize.nBufSize)
		return -1;  // oops, buffer's too small
	else
	{
		// send the command
		ctlData.ctlCode = GET_FRAME;
		sendCtl();
		getResult(buf, g_frameSize.nBufSize);
		return 0;
	}
}


CvSize getIplImageSize()
{
	if( !g_frameSize.nBufSize )
		getFrameSize( &g_frameSize );

	CvSize size;
	size.width  = g_frameSize.width;
	size.height = g_frameSize.height;

	return size;
}


//int getIplImageData(IplImage * pImg, BYTE * imageData)
int getIplImageData(IplImage * pImg)
{
	if( !g_frameSize.nBufSize )
		getFrameSize( &g_frameSize );

	if(pImg->width     != g_frameSize.width ||
	   pImg->height    != g_frameSize.height ||
	   pImg->nChannels != 3 ||
	   pImg->depth     != IPL_DEPTH_8U)
	   { return -1; }

	BYTE * buf = new BYTE[g_frameSize.nBufSize];
	getFrame(buf, g_frameSize.nBufSize);

	pImg->origin = 1;     // origin at lower left (windows bitmap style)
	pImg->dataOrder = 0;  // interleaved data

	BYTE * pFrameData = buf;
	BYTE * imageData = (BYTE *)pImg->imageData;
	int widthStepFrame = 3*g_frameSize.width;
	int widthStepIpl = pImg->widthStep;

	cout << "widthStepIpl = " << widthStepIpl << endl;
	cout << "g_frameSize.nBufSize = " << g_frameSize.nBufSize << endl;

	for(int i=0; i<g_frameSize.height; i++)
	{
		memcpy(imageData, pFrameData, widthStepFrame);
		imageData += widthStepIpl;
		pFrameData += widthStepFrame;
	}

	if(buf) delete[] buf;

	return 0;
}


int getTiltAngle(double * pAngle)
{
	ctlData.ctlCode = GET_TILT_ANGLE;
	sendCtl();
	getResult(pAngle, sizeof(double));
	return 0;
}


int setTiltAngle(double angle)
{
	double newAngle;
	ctlData.ctlCode = SET_TILT_ANGLE;
	ctlData.dblValue = angle;
	sendCtl();
	getResult(&newAngle, sizeof(double));
	return (newAngle != angle);
}


void getResult(void * pData, int nBytes)
{
	WaitForSingleObject(hResultEvent, INFINITE);  // wait for mavis to signal
	WaitForSingleObject(hResultMutex, INFINITE);  // capture mutex
	memcpy( pData, resultAdd, nBytes );           // read from shared memeory
	ReleaseMutex(hResultMutex);                   // release the mutex
}


///////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this
// license. If you do not agree to this license, do not download, install, copy or
// use the software.
//
//
//                        Mavis License Agreement
//
// Copyright (c) 2004-2005, Robin Hewitt (http://www.robin-hewitt.com).
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
// This software is provided "as is" and any express or implied warranties, including,
// but not limited to, the implied warranties of merchantability and fitness for a
// particular purpose are disclaimed. In no event shall the authors or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or consequential
// damages (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused and on any
// theory of liability, whether in contract, strict liability, or tort (including
// negligence or otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
///////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -