package org.myrobotlab.headtracking; import java.io.Serializable; import java.util.ArrayList; import org.myrobotlab.kinematics.Point; import org.myrobotlab.logging.LoggerFactory; import org.myrobotlab.service.OculusRift; import org.myrobotlab.service.data.OculusData; import org.slf4j.Logger; import com.oculusvr.capi.Hmd; import com.oculusvr.capi.HmdDesc; import com.oculusvr.capi.TrackingState; /** * OculusHeadTracking -This is a helper thread that will poll the oculus head * tracking information and it will publish the roll/pitch/yaw information. * */ public class OculusHeadTracking implements Runnable, Serializable { public final static Logger log = LoggerFactory.getLogger(OculusHeadTracking.class); private static final long serialVersionUID = -4067064437788846187L; protected final Hmd hmd; protected final HmdDesc hmdDesc; boolean running = false; transient public OculusRift oculus; transient Thread trackerThread = null; private int pollIntervalMS = 20; public OculusHeadTracking(Hmd hmd, HmdDesc hmdDesc) { // Grab a handle to the initialized hmd. this.hmd = hmd; this.hmdDesc = hmdDesc; } @Override public void run() { running = true; while (running) { TrackingState trackingState = hmd.getTrackingState(0); // TODO: do we care about "w" ? // double w = Math.toDegrees(trackingState.HeadPose.Pose.Orientation.w); // rotations about x axis (pitch) double pitch = Math.toDegrees(trackingState.HeadPose.Pose.Orientation.x); // rotation about y axis (yaw) double yaw = Math.toDegrees(trackingState.HeadPose.Pose.Orientation.y); // rotation about z axis (roll) double roll = Math.toDegrees(trackingState.HeadPose.Pose.Orientation.z); // log.info("Roll: " + z*RAD_TO_DEGREES); // log.info("Pitch:"+ x*RAD_TO_DEGREES); // log.info("Yaw:"+ y*RAD_TO_DEGREES ); // TODO: remove the oculus data class and just use the point publisher // stuff. OculusData headTrackingData = new OculusData(roll, pitch, yaw); oculus.invoke("publishOculusData", headTrackingData); // positional information. double x = trackingState.HeadPose.Pose.Position.x; double y = trackingState.HeadPose.Pose.Position.y; double z = trackingState.HeadPose.Pose.Position.z; ArrayList<Point> points = new ArrayList<Point>(); points.add(new Point(x, y, z, roll, pitch, yaw)); oculus.invoke("publishPoints", points); try { // There need to be polling interval here. Thread.sleep(pollIntervalMS); } catch (InterruptedException e) { e.printStackTrace(); // break out ... break; } } } public boolean isRunning() { return running; } public void setRunning(boolean running) { this.running = running; } public OculusRift getOculus() { return oculus; } public void setOculus(OculusRift oculus) { this.oculus = oculus; } public void start() { log.info("starting head tracking"); if (trackerThread != null) { log.info("Head tracker thread already started."); return; } trackerThread = new Thread(this, String.format("%s_oculusHeadTracking", oculus.getName())); trackerThread.start(); } public void stop() { log.debug("stopping head tracking"); running = false; trackerThread = null; } // default 20 ms public int getPollIntervalMS() { return pollIntervalMS; } public void setPollIntervalMS(int pollIntervalMS) { this.pollIntervalMS = pollIntervalMS; } }