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

📄 mediator.cpp

📁 robocup源代码2001年清华机器人源代码
💻 CPP
字号:
/*
    Copyright (C) 2001  Tsinghuaeolus

    Authors : ChenJiang, YaoJinyi, CaiYunpeng, Lishi

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

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

	If you make any changes or have any comments we would appreciate a 
	message to yjy01@mails.tsinghua.edu.cn.
*/

#include "stdafx.h"

#include "global.h"
#include "mediator.h"

/**************   PrioredCommand *************************/
PrioredCommand::PrioredCommand(){
	Command::Command();
	priority = 0.0f;
	actiontype = Action_none;
}

/*************	VisualRequestQueue	*************************/
VisualRequest::VisualRequest(float priority, AngleDeg angle){
	this->priority = priority;
	this->angle = NormalizeAngle(angle);
}

AngleDeg VisualRequest::RequestedAngle_(){
	return MidAngle(angle,angle_inf);
}

float VisualRequest::RequestedPriority(){
	if(view_width == VW_Narrow) return priority * CP_VW_Narrowfactor;
	else return priority;
}

/**********		Mediator	**************************/
Mediator::Mediator(){

	VisualRequest test[10];
	VisualRequest requests[10];
	int total;

	test[0] = VisualRequest(1.0f, 98.5f);
	test[1] = VisualRequest(1.0f, 106.5f);
	test[2] = VisualRequest(1.0f, 40.0f);
	test[3] = VisualRequest(1.0f, 60.0f);
	vr_queue.cleanup();
	vr_queue.enqueue(test[0]);
	vr_queue.enqueue(test[1]);
	vr_queue.enqueue(test[2]);
	vr_queue.enqueue(test[3]);

	total = 0;
	SetVisualRequests(visualrequests, totalvisualrequests, VW_Narrow);
	SetVisualRequests(visualrequests, totalvisualrequests, VW_Normal);
}

void Mediator::ResetBuffer(){
//	visualrequestqueue.cleanup();
//	countervisualrequestqueue.cleanup();
	vr_queue.cleanup();
	ac_queue.cleanup();
	totalvisualrequests = 0;
}


bool Mediator::enroll(PrioredCommand& pcmd){
	DoLog("Enroll cmdtype %d actype %d p %.2f", pcmd.type, pcmd.actiontype, pcmd.priority);
	if(pcmd.type == CMD_none) return false;
	pcmd.priority = priority_mapping(pcmd.actiontype, pcmd.priority);
	return ac_queue.enqueue(pcmd);
}

bool Mediator::enroll(Command& command, ActionType actiontype, float priority){
	return enroll(PrioredCommand(command, actiontype, priority));
}

void Mediator::Getbestaction(PrioredCommand& bestaction){
	bestaction.Reset();
	if(!ac_queue.IsEmpty()){
		bestaction = ac_queue.GetData(ac_queue.ActualHead());
	}
}

void Mediator::SetViewWidth(VIEWWIDTH view_width){
	if(view_width == VW_Narrow)
		DoLog(LOG_MEDIATION, "force narrow mode");
	else if(view_width == VW_Normal)
		DoLog(LOG_MEDIATION, "force normal mode");
	else
		DoLog(LOG_MEDIATION, "force wide mode");
	designated_viewwidth.Setdata(view_width, situation.CurrentTime);
}

void Mediator::DisableViewWidth(){
	designated_viewwidth.time = -2;
}

bool Mediator::enroll(float priority, AngleDeg angle){
	DoLog(LOG_MEDIATION, "enroll %.2f %.2f", priority, angle);
	return vr_queue.enqueue(VisualRequest(priority_mapping(Action_visual, priority), angle));
}

