import java.util.Iterator;
public class TreeDeployAgent implements ITreeAlgAgent {
int m_nDim; //always 2
double m_lfCommRad;
double m_lfVel;
public TreeDeployAgent() {
m_nDim = 2;
m_lfVel = 0.25;
}
public TreeDeployAgent(double lfCommRad) {
m_lfCommRad = lfCommRad;
m_lfVel = 0.25;
m_nDim = 2;
}
public TreeDeployAgent(double lfCommRad, double lfVel) {
m_lfCommRad = lfCommRad;
m_lfVel = lfVel;
m_nDim = 2;
}
public TreeDeployAgent(TreeDeployAgent src) {
m_lfCommRad = src.m_lfCommRad;
m_nDim = src.m_nDim;
m_lfVel = src.m_lfVel;
}
public boolean checkStateValidity(StateBundle state) {
// TODO Auto-generated method stub
return false;
}
/**
*
Given the state of an agent, and the channels
* it can send messages on, push the next set of messages
* onto the appropriate channels.
* Channels are assumed to be modified by this operation.
* One weakness of this signature is that it requires
* programmer discipline not to look at the continuous state
* of agents other then your neighbors.
* @param discreteState discrete component of agent state
* @param arrLfStateCont global vector of continuous state
* @param nIdxStateOffset offset into global state vector
* corresonding to this agent.
* @param channelsToSendOn Iterator containing objects of type
* CommLink corresponding to channels to send messages
* on (neighbor indices can be ascertained from channels).
* @see CommLink for type handled by iterator
*/
public void getMsgs(ILogicVarBundle discreteState,
IDiscreteDynamicsCallback dynCallback,
double arrLfStateCont[],
double lfCurrTime,
int nIdxStateOffset,
Iterator channelsToSendOn)
{
dynCallback.doCallback(discreteState, arrLfStateCont);
AgentMsgHelpers.PosMsg msg =
new AgentMsgHelpers.PosMsg(arrLfStateCont, nIdxStateOffset,2);
while(channelsToSendOn.hasNext()) {
CommLink linkSendOn =
(CommLink)channelsToSendOn.next();
if(linkSendOn != null && linkSendOn.queue() != null) {
linkSendOn.queue().sendMsg(new AgentMsgHelpers.PosMsg(msg) );
}
}
}
public ITreeAlgAgent makeCopy() {
// TODO Auto-generated method stub
return new TreeDeployAgent(this);
}
public StateBundle updateState(ILogicVarBundle statePrev,
double[] arrLfStateCont, double lfCurrTime,
int idxStateOffset, IEnvironment env,
Iterator channelsRecieveFrom) {
// TODO Auto-generated method stub
DistributedDelaunayClip clipAgent =
new DistributedDelaunayClip(arrLfStateCont[idxStateOffset],
arrLfStateCont[idxStateOffset+1]);
while(channelsRecieveFrom.hasNext()) {
CommLink link = channelsRecieveFrom.next();
IMsgChannel channel = link.queue();
IMsg msg = channel.readMsg();
if(link.from() == link.to()) {
continue;
}
AgentMsgHelpers.PosMsg posMsg = (AgentMsgHelpers.PosMsg)msg;
clipAgent.addEdge(link.from(),
posMsg.getPos(0), posMsg.getPos(1));
}
double [] arrLfCurrPos =
MathUtils.arrDblCpyRange(arrLfStateCont,
idxStateOffset, idxStateOffset+2);
//
// add boundary to make voronoi cells closed
IBoundary bounds = env.getBoundary();
double [] arrLfMinBound = bounds.bboxMinCorner();
double [] arrLfMaxBound = bounds.bboxMaxCorner();
double [] arrLfTmp = new double[2];
arrLfTmp[0] = arrLfCurrPos[0];
arrLfTmp[1] = arrLfMinBound[1] +
(arrLfMinBound[1]-arrLfCurrPos[1]);
clipAgent.addEdge(-1, arrLfTmp[0], arrLfTmp[1]);
arrLfTmp[1] = arrLfMaxBound[1] +
(arrLfMaxBound[1]-arrLfCurrPos[1]);
clipAgent.addEdge(-1, arrLfTmp[0], arrLfTmp[1]);
arrLfTmp[1] = arrLfCurrPos[1];
arrLfTmp[0] = arrLfMinBound[0] +
(arrLfMinBound[0]-arrLfCurrPos[0]);
clipAgent.addEdge(-1, arrLfTmp[0], arrLfTmp[1]);
arrLfTmp[0] = arrLfMaxBound[0] +
(arrLfMaxBound[0]-arrLfCurrPos[0]);
clipAgent.addEdge(-1, arrLfTmp[0], arrLfTmp[1]);
//
// end of "add boundary to make voronoi cells closed"
VoronoiHolder stateNext = null;
stateNext = new VoronoiHolder(
new NullLogicVarBundle(idxStateOffset/2),
clipAgent);
IScalarField scalField =
new ScalarFieldUtils.ScalarFieldFromEnv(env,0);
IScalarField fieldX =
new ScalarFieldUtils.LinearScalarField(arrLfCurrPos[0],
arrLfCurrPos[1], 0, 0.0);
fieldX =
new ScalarFieldUtils.ScalarFieldProduct(fieldX,scalField);
IScalarField fieldY =
new ScalarFieldUtils.LinearScalarField(arrLfCurrPos[0],
arrLfCurrPos[1], 1, 0.0);
fieldY =
new ScalarFieldUtils.ScalarFieldProduct(fieldY,scalField);
double lfIntegralX = 0.0, lfIntegralY = 0.0, lfIntegral = 0.0;
double lfAreaEps = 0.05; // was 0.01
IAreaIntegrator integrator =
new NumericalAreaIntegrator(scalField, lfAreaEps);
IAreaIntegrator integratorX =
new NumericalAreaIntegrator(fieldX, lfAreaEps);
IAreaIntegrator integratorY =
new NumericalAreaIntegrator(fieldY, lfAreaEps);
while(clipAgent.hasNext()) {
DistributedDelaunayClip.Edge currEdge = clipAgent.next();
lfIntegral += integrator.integrateClippedTriangle(arrLfCurrPos,
clipAgent.getEdgeStart(currEdge,100*m_lfCommRad),
clipAgent.getEdgeEnd(currEdge,100*m_lfCommRad),
m_lfCommRad, arrLfCurrPos);
lfIntegralX += integratorX.integrateClippedTriangle(arrLfCurrPos,
clipAgent.getEdgeStart(currEdge,100*m_lfCommRad),
clipAgent.getEdgeEnd(currEdge,100*m_lfCommRad),
m_lfCommRad, arrLfCurrPos);
lfIntegralY += integratorY.integrateClippedTriangle(arrLfCurrPos,
clipAgent.getEdgeStart(currEdge,100*m_lfCommRad),
clipAgent.getEdgeEnd(currEdge,100*m_lfCommRad),
m_lfCommRad, arrLfCurrPos);
}
double lfNewPosX = 0.0;
double lfNewPosY = 0.0;
if(Math.abs(lfIntegral) > 0.0) {
lfNewPosX = lfIntegralX/lfIntegral;
lfNewPosY = lfIntegralY/lfIntegral;
}
IControlFunc ctrlFunc =
new ControlFuncMoveTowards(
lfNewPosX + arrLfCurrPos[0],
lfNewPosY + arrLfCurrPos[1],
m_lfVel);
return new StateBundle(stateNext,
ctrlFunc);
}
public IMsg getMsgAnnotation(ILogicVarBundle vars,
double [] arrLfState, int nIdx) {
return new AgentMsgHelpers.PosMsg(arrLfState,
nIdx*m_nDim, m_nDim);
}
public java.lang.reflect.Type getAnnoteType() {
return AgentMsgHelpers.PosMsg.class;
}
class lclCompare implements java.util.Comparator {
TreeConstraintState m_agentSorting;
AgentMsgHelpers.PosMsg m_posMsg;
public lclCompare(TreeConstraintState agentSorting)
{
m_agentSorting = agentSorting;
m_posMsg = (AgentMsgHelpers.PosMsg)
(m_agentSorting.getMsgAddition(AgentMsgHelpers.PosMsg.class));
}
/**
* smaller number means more preference.
*/
public int compare(TreeConstraintState treeState1,
TreeConstraintState treeState2) {
IMsg attach1 = treeState1.getMsgAddition(AgentMsgHelpers.PosMsg.class);
IMsg attach2 = treeState2.getMsgAddition(AgentMsgHelpers.PosMsg.class);
// prefer to attach to things other than yourself
if(treeState1.getId() == m_agentSorting.getId() &&
treeState2.getId() != m_agentSorting.getId()) {
return 1;
} else if(treeState2.getId() == m_agentSorting.getId() &&
treeState1.getId() != m_agentSorting.getId()) {
return -1;
}
if(treeState1.getRootId() >= 0 &&
treeState1.getRootId() < treeState2.getRootId()) {
return -1;
}
if(treeState2.getRootId() >= 0 &&
treeState2.getRootId() < treeState1.getRootId()) {
return 1;
}
try {
AgentMsgHelpers.PosMsg pos1 =
(AgentMsgHelpers.PosMsg) attach1;
AgentMsgHelpers.PosMsg pos2 =
(AgentMsgHelpers.PosMsg) attach2;
double lfDist1Sqrd = m_posMsg.getDistSqrd(pos1);
double lfDist2Sqrd = m_posMsg.getDistSqrd(pos2);
if(lfDist1Sqrd < lfDist2Sqrd) {
return -1;
}
if(lfDist1Sqrd > lfDist2Sqrd) {
return 1;
}
} catch(Exception e) {
}
if(treeState1.getId() == m_agentSorting.getParentId() &&
treeState2.getId() != m_agentSorting.getParentId()) {
return -1;
}
if(treeState2.getId() == m_agentSorting.getParentId() &&
treeState1.getId() != m_agentSorting.getParentId()) {
return 1;
}
return 0; // equality if all else fails
}
}
/**
* gets a comparator for sorting ITreeAlgAgent nodes by preference
* @return Comparator -- smaller number means more preference
*/
public java.util.Comparator
getPrefComp(TreeConstraintState agentSorting) {
return new lclCompare(agentSorting);
}
}