#Joints+Constraints..

1 messages · Page 1 of 1 (latest)

lime mason
#

Have posted over on the Physics forum on this but it's pretty quiet over there so here goes..

So i have some active ragdolls, and i'm driving rotation with anim data inside an iSystem..

My hacky workaround is using PhysicsVelocity.CalculateVelocityToTarget and setting velocity directly which works but the ragdolls obviously don't respond well to collisions ( i have to manually detect collisions and lerp the 'strength' of this velocity based on the ragdoll being hit by something )..

So i'm trying again to drive joint constraints directly.. The setup i'm trying out is as follows, three simple angular constraints on the joint, one for each rot axis ( and another joint with fixed linear position to hold the joints together )..

#

So i'm using the anim data ( which is actually the transform.localEulerAngles of the source anim rig ) to drive the Min/Max values directly..

This seems to work as shown in the following clip but as seen rotations aren't following exactly ( lower leg and feet ) and i think this is probably something to do with the math behind quaternions/euler/rotation-order etc etc.. Maybe using three angular constraints like this isn't ever going to produce the correct rotations, i have no idea as i don't know how it works under the hood or the maths involved.. The NoPhysics character below is just having those rot values applied directly to the LocalTransform of the limbs directly and obviously suffers no problems, it matches the source animation exactly:
https://i.gyazo.com/abdc86c7654bf8e87713fa2c190d3ab1.gif

#

It's been suggested to me maybe i'll have to use 3 joints to achieve this with some kind of ball and socket setup in order to drive all three axis like this, but any help/advice would be appreciated as i really don't know what i should be trying, i've tried various configurations up until now.
.

#

For reference -

My source animation is just getting stored to a blob like this:

#

And the values are being applied to the joint constraints like this:

#

Any help or ideas on this appreciated

kind adder
#

Have you ensured that all colliders that are close to each other are ticked to ignore collisions among each other?

lime mason
kind adder
lime mason
kind adder
#

if you try kinematic

#

how would it work?

lime mason
#

I'm suspecting it's something to do with the Twist axis and setting that z rotation, but the math behind that is beyond me

lime mason
#

( just to point out, the hip is kinematic - otherwise it would just collapse )

#

