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

📄 voycmd.cpp

📁 足球机器人功能demo
💻 CPP
字号:
// VoyCmd.cpp: implementation of the CVoyCmd class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "VoyCmd.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

//自动查询超声传感器线程
UINT QueryUSonicThread(LPVOID pParam)
{
	CVoyCmd * pcmd = (CVoyCmd *)pParam;
	const UINT Time = pcmd->QueryUSonicTime;
	while (Time == pcmd->QueryUSonicTime && FALSE == pcmd->bToEndThreads)
	{
		pcmd->QueryUltrasonicSensor();		
		Sleep(Time);
	}
	return 0L;
}

//自动查询红外传感器线程
UINT QueryInfraRedThread(LPVOID pParam)
{
	CVoyCmd * pcmd = (CVoyCmd *)pParam;
	const UINT Time = pcmd->QueryInfraRedTime;
	while (Time == pcmd->QueryInfraRedTime && FALSE == pcmd->bToEndThreads)
	{
		pcmd->QueryInfrared();
		Sleep(Time);
	}
	return 0L;
}

//自动查询罗盘信息线程
UINT QueryCompassThread(LPVOID pParam)
{
	CVoyCmd * pcmd = (CVoyCmd *)pParam;
	const UINT Time = pcmd->QueryCompassTime;
	while (Time == pcmd->QueryCompassTime && FALSE == pcmd->bToEndThreads)
	{
		pcmd->QueryCompass();
		Sleep(Time);
	}
	return 0L;
}

CVoyCmd::CVoyCmd()
{
	m_charUltrasonic=new UCHAR[ULTRASONICAMOUNT];
	EnableUSonic= new BOOL[ULTRASONICAMOUNT];
	ValUSonic = new DOUBLE[ULTRASONICAMOUNT];

	m_charInfrared= new UCHAR[INFRAREDCHAR];
	EnableInfrared = new BOOL[INFRAREDMOUNT];
	ValInfrared = new BOOL[INFRAREDMOUNT];

	for (int i=0;i<ULTRASONICAMOUNT;i++)
	{
		ValUSonic[i] = 1;
	}

	for (i=0;i<ULTRASONICAMOUNT;i++)
	{
		EnableUSonic[i] = TRUE;
		EnableInfrared[i] = TRUE;
	}

	for (i=0;i<INFRAREDMOUNT;i++)
	{
		ValInfrared[i] = FALSE;
	}
	
	event=CreateEvent(NULL,TRUE,FALSE,NULL);

	nState =0;
	m_iLspeed = m_iRspeed = 0;

	m_pRcvBuf=new UCHAR[MAX_BUF];
	m_pSendBuf=new UCHAR[MAX_BUF];
	m_nRcvIndex = 0;

	m_pBeh = NULL;
	m_pPhy = NULL;
	m_pCap = NULL;

	QueryUSonicTime = 0;
	QueryInfraRedTime = 0;
	QueryCompassTime = 0;

	bToEndThreads = FALSE;
	bToRemoveBeh = FALSE;

	CmdShow_Send = NULL;
	CmdShow_Rec = NULL;

	USDataShow = NULL;
	IRDataShow = NULL;
	CmpsDataShow = NULL;
}

CVoyCmd::~CVoyCmd()
{
	QueryUSonicTime = 0;
	QueryInfraRedTime = 0;
	
	bToEndThreads = TRUE;

	CloseHandle(event);
	
	delete[] m_charUltrasonic;
	delete[] EnableUSonic;
	delete[] ValUSonic;
	delete[] m_charInfrared;
	delete[] ValInfrared;
	delete[] EnableInfrared;
	m_charInfrared = m_charUltrasonic = NULL;

	delete []m_pRcvBuf;
	delete []m_pSendBuf;

	//延时,给查询线程足够的时间退出
	if (QueryUSonicTime > QueryInfraRedTime)
	{
		Sleep(QueryUSonicTime+10);
	}
	else
	{
		Sleep(QueryInfraRedTime+10);
	}
	CoUninitialize();
}