void Mediator::SetVisualRequests(VisualRequest * requests, int& totalrequests, VIEWWIDTH view_width, int max_requests){
	int p, q;
	float ang, priority, sum_priority, angle_inf, angle_sup, view_width_ang;
	VisualRequest treq;

	if (totalrequests < 0) return;
	if (vr_queue.IsEmpty()) return;

	p = q = vr_queue.ActualHead();
	priority = sum_priority = 0.0f;
	
	view_width_ang = sensory.MyViewWidth(view_width);

	//set visual-requests clockwisely
	while(vr_queue.IsValid(p)){
		if (totalrequests >= max_requests)//exceed max requests
			break;

		requests[totalrequests].angle = vr_queue.GetData(p).angle;
		requests[totalrequests].view_width = view_width;

		if (sum_priority > 0){
			requests[totalrequests].priority = sum_priority
				= priority_sub(sum_priority, priority);
		}
		else{
			sum_priority = requests[totalrequests].priority = 0.0f;
		}

		if(p == q){
			requests[totalrequests].angle_inf = requests[totalrequests].angle;
		}
		else{
			requests[totalrequests].angle_inf = angle_inf;
		}
		
		vr_queue.GetData(p).view_width = view_width;
		priority = vr_queue.GetData(p).RequestedPriority();

		do{
			treq = vr_queue.GetData(q);
			treq.view_width = view_width;
			ang = NormalizeAngle(treq.angle - requests[totalrequests].angle, 0.0f);
			if (ang > view_width_ang){
				break;
			}
			angle_inf = requests[totalrequests].angle_inf = treq.angle;
			sum_priority = requests[totalrequests].priority = 
				priority_sum(requests[totalrequests].priority, treq.RequestedPriority());
			q = vr_queue.CircularNext(q);
		}while(q != p && vr_queue.IsValid(q));
		//when searching counterclockwisely, some requests will recur, seting angle_inf
		//will help to detect it
		vr_queue.GetData(p).angle_inf = angle_inf;

		totalrequests ++;
		p = vr_queue.Next(p);
	}
//set visual-requests counter-clockwisely
	p = q = vr_queue.Tail();
	priority = sum_priority = 0.0f;
	int sup_element = -1;
	
	while(!vr_queue.IsHead(p) && vr_queue.IsValid(p)){
		if (totalrequests >= max_requests)//exceed max requests
			break;

		requests[totalrequests].angle_inf = vr_queue.GetData(p).angle;
		requests[totalrequests].view_width = view_width;

		if (sum_priority > 0){
			requests[totalrequests].priority = sum_priority 
				= priority_sub(sum_priority, priority);
		}
		else{
			sum_priority = requests[totalrequests].priority = 0.0f;
		}

		if(p == q){
			requests[totalrequests].angle = requests[totalrequests].angle_inf;
		}
		else{
			requests[totalrequests].angle = angle_sup;
		}

		vr_queue.GetData(p).view_width = view_width;
		priority = vr_queue.GetData(p).RequestedPriority();

		do{
			treq = vr_queue.GetData(q);
			treq.view_width = view_width;
			ang = NormalizeAngle(requests[totalrequests].angle_inf - treq.angle, 0.0f);
			if (ang > view_width_ang){
				break;
			}
			angle_sup = requests[totalrequests].angle = treq.angle;
			sum_priority = requests[totalrequests].priority = 
				priority_sum(requests[totalrequests].priority, treq.RequestedPriority());

			sup_element = q;
			q = vr_queue.CircularPrev(q);
		}while(q != p && vr_queue.IsValid(q));

		if (vr_queue.IsValid(sup_element)){
			if (vr_queue.GetData(sup_element).angle_inf != vr_queue.GetData(p).angle)
				totalrequests ++;
		}

		p = vr_queue.Prev(p);
	}
}


void Mediator::SetVisualRequests(){
	if (designated_viewwidth.time == situation.CurrentTime){
		SetVisualRequests(visualrequests, totalvisualrequests, designated_viewwidth.data);
	}
	else{
		SetVisualRequests(visualrequests, totalvisualrequests, VW_Narrow);
		SetVisualRequests(visualrequests, totalvisualrequests, VW_Normal);
	}
}