So, kinematic produces no results ( i'm guessing because the joints are not being solved at all, not necessary ):

#

The NoPhysics guy on the right - is exactly the same character, but without any physics components and the rotations are being written directly to LocalTransform Rotation

#

So exact same anim data, but one is getting written to LocalTransform and the other is writing obviously to joint constraints min/max fields

kind adder
#

what rotations?

lime mason
#

Just some anim data stored in a blob ( there's an image in my op )

kind adder
#

ah, you mean parent rotations?

lime mason
#

it's just some local transform rotations

kind adder
#

I see

#

so

#

how do you set velocity to physics bodies?

lime mason
#

i don't, simply setting min/max on constraints

kind adder
#

uugh

#

that does not sound like a good approach

#

why not just set delta velocity ?

lime mason
#

my actual in-game version uses CalculateVelocityToTarget to push the bones around, which works fine, but it doesn't react in a springy way ( kindof hard to explain ) because it's constantly getting the full velocity to target ( unless i use some lerping and strength values etc which i am )

kind adder
#

well in this case you need velocity to rotation I guess?

lime mason
kind adder
#

at least

#

what it does is simply applying force that would put object to target rotation/position on next frame

lime mason
#

which is what i have now really

kind adder
#

which will disable body getting next velocity until collisions stop

lime mason
#

so if it gets a small hit, it reacts in a small way, or a big hit and it goes full ragdoll, etc

kind adder
#

so what's the problem then?

lime mason
#

this does work, but the problem is it's just not as natural as a solution that is integral to the joint constraints..

kind adder
#

if you simply modify joint constraints without moving objects outside of constraints bounds - they will likely just make a jump, as if they were being forced by pressure

#

also forcing constraints doesn't sound like very natural

lime mason
#

so with an angular constraint - you have a min/max kindof 'ideal' value.. the joint will try and maintain this value, but when it's hit by something it will spring/flop around before resolving back to that value ( based on spring freq/damping ).. this is really the ideal situation as i can use the min/max values to tell the joint what rotation i want to be it's 'ideal' and the engine does the rest.. it's really similar to how the monobehaviour ConfigurableJoint works, which can be used to do exactly what i'm trying to do

kind adder
#

well

#

and if force big enough

#

your body will quickly smash against it's min/max values

lime mason
lime mason
kind adder
lime mason
#

in fact it would be a problem with an angular constraint whether you're setting min/max or not

kind adder
#

let's say something hits leg and it's meant to go back a bit - it'll be stuck within constraints

lime mason
#

i could actually record a clip of this if you gimme five mins ( juggling things here atm )

lime mason
#

So while it's true that if i hit that too hard or hit both legs together they fly into infinite death spiral of rotation.. but i kinda view that as a separate problem and something that could be resolved in other ways ( at least that's the idea )

#

Essentially i just want this to behave like ConfigurableJoint in physx and damnit there must be a way ( i know a lot of others are looking for the same thing )

#

The Drive mode in ConfigJoint in particular, physx afaik just uses the PD from a PiD controller

kind adder
#

doesn't look too natural

#

a lot of ugly deformations

#

with invalid angle

lime mason
#

mostly the linear constraint causing the joints to separate but again that's a separate issue

kind adder
#

Once again: why not just apply angular velocity?

lime mason
#

Cos it overrides collision velocity.. unless i can figure out some math to not do that

#

It's what i'm already doing, which i can demonstrate, it's ok but really it's a hack

kind adder
#

it won't override if you simply take it into account

#

or actually

#

just have a threshold for velocity

#

if it's too much - decrease it gradually

#

until it's low enough

#

and then do snapping again

#

this will be pretty much how it works irl

lime mason
#

That's kindof what i'm doing

kind adder
#

but you are using joint constraints, no?

lime mason
#

The problem is it looks lerpy

#

not really natural

kind adder
#

do you have any clips of that?

lime mason
#

I'm trying to protect disclosure as much as i can of actual assets etc but i think i could show that working on the example characters i'm using

#

Just going to grab some dinner etc but i'll show that in an hour or two, definitely worth digging into

#

Just thinking out loud here but wanted to make a note so i don't forget - if i could find a way to apply force to target bone pos/rot rather than velocity it might not override collisions so much and be more of a natural behaviour ( currently the CalculateVelocityToTarget method i think takes into account the body's current velocity and so if it's been impacted by a collision the method will return a large velocity that compensates for that collision velocity to move the body straight to target in one step )

kind adder
#

if current velocity lower than threshold (body part strength)

#

snap

#

if higher - gradually decrease

lime mason
#

Force though, not velocity ( or velocity if the current bodys velocity without collision can be removed, or something )

kind adder
#

you can also clamp resulting velocity

lime mason
kind adder
#

to some values

lime mason
#

i do already clamp max

kind adder
#

in case you think body part is moving too fast

lime mason
#

Ok going to organize food, will post a clip of how the current method i use looks a bit later

lime mason
#

So you can see the problem with it is this kindof wobble and overshoot while it tries to move back to target pos/rot values

kind adder
#

if it isn't

#

or you don't want it to be

#

then you probably want to play with mass value

#

in fact

lime mason
#

The thing with the mono physx ConfigurableJoint's Drive approach ( which allows you to pipe anim data into the TargetRotation field ) is that internally it uses a PiD to more smoothly drive towards target values without all this wobble and overshoot, which is kindof the key thing here

kind adder
#

when ball hits head

#

It seems VERY natural to me

#

right near end of clip

lime mason
#

Yeah lucky shot.. but the point is this wobble right, the overshoot

kind adder
#

PID controller?

lime mason
#

The ConfigJoint doesn't have this problem it solves it

kind adder
#

Just make mass of ball much less

#

and see for yourself

#

you should get far more natural behaviour

lime mason
#

yeah PiD is basically an algorithm that drives nicely towards target without overshoot, it's used in real life mechanics etc

kind adder
#

yeah, I learnt how to use PID for industrial programming 😅

lime mason
kind adder
#

surprised it's used outside of industry

#

then increase mass of character

lime mason
#

point is, i'd like to achieve basically the same as config joint but with physics joints

lime mason
kind adder
#

but physics is not that close to real world

#

so sticking to irl values will likely to introduce set of problems

lime mason
#

i can tweak masses, but if character is hit by a larger projectile, same problem.. doing that doesn't solve the underlying problem

kind adder
#

well, the way I see it - you are trying to hit a human with object twice his size. I doubt many people will not fall from that when hit unprepared 😅

#

you could reduce size of ball to be closer to some football size

#

it should also reduce mass dramatically

#

as for approach without physics joints - impossible

#

that's the only thing that will keep physics bodies together

lime mason
#

kinda missing the point a bit here.. the collision behavior is perfect, the character is knocked around nicely the issue is when sortof 'lerping' back to the animated values it's overshooting and wobbling around... like in real life if a ball hits your outstretch arm you arm flies back and then you use strength to pull it back to where it was, it doesn't kinda wobble around and oscillate like that if you get what i mean

lime mason
#

which, would be quite nice actually given the constraints have frequency and damping values that can be tweaked

kind adder
#

hmm

lime mason
#

but, as shown in the original clip, there's some issue i think with that twist axis, rots are getting a little wacky

kind adder
#

It's pretty clear character has fell from pressure 😅

#

ofc going back to animated state will be unnatural

#

also

#

it seems like you are not snapping

#

or wait

#

hmm

#

5th second

#

Right leg already is bad into proper position

#

but it's still flying around

#

because velocity is likely too high

#

and your clamping algorythm does not take it into account

#

so my guess what could help - adding additional check if distance to target position is small enough

#

and if it is - kill all velocity and snap it

lime mason
#

so what i'm actually doing is -
if you look at the blue bar on the healthbar - that's actually the 'strength' which is affected by collisions..
so when it gets hit, strength goes down ( then climbs back up to full )
i'm using this strength value to lerp between current actual velocities based on collision and animated move to target velocities
if that makes sense

kind adder
#

it is, just another setting for values

#

try adding distance check

#

and see how it goes

lime mason
kind adder
#

you only snap when leg is already back to correct position

#

but still have inertia velocity

lime mason
#

but yeah i mean some kind of math approach might solve it.. i did try and implement a PiD into it but was finding it impossible to get setup

kind adder
#

you don't need PID

lime mason
lime mason
#

i need a nice lerp towards position without overshoot

#

which is what a pid does actually

kind adder
#

It is a nice lerp

#

It's what you want

#

what happens right now

lime mason
#

hmm

kind adder
#

after impact

#

leg goes back (impact vector)

#

hits maximum of joint

#

goes back (forward)

#

reaches correct position

#

but velocity is still too high

#

so it goes to another maximum, but other side

#

and then a couple more times same thing

lime mason
#

actually just to point out - i'm not using angular constraints on the in-game setup so there are no limits

kind adder
#

until velocity dropped to normal value

kind adder
lime mason
lime mason
kind adder
#

those constraints are joints?

#

I mean, are bodies attached by 1 specific point or not?

lime mason
#

so on this version - each bone has one single joint, with one single linear position constraint ( to prevent joints from moving apart )

#

no rotational constraints

kind adder
#

yeah, that's what I meant

lime mason
#

its free rotation

#

yep

#

so that oscillating, you've described that perfectly

kind adder
#

so it's literally just figuring out algorythm how to apply velocity

#

in order to get wanted behaviour

lime mason
#

it overshoots, then tries to push back from the other side, and does that a few times until it settles

lime mason
kind adder
#

there are actually multiple ways

#

which will do same thing, but just a bit differently

lime mason
#

pid is one 😛

kind adder
#

the main goal basically - ensure that after hitting first extremum body goes back to target position

kind adder
lime mason
#

well i don't think you can set extremes or limits as such

#

just always know the target value

kind adder
#

so if impact is like this, PID is meant to do something like that

#

depending on it's settings

lime mason
#

it's supposed to prevent wobble/overshoot

kind adder
#

yes, but it depends on it's settings

#

which are kind of hard to figure

lime mason
#

if it's hit, it should produce a continuous drive towards target with minimal overshoot or drag

#

ie not too fast ( to prevent overshoot ) and not too slow ( or it's too draggy )

#

that's the whole point of it

kind adder
#

I doubt you'll be able to set it up to match all impact cases

#

In industry there's literally a job to set up PIDs that hired companies do 😅

#

and the more complex the process

lime mason
#

not all, but that's what i'm saying ConfigJoint Drive does this perfectly, and uses PD under the hood

kind adder
#

the less accurate PID can be

lime mason
#

i do know that physics is calculating error and stuff during the angular constraint solve

#

so i think is doing something very similar to configjoint

#

problem is when i try this approach ( like in my OP ) it has problems

kind adder
#

Using P/PI/PID controller is one way of solution and is not the most trivial one. YOu can't just slap it and expect it to work. It took us 1 year course to learn how to use properly just for simple water heating algorythms based on irl physic laws

#

also

#

it's computationally heavy

#

so I simply suggest more trivial approach of trial and error with some curve/lerp based way to modify velocity

lime mason
#

as i say i think physics constraints are 3/4 of the way to doing what a pid does anyway ie iterative solver over steps and measuring the error each step

#

so uh, i was hoping to leverage that for this

kind adder
#

but then what if your character won't get hit for a while?

lime mason
#

the physx source is available online

#

but unfortunately i'm not the guy to get what the math is doing and translate it over to here

#

i just know what it's doing, not how the math works, hence my post here 🙂

kind adder
#

you don't need to know how PID works, just lookup something like "PID parameters explained"

lime mason
#

yeah i tried

kind adder
#

It's mostly I and D that give most headache

lime mason
#

as you said yourself, not simple to setup

#

this is why i've posted here and the physics forums.. i'm like 'physics devs, you know about this stuff, help me out here'

#

but they're busy as are we all 🥹

kind adder
#

just try my approach sir 😅

#

at least that's where I can help

#

and what will be easy to understand

lime mason
#

so could you psuedo code what you mean exactly

kind adder
#

var targetVector = target - current; (position)
var magnitude = targetVector.magnitude (math. method)
var shouldSnap = magnitude < threshold;
var deltaVelocity = math.select(targetVector*someModified, -curVelocity+targetVector ** someOtherModifier, shouldSnap);
velocity.linear += deltaVelocity;

#

same for angular

#

but I don't remember math for it

#

this is practically makes it so distance to target small enough it'll start snapping

#

actually this need some other smoothing modifier

#

so it's not literally snapped

#

but instead just kept getting lerped

#

but with nullified velocity

#

I'll edit it to make it clearer

#

also

#

potentially could avoid treshold

#

and instead use curve

#

precomputed into method with switch

#

so it's even more lerpy

#

oh, damn

#

one other moment

#

I forgot about taking into account the moment when it first impacted

lime mason
#

Alright lemme digest this..
Literally digesting..

kind adder
#

this need to be thought of too

#

so... you said you have special state to rely on

#

strength

#

this could help

#

is it possible to get value of max distance from joint?

#

ah nvm, that's not useful at all

lime mason
#

soo, i don't quite get what this is doing but i'm willing to go with you on it, definitely if there is some way to get that smooth motion back to target without all the overshoot, i'd like to find it

kind adder
#

I'm thinking of some stateless algo that will figure when body has already reached extremum

lime mason
#

well the thing with pid is it doesn't use any extreme value right

kind adder
#

it does, by assumption with P parameter

lime mason
#

but there is a kinda implied reach baked into the tuning i guess right

#

right

kind adder
#

basically P defines instant reaction to error

lime mason
#

so i mean if need be i could put min/max values into each joint data component, just like a ragdoll setup would normall do

kind adder
#

and this is usually the one which takes extremums into account

lime mason
#

so it's the proportional value right

kind adder
#

yes

#

have you tried doing simple const velocity delta?

lime mason
#

i think really we're trying to reinvent the pid here 😛

kind adder
#

I'm curious how it looks

lime mason
kind adder
#

calculate target velocity * modifier

lime mason
#

ah like always same magnitude velocity

kind adder
#

velocity.linear += calculate target velocity * modifier

#

this would be P controller, yes 😅

lime mason
#

well that would just reduce or increase the strength

#

what you mean i think is can i force velocity magnitude to always be a set value

#

that's possible but i think would be unnatural, i could try

kind adder
#

ooooh

#

I just got an idea

#

but this involves a state

#

and yeah, practically reinventing PID 🤣

lime mason
#

i can store state in my custom joint data component if need be ( i'd need it for pid anyway ) ( or on a small buffer )

#

currently just holds bone name and root entity

kind adder
#

so the idea is that magnitude is written if it's bigger than current stored value

#

and every tick it's constantly reduced

#

what this gives us - short memory of impact

#

this value will be a modifier for velocity delta

#

so right after impact after limb reached extremum - modifier will be at it's biggest

#

and quickly will move limb back to normal

#

while slowly reducing itself to the point it has no memory of impact again

lime mason
#

hmmmm

kind adder
#

this modifier though will not be directly modifier

#

but a maximum for clamping

lime mason
#

somethings telling me it's the same really as current - strength value is set low after collision, and increases gradually to full

kind adder
#

yeah, you can reset it on collision

#

this will be a good for algo

#

but it's not gradually increased to full

#

it need to depend directly on magnitude to target position

#

so it'll practically know extremums

lime mason
#

mm yeah so proportional to magnitude/distance

kind adder
#

and this value needs to constantly be reduced (expect when magnitude is growing ofc)

#

so that short memory of impact goes away

#

as it goes

lime mason
#

well if you think about it, CalculateVelocityToTarget is already doing this it calculates the perfect velocity to reach target ( well, kindof, as it doesn't account for the joint chain masses and stuff i think )

kind adder
#

no

#

perfect velocity is not it

#

perfect velocity is just target-current, right?

lime mason
#

basically yeah

kind adder
#

this is just source of target vector

#

and maximum magnitude

lime mason
#

if you just mean clamp magnitude of the CalculateVelocityToTarget result then i'm already doing that

#

lemme show you what i'm currently doing

kind adder
#

no, that's not what I meant

#

step one - make a field of float. I'd call it stress I guess

#

step two - stress = math.max(stress, magnitude to target)

#

step three - before previous line stress -= somevalue

#

then use this stress value as multiplier to CalculateVelocityToTarget (for moste primitive approach)

lime mason
#

hmm, thinking

#

alright i'm not sure but i'll maybe give this a whack

kind adder
#

does this calculate method take gravity into account?

lime mason
#

gravity is already baked in to body velocity by the solver

kind adder
#

no, I meant that it could take gravity into account to apply a little more to up vector

lime mason
#

so i'll show what i'm currently doing first, so you can see what's happening :

kind adder
#

so that on next tick gravity does not make anything to body

#

it's not really important

#

as it seems like without it it's fine

#

judging by your clips

lime mason
#

so you see what's happening in my code

#

just getting world space animated pos/rot values

#

piping those into CalculateVelocityToTarget

#

capping the magnitude

#

then lerping between current velocity and the new target velocity based on current strength

#

so i'm wondering where your stress idea would come in

kind adder
#

stress would be t on lerp I guess

#

but probably modified in some way

lime mason
#

so it's like my current strength value, but takes distance/magnitude into account

#

trying to conceive how that would work

kind adder
#

stress = short memory of impact

#

the more body goes away from target position

lime mason
#

because CalVelToTarg already works out velocity based on dist etc

kind adder
#

the more stress is

#

and the higher velocity change towards proper velocity will be

#

so it'll reach it's maximum

#

on actual body extremum

kind adder
#

it's about figuring how hard it needs to be lerped to

lime mason
#

yeahhhhhhh i'm wondering if any different

#

i could simply try 😛

#

see how it looks

#

is there a helper anywhere for angletotarget

#

to get angular distance

kind adder
#

I don't remember

#

is angular velocity written as euler?

lime mason
#

it's a float3 yeah

#

stealing this and crossing fingers

kind adder
#

damn, euler is ugly

#

hmm

#

nah, I don't remember at all

#

better look it up in web

lime mason
#

k so i'm going to try with this:

#

arbitrary rot/pos max values

#

if unity would stop locking me from saving my code every ten seconds

kind adder
#

this is not what I had in mind

#

stress should be stored raw as distance

#

and reduced every tick

#

on some const (for example) value

#

overwritten only if distance > currentStress

#

and then you use it as value for your calculations

lime mason
kind adder
#

basically it'll be smth like: stress / maxStress

kind adder
#

it'll fix it

#

toggle it if this bug occures

lime mason
#

ah ok

#

normally i save a separate cs file untouched

#

just annoying to have to toggle back and forth

#

unity life

kind adder
#

I haven't gotten it once in 14f

#

Maybe it was fixed?

lime mason
#

still on 13

#

i think 14 came out the day after i installed 13 which was annoying

#

can be a fair amount of upheaval stepping up versions so uhhh, don't like doing it unless i have to ( and i had to step up to 13 )

#

now i had entity scene header so need restart

#

it's just an endless bundle of fun

#

alright grabbing some lunch will come back to this in a bit 😐