From: <mi...@mi...> - 2006-11-24 21:33:02
|
Thank you. I'll look into that. - Miriam > setting your worlds ERP and CFM to zero seems to fix this, not sure why tho.. > -brett > > > --- mi...@mi... wrote: > > > Hi folks, > > > > A friend (he's probably joining pyode-user as I send this) sent me the two small python scripts > > (attached). They both drop a block near another. They are the same except for one being at > > (0,0,0) the other at (10,10,10), but their behavior is markedly different. Why? > > > > Is there any way to ensure that behavior has positional independence? ...at least in fairly > > ordinary ranges. I know things will get crazy near the limits of numerical precision, but this > > is just a little over 10 units from the center of the universe. > > > > Is there some other parameter that needs to be handled to take account of the position? > > > > Best wishes, > > > > - Miriam > > -- > > ---------=---------=---------=---------=---------=---------=------ > > A life! Cool! Where can I download one of those from? > > ---------=---------=---------=---------=---------=---------=------ > > Website: http://miriam-english.org > > Blog: http://www.livejournal.com/users/miriam_e/ > > > # pyODE example 3: Collision detection > > # origin > > > > # Originally by Matthias Baas. > > # Updated by Pierre Gay to work without pygame or cgkit. > > > > import sys, os, random, time > > from math import * > > from OpenGL.GL import * > > from OpenGL.GLU import * > > from OpenGL.GLUT import * > > > > import ode > > > > # geometric utility functions > > def scalp (vec, scal): > > vec[0] *= scal > > vec[1] *= scal > > vec[2] *= scal > > > > def length (vec): > > return sqrt (vec[0]**2 + vec[1]**2 + vec[2]**2) > > > > # prepare_GL > > def prepare_GL(): > > """Prepare drawing. > > """ > > > > # Viewport > > glViewport(0,0,640,480) > > > > # Initialize > > glClearColor(0.8,0.8,0.9,0) > > glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); > > glEnable(GL_DEPTH_TEST) > > glDisable(GL_LIGHTING) > > glEnable(GL_LIGHTING) > > glEnable(GL_NORMALIZE) > > glShadeModel(GL_FLAT) > > > > # Projection > > glMatrixMode(GL_PROJECTION) > > glLoadIdentity() > > gluPerspective (45,1.3333,0.2,20) > > > > # Initialize ModelView matrix > > glMatrixMode(GL_MODELVIEW) > > glLoadIdentity() > > > > # Light source > > glLightfv(GL_LIGHT0,GL_POSITION,[0,0,1,0]) > > glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1]) > > glLightfv(GL_LIGHT0,GL_SPECULAR,[1,1,1,1]) > > glEnable(GL_LIGHT0) > > > > # View transformation > > gluLookAt (2.4, 3.6, 4.8, 0.5, 0.5, 0, 0, 1, 0) > > > > # draw_body > > def draw_body(body): > > """Draw an ODE body. > > """ > > > > x,y,z = body.getPosition() > > R = body.getRotation() > > #rot = [R[0], R[3], R[6], 0., > > # R[1], R[4], R[7], 0., > > # R[2], R[5], R[8], 0., > > # x, y, z, 1.0] > > rot = [1, 0.0, 0.0, 0.0, > > 0.0, 1, 0.0, 0.0, > > 0.0, 0.0, 1.0, 0.0, > > x, y, z, 1.0] > > glPushMatrix() > > glMultMatrixd(rot) > > if body.shape=="box": > > sx,sy,sz = body.boxsize > > glScale(sx, sy, sz) > > glutSolidCube(1) > > glPopMatrix() > > > > > > # create_box > > def create_box(world, space, density, lx, ly, lz): > > """Create a box body and its corresponding geom.""" > > > > # Create body > > body = ode.Body(world) > > M = ode.Mass() > > M.setBox(density, lx, ly, lz) > > body.setMass(M) > > > > # Set parameters for drawing the body > > body.shape = "box" > > body.boxsize = (lx, ly, lz) > > > > # Create a box geom for collision detection > > geom = ode.GeomBox(space, lengths=body.boxsize) > > geom.setBody(body) > > > > return body > > > > # create box object > > def create_object(posx, posy, posz): > > """create one box at a given position.""" > > > > global bodies, counter, objcount > > > > body = create_box(world, space, 1000, 1.0,1.0,1.0) > > body.setPosition((posx, posy, posz)) > > bodies.append(body) > > #counter=0 > > objcount+=1 > > > > > > # drop_object > > def drop_object(posx, posy, posz): > > """Drop an object into the scene.""" > > > > global bodies, counter, objcount > > > > body = create_box(world, space, 1000, 1.0,1.0,1.0) > > body.setPosition((posx, posy, posz)) > > bodies.append(body) > > #counter=0 > > objcount+=1 > > > > # Collision callback > > def near_callback(args, geom1, geom2): > > """Callback function for the collide() method. > > > > This function checks if the given geoms do collide and > > creates contact joints if they do. > > """ > > > > # Check if the objects do collide > > contacts = ode.collide(geom1, geom2) > > > > # Create contact joints > > world,contactgroup = args > > for c in contacts: > > c.setBounce(0.2) > > c.setMu(5000) > > j = ode.ContactJoint(world, contactgroup, c) > > j.attach(geom1.getBody(), geom2.getBody()) > > > > > > > > ###################################################################### > > > > # Initialize Glut > > glutInit ([]) > > > > # Open a window > > glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE) > > > > x = 0 > > y = 0 > > width = 640 > > height = 480 > > glutInitWindowPosition (x, y); > > glutInitWindowSize (width, height); > > glutCreateWindow ("(0,0,0)") > > > > # Create a world object > > world = ode.World() > > world.setGravity( (0,-9.81,0) ) > > world.setERP(0.8) > > world.setCFM(1E-5) > > > > # Create a space object > > space = ode.Space() > > > > # Create a plane geom which prevent the objects from falling forever > > floor = ode.GeomPlane(space, (0,1,0), 0) > > > > # A list with ODE bodies > > bodies = [] > > > > # A joint group for the contact joints that are generated whenever > > # two bodies collide > > contactgroup = ode.JointGroup() > > > > # Some variables used inside the simulation loop > > fps = 50 > > dt = 1.0/fps > > running = True > > state = 0 > > counter = 0 > > objcount = 0 > > lasttime = time.time() > > > > > > # keyboard callback > > def _keyfunc (c, x, y): > > sys.exit (0) > > > > glutKeyboardFunc (_keyfunc) > > > > # draw callback > > def _drawfunc (): > > > === message truncated ===> # pyODE example 3: Collision detection > > # 1000 > > > > # Originally by Matthias Baas. > > # Updated by Pierre Gay to work without pygame or cgkit. > > > > import sys, os, random, time > > from math import * > > from OpenGL.GL import * > > from OpenGL.GLU import * > > from OpenGL.GLUT import * > > > > import ode > > > > # geometric utility functions > > def scalp (vec, scal): > > vec[0] *= scal > > vec[1] *= scal > > vec[2] *= scal > > > > def length (vec): > > return sqrt (vec[0]**2 + vec[1]**2 + vec[2]**2) > > > > # prepare_GL > > def prepare_GL(): > > """Prepare drawing. > > """ > > > > # Viewport > > glViewport(0,0,640,480) > > > > # Initialize > > glClearColor(0.8,0.8,0.9,0) > > glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); > > glEnable(GL_DEPTH_TEST) > > glDisable(GL_LIGHTING) > > glEnable(GL_LIGHTING) > > glEnable(GL_NORMALIZE) > > glShadeModel(GL_FLAT) > > > > # Projection > > glMatrixMode(GL_PROJECTION) > > glLoadIdentity() > > gluPerspective (45,1.3333,0.2,20) > > > > # Initialize ModelView matrix > > glMatrixMode(GL_MODELVIEW) > > glLoadIdentity() > > > > # Light source > > glLightfv(GL_LIGHT0,GL_POSITION,[0,0,1,0]) > > glLightfv(GL_LIGHT0,GL_DIFFUSE,[1,1,1,1]) > > glLightfv(GL_LIGHT0,GL_SPECULAR,[1,1,1,1]) > > glEnable(GL_LIGHT0) > > > > # View transformation > > gluLookAt (12.4, 13.6, 14.8, 10.5, 10.5, 10, 0, 1, 0) > > > > # draw_body > > def draw_body(body): > > """Draw an ODE body. > > """ > > > > x,y,z = body.getPosition() > > R = body.getRotation() > > #rot = [R[0], R[3], R[6], 0., > > # R[1], R[4], R[7], 0., > > # R[2], R[5], R[8], 0., > > # x, y, z, 1.0] > > rot = [1, 0.0, 0.0, 0.0, > > 0.0, 1, 0.0, 0.0, > > 0.0, 0.0, 1.0, 0.0, > > x, y, z, 1.0] > > glPushMatrix() > > glMultMatrixd(rot) > > if body.shape=="box": > > sx,sy,sz = body.boxsize > > glScale(sx, sy, sz) > > glutSolidCube(1) > > glPopMatrix() > > > > > > # create_box > > def create_box(world, space, density, lx, ly, lz): > > """Create a box body and its corresponding geom.""" > > > > # Create body > > body = ode.Body(world) > > M = ode.Mass() > > M.setBox(density, lx, ly, lz) > > body.setMass(M) > > > > # Set parameters for drawing the body > > body.shape = "box" > > body.boxsize = (lx, ly, lz) > > > > # Create a box geom for collision detection > > geom = ode.GeomBox(space, lengths=body.boxsize) > > geom.setBody(body) > > > > return body > > > > # create box object > > def create_object(posx, posy, posz): > > """create one box at a given position.""" > > > > global bodies, counter, objcount > > > > body = create_box(world, space, 1000, 1.0,1.0,1.0) > > body.setPosition((posx, posy, posz)) > > bodies.append(body) > > #counter=0 > > objcount+=1 > > > > > > # drop_object > > def drop_object(posx, posy, posz): > > """Drop an object into the scene.""" > > > > global bodies, counter, objcount > > > > body = create_box(world, space, 1000, 1.0,1.0,1.0) > > body.setPosition((posx, posy, posz)) > > bodies.append(body) > > #counter=0 > > objcount+=1 > > > > # Collision callback > > def near_callback(args, geom1, geom2): > > """Callback function for the collide() method. > > > > This function checks if the given geoms do collide and > > creates contact joints if they do. > > """ > > > > # Check if the objects do collide > > contacts = ode.collide(geom1, geom2) > > > > # Create contact joints > > world,contactgroup = args > > for c in contacts: > > c.setBounce(0.2) > > c.setMu(5000) > > j = ode.ContactJoint(world, contactgroup, c) > > j.attach(geom1.getBody(), geom2.getBody()) > > > > > > > > ###################################################################### > > > > # Initialize Glut > > glutInit ([]) > > > > # Open a window > > glutInitDisplayMode (GLUT_RGB | GLUT_DOUBLE) > > > > x = 0 > > y = 0 > > width = 640 > > height = 480 > > glutInitWindowPosition (x, y); > > glutInitWindowSize (width, height); > > glutCreateWindow ("(10,10,10)") > > > > # Create a world object > > world = ode.World() > > world.setGravity( (0,-9.81,0) ) > > world.setERP(0.8) > > world.setCFM(1E-5) > > > > # Create a space object > > space = ode.Space() > > > > # Create a plane geom which prevent the objects from falling forever > > floor = ode.GeomPlane(space, (0,1,0), 10) > > > > # A list with ODE bodies > > bodies = [] > > > > # A joint group for the contact joints that are generated whenever > > # two bodies collide > > contactgroup = ode.JointGroup() > > > > # Some variables used inside the simulation loop > > fps = 50 > > dt = 1.0/fps > > running = True > > state = 0 > > counter = 0 > > objcount = 0 > > lasttime = time.time() > > > > > > # keyboard callback > > def _keyfunc (c, x, y): > > sys.exit (0) > > > > glutKeyboardFunc (_keyfunc) > > > > # draw callback > > def _drawfunc (): > > > === message truncated ===> > ------------------------------------------------------------------------- > > Take Surveys. Earn Cash. Influence the Future of IT > > Join SourceForge.net's Techsay panel and you'll get the chance to share your > > opinions on IT & business topics through brief surveys - and earn cash > > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV> > _______________________________________________ > > Pyode-user mailing list > > Pyo...@li... > > https://lists.sourceforge.net/lists/listinfo/pyode-user > > > > > > > ____________________________________________________________________________________ > Do you Yahoo!? > Everyone is raving about the all-new Yahoo! Mail beta. > http://new.mail.yahoo.com |
From: <mi...@mi...> - 2006-11-24 21:41:05
|
Strange. There is no 's' variable... apart from sx,sy,sz when setting glScale in the draw_body() part. Setting scale to zero would give an error, but they shouldn't be zero. Thanks for checking on your machine. I wonder what's happening there. - Miriam > mi...@mi... wrote: > > but their behavior is markedly different. Why? > > They behave the same on my machine, but both generate this message: > > ODE Message 3: LCP internal error, s <= 0 (s=-0.0000e+00) > > Ethan |
From: Matthias B. <ba...@ir...> - 2006-11-27 09:33:48
|
mi...@mi... wrote: > Strange. There is no 's' variable... apart from sx,sy,sz when setting glScale in the draw_body() part. Setting scale to zero would give an error, but they shouldn't be zero. I also get such a message, but only for the version at the origin: ODE Message 3: LCP internal error, s <= 0 (s=-5.2075e-003) This is a message that originates from ODE (not PyODE), so the variable 's' doesn't refer to any Python variable but rather to a variable that is most likely be used somewhere in the source code of ODE. As one version shows the above error and the other doesn't, it is not very surprising that the results differ. Now as to why the error occurs I have no idea, I'd recommend to post a message into the ODE mailing list. By the way, when I slightly rotate the cube (just so that it isn't perfectly aligned with the ground plane anymore) then the error does not occur anymore and the two simulations look the same. - Matthias - PS: I think the other case with the different start times is just the same. |
From: Ricardo K. <ric...@gm...> - 2006-11-27 13:36:21
|
Hi: I came up with this error a few times myself Matthias Baas wrote: > mi...@mi... wrote: >> Strange. There is no 's' variable... apart from sx,sy,sz when setting glScale in the draw_body() part. Setting scale to zero would give an error, but they shouldn't be zero. > > I also get such a message, but only for the version at the origin: > > ODE Message 3: LCP internal error, s <= 0 (s=-5.2075e-003) What this means is that the matrix (that represents the current state of the simulation) to be solved is near singular, and thus the LCP solver fails. It cannot solve this matrix, because it cannot find the inverse matrix to solve the equation system. This happens mostly when using the WorldStep method, because this method depends on finding the exact inverse matrix. There is another method QuickStep, which uses an iterative approach to solve the equation system, that can handle most of these cases. The only problem with QuickStep is that the simulation becomes less accurate (although faster). As far as I know there is not (yet) a real solution to this problem. There was some discussion about throwing an exception when this occurred, so that people could handle the error, instead of just breaking the simulations, but I am not quite sure what the state of that is right now. I hope you could understand at least a little of what I tried to explain (due to my bad english :)) ricardo |
From: Matthias B. <ba...@ir...> - 2006-11-28 12:16:24
|
chris wrote: > FYI, I get this error for all versions where I set CFP and ERP to 0, > including 10, 1000 and 10000 from the origin. For example look at the > attached and see the difference in rest position, When CFM and ERP are both 0 I get the LCP error in every step. I think an ERP of 0 doesn't make any sense anyway, does it? I wonder why the collision is resolved at all. Doesn't ERP=0 mean that the joint force isn't taken into account at all? Similarly, I also wouldn't recommend a CFM value of exactly 0 (see the ODE manual: "In fact, if the system is mis-behaving, one of the first things to try is to increase the global CFM.") By the way, as was mentioned in a previous mail, if you switch to quickStep() there's no error message anymore (but the movement is not identical anyway). Anyway, as these things happen right inside ODE and are not particular to PyODE I recommend to post a message in the ODE mailing list. - Matthias - |
From: chris <dra...@gm...> - 2006-11-28 12:39:09
|
On 11/28/06, Matthias Baas <ba...@ir...> wrote: > chris wrote: > > FYI, I get this error for all versions where I set CFP and ERP to 0, > > including 10, 1000 and 10000 from the origin. For example look at the > > attached and see the difference in rest position, > > When CFM and ERP are both 0 I get the LCP error in every step. I think > an ERP of 0 doesn't make any sense anyway, does it? I wonder why the > collision is resolved at all. Doesn't ERP=0 mean that the joint force > isn't taken into account at all? > Similarly, I also wouldn't recommend a CFM value of exactly 0 (see the > ODE manual: "In fact, if the system is mis-behaving, one of the first > things to try is to increase the global CFM.") yeah it probably is not sensibel to set these to zero. I just didi it because someone suggested it and I thought I would prove that it still does not remove the problem (it fixes it for displacement of 10 but not for general case). > > By the way, as was mentioned in a previous mail, if you switch to > quickStep() there's no error message anymore (but the movement is not > identical anyway). ok > > Anyway, as these things happen right inside ODE and are not particular > to PyODE I recommend to post a message in the ODE mailing list. yes, will do, bit busy atm - at a conference, cheers, chris > > - Matthias - > > ------------------------------------------------------------------------- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to share your > opinions on IT & business topics through brief surveys - and earn cash > http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > Pyode-user mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyode-user > |