void Mediator::mediation(){
	
	PrioredCommand bestaction, retraction;
	Command cmd1, cmd2;
	VisualRequest tmprequest;
	float ang, bdfy, sum_priority, maxpriority, maxvisualpriority, bestaction_bdfy, ang_inf, ang_sup;
	int vreq_idx, p, max_vreq_idx;

	SetVisualRequests();
	//sort the visualrequests by priority
	for(int i =0; i < totalvisualrequests - 1; i ++){
		for(int j =i+1; j < totalvisualrequests; j ++){
			if (visualrequests[j].priority > visualrequests[i].priority){
				Swap(visualrequests[i], visualrequests[j]);
			}
		}
	}

	//see if the visualrequests is reachable
	ang = Min(SP_max_neck_angle + sensory.MyViewAngle(visualrequests[i].view_width) + action.Max_TurnAng(),
		180.0f);
	ang_inf = NormalizeAngle(Self.bodyfacing - ang);
	ang_sup = 2 * ang;
	max_vreq_idx = -1;
	maxvisualpriority = 0.0f;
	for(i = 0; i < totalvisualrequests; i ++){
		ang = Max(NormalizeAngle(visualrequests[i].angle - ang_inf, 0.0f),
				NormalizeAngle(visualrequests[i].angle_inf - ang_inf, 0.0f));
		if (ang > ang_sup) visualrequests[i].valid = false;
		else{
			visualrequests[i].valid = true;
			if (max_vreq_idx == -1){
				max_vreq_idx = i;
				maxvisualpriority = visualrequests[i].priority;
			}
		}
	}

	for(i =0; i < totalvisualrequests; i ++){
		if (!visualrequests[i].valid) continue;
//		DoLog(LOG_MEDIATION, "v r %d p %f (%.2f %.2f) %d", i,
//			visualrequests[i].priority, visualrequests[i].angle, visualrequests[i].angle_inf, visualrequests[i].view_width);
	}

	bestaction.Reset();
	vreq_idx = -1;
	maxpriority = 0.0f;

	
	p = ac_queue.ActualHead();
	//while(ac_queue.IsValid(p)){
	if(ac_queue.IsValid(p)){
		retraction = ac_queue.GetData(p);
		DoLog(LOG_ACTION,"action priority %.2f",retraction.GetPriority());

	//	if (priority_sum(retraction.priority, maxvisualpriority) <= maxpriority)
	//		break;

		bdfy = Self.bodyfacing;//bdfy when exec this command
		if (retraction.type == CMD_turn){
			bdfy = NormalizeAngle(retraction.angle * action.Turnrate() + bdfy);
		}

		//check if visual reuqests are compatible with the action
		if (retraction.type == CMD_stay){
			i = max_vreq_idx;
		}
		else{
			for(i =0; i < totalvisualrequests; i ++){
				if (!visualrequests[i].valid) continue;
				ang_inf = NormalizeAngle(bdfy - SP_max_neck_angle - sensory.MyViewAngle(visualrequests[i].view_width));
				ang_sup = 2 * (SP_max_neck_angle + sensory.MyViewAngle(visualrequests[i].view_width));
				
				ang = Max(NormalizeAngle(visualrequests[i].angle - ang_inf, 0.0f),
					NormalizeAngle(visualrequests[i].angle_inf - ang_inf, 0.0f));

				if (ang > ang_sup) continue;

				break;
			}
		}

		if (i >= totalvisualrequests){
		//no visual request that is compatible with this action
			sum_priority = retraction.priority;
			i = -1;
		}
		else{
			sum_priority = priority_sum(retraction.priority, visualrequests[i].priority);
		}

		if (sum_priority > maxpriority){
			maxpriority = sum_priority;
			vreq_idx = i;
			bestaction = retraction;
			bestaction_bdfy = bdfy;
		}

		p= ac_queue.Next(p);
	}

	if (max_vreq_idx != -1){
		if (visualrequests[max_vreq_idx].priority > maxpriority){
			bestaction.Reset();
			vreq_idx = max_vreq_idx;
		}
	}

//execute it
	if (bestaction.type != CMD_none && bestaction.type != CMD_stay){
		action.execute(bestaction);
		if (vreq_idx != -1){
			DoLog(LOG_MEDIATION, "view width %d %d", visualrequests[vreq_idx].view_width, sensory.LastViewWidth);
			if(Self.viewwidth.Data(situation.CurrentTime) != visualrequests[vreq_idx].view_width){
				action.change_view(visualrequests[vreq_idx].view_width, VQ_High);
			}

			motion.turn_neck_to(visualrequests[vreq_idx].RequestedAngle_(),
				bestaction_bdfy, cmd2);
		}
		else if (designated_viewwidth.time == situation.CurrentTime){			
			DoLog(LOG_MEDIATION, "view width %d", designated_viewwidth.data);
			if(Self.viewwidth.Data(situation.CurrentTime) != designated_viewwidth.data){
				action.change_view(designated_viewwidth.data, VQ_High);
			}
		}
		action.execute(cmd2);
	}
	else{
		if (vreq_idx != -1){
			DoLog(LOG_MEDIATION, "view width %d %d", visualrequests[vreq_idx].view_width, sensory.LastViewWidth);
			if(Self.viewwidth.Data(situation.CurrentTime) != visualrequests[vreq_idx].view_width){
				action.change_view(visualrequests[vreq_idx].view_width, VQ_High);
			}
			bdfy = NormalizeAngle(Self.bodyfacing +
				motion.turn_to(visualrequests[vreq_idx].RequestedAngle_(), cmd1));
			motion.turn_neck_to(visualrequests[vreq_idx].RequestedAngle_(),
				bdfy, cmd2);
			action.execute(cmd1);
			action.execute(cmd2);
		}
		if (designated_viewwidth.time == situation.CurrentTime){
			DoLog(LOG_MEDIATION, "view width %d %d", designated_viewwidth.data, sensory.LastViewWidth);
			if(Self.viewwidth.Data(situation.CurrentTime) != designated_viewwidth.data){
				action.change_view(designated_viewwidth.data, VQ_High);
			}
		}
	}
//feedback
	feedback(bestaction, vreq_idx);
}