//将接受到的数据分割组合成完整指令
void CVoyCmd::m_ParseBuffer(const UCHAR buf)
{
	//search for frame start tag
		if (buf==(UCHAR)0xaa && m_cLast==(UCHAR)0x55 && !m_bFrameStart)
		{
			m_pRcvBuf[0] = 0x55;
			m_pRcvBuf[1] = 0xAA;
			m_bFrameStart=true;
			return;
		}
			
		if (m_bFrameStart)
		{
			//put received data into buffer
			m_cLast=0x00;
			m_pRcvBuf[m_nRcvIndex+2]=buf;
			if (m_nRcvIndex==1)
			{
				m_nFrameLength=(buf & 0x3f)+4;
			}
			m_nRcvIndex++;
			//receive one frame, invoke ParseFrame to parse
			if (m_nRcvIndex==m_nFrameLength)
			{ 
				m_ParseFrame(m_pRcvBuf+2, m_nRcvIndex); 
				m_ResetRcvBuf(); 
			}

			//receive buffer overflow
				if (m_nRcvIndex>=MAX_BUF) 
				{
					m_ResetRcvBuf();
				}
		}
		else
			m_cLast=buf;
}

void CVoyCmd::m_ParseFrame(UCHAR *buf, int length)
{
	CString str,strTemp;

	if (!m_ValidFrame(buf,length))
	{
		m_ResponseError();
		return;
	}

	//通过局域网转发指令
	if (m_netsend.isConnecting())
	{
		m_netsend.Send(m_pRcvBuf,length+2);
	}

	bool ctrlcodevalid=true;
	switch (buf[2])
	{
		//there are two section of response
		//first is for query response
	case 0x30:
		{
			//query ultrasonic sensor response
			for (int i=0;i<ULTRASONICAMOUNT;i++)
			{
				m_charUltrasonic[i]=buf[i+3];
				ValUSonic[i] = m_CalDistance(m_charUltrasonic[i]);	//换算成距离
			}

			ShowSensor();

			if (m_pBeh != NULL)
			{
				if (bToRemoveBeh == TRUE)
				break;

				m_pBeh->AfterUpdateUSonic(ValUSonic,EnableUSonic,nState);
			}
			break;
		}
	case 0x34:
		{	//罗盘陀螺仪返回数据
			/*if (compass != NULL)
			{
				compass->Update(&buf[5],2);
				compass->Invalidate();
			}*/
			if (CmpsDataShow != NULL)
			{
				if (buf[3] < 0x80)
				{
					str.Format("X轴滚转角度:%d°\n\n",buf[3]);
				}
				else
				{
					str.Format("X轴滚转角度:%d°\n\n",-(0xff-buf[3]));
				}

				if (buf[4] < 0x80)
				{
					strTemp.Format("Y轴滚转角度:%d°",buf[4]);
				}
				else
				{
					strTemp.Format("Y轴滚转角度:%d°",-(0xff-buf[4]));
				}
				str += strTemp;
				CmpsDataShow->SetWindowText(str);
			}
			break;
		}
	case 0x36:
		{
			//query infrared sensor response
			for (int i=0;i<INFRAREDCHAR;i++)
			{
				m_charInfrared[i]=buf[i+3];
				for (int j=7;j>=0;j--)
				{
				
					if ((m_charInfrared[i] & 0x01)==0x01)
					{
						ValInfrared[j+8*i]=false;
					}
					else
					{
						ValInfrared[j+8*i]=true;
					}

					m_charInfrared[i]=m_charInfrared[i] >> 1;
				}
				m_charInfrared[i]=m_charInfrared[i] >> 1;	//使m_charInfrared恢复到原来的位顺序
			}

			ShowSensor();
			
			if (m_pBeh != NULL)
			{
				if(bToRemoveBeh == TRUE)
					break;

				m_pBeh->AfterUpdateInfrared(m_charInfrared,EnableInfrared,nState);
			}
			break;
		}
		//second is for setting response
	case 0x21: break;
	case 0x24: break;
	case 0x25: break;
	case 0x26: break;
	case 0x2c: break;	//罗盘闭环直行回执
	case 0x2d: break;	//罗盘闭环旋转回执
	default:
		{
			ctrlcodevalid=false;
			break;
		}
	}
	
	SetEvent(event);

	if (ctrlcodevalid)
		m_Response(buf,length);
	else
		m_ResponseError();
}

void CVoyCmd::Parse(void *buf, int length)
{
	if (length==0 || buf==NULL) return;
			
		for (int i=0;i<length;i++)
			m_ParseBuffer(((UCHAR*)buf)[i]);
}

void CVoyCmd::m_ResetRcvBuf()
{
	memset(m_pRcvBuf, 0, MAX_BUF);
	m_nRcvIndex=0;
	m_bFrameStart=false;
	m_cLast=0x00;
	m_nFrameLength=0;
}

