/*
* 作成日: 2008/12/30
*/
package jp.ac.fit.asura.nao.webots;
import java.util.EnumMap;
import jp.ac.fit.asura.nao.Effector;
import jp.ac.fit.asura.nao.Joint;
import jp.ac.fit.asura.nao.PressureSensor;
import jp.ac.fit.asura.nao.Sensor;
import jp.ac.fit.asura.nao.SensorContext;
import jp.ac.fit.asura.nao.misc.MathUtils;
import com.cyberbotics.webots.controller.Accelerometer;
import com.cyberbotics.webots.controller.DistanceSensor;
import com.cyberbotics.webots.controller.GPS;
import com.cyberbotics.webots.controller.Gyro;
import com.cyberbotics.webots.controller.Robot;
import com.cyberbotics.webots.controller.Servo;
import com.cyberbotics.webots.controller.TouchSensor;
/**
* @author sey
*
* @version $Id: $
*
*/
class Webots6Driver {
private WebotsSensor sensor;
private WebotsEffector effector;
private EnumMap<Joint, Servo> joints;
private EnumMap<PressureSensor, TouchSensor> fsr;
private DistanceSensor[] usSensors;
private Accelerometer accelerometer;
private Gyro gyro;
private GPS gps;
private EnumMap<Joint, Boolean> power;
private Robot robot;
private long time;
/**
*
*/
public Webots6Driver(Robot robot) {
this.robot = robot;
joints = new EnumMap<Joint, Servo>(Joint.class);
for (Joint joint : Joint.values()) {
Servo device = robot.getServo(joint.toString());
device.enablePosition(Webots6Player.SIMULATION_STEP);
device.enableMotorForceFeedback(Webots6Player.SIMULATION_STEP);
joints.put(joint, device);
}
fsr = new EnumMap<PressureSensor, TouchSensor>(PressureSensor.class);
for (PressureSensor ts : PressureSensor.values()) {
TouchSensor device = robot.getTouchSensor(ts.getDeviceTag());
device.enable(Webots6Player.SIMULATION_STEP);
fsr.put(ts, device);
}
accelerometer = robot.getAccelerometer("accelerometer");
accelerometer.enable(Webots6Player.SIMULATION_STEP);
gyro = robot.getGyro("gyro");
gyro.enable(Webots6Player.SIMULATION_STEP);
usSensors = new DistanceSensor[4];
usSensors[0] = robot.getDistanceSensor("US/TopRight");
usSensors[0].enable(Webots6Player.SIMULATION_STEP);
usSensors[1] = robot.getDistanceSensor("US/BottomRight");
usSensors[1].enable(Webots6Player.SIMULATION_STEP);
usSensors[2] = robot.getDistanceSensor("US/TopLeft");
usSensors[2].enable(Webots6Player.SIMULATION_STEP);
usSensors[3] = robot.getDistanceSensor("US/BottomLeft");
usSensors[3].enable(Webots6Player.SIMULATION_STEP);
// GPSセンサ
gps = robot.getGPS("gps");
gps.enable(Webots6Player.SIMULATION_STEP);
sensor = new WebotsSensor();
effector = new WebotsEffector();
power = new EnumMap<Joint, Boolean>(Joint.class);
for (Joint j : Joint.values())
power.put(j, Boolean.TRUE);
}
Sensor getSensor() {
return sensor;
}
Effector getEffector() {
return effector;
}
private class WebotsSensor implements Sensor {
@Override
public SensorContext create() {
return new WebotsSensorContext();
}
@Override
public void update(SensorContext sensorContext) {
WebotsSensorContext sc = (WebotsSensorContext) sensorContext;
for (Joint joint : Joint.values()) {
sc.jointValues[joint.ordinal()] = (float) joints.get(joint)
.getPosition();
sc.jointForces[joint.ordinal()] = (float) joints.get(joint)
.getMotorForceFeedback();
}
sc.accels[0] = (float) ((accelerometer.getValues())[1]);
sc.accels[1] = (float) ((accelerometer.getValues())[2]);
sc.accels[2] = (float) ((accelerometer.getValues())[0]);
sc.gyros[0] = (float) ((gyro.getValues())[1]);
sc.gyros[1] = (float) ((gyro.getValues())[0]);
for (PressureSensor ps : PressureSensor.values())
sc.forces[ps.ordinal()] = (float) fsr.get(ps).getValue();
sc.gps[0] = (float) ((gps.getValues())[0]);
sc.gps[1] = (float) ((gps.getValues())[1]);
sc.gps[2] = (float) ((gps.getValues())[2]);
sc.time = time;
}
@Override
public void poll() {
}
@Override
public boolean isSupported(Function func) {
switch (func) {
case ACCEL:
case GYRO:
case FORCE:
case JOINT_ANGLE:
case JOINT_FORCE:
case GPS:
return true;
default:
return false;
}
}
@Override
public void init() {
}
@Override
public void before() {
}
@Override
public void after() {
}
}
private class WebotsEffector implements Effector {
private float[] eAngles;
private boolean hasTimedCommand;
private float[] angleMatrix;
private int[] durationInMills;
private int commandTime;
private int commandIndex;
public WebotsEffector() {
eAngles = new float[Joint.values().length];
}
@Override
public void setJoint(Joint joint, float valueInRad) {
assert joints.containsKey(joint);
eAngles[joint.ordinal()] = valueInRad;
}
@Override
public void setJoint(Joint joint, float valueInRad, int durationInMills) {
// FIXME implement
assert joints.containsKey(joint);
eAngles[joint.ordinal()] = valueInRad;
}
@Override
public void setJointDegree(Joint joint, float valueInDeg) {
setJoint(joint, MathUtils.toRadians(valueInDeg));
}
@Override
public void setJointMicro(Joint joint, int valueInMicroRad) {
setJoint(joint, valueInMicroRad / 1000000.0F);
}
@Override
public void setJoint(Joint joint, float[] angleValues,
int[] durationInMills) {
}
@Override
public void setBodyJoints(float[] angleMatrix, int[] durationInMills) {
if (hasTimedCommand)
return;
this.angleMatrix = angleMatrix;
this.durationInMills = durationInMills;
hasTimedCommand = true;
commandTime = 0;
commandIndex = 0;
}
public void setForce(Joint joint, float value) {
if (power.get(joint).booleanValue()) {
joints.get(joint).setForce(value);
// jointForces[joint.ordinal()] = value;
}
}
@Override
public void setPower(float power) {
for (Joint j : Joint.values())
Webots6Driver.this.power.put(j, power != 0);
}
@Override
public void setPower(Joint joint, float power) {
}
@Override
public void setLed(String ledName, float luminance) {
}
@Override
public void init() {
}
@Override
public void before() {
robot.step(Webots6Player.SIMULATION_STEP);
time += Webots6Player.SIMULATION_STEP;
}
@Override
public void after() {
// TimedCommandがあるときは処理を分ける
if (hasTimedCommand) {
do {
if (commandTime > durationInMills[commandIndex + 1]) {
commandIndex++;
}
if (commandIndex + 1 == durationInMills.length) {
hasTimedCommand = false;
return;
}
} while (commandTime > durationInMills[commandIndex + 1]);
commandTime += Webots6Player.SIMULATION_STEP;
for (Joint joint : Joint.values()) {
if (!power.get(joint).booleanValue())
continue;
if (joint == Joint.HeadYaw || joint == Joint.HeadPitch) {
joints.get(joint).setPosition(eAngles[joint.ordinal()]);
continue;
}
int jointNum = Joint.values().length - 2;
float prev = angleMatrix[jointNum * (commandIndex)
+ joint.ordinal() - 2];
float next = angleMatrix[jointNum * (commandIndex + 1)
+ joint.ordinal() - 2];
int duration = durationInMills[commandIndex + 1]
- durationInMills[commandIndex];
int curTime = commandTime - durationInMills[commandIndex];
float cur = prev + (next - prev)
* ((float) curTime / duration);
eAngles[joint.ordinal()] = cur;
joints.get(joint).setPosition(cur);
}
return;
}
for (Joint joint : Joint.values())
if (power.get(joint).booleanValue())
joints.get(joint).setPosition(eAngles[joint.ordinal()]);
}
@Override
public void say(String text) {
}
}
}