package jp.ac.fit.asura.nao.motion.motions;
import javax.vecmath.Matrix3f;
import javax.vecmath.Vector3f;
import jp.ac.fit.asura.nao.Joint;
import jp.ac.fit.asura.nao.misc.Coordinates;
import jp.ac.fit.asura.nao.misc.Kinematics;
import jp.ac.fit.asura.nao.misc.MathUtils;
import jp.ac.fit.asura.nao.misc.MatrixUtils;
import jp.ac.fit.asura.nao.misc.SingularPostureException;
import jp.ac.fit.asura.nao.motion.Motion;
import jp.ac.fit.asura.nao.motion.MotionParam;
import jp.ac.fit.asura.nao.motion.MotionParam.ShotParam;
import jp.ac.fit.asura.nao.physical.Robot;
import jp.ac.fit.asura.nao.physical.Robot.Frames;
import jp.ac.fit.asura.nao.sensation.FrameState;
import jp.ac.fit.asura.nao.sensation.SomaticContext;
import jp.ac.fit.asura.vecmathx.GfVector;
import org.apache.log4j.Logger;
/**
*
* @author sey
*
*/
public class GeneralizedKick extends Motion {
private static final Logger log = Logger.getLogger(GeneralizedKick.class);
ShotParam lastParam;
float[] frames;
int[] times;
int sequence;
int sequenceStep;
boolean isStarted;
long startTime;
int totalTimes;
public GeneralizedKick() {
setName("GeneralizedKick");
}
private void setBodyAngles(SomaticContext sc, float[] framesInDeg) {
assert framesInDeg.length == 20;
sc.get(Frames.LShoulderPitch).setAngle(
MathUtils.toRadians(framesInDeg[0]));
sc.get(Frames.LShoulderRoll).setAngle(
MathUtils.toRadians(framesInDeg[1]));
sc.get(Frames.LElbowYaw).setAngle(MathUtils.toRadians(framesInDeg[2]));
sc.get(Frames.LElbowRoll).setAngle(MathUtils.toRadians(framesInDeg[3]));
sc.get(Frames.LHipYawPitch).setAngle(
MathUtils.toRadians(framesInDeg[4]));
sc.get(Frames.LHipRoll).setAngle(MathUtils.toRadians(framesInDeg[5]));
sc.get(Frames.LHipPitch).setAngle(MathUtils.toRadians(framesInDeg[6]));
sc.get(Frames.LKneePitch).setAngle(MathUtils.toRadians(framesInDeg[7]));
sc.get(Frames.LAnklePitch)
.setAngle(MathUtils.toRadians(framesInDeg[8]));
sc.get(Frames.LAnkleRoll).setAngle(MathUtils.toRadians(framesInDeg[9]));
sc.get(Frames.RHipYawPitch).setAngle(
MathUtils.toRadians(framesInDeg[10]));
sc.get(Frames.RHipRoll).setAngle(MathUtils.toRadians(framesInDeg[11]));
sc.get(Frames.RHipPitch).setAngle(MathUtils.toRadians(framesInDeg[12]));
sc.get(Frames.RKneePitch)
.setAngle(MathUtils.toRadians(framesInDeg[13]));
sc.get(Frames.RAnklePitch).setAngle(
MathUtils.toRadians(framesInDeg[14]));
sc.get(Frames.RAnkleRoll)
.setAngle(MathUtils.toRadians(framesInDeg[15]));
sc.get(Frames.RShoulderPitch).setAngle(
MathUtils.toRadians(framesInDeg[16]));
sc.get(Frames.RShoulderRoll).setAngle(
MathUtils.toRadians(framesInDeg[17]));
sc.get(Frames.RElbowYaw).setAngle(MathUtils.toRadians(framesInDeg[18]));
sc.get(Frames.RElbowRoll)
.setAngle(MathUtils.toRadians(framesInDeg[19]));
}
private void setDefaultPosition(SomaticContext sc) {
setBodyAngles(sc, new float[] { 110, 20, -80, -90, 0, 0, -25, 40, -20,
0, 0, 0, -25, 40, -20, 0, 110, -20, 80, 90 });
}
private void setReadyPositionRight(SomaticContext sc) {
setBodyAngles(sc, new float[] { 110, 20, -80, -90, 0, -15, -25, 40,
-20, 20, 0, -15, -25, 40, -20, 20, 110, -20, 80, 90 });
}
@Override
public void start(MotionParam param) throws IllegalArgumentException {
isStarted = false;
startTime = context.getTime();
log.debug("start" + startTime);
ShotParam sp;
if (lastParam != null && lastParam.equals(param))
return;
if (param instanceof ShotParam) {
sp = (ShotParam) param;
} else {
assert false;
sp = new ShotParam();
}
generateMotion(sp);
}
private void generateMotion(ShotParam sp) {
Robot robot = context.getSomaticContext().getRobot();
SomaticContext sc = new SomaticContext(context.getSomaticContext());
int len = 9;
int joints = Joint.values().length - 2;
frames = new float[len * joints];
int[] timesJointSpace = new int[len];
try {
log.debug("ball: " + sp.getBall());
// 腕をセット
sc.get(Frames.LShoulderPitch).setAngle(MathUtils.toRadians(110));
sc.get(Frames.LShoulderRoll).setAngle(MathUtils.toRadians(20));
sc.get(Frames.LElbowYaw).setAngle(MathUtils.toRadians(-80));
sc.get(Frames.LElbowRoll).setAngle(MathUtils.toRadians(-90));
sc.get(Frames.RShoulderPitch).setAngle(MathUtils.toRadians(110));
sc.get(Frames.RShoulderRoll).setAngle(MathUtils.toRadians(-20));
sc.get(Frames.RElbowYaw).setAngle(MathUtils.toRadians(80));
sc.get(Frames.RElbowRoll).setAngle(MathUtils.toRadians(90));
Vector3f vec1 = new Vector3f(-4.7f, 1.71f, 4.93f);
vec1.scale(MathUtils.PIf / 180);
Matrix3f supportRot = new Matrix3f();
MatrixUtils.pyr2rot(vec1, supportRot);
Vector3f vec2 = new Vector3f(0, 0, 5);
vec2.scale(MathUtils.PIf / 180);
Matrix3f swingRot = new Matrix3f();
MatrixUtils.pyr2rot(vec2, swingRot);
for (int i = 0; i < len; i++) {
log.trace("Frame " + i);
FrameState ls = new FrameState(robot.get(Frames.LSole));
FrameState rs = new FrameState(robot.get(Frames.RSole));
switch (i) {
case 0:
// 腰を落とす
setDefaultPosition(sc);
timesJointSpace[i] = 1000;
break;
case 1:
// 腰を落とす
setDefaultPosition(sc);
timesJointSpace[i] = 800;
break;
case 2:
// 支持脚(左足)に体重を移す
setReadyPositionRight(sc);
timesJointSpace[i] = 800;
break;
case 3:
// 脚を上げる
ls.getBodyPosition().set(5, -310, 20);
rs.getBodyPosition().set(-87, -284, 6.9f);
ls.getBodyRotation().set(supportRot);
rs.getBodyRotation().set(swingRot);
Kinematics.calculateInverse(sc, ls);
// Kinematics.calculateInverse(sc, rs);
Kinematics.calculateInverse(sc, rs, 1, 1, 1, 0.125f,
0.125f, 0.125f);
timesJointSpace[i] = 800;
break;
case 4:
// 蹴る
ls.getBodyPosition().set(5, -310, 20);
ls.getBodyRotation().set(supportRot);
Vector3f ball = new Vector3f();
Coordinates.robot2bodyCoord(sc, sp.getBall(), ball);
sp.getBall().z *= 0.75f;
sp.getBall().z = MathUtils.clipAbs(sp.getBall().z, 180);
// sp.getBall().y = MathUtils.clipAbs(sp.getBall().y, 250);
rs.getBodyPosition().set(sp.getBall());
// rs.getBodyPosition().set(new Vector3f(-78, -252, 158));
// Vector3f vec3 = new Vector3f(-9.41f, 3.4f, 4.71f);
// vec3.scale(MathUtils.PIf / 180);
// MatrixUtils.pyr2rot(vec3, rs.getBodyRotation());
//
rs.getBodyRotation().set(swingRot);
log.debug("Shot target:" + sp.getBall());
Kinematics.calculateInverse(sc, ls);
Kinematics.calculateInverse(sc, rs, 0.125f, 0.0001f, 0.25f,
0, 0, 0);
timesJointSpace[i] = 400;
break;
case 5:
// 脚を戻す
ls.getBodyPosition().set(5, -310, 20);
rs.getBodyPosition().set(-87, -284, 6.9f);
ls.getBodyRotation().set(supportRot);
rs.getBodyRotation().set(swingRot);
Kinematics.calculateInverse(sc, ls);
Kinematics.calculateInverse(sc, rs, 1, 1, 1, 0.125f,
0.125f, 0.125f);
timesJointSpace[i] = 800;
break;
case 6:
// 脚をおろす
setReadyPositionRight(sc);
timesJointSpace[i] = 800;
break;
case 7:
case 8:
// 腰を戻す
setDefaultPosition(sc);
timesJointSpace[i] = 500;
break;
}
// 計算結果をモーションデータにセット
for (Frames f : Frames.values())
if (f.isJoint() && f != Frames.HeadYaw
&& f != Frames.HeadPitch) {
int idx = i * joints + f.toJoint().ordinal() - 2;
if (idx >= 0)
frames[idx] = sc.get(f).getAngle();
}
}
} catch (SingularPostureException e) {
totalTimes = 0;
e.printStackTrace();
return;
}
int time = 500;
this.times = new int[timesJointSpace.length];
for (int i = 0; i < timesJointSpace.length; i++) {
time += timesJointSpace[i];
this.times[i] = time;
}
totalTimes = time + 1000;
log.debug("new GeneralizedKick with matrix:" + frames.length
+ " totalTimes:" + totalTimes);
}
@Override
public boolean canAccept(MotionParam param) {
ShotParam sp;
if (param != null && param instanceof ShotParam) {
sp = (ShotParam) param;
} else {
return false;
}
try {
generateMotion(sp);
lastParam = sp;
return true;
} catch (SingularPostureException spe) {
return false;
}
}
@Override
public void stop() {
log.debug("stop" + System.currentTimeMillis());
}
@Override
public void step() {
if (isStarted)
return;
context.getRobotContext().getEffector().setBodyJoints(frames, times);
isStarted = true;
}
@Override
public boolean hasNextStep() {
long current = context.getTime();
return current - startTime < totalTimes;
}
}