void CVoyCmd::m_ResetSendBuf()
{
	memset(m_pSendBuf, 0, MAX_BUF); 
	m_nSendlength=0;
}

BOOL CVoyCmd::m_ValidFrame(UCHAR *buf, int length)
{
	if ((buf[1] & 0x3f)!=length-4)
		return false;

	int sum=0x000000ff;

	for (int i=0;i<length-1;i++)
		sum+=buf[i];

	if (buf[length-1]!=(UCHAR)(sum & 0x000000ff))
		return false;

	return true;
}

void CVoyCmd::m_ResponseError()
{	
	//解析不合协议的指令回调

}

void CVoyCmd::m_Response(UCHAR *recbuf, int length)
{	//解析合法指令回调
	m_pPhy->bSending = FALSE;

	//显示接收指令
	if (CmdShow_Rec != NULL)
	{
		CString cmd,str;
		CTime tm;
		tm = CTime::GetCurrentTime();
		cmd = tm.Format("%X:");
		for (int i=0;i<length+2;i++)
		{
			str.Format("%.2X ",m_pRcvBuf[i]);
			cmd += str;
		}
		CmdShow_Rec->AddString(cmd);
		CmdShow_Rec->SetCurSel(CmdShow_Rec->GetCount()-1);
	}
}

UCHAR CVoyCmd::m_CalSum(int length)
{
	int temp=0;
	for (int i=0;i<length;i++)
	temp+=m_pSendBuf[i];

	UCHAR ret;
	ret=(UCHAR)(temp & 0x000000ff);
	return ret;
}

DOUBLE CVoyCmd::m_CalDistance(UCHAR inUSChar)
{
	DOUBLE Distance;
	Distance = (DOUBLE) inUSChar*0.02174;
	return Distance;
}

void CVoyCmd::m_GenerateSendBuffer(UCHAR addr, UCHAR status, UCHAR length, UCHAR ctrlcode, UCHAR *data)
{
	m_pSendBuf[0]=(UCHAR)0x55;
	m_pSendBuf[1]=(UCHAR)0xaa;
	m_pSendBuf[2]=addr;
	m_pSendBuf[3]=((status << 6) & 0xc0) | (length & 0x3f);
	m_pSendBuf[4]=ctrlcode;
	if (length>0 && data!=NULL)
	{
		memcpy(&m_pSendBuf[5],data,length);
	}
	m_pSendBuf[length+5]=m_CalSum(length+5);

	m_nSendlength=length+6;

	//发送指令
	if (m_pPhy != NULL )
	{
		m_pPhy->Send(m_pSendBuf,m_nSendlength);

		//显示发送指令
		if (CmdShow_Send != NULL)
		{
			CString cmd,str;
			CTime tm;
			tm = CTime::GetCurrentTime();
			cmd = tm.Format("%X: ");
			for (int i=0;i<m_nSendlength;i++)
			{
				str.Format("%.2X ",m_pSendBuf[i]);
				cmd += str;
			}
			CmdShow_Send->AddString(cmd);
			CmdShow_Send->SetCurSel(CmdShow_Send->GetCount()-1);
		}
	}
	
	if (m_pBeh!= NULL)
	{
		m_pBeh->AfterSendCommand(m_pSendBuf,m_nSendlength,nState);
	}
	
}


void CVoyCmd::Brake(UCHAR breakmode)
{
	m_GenerateSendBuffer((UCHAR)0x01,0,1,(UCHAR)0x21,&breakmode);
	m_iLspeed = 0;
	m_iRspeed = 0;
	nState = STOP;
}

void CVoyCmd::SetBothMotorsSpeed(int inleftspeed, int inrightspeed)
{
	if (inleftspeed == m_iLspeed && inrightspeed == m_iRspeed)
	{
		return;
	}
	m_iLspeed = inleftspeed;
	m_iRspeed = inrightspeed;
	
    WORD leftspeed = m_CalculateSpeed(inleftspeed);
	WORD rightspeed = m_CalculateSpeed(inrightspeed);

	UCHAR bothspeed[4];	
	
	bothspeed[0]=(UCHAR)((leftspeed >> 8) & 0x00ff);
	bothspeed[1]=(UCHAR)(leftspeed & 0x00ff);

	bothspeed[2]=(UCHAR)((rightspeed >> 8) & 0x00ff);
	bothspeed[3]=(UCHAR)(rightspeed & 0x00ff);	

	m_GenerateSendBuffer((UCHAR)0x01,0,4,(UCHAR)0x26,bothspeed);
	m_UpdateState();
}