void Mediator::feedback(const PrioredCommand& bestaction, int vr_idx){
	lastactiontype = bestaction.actiontype;
	lastcmdtype = bestaction.type;
	switch (bestaction.actiontype){
	case Action_interception:
		DoLog(LOG_ACTION, "Interception");
		break;
	case Action_turn_ball:
		DoLog(LOG_ACTION,"Turn Ball");
		break;
	case Action_shoot:
		DoLog(LOG_ACTION,"Shoot (spd %.2f angle %.2f)", motion.GetMinShootSpeed(), motion.GetShootAngle());
		break;
	case Action_dribble:
		DoLog(LOG_ACTION,"Dribble ang %.1f",motion.GetDribbleAngle());
		break;
	case Action_fastdribble:
		DoLog(LOG_ACTION,"FasetDribble");
		break;
	case Action_positioning_coordinate:
		DoLog(LOG_ACTION,"Coordinated attack");
		break;
	case Action_avoidenemy:
		DoLog(LOG_ACTION,"Avoid enemy");
		break;
	case Action_pass:
		PassOut.time = situation.CurrentTime;
		DoLog(LOG_ACTION,"Pass to %d(spd %.2f,angle %.1f)",motion.GetReceiver(), motion.GetPassSpeed(), motion.GetPassAngle());
		break;
	case Action_passwait:
		DoLog(LOG_ACTION,"(Waiting)Pass to %d(spd %.2f,angle %.1f)",motion.GetReceiver(), motion.GetPassSpeed(), motion.GetPassAngle());
		break;
	case Action_holdball:
		DoLog(LOG_ACTION, "Hold ball");
		break;
	case Action_positioning_offense:
		DoLog(LOG_ACTION, "Position Offense");
		break;
	case Action_positioning_defense:
		DoLog(LOG_ACTION, "Position Defense");
		break;
	case Action_positioning_block:
		DoLog(LOG_ACTION, "Position Block");
		break;
	case Action_positioning_mark:
		DoLog(LOG_ACTION, "Position Mark");
		break;
	case Action_press:
		DoLog(LOG_ACTION, "Press");
		break;
	case Action_other:
		DoLog(LOG_ACTION, "Other");
		break;
	case Action_clear:
		DoLog(LOG_ACTION, "ClearBall");
		break;
	case Action_none:
		if (!situation.ClockStopped && situation.playmode == PM_Play_On)
			DoLog(LOG_ACTION, "None");
		break;
	default:
		DoLog(LOG_ACTION, "Not defined");
		break;
	}
	if (vr_idx != -1){
		DoLog(LOG_ACTION, "Visual request %d (%.2f %.2f)", vr_idx, visualrequests[vr_idx].angle, visualrequests[vr_idx].angle_inf);
	}
}

ActionType Mediator::LastActionType(){
	return lastactiontype;
}

CMDType Mediator::LastCmdType(){
	return lastcmdtype;
}

float Mediator::priority_mapping(ActionType actiontype, float priority){
	switch(actiontype){
	case Action_pass:
	case Action_passwait:
	case Action_shoot:
	case Action_dribble:
	case Action_fastdribble:
	case Action_catch:
	case Action_turn_ball:
	case Action_holdball:
	case Action_avoidenemy:
	case Action_clear:
		return priority * 0.2f + 0.8f;
	case Action_visual:
		return priority * 0.4f;
	case Action_interception:
		return priority * 0.4f + 0.4f;
	case Action_positioning_offense:
	case Action_positioning_defense:
	case Action_positioning_block:
	case Action_positioning_mark:
	case Action_positioning_coordinate:
	case Action_positioning_setplay:
	case Action_press:
		return priority * 0.4f + 0.4f;
	default:
		break;
	}
	return priority;
}

⌨️ 快捷键说明

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