mirror of
https://github.com/SlimeVR/SlimeVR-Server.git
synced 2026-04-06 02:01:58 +02:00
AutoBone: Add more configs, fix recording reading
This commit is contained in:
@@ -134,8 +134,6 @@ public class SkeletonConfig extends EJBag {
|
||||
} else {
|
||||
frameRecordings.add(Pair.of(file.getName(), frames));
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,14 +163,18 @@ public class SkeletonConfig extends EJBag {
|
||||
LogManager.log.info("[AutoBone] Processing frames from \"" + recording.getKey() + "\"...");
|
||||
autoBone.setFrames(recording.getValue());
|
||||
|
||||
int epochs = server.config.getInt("autobone.epochCount", AutoBone.NUM_EPOCHS);
|
||||
autoBone.minDataDistance = server.config.getInt("autobone.minimumDataDistance", autoBone.minDataDistance);
|
||||
autoBone.maxDataDistance = server.config.getInt("autobone.maximumDataDistance", autoBone.maxDataDistance);
|
||||
autoBone.numEpochs = server.config.getInt("autobone.epochCount", autoBone.numEpochs);
|
||||
autoBone.initialAdjustRate = server.config.getFloat("autobone.adjustRate", autoBone.initialAdjustRate);
|
||||
autoBone.adjustRateDecay = server.config.getFloat("autobone.adjustRateDecay", autoBone.adjustRateDecay);
|
||||
autoBone.slideErrorFactor = server.config.getFloat("autobone.slideErrorFactor", autoBone.slideErrorFactor);
|
||||
autoBone.offsetErrorFactor = server.config.getFloat("autobone.offsetErrorFactor", autoBone.offsetErrorFactor);
|
||||
autoBone.heightErrorFactor = server.config.getFloat("autobone.heightErrorFactor", autoBone.heightErrorFactor);
|
||||
|
||||
boolean calcInitError = server.config.getBoolean("autobone.calculateInitialError", true);
|
||||
float adjustRate = server.config.getFloat("autobone.adjustRate", AutoBone.INITIAL_ADJUSTMENT_RATE);
|
||||
float adjustRateDecay = server.config.getFloat("autobone.adjustRateDecay", AutoBone.ADJUSTMENT_RATE_DECAY);
|
||||
int minDataDist = server.config.getInt("autobone.minimumDataDistance", AutoBone.MIN_DATA_DISTANCE);
|
||||
int maxDataDist = server.config.getInt("autobone.maximumDataDistance", AutoBone.MAX_DATA_DISTANCE);
|
||||
float targetHeight = server.config.getFloat("autobone.manualTargetHeight", -1f);
|
||||
heightPercentError.add(autoBone.processFrames(epochs, calcInitError, adjustRate, adjustRateDecay, minDataDist, maxDataDist, targetHeight));
|
||||
heightPercentError.add(autoBone.processFrames(calcInitError, targetHeight));
|
||||
|
||||
LogManager.log.info("[AutoBone] Done processing!");
|
||||
|
||||
|
||||
@@ -17,35 +17,35 @@ import io.eiren.vr.processor.HumanSkeletonWithWaist;
|
||||
|
||||
public class AutoBone {
|
||||
|
||||
public final static int MIN_DATA_DISTANCE = 1;
|
||||
public final static int MAX_DATA_DISTANCE = 2;
|
||||
public int minDataDistance = 1;
|
||||
public int maxDataDistance = 2;
|
||||
|
||||
public final static int NUM_EPOCHS = 75;
|
||||
public int numEpochs = 100;
|
||||
|
||||
public final static float INITIAL_ADJUSTMENT_RATE = 2.5f;
|
||||
public final static float ADJUSTMENT_RATE_DECAY = 1.045f;
|
||||
public float initialAdjustRate = 2.5f;
|
||||
public float adjustRateDecay = 1.03f;
|
||||
|
||||
protected final static float SLIDE_ERROR_FACTOR = 1.0f;
|
||||
protected final static float OFFSET_ERROR_FACTOR = 0.0f;
|
||||
protected final static float HEIGHT_ERROR_FACTOR = 0.0f;
|
||||
public float slideErrorFactor = 1.0f;
|
||||
public float offsetErrorFactor = 0.0f;
|
||||
public float heightErrorFactor = 0.004f;
|
||||
|
||||
protected final static float HEADSET_HEIGHT_RATIO = 1.0f;
|
||||
/*
|
||||
public float NECK_WAIST_RATIO_MIN = 0.2f;
|
||||
public float NECK_WAIST_RATIO_MAX = 0.3f;
|
||||
|
||||
protected final static float NECK_WAIST_RATIO_MIN = 0.2f;
|
||||
protected final static float NECK_WAIST_RATIO_MAX = 0.3f;
|
||||
public float CHEST_WAIST_RATIO_MIN = 0.35f;
|
||||
public float CHEST_WAIST_RATIO_MAX = 0.6f;
|
||||
|
||||
protected final static float CHEST_WAIST_RATIO_MIN = 0.35f;
|
||||
protected final static float CHEST_WAIST_RATIO_MAX = 0.6f;
|
||||
|
||||
protected final static float HIP_MIN = 0.08f;
|
||||
protected final static float HIP_WAIST_RATIO_MAX = 0.4f;
|
||||
public float HIP_MIN = 0.08f;
|
||||
public float HIP_WAIST_RATIO_MAX = 0.4f;
|
||||
|
||||
// Human average is 1.1235 (SD 0.07)
|
||||
protected final static float LEG_WAIST_RATIO_MIN = 1.1235f - ((0.07f * 3f) + 0.05f);
|
||||
protected final static float LEG_WAIST_RATIO_MAX = 1.1235f + ((0.07f * 3f) + 0.05f);
|
||||
public float LEG_WAIST_RATIO_MIN = 1.1235f - ((0.07f * 3f) + 0.05f);
|
||||
public float LEG_WAIST_RATIO_MAX = 1.1235f + ((0.07f * 3f) + 0.05f);
|
||||
|
||||
protected final static float KNEE_LEG_RATIO_MIN = 0.42f;
|
||||
protected final static float KNEE_LEG_RATIO_MAX = 0.58f;
|
||||
public float KNEE_LEG_RATIO_MIN = 0.42f;
|
||||
public float KNEE_LEG_RATIO_MAX = 0.58f;
|
||||
*/
|
||||
|
||||
protected final VRServer server;
|
||||
|
||||
@@ -234,34 +234,14 @@ public class AutoBone {
|
||||
}
|
||||
|
||||
public void processFrames() {
|
||||
processFrames(NUM_EPOCHS, true);
|
||||
processFrames(-1f);
|
||||
}
|
||||
|
||||
public void processFrames(float targetHeight) {
|
||||
processFrames(NUM_EPOCHS, true, targetHeight);
|
||||
processFrames(true, targetHeight);
|
||||
}
|
||||
|
||||
public void processFrames(int epochs, boolean calcInitError) {
|
||||
processFrames(epochs, calcInitError, INITIAL_ADJUSTMENT_RATE, ADJUSTMENT_RATE_DECAY);
|
||||
}
|
||||
|
||||
public void processFrames(int epochs, boolean calcInitError, float targetHeight) {
|
||||
processFrames(epochs, calcInitError, INITIAL_ADJUSTMENT_RATE, ADJUSTMENT_RATE_DECAY, targetHeight);
|
||||
}
|
||||
|
||||
public void processFrames(int epochs, boolean calcInitError, float adjustRate, float adjustRateDecay) {
|
||||
processFrames(epochs, calcInitError, adjustRate, adjustRateDecay, MIN_DATA_DISTANCE, MAX_DATA_DISTANCE);
|
||||
}
|
||||
|
||||
public void processFrames(int epochs, boolean calcInitError, float adjustRate, float adjustRateDecay, float targetHeight) {
|
||||
processFrames(epochs, calcInitError, adjustRate, adjustRateDecay, MIN_DATA_DISTANCE, MAX_DATA_DISTANCE, targetHeight);
|
||||
}
|
||||
|
||||
public void processFrames(int epochs, boolean calcInitError, float adjustRate, float adjustRateDecay, int minDataDist, int maxDataDist) {
|
||||
processFrames(epochs, calcInitError, adjustRate, adjustRateDecay, minDataDist, maxDataDist, -1f);
|
||||
}
|
||||
|
||||
public float processFrames(int epochs, boolean calcInitError, float adjustRate, float adjustRateDecay, int minDataDist, int maxDataDist, float targetHeight) {
|
||||
public float processFrames(boolean calcInitError, float targetHeight) {
|
||||
Set<Entry<String, Float>> configSet = configs.entrySet();
|
||||
|
||||
SimpleSkeleton skeleton1 = new SimpleSkeleton(configSet);
|
||||
@@ -269,7 +249,9 @@ public class AutoBone {
|
||||
|
||||
int epochCounter = calcInitError ? -1 : 0;
|
||||
|
||||
int cursorOffset = minDataDist;
|
||||
int cursorOffset = minDataDistance;
|
||||
|
||||
float adjustRate = initialAdjustRate;
|
||||
|
||||
float sumError = 0f;
|
||||
int errorCount = 0;
|
||||
@@ -288,13 +270,13 @@ public class AutoBone {
|
||||
}
|
||||
|
||||
// Estimate target height from HMD height
|
||||
targetHeight = hmdHeight * HEADSET_HEIGHT_RATIO;
|
||||
targetHeight = hmdHeight;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
// Detect end of iteration
|
||||
if (cursorOffset >= frames.length || cursorOffset > maxDataDist) {
|
||||
if (cursorOffset >= frames.length || cursorOffset > maxDataDistance) {
|
||||
epochCounter++;
|
||||
|
||||
// Calculate average error over the epoch
|
||||
@@ -306,11 +288,11 @@ public class AutoBone {
|
||||
|
||||
LogManager.log.info("[AutoBone] Epoch " + epochCounter + " average error: " + avgError);
|
||||
|
||||
if (epochCounter >= epochs) {
|
||||
if (epochCounter >= numEpochs) {
|
||||
break;
|
||||
} else {
|
||||
// Reset cursor offset and decay the adjustment rate
|
||||
cursorOffset = minDataDist;
|
||||
cursorOffset = minDataDistance;
|
||||
adjustRate /= adjustRateDecay;
|
||||
}
|
||||
}
|
||||
@@ -338,7 +320,7 @@ public class AutoBone {
|
||||
|
||||
float totalLength = getLengthSum(configs);
|
||||
float curHeight = getHeight(configs);
|
||||
float errorDeriv = getErrorDeriv(skeleton1, skeleton2, curHeight - targetHeight);
|
||||
float errorDeriv = getErrorDeriv(skeleton1, skeleton2, targetHeight - curHeight);
|
||||
float error = errorFunc(errorDeriv);
|
||||
|
||||
// In case of fire
|
||||
@@ -370,6 +352,7 @@ public class AutoBone {
|
||||
float originalLength = entry.getValue();
|
||||
|
||||
// Try positive and negative adjustments
|
||||
boolean isHeightVar = heightConfigs.contains(entry.getKey());
|
||||
float minError = error;
|
||||
float finalNewLength = -1f;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
@@ -384,8 +367,8 @@ public class AutoBone {
|
||||
|
||||
updateSekeletonBoneLength(skeleton1, skeleton2, entry.getKey(), newLength);
|
||||
|
||||
float newHeight = heightConfigs.contains(entry.getKey()) ? curHeight + curAdjustVal : curHeight;
|
||||
float newError = errorFunc(getErrorDeriv(skeleton1, skeleton2, newHeight - targetHeight));
|
||||
float newHeight = isHeightVar ? curHeight + curAdjustVal : curHeight;
|
||||
float newError = errorFunc(getErrorDeriv(skeleton1, skeleton2, targetHeight - newHeight));
|
||||
|
||||
if (newError < minError) {
|
||||
minError = newError;
|
||||
@@ -491,7 +474,7 @@ public class AutoBone {
|
||||
return Math.abs(finalHeight - targetHeight);
|
||||
}
|
||||
|
||||
protected static float getErrorDeriv(SimpleSkeleton skeleton1, SimpleSkeleton skeleton2, float heightChange) {
|
||||
protected float getErrorDeriv(SimpleSkeleton skeleton1, SimpleSkeleton skeleton2, float heightChange) {
|
||||
float slideLeft = skeleton1.getLeftFootPos().distance(skeleton2.getLeftFootPos());
|
||||
float slideRight = skeleton1.getRightFootPos().distance(skeleton2.getRightFootPos());
|
||||
|
||||
@@ -505,10 +488,10 @@ public class AutoBone {
|
||||
float distError = (dist1 + dist2) / 2f;
|
||||
|
||||
// Minimize sliding, minimize foot height offset, minimize change in total height
|
||||
return ((SLIDE_ERROR_FACTOR * Math.abs(slideError)) +
|
||||
(OFFSET_ERROR_FACTOR * Math.abs(distError)) +
|
||||
(HEIGHT_ERROR_FACTOR * Math.abs(heightChange))) /
|
||||
(SLIDE_ERROR_FACTOR + OFFSET_ERROR_FACTOR + HEIGHT_ERROR_FACTOR);
|
||||
return ((slideErrorFactor * Math.abs(slideError)) +
|
||||
(offsetErrorFactor * Math.abs(distError)) +
|
||||
(heightErrorFactor * Math.abs(heightChange))) /
|
||||
(slideErrorFactor + offsetErrorFactor + heightErrorFactor);
|
||||
}
|
||||
|
||||
// Mean square error function
|
||||
|
||||
Reference in New Issue
Block a user