void CVoyCmd::SetLMotorSpeed(int inleftspeed)
{
	if (inleftspeed == m_iLspeed)
	{
		return;
	}

	m_iLspeed = inleftspeed;

	WORD leftspeed = m_CalculateSpeed(inleftspeed);

	UCHAR lspeed[2];

	lspeed[1]=(UCHAR)(leftspeed & 0x00ff);
	lspeed[0]=(UCHAR)((leftspeed >> 8) & 0x00ff);

	m_GenerateSendBuffer((UCHAR)0x01,0,2,(UCHAR)0x24,lspeed);
	m_UpdateState();
}

void CVoyCmd::SetRMotorSpeed(int inrightspeed)
{
	if (inrightspeed == m_iRspeed)
	{
		return;
	}
	m_iRspeed = inrightspeed;

	WORD rightspeed = m_CalculateSpeed(inrightspeed);

	UCHAR rspeed[2];

	rspeed[1]=(UCHAR)(rightspeed & 0x00ff);
	rspeed[0]=(UCHAR)((rightspeed >> 8) & 0x00ff);

	m_GenerateSendBuffer((UCHAR)0x01,0,2,(UCHAR)0x25,rspeed);
	m_UpdateState();
}

void CVoyCmd::QueryInfrared()
{
	m_GenerateSendBuffer((UCHAR)0x02,0,0,(UCHAR)0x36,NULL);
}

void CVoyCmd::QueryUltrasonicSensor()
{	
	UCHAR ultrasonicchar[3];

	for (int i=0;i<=3;i++)
	{
		ultrasonicchar[i]=0xff;
	}
	

	m_GenerateSendBuffer((UCHAR)0x02,0,3,(UCHAR)0x30,ultrasonicchar);
}

void CVoyCmd::SetBehavior(IBehavior *pBeh)
{
	if (pBeh != NULL)
	{
		m_pBeh = pBeh;
		m_pBeh->SetCmd(this);
	}
	else
	{	//去除行为
		bToRemoveBeh = TRUE;

		/*if (m_pBeh != NULL)
		{
			//等待行为调用完毕
			while(m_pBeh->m_Ref >0)
			{
				;
			}
		}*/
		
		m_pBeh = NULL;
		bToRemoveBeh = FALSE;
	}
}

WORD CVoyCmd::m_CalculateSpeed(int speed)
{
	BOOL forward;
	if (speed >= 0)
	{
		forward = TRUE;
	}
	else
	{
		forward = FALSE;
		speed = -speed;
	}

	if (speed > 30000)
	{
		speed = 30000;
	}

	WORD ret=0;
	speed &=0x7fff;

	if (forward)
		speed &= 0x7fff;
	else
		speed |= 0x8000;

	ret=speed;
	return ret;
}

void CVoyCmd::m_UpdateState()
{
	//左右速度相等
	if (m_iLspeed == m_iRspeed)
	{
		if (0 == m_iRspeed)
		{
			nState = STOP;
			return;
		}
		if (m_iLspeed > 0)
		{
			nState = FORWARD;
		}
		else
		{
			nState = BACKWARD;
		}
		return;
	}

	//左右电机大小相等,方向相反
	if (m_iLspeed == -m_iRspeed)
	{
		if (m_iLspeed > 0)
		{
			nState = RIGHT;
		}
		else
		{
			nState = LEFT;
		}
		return;
	}

	//右电机比左电机大(正方向上)
	if (m_iLspeed < m_iRspeed)
	{
		if (m_iLspeed + m_iRspeed > 0)
		{	//右前进速度较大
			nState = LEFTFRONT;
		} 
		else
		{	//左后退速度较大
			nState = RIGHTBACK;
		}
	}
	else
	{	//m_iLspeed > m_iRspeed
		if (m_iLspeed + m_iRspeed > 0)
		{	//左前进速度较大
			nState = RIGHTFRONT;
		} 
		else
		{	//右后退速度较大
			nState = LEFTBACK;
		}		
	}
}

UINT CVoyCmd::GetState()
{
	return nState;
}

