Need help with matching a SDK float value so it aligns with a rotation value

Hello everybody!
I want to be able to find a slider value so the bone it drives, aligns with the rotation of a goal bone.

The setup is as follows:
I have 2 bones(single chain) with a locator at each bone’s end joint.
One bone is driven by a float value from 0 to 10. The other is free to simply rotate as usual.

I have created two functions which have their pros and cons.
The first function effectively compares the distances of the base locator to the target locator. First I get distance1 at the slider’s min value and then distance2 at its max value. Depending on what distance is shorter I then divide the range, either setting the max value to this new mid value or the min value. The effect is that it will eventually come closer and closer to the rotation value of the goal bone.
This works great as long as you have a linear curve in your SDK, but not if you have ease-in and ease-out. Then the values will not work well.

The next approach I took is starting from the SDK max value and just decrement with a small value until you come closest to the goal locator.
This works better with ease-in and ease-out, but you need a very small value so decrementing this takes a lot of time. Very ineffective.

Those are the ideas I had from the top of my head.
Was hoping someone had better ideas :slight_smile:

import pymel.core as pm
import math

baseControl ='ctrl_01_jnt')[0]
attr = 'toe'
baseLoc ='base_loc')[0]
goalLoc ='goal_loc')[0]
numLoops = 50

# 1st approach
floatTickerLinear(baseControl, attr, baseLoc, goalLoc, numLoops)
def floatTickerLinear(baseControl, attr, baseLoc, goalLoc, numLoops):
    valRange = pm.attributeQuery(attr, node=baseControl, r=True)
    startVal = valRange[0]
    endVal = valRange[1]
    for i in range(numLoops):
        baseControl.setAttr(attr, startVal)
        dist1 = getDist(baseLoc.getRotatePivot(space='world'), goalLoc.getRotatePivot(space='world'))
        baseControl.setAttr(attr, endVal)
        dist2 = getDist(baseLoc.getRotatePivot(space='world'), goalLoc.getRotatePivot(space='world'))
        midVal = (endVal - startVal) / 2.0
        if dist1 < dist2:
            endVal = endVal-midVal
            startVal = startVal+ midVal

# 2nd approach
# need a small increment value, but it still isn't perfectly aligned een if I turn it up(or down) to 0.0001
increment = 0.001
floatTicker(baseControl, attr, baseLoc, goalLoc, increment)

def floatTicker(baseControl, attr, baseLoc, goalLoc, increment):
    valRange = pm.attributeQuery(attr, node=baseControl, r=True)
    startVal = valRange[0]
    endVal = valRange[1]
    # first set the slider to its max value
    baseControl.setAttr(attr, endVal)
    # get the start distance
    dist = getDist(baseLoc.getRotatePivot(space='world'), goalLoc.getRotatePivot(space='world'))
    # then increment the slider so there's a new distance to calculate
    baseControl.setAttr(attr, endVal-increment)
    # because I first set the slider with the first increment, I neeed to start here with increment 2
    for i in range(2, int(endVal/increment) ):
        newDist = getDist(baseLoc.getRotatePivot(space='world'), goalLoc.getRotatePivot(space='world'))

        if newDist < dist:
            dist = newDist
            baseControl.setAttr(attr, endVal-increment*(i))

            # if overshot, just push it back.
            baseControl.setAttr(attr, endVal-(increment*(i-1)))

# just to return distance between two positions
def getDist(a, b):
    return( math.sqrt( (a.x-b.x)**2 + (a.y-b.y)**2 + (a.z-b.z)**2 ) )