# Locking channels | General SmartBody Discussion | Forum

10:18 am

February 23, 2016

Hello.

I'm working with beaviohrsetreaching.py file and i want to create a new skeleton like common.sk with certain constraints. For example, in the file common.sk how can i block a knee when Brad is triyng to pick-up a pawn?

I tried:

joint l_knee

{ offset 0 7.782680 0

channel XPos 0 lim 0.00 0.01

channel YPos 0 lim 0.00 0.01

channel ZPos 0 lim 0.00 0.01

channel Quat

and:

joint l_knee

{ offset 0 0 0

channel XPos 0 lim 0.00 0.01

channel YPos 0 lim 0.00 0.01

channel ZPos 0 lim 0.00 0.01

channel Quat

and and a bunch of stuf, but nothing has change.

Thank you.

I just checked the code; there is no limit description for 'Quat' joints.

I suppose you could put in a controller (in Python) that enforces the limits, something like:

1. decompose the Quaternion into XYZ Euler angles

2. compare Euler angles to Euler angle limits

3. if limit is exceeded, restrict to limit

Perhaps this should be native SmartBody functionality.

I don't have the Python function but some C++ code is here: (first convert the quaternion to a matrix):

inline euler_t eulerFrom3x3( const vector_t col[3] )

{

register gw_float ex_rad, ey_rad, ez_rad;

gw_float s = -col[2].y();

ex_rad = safe_asin( s );

if( ( 1.0 - fabs( s ) ) > epsilon6() ) {

ey_rad = atan2( col[2].x(), col[2].z() );

ez_rad = atan2( col[0].y(), col[1].y() );

}

else {

ey_rad = atan2( -col[0].z(), col[0].x() );

ez_rad = 0.0;

}

return( euler_t( DEG( ex_rad ), DEG( ey_rad ), DEG( ez_rad ) ) );

}

The least invasive way to do this is to create a Python-based controller something like this:

class MyController (PythonController):

def init(self, pawn):

print "Init..."

def evaluate(self):

# every time step, make sure that the joint adheres to limits

# ......

myc = MyController()

# get the character

character = scene.getCharacter('char0')

# run this controller in position 17

character.addController(17, myc)

where the number '17' represents the order of evaluation of the controllers (thus, you could place it after the reach controller).

Ari

2:39 am

February 23, 2016

This was my attemp:

character = scene.getCharacter('ChrBrad0')

jointName1 = "l_knee"

joint1 = character.getSkeleton().getJointByName(jointName1)

x1 = joint1.getMatrixGlobal().getData(3,0)

y1 = joint1.getMatrixGlobal().getData(3,1)

z1 = joint1.getMatrixGlobal().getData(3,2)

euler_t = []

leng(euler_t) = 3

ex_rad = 0

ey_rad = 0

ez_rad = 0

from math import fabs

class MyController (PythonController):

def init(self, pawn):

def evaluate(self):

global ex_rad, ey_rad, ez_rad

s = -euler_t[2].y1

ex_rad = safe_asin(s)

if ((1.0-fabs(s)>epsilon6()):

ey_rad = atan2(euler_t[2].x1, euler_t[2].z1))

ez_rad = atan2(euler_t[2].y1), euler_t[2][1].y1)

ey_rad = atan2(-euler_t[0].z1, euler_t[0].x1)

return (euler_t(degrees(ex_rad), degrees(ey_rad), degrees(ez_rad)));

myc = MyController()

# get the character

character = scene.getCharacter('ChrBrad0')

# run this controller in position 17

character.addController(17, myc)

9:51 am

February 23, 2016

This is what i've got.. And still not working. :/

character = scene.getCharacter('ChrBrad0')

jointName1 = "l_knee"

joint1 = character.getSkeleton().getJointByName(jointName1)

x1 = joint1.getMatrixGlobal().getData(3,0)

y1 = joint1.getMatrixGlobal().getData(3,1)

z1 = joint1.getMatrixGlobal().getData(3,2)

class MyController (PythonController):

def init(self, euler_t):

euler_t = [0.00, 0.00, 0.00]

ex_rad = 0

ey_rad = 0

ez_rad = 0

s = -euler_t[2].y1

s1 = 1.0 - fabs(s)

e = sys.float_info.epsilon

ex_rad = safe_asinh(s)

if s1 > e:

ey_rad = atan2(euler_t[2].x1, euler_t[2].z1)

ez_rad = atan2(euler_t[2].y1, euler_t[2][1].y1)

ey_rad = atan2(-euler_t[0].z1, euler_t[0].x1)

euler_t = [degrees(ex_rad), degrees(ey_rad), degrees(ez_rad)]

myc = MyController()

# get the character

character = scene.getCharacter('ChrBrad0')

# run this controller in position 17

character.addController(17, myc)

Try something like this:

import math

def degrees(rad):

return rad * 180.0 * 3.14159

class MyController (PythonController):

def evaluate(self):

character = scene.getCharacter('ChrBrad')

jointName1 = "l_knee"

joint1 = character.getSkeleton().getJointByName(jointName1)

mat = joint1.getMatrixGlobal()

col1 = SrVec()

col1.setData(0, mat.getData(0,0))

col1.setData(1, mat.getData(0,1))

col1.setData(2, mat.getData(0,2))

col2 = SrVec()

col2.setData(0, mat.getData(1,0))

col2.setData(1, mat.getData(1,1))

col2.setData(2, mat.getData(1,2))

col3 = SrVec()

col3.setData(0, mat.getData(2,0))

col3.setData(1, mat.getData(2,1))

col3.setData(2, mat.getData(2,2))

euler_t = [0.00, 0.00, 0.00]

ex_rad = 0

ey_rad = 0

ez_rad = 0

s = -col3.getData(1)

s1 = 1.0 - math.fabs(s)

e = sys.float_info.epsilon

ex_rad = math.asinh(s)

if s1 > e:

ey_rad = math.atan2(col3.getData(0), col3.getData(2))

ez_rad = math.atan2(col3.getData(1), col2.getData(1))

else:

ey_rad = math.atan2(-col1.getData(2), col1.getData(0))

euler_t = [degrees(ex_rad), degrees(ey_rad), degrees(ez_rad)]

print euler_t

myc = MyController()

# get the character

character = scene.getCharacter('ChrBrad')

# run this controller in position 17

character.addController(17, myc)

character.removeController(myc)

Sorry, don't add the last line:

character.removeController(myc)

The tabs are missing on the code that I sent you which might be giving you the wrong results. Make sure your code looks something like this:

class MyController (PythonController): def evaluate(self): character = scene.getCharacter('ChrBrad') jointName1 = "l_knee" joint1 = character.getSkeleton().getJointByName(jointName1) mat = joint1.getMatrixGlobal() col1 = SrVec() col1.setData(0, mat.getData(0,0)) col1.setData(1, mat.getData(0,1)) col1.setData(2, mat.getData(0,2)) col2 = SrVec() col2.setData(0, mat.getData(1,0)) col2.setData(1, mat.getData(1,1)) col2.setData(2, mat.getData(1,2)) col3 = SrVec() col3.setData(0, mat.getData(2,0)) col3.setData(1, mat.getData(2,1)) col3.setData(2, mat.getData(2,2)) euler_t = [0.00, 0.00, 0.00] ex_rad = 0 ey_rad = 0 ez_rad = 0 s = -col3.getData(1) s1 = 1.0 - math.fabs(s) e = sys.float_info.epsilon ex_rad = math.asinh(s) if s1 > e: ey_rad = math.atan2(col3.getData(0), col3.getData(2)) ez_rad = math.atan2(col3.getData(1), col2.getData(1)) else: ey_rad = math.atan2(-col1.getData(2), col1.getData(0)) euler_t = [degrees(ex_rad), degrees(ey_rad), degrees(ez_rad)] print euler_t

Within a controller you can do something like:

class MyController (PythonController):

def evaluate(self):

bodyRot = SrQuat() # identity quat

axis = rot.getAxis()

angle = rot.getAngle()

angle = angle * .1

bodyRot.setData(0, rot.getData(0) * .2)

bodyRot.setAxisAngle(axis, angle)

self.setChannelQuatLocal('base', bodyRot)

myc = MyController()

character = scene.getCharacter('char0')

character.addController(17, myc)

3:52 am

February 23, 2016

I tried this:

bodyRot = SrQuat()

axis = bodyRot.getAxis() #Gets the axis of the quaternation.

angle = bodyRot.getAngle() #Gets the angle of the quaternion.

angle = angle * .1

bodyRot.setData(0, bodyRot.getData(0) * .2)

bodyRot.setAxisAngle(axis, angle)

self.setChannelQuatLocal('base', bodyRot)

And it says:

'MyController' object has no attribute 'setChannelQuatLocal'

10:46 am

February 23, 2016

Hi.

I'm continuing with the rotations of joints.

I'm still not understand some aspects..

Can you tell me why i get the value : 6,..... when i do this?

Where can i see the value of the rotation? In this case 90 degrees..

character = scene.getCharacter('ChrBrad0')

targetJoint = character.getSkeleton().getJointByName('skullbase')

targetJoint.setPrerotation(SrQuat(SrVec(1,0,0),3.1415/2))

quat = targetJoint.getQuat()

angle = quat.getAngle()

print angle

12:07 pm

February 23, 2016

Thanks but I think that is solved.

Sorry to ask you again. But about the definitions of BML, I think that i miss something.

Can you tell me more specifically where is the implementation of all the attributes?

All the tags?

For example, in tag locomotion you have an attribute that is speed. Where is speed and the rest of attributes implemented?

The attribute is defined in BMLDef.h/.cpp. It defines the names of each attributes to be parsed.

As for the actual implementation, you can usually find how it's being used by a controller in its corresponding bml_*.cpp. For example, you can check 'bml_locomotion.hpp/.cpp' for how the attributes of locomotion BML are parsed and applied in locomotion controller.

Hope this helps and let me know if you have any questions.

Andrew

1:27 am

February 23, 2016

Thank you very much.

I'm working on extending the language bml.

For instance, if i want to add an attribute in locomotion like 'lenght of the step' the things that i need to do are:

Add in BMLDefs:

XMLCh* BMLDefs::ATTR_LENGHT_STEPS = NULL;

Add in bml_locomotion the code for that attribute.

And then compile in visual studio? And i'll be able to test via pyhton?

Thanks for the attention.

Hi,

You will also need to define the tag name as "ATTR_LENGHT_STEPS = XMLString::transcode("step_length");" in BMLDef.cpp.

This would add this new "step_length" tag in BML locomotion during parsing. Thus now you can add code to handle this tag in bml_locomotion.cpp and also adjust the behvaior in locomotion controller code accordingly.

Let me know if you have any other questions.

Andrew

I don't think there is an easy way to change the locomotion controller to achieve this. You can either implement a new locomotion controller that move the character without moving the knees. Or you can reuse the current example-based locomotion controller and provides a different sets of example motions that do not have knee movements.

Andrew

7:30 am

February 23, 2016

Right.

My doubt what should I change?

In which part of the code is the movement of the legs, foot contact with the ground, speed of the joints, angle of the joints, and all that stuff that makes the movement of walking..

I've been looking the code in me_ct_locomotion.cpp.. And in some parts seems that you 'the walking' with an animation, in other parts seems not.

I'm a little bit confused if i really can do what i want and how should i do it..

9:40 am

February 23, 2016

In other words.. Where is this defined?

Hi,

The current locomotion in SmartBody is purely data-driven and we do not apply physical or heuristic control over joint angles and speed, nor handling ground contact. What you are referring to are legacy codes of an earlier implementation, which is a semi-procedural locomotion controller which handles finer per joint control and speed procedurally. However, it is not being actively updated anymore after we switch to current data-driven model.

The current locomotion uses parameterized animation interpolations and the interpolation parameters are controlled by the steering engine to move the character around. So all the character movements and walking/running motions are generated by adjusting the blending weights of different walking, jogging, and turning animations.

You can find more details in the source code. You can start from "SBAnimationBlend" class for motion interpolation, and the "PRAISteeringAgent" class for steering control.

Andrew

Most Users Ever Online: 733

Currently Online:

71 Guest(s)

Currently Browsing this Page:

1 Guest(s)

Top Posters:

jwwalker: 80

jyambao: 53

rbaral: 47

adiaz: 30

WargnierP: 29

lucky7456969: 28

mbarros: 28

avida.matt: 26

JonathanW: 24

laguerre: 23

Member Stats:

Guest Posters: 74

Members: 2025

Moderators: 1

Admins: 3

Forum Stats:

Groups: 1

Forums: 5

Topics: 527

Posts: 2473

Newest Members:

westergaardwestergaard4, Rujawitznewinvink, krabbepotter0, secher13aarup, quinlanvalentin80, sandersmalmberg00, toppvinter51, delightfulim25, gallegosdrake06, AlfonsobriLkModerators: smbyadmin: 0

Administrators: Ari Shapiro: 985, Eddie Fast: 0, Andrew Feng: 52