package jp.ac.fit.asura.nao.communication; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import jp.ac.fit.asura.nao.localization.WorldObject; import jp.ac.fit.asura.nao.localization.WorldObject_set; import jp.ac.fit.asura.nao.localization.WorldObjects; import jp.ac.fit.asura.nao.physical.Ball; import jp.ac.fit.asura.nao.strategy.Role; import jp.ac.fit.asura.nao.strategy.StrategyContext; import org.apache.log4j.Logger; public class AsuraLinkStrategyReceiveData extends AsuraLinkReceiveData { private Logger log = Logger.getLogger(AsuraLinkStrategyReceiveData.class); private StrategyContext context; /** * ストラテジの協調でやり取りするデータを表す内部クラス. 受信時刻、ペナルティ状態、ポジションとWorldObjectの情報. * * @author takata */ private class StrategyInfo extends WorldObject_set { /** データを受信した時刻 **/ private long time; /** ペナルティ状態 */ private boolean isPenalty; /** ポジション */ private Role role; /** WorldObjectデータ */ private Map<WorldObjects, WorldObject> wo; /** コンストラクタ */ protected StrategyInfo() { wo = new HashMap<WorldObjects, WorldObject>(); // WorldObjectをインスタンス化 for (WorldObjects type : WorldObjects.values()) { wo.put(type, new WorldObject(type)); } } /** * 受信時刻を更新する. * * @param time * データを受信した時刻 */ protected void updateTime(long time) { this.time = time; log.trace("set Time receiving strategy data : " + time); } /** * ポジションを更新する. * * @param role */ protected void updateRole(int roleNum) { role = Role.toRole(roleNum); } /** * ペナルティ状態を更新する. * * @param isPenalty * Penalizedなら1 */ protected void updateIsPenalty(int isPenalty) { if (isPenalty == 1) { this.isPenalty = true; } else { this.isPenalty = false; } } /** * WorldObjectの情報を更新する. 信頼度, X座標, Y座標, 距離, Heading, 最後に認識してからの時間 * (Selfは+Yaw姿勢) のみ. * * @param type * @param w */ protected void updateWorldObjectData(ByteBuffer buf) { WorldObjects type = WorldObjects.toWorldObjects(buf.getInt()); WorldObject obj = wo.get(type); setConfidence(obj, buf.getInt()); setTeamX(obj, buf.getInt()); setTeamY(obj, buf.getInt()); setDistance(obj, buf.getInt()); setHeading(obj, buf.getFloat()); setDifftime(obj, buf.getLong()); if (type == WorldObjects.Self) setTeamYaw(obj, buf.getFloat()); log.trace("update " + type + "'s data. conf:" + obj.getConfidence() + " x:" + obj.getX() + " y:" + obj.getY() + " dist:" + obj.getDistance() + " head:" + obj.getHeading() + " diff:" + obj.getDifftime()); } /** * 情報が古い場合は信頼度を0にする. */ protected void checkData() { long diff = context.getTime() - time; if (diff > 10000) { for (WorldObjects type : WorldObjects.values()) { wo.get(type).invalidate(); } } } } /** 他ロボットのデータ */ private List<StrategyInfo> teammate_data; /** コンストラクタ */ public AsuraLinkStrategyReceiveData(StrategyContext context) { super(context); this.context = context; teammate_data = new ArrayList<StrategyInfo>(); // プレイヤー数だけStrategyInfoをインスタンス化 for (int i = 0; i < TeamInfo.MAX_NUM_PLAYERS; i++) { teammate_data.add(i, new StrategyInfo()); } } @Override public void parseBuf(ByteBuffer buf, int sender, long frame) { StrategyInfo data = teammate_data.get(sender-1); data.updateTime(frame); // 受信時刻の更新 data.updateRole(buf.getInt()); // ポジションの更新 data.updateIsPenalty(buf.getInt()); // ペナルティ状態の更新 for (WorldObjects type : WorldObjects.values()) { data.updateWorldObjectData(buf); } } /** * robotIdから受け取ったデータを持っているWorldObjectを取得する. * * @param type * @param robotId * @return */ public WorldObject get(WorldObjects type, int robotId) { log.trace("get Object's data: " + type + " " + robotId); return teammate_data.get(robotId-1).wo.get(type); } /** * ロボットIDがrobotIdであるチームメイトのペナルティ状態を取得する. * @param robotId * @return */ public boolean isPenalized(int robotId) { return teammate_data.get(robotId-1).isPenalty; } /** * ロボットIDがrobotIdであるチームメイトのポジションを取得する. * @param robotId * @return */ public Role getRole(int robotId) { return teammate_data.get(robotId-1).role; } /** * 情報が古くないか確認する. */ public void checkData() { for (StrategyInfo td : teammate_data) { td.checkData(); } } }