void CVoyCmd::AutoQueryUSonic(UINT TimeGap)
{
	if (TimeGap == QueryUSonicTime)
	{
		return;
	}
	QueryUSonicTime = TimeGap;

	if (QueryUSonicTime != 0)
	{
		UCHAR sw = 0x01;
		m_GenerateSendBuffer(2,0,1,0x31,&sw);
		AfxBeginThread(QueryUSonicThread,(LPVOID)this,THREAD_PRIORITY_TIME_CRITICAL);
	}
	else
	{	//参数为0 ,停止超声硬件工作
		UCHAR sw = 0x00;
		m_GenerateSendBuffer(2,0,1,0x31,&sw);
	}
}

void CVoyCmd::AutoQueryInfraRed(UINT TimeGap)
{
	if (TimeGap == QueryInfraRedTime)
	{
		return;
	}
	QueryInfraRedTime = TimeGap;
	if (QueryInfraRedTime != 0)
	{
		AfxBeginThread(QueryInfraRedThread,(LPVOID)this,THREAD_PRIORITY_NORMAL);
	}
}

void CVoyCmd::AutoQueryCompass(UINT TimeGap)
{
	if (TimeGap == QueryCompassTime)
	{
		return;
	}
	QueryCompassTime = TimeGap;
	if (QueryCompassTime != 0)
	{
		AfxBeginThread(QueryCompassThread,(LPVOID)this,THREAD_PRIORITY_NORMAL);
	}
}

void CVoyCmd::ShowSensor()
{
	CString strUS,strIR;
	CString temp;
	int i;

	if (USDataShow != NULL)
	{
		for (i=0;i<ULTRASONICAMOUNT;i++)
		{
			if (EnableUSonic[i] == FALSE)
			{
				continue;
			}
			
			temp.Format("%2d号:%2.2f   ",i+1,ValUSonic[i]);
			strUS += temp;
			/*if ((i+1)%3 == 0)
			{
				*inUSstr += "\r";
			}*/
		}
		USDataShow->SetWindowText(strUS);
	}

	if (IRDataShow != NULL)
	{
		for (i=0;i<INFRAREDMOUNT;i++)
		{
			if (EnableInfrared[i] == FALSE)
			{
				continue;
			}
			
			temp.Format("%2d号:",i+1);
			if (ValInfrared[i] == TRUE)
			{
				temp+="有  ";
			} 
			else
			{
				temp+="无  ";
			}
			strIR += temp;
			/*if (i%2 == 1)
			{
				*inIRstr += "\r";
			}*/
		}
		IRDataShow->SetWindowText(strIR);
	}

	/*if (pieSensor != NULL)
	{
		pieSensor->UpdateUntrasonic(ValUSonic,EnableUSonic);
		pieSensor->UpdateInfrared(ValInfrared);
		pieSensor->Invalidate();
	}*/
}

void CVoyCmd::SpeedByCmps(int inSpeed)
{
	WORD wspeed = m_CalculateSpeed(inSpeed);
	UCHAR speed[4];
	speed[0] = 0x00;
	speed[1] = 0x00;
	speed[3] = (UCHAR)(wspeed & 0x00ff);
	speed[2] = (UCHAR)((wspeed>>8) & 0x00ff);

	m_GenerateSendBuffer((UCHAR) 0x01,0,4,0x2C,speed);
}

void CVoyCmd::CircleByCmps(int inAngle, int inSpeed)
{
	if (inAngle <-360 || inAngle > 360)
	{
		return;
	}

	WORD wAngle,wSpeed;
	UCHAR toSend[4];

	wAngle = m_CalculateSpeed(inAngle*39000/3445);
	toSend[1] = (UCHAR) wAngle&0x00ff;
	toSend[0] = (UCHAR) (wAngle>>8)&0x00ff;

	wSpeed = m_CalculateSpeed(inSpeed);
	toSend[3] = (UCHAR)(wSpeed & 0x00ff);
	toSend[2] = (UCHAR)((wSpeed>>8) & 0x00ff);

	m_GenerateSendBuffer((UCHAR) 0x01,0,4,0x2D,toSend);
}

void CVoyCmd::QueryCompass()
{
	m_GenerateSendBuffer(0x03,0,0,0x34,NULL);
}

void CVoyCmd::Kick()
{
	m_GenerateSendBuffer(0x04,0,0,0x2f,NULL);
}

void CVoyCmd::Demarcate()
{
	m_GenerateSendBuffer(0x01,0,0,0x2f,NULL);
}

⌨️ 快捷键说明

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