CCDIK rotation troubles

Hello, I’m currently trying to utilize the CCDIK algorithm which works by applying a rotation to the joint from:

  1. the joint position to the end effector which is the joint of the foot denoted by an attachment in the foot.

  2. Towards the joint position towards the goal position

And it works :+1: as seen in the video, the leg is formerly at the blue wedge part, is then rotated towards the red wedge part pointing towards the goal:

The issue occurs when the goal position is set above the joint :sob:. It looks like instead of the rotation applied being from the blue wedgepart towards the red wedgepart, the rotation is instead going in the opposite direction.

Consequently, because of this weird scenario, the algorithm will work for the full leg until this odd scenario occurs where the leg will spaz out.

The code to do this uses EgoMooses advanced CFrame tricks due to the fact that his method of getting a rotation between two vectors takes into account the weird edge cases.

--Axis angle version
local function fromToRotation(u,v,axis)
    local dot = u:Dot(v)
    if (dot > 0.99999) then
        -- situation 1
        return CFrame.new()
    elseif (dot < -0.99999) then
        -- situation 2
        return CFrame.fromAxisAngle(axis, math.pi)
    end
    -- situation 3
    return CFrame.fromAxisAngle(u:Cross(v), math.acos(dot))
end

--Quanternion rotation version from Egomoose
local function getRotationBetween(u, v, axis)
    local dot, uxv = u:Dot(v), u:Cross(v)
    if (dot < -0.99999) then return CFrame.fromAxisAngle(axis, math.pi) end
    return CFrame.new(0, 0, 0, uxv.x, uxv.y, uxv.z, 1 + dot)
end

local rotationCFrame = getRotationBetween(directionToEffector,directionToGoal,part0CF.RightVector)
motor6d.C0 = motor6d.C0*rotationCFrame

Both those functions work, so I suspect it has something to do with the positioning of the C1 which prevents the rotation from being applied to reaching the goal which I’m stumped on.

Here’s the test place for easier debugging.

TestPlace.rbxlx (251.6 KB)

I think there’s a specific mathematical phenomenon like gimbal lock which causes this to happen but I’m not sure where to go from this currently. Any thoughts on what’s causing the issue?

2 Likes

NVM, found out how to do it. Gotta apply the rotation to the part1 of the CFrame then inverse the part 0 it to make the rotation relative to the C0 :sob: in this CFrame order.

	rotationCFrame = rotationCFrame*motor6d.Part1.CFrame*part0CF:Inverse()
	rotationCFrame = rotationCFrame-rotationCFrame.Position
	motor6d.C0 = CFrame.new(motor6d.C0.Position)*rotationCFrame

Before:

After:

Still looks wonky without constraints but thats for another day…But hey turns out no quaternions directly needed for now.

3 Likes