@@@'s TODO for COLLISION ------------------ box-box collision: adjust generated face-face contact points by depth/2 to be more fair. what happens when a GeomTransform's encapsulated object is manipulated, e.g. position changed. should this be disallowed? should a GeomTransform behave like a space and propagate dirtyness upwards? make sure that when we are using a large space for static environmental geoms, that there is not excessive AABB computation when geoms are added/removed from the space. the space AABB is pretty much guaranteed to cover everything, so there's no need to compute/test the AABB in this case. hash space: implement collide2() efficiently instead of the current simple-space-like brute-force approach. hash space: incremental scheme, so we dont have to rebuild the data structures for geoms that don't move. disabled geoms (remove from all collision considerations) ... isn't this the same as just taking it out of its enclosing group/space? integrate: dRay triangle collider - get latest tri collider code from erwin erwin's quadtree space tests: all aspects of collision API dGeomSetBody(0) maintains body-geom linked list properly. simple space: instantiate lots of non-moving geoms (i.e. environmental geoms and make sure that we're still able to collide efficiently. make sure AABB computation is efficient, or can be made efficient through proper use of the API. test C interface support for making new classes. make sure the dxGeom::aabbTest() function behaves as advertised. testing for contact point consistency: test for things that would cause the dynamics to fail or become unstable test for: small adjustment in geom position causes a big jump in the contact point set (bad for dynamics). test for: if contact constraints observed then it's impossible (or hard) to move the objects so that the penetration is increased. relax this when only a subset of the contact points are returned. test for consistency, e.g. the boundary of geoms X and Y can be defined by intersecting with a point, so test the intersection of X and Y by comparing with the point tests. check that contact points are in the collision volume all existing space tests, and more. demos: test_buggy: make a terrain out of non-moving geoms. use heirarchical groups to get efficient collision, even with the simple space. go though the new collision docs and make sure the behavior that is described there is actually implemented. multi-resolution hash table: the current implementation rebuilds a new hash table each time collide() is called. we don't keep any state between calls. this is wasteful if there are unmoving objects in the space. make sure we prevent multiple collision callbacks for the same pair better virtual address function. the collision search can perhaps be optimized - as we search chains we can come across other candidate intersections at other levels, perhaps we should do the intersection check straight away? --> save on list searching time only, which is not too significant. collision docs: optimization guide: whenever a single geom changes in a simple space, the space AABB has to be recomputed by examining EVERY geom. document this, or find a better behavior. TODO BEFORE NEXT RELEASE ------------------------ g++ needed for compiling tests using gcc 3.2 ? what is the problem? add joint feedback info from lambda, so that we can get motor forces etc. need a way to map constraint indexes to what they mean. track down and fix the occasional popping/jumping problem in test_boxstack, especially when boxes are piled on top of each other. find out if this is caused by a configuration singularity or whether there is a bug in LCP. i need to add some kind of diagnostic tool to help resolve these kinds of problems. fixup ground plane jitter and shadow jumping in drawstuff. the inertias/COMs don't appear to be totally correct for the boxstack demo. fix up, and add a mode that shows the effective mass box (for a given density). Improve box-box collision, especially for face-face contact (3 contact points). Improve cylinder-box collision (2 contact points). windows DLL building and unix shared libs. libtool? also MSVC project files. dBodyGetPointVel() contrib directory - all stuff in ~/3/ode functions to allow systems to be copied/cloned dBodyTransplant (b, world) dTransplantIsland (b, world) dBodyCopy (bdest, bsrc) dJointCopy (jdest, jsrc) -- what about body connections? dCloneBody() dCloneJoint() dCloseBodyAndJointList() dCloneIsland() this collision rule: // no contacts if both geoms on the same body, and the body is not 0 if (g1->body == g2->body && g1->body) return 0; needs to be replaced. sometimes we want no collision when both bodies are 0, but this wont work for geomgroup-to-environment. avoid stupid stuff like dGeomSetBody (geom_group, (dBodyID) 1); this also causes "failed-to-report" errors in the space test. Expose type-specific collision functions? Automatic code optimization process. joint limit spongyness: interacts with powered joints badly, because when the limit is reached full power is applied. fix or doc. various hinge2 functions may not function correctly if axis1 and axis2 are not perpendicular. in particular the getAngle() and getAngleRate() functions probably will give bogus answers. slow step function will not respect the joint getinfo2 functions calling addTorque() because it reads the force/torque accumulators before the getinfo2 functions are called. spaces need multiple lists of objects that can never overlap. objects in these lists are never tested against each other. deleting a body a joint is attached to should adjust the joint to only have one body attached. currently the connected joints have *both* their body attachments removed. BUT, dont do this if the dJOINT_TWOBODIES flag is set on the joint. document error, mem and math functions. Web pages credits section projects using ODE update C++ interface? use SWIG? collision exclusion groups - exclude if obj1.n == obj2.n ? make sure the amotor joint can be used with just one body. at the moment it only allows two-body attachments. implement dJointGetAMotorAngleRate() erwin says: Should the GeomGroup have a cleanupmode as the GeomTransform has? erwin says: http://q12.org/pipermail/ode/2002-January/000766.html and http://q12.org/pipermail/ode/2001-December/000753.html rename duplicate filenames (object.h?) - some environments can't handle this. naming inconsistency: dCreateSphere() should be dSphereCreate() (etc...) to match the rest of the API. TODO ---- joint allocation in joint groups. allocation size should be rounded up using dEFFICIENT_SIZE, to properly align all the data members. all dAlloc() allocations should be aligned using dEFFICIENT_SIZE() ??? automatic body & joint disabling / enabling. sometimes getting LCP infinite loops. function to get the entire island of bodies/joints joints: hinge2 joint - implement trail, i.e. non-convergent steering and wheel axes. erp individually settable for each joint? more joints: angular3 (constrian full angle not position) fixed path 1 (point must follow fixed path, etc etc) - other fixed path joints. linear a (point in 1 body fixed to plane of other) linear b (point in 1 body fixed to line on other) linear c (line in 1 body fixed to plane on other) linear d (line in 1 body fixed to line on other) - like prismatic but orientation along line can change Relative-Path-Relative-Oriention Joint (set all dofs of 2 bodies relative to each other) spring (with natural length) universal (2 kinds) various angular relationships when attaching joints to static env, provision to move attachment point (e.g. give it a linear/angular velocity). this can be used instead of a FPFO joint on a body in many cases. also do this with contacts to static env, to allow for contacts to *moving* objects in the static env. interpretation of erp: is it (1) the error reduction per timestep, (2) or a time constant independent of timestep?? if it's (2) then perhaps this should be universal - this is already the meaning for the suspension. hinge2 suspension: suspension limits suspension limit restitution and spongyness?? use autoconf? set paths in makefile? no-arg init functions, for andy explore: do joint parameters need to be set for the joint to be setup correctly, or should set some proper body-dependent params when it is attached? this is only really an issue for joints that have no parameters to set, such as the fixed joint. dAlloc() should take an arena parameters which is stored in dWorld. debugging mode should use dASSERT2 that prints a descriptive error message on error, not just the file:line or function. use dASSERT for internal consistency checking. when vectors and matrices are initialized, we must ensure that the padding elements are set to 0. this is going to be a problem everywhere! don't use 3-vectors anywhere. use SIMD friendly 4-vectors. make sure all data in body/joint etc objects is aligned well for single precision SIMD (i.e. all vectors start on a 16 byte boundary). think about more complicated uses of collision, e.g. a single geom representing an articulated structure. bodyGroup? (like joint group but for bodies). systemGroup? check the overhead of resizing Array<>s as elements are pushed on to them. replace alloca() with dPushFrame(), dPopFrame(), and dAlloca() ? allow for the possibility of allocating in non-stack memory ? make sure that we can set mass parameters with non-zero center of mass. if this is done after the body position is set, the position is adjusted. if this is done before the body position is set, what do we do when the pos is set? does the pos always refer to the center of mass from the user's point of view? consider splitting solver into functions, which can be optimized separately. might make things go faster. faster code for islands with a single body? faster code for dynamically symmetric bodies? rotation.cpp functions that set matrices should also set padding elements. lcp solver must return (L,d) and some other information, so we can re-solve for other right hand sides later on, but using the same complimentarity solution so there are no integrator discontinuities. dSetZero() - make fast inline functions for fixed n e.g. (1-4). need proper `sticky' friction, i.e. compensation for numerical slip. on windows, make sure gcc-compiles libs can be linked with VC++ apps. need to make sure some C++ runtime bits are present? kill all references to dArray<> (in geom.cpp). need testing code to test all joints with body-to-static-env copy stack.cpp, memory.cpp stuff to reuse dFactorLDLT() is not so efficient for matrix sizes < block size, e.g. redundant calls, zero loads, adds etc contacts: cheaper friction: viscous friction? one step delay friction force. in geom.cpp, for objects that are never meant to collide, dCollide() will always try to find the collider functions, which wastes a bit of time. geom.cpp:dCollideG() - handle special case of colliding 2 groups more efficiently. timer reporting function: void timerReport (void (*printFunction)(char *, ...)); disabled bodies stored in a separate list, so they are never traversed at all, for speed when there are many disabled bodies. MAYBE ----- new implementation for joint groups that is not so system dependent. maybe individual contacts are reusable? in this case contact information should be settable in the contact joints. max_size arg is really annoying. consider making anchor,axis, (everything) into a joint parameter and setting them with a consistent interface. also consider overload the joint functions so they are not distinguished by joint type?? collision memory optimizations? collision: support for persistent contact information? multiply reference tri list data so that it can be cloned if the tri-list geoms could support rot/pos transformations then we could have several tri-lists pointing to the same vertex information. height fields pre-converted collision data -- Creating a hash space and associated opcode tree structures may take significant amounts of time for a large world with many 10s of thousands of triangles. Any chance of pre-building that off-line and passing a memory block pointer to the collision system? putting objects in multiple spaces -- If it was possible to add objects to more than one space, you could do collision queries other than 1vsN and NvsN. That flexibility might be useful when you want to only collide against a subset of the space. For example, a camera system may want to collide some rays with occlusion walls but the occlusion walls may also need to be in the game-level space to bounce against. ALWAYS ------ make sure functions check their arguments in debug mode (e.g. using dASSERT). make sure joint/geom functions check for the specific object type. vectors alloca()ed on the stack must have the correct alignment, use ALLOCA16. library should have no global constructors, as it might be used with C linkage. use `const' in function arguments. blah. DON'T BOTHER ------------ warning if user tries to set mass params with nonzero center of mass. DONE ---- check: when contact attached with (body1,0) and (0,body1), check that polarity on depth and error info is okay for the two cases. set a better convention for which is the 1st and 2nd body in a joint, because sometimes we get things swapped (because of the way the joint nodes are used). hinge and prismatic, attachment to static environment. turn macros into C++ inline functions? what about C users? remove `space' argument to geom creation functions? make user add it? or just remove it from dCreateGeom() ? <-- did this one. test_chain should be in C, not C++. but first must remove global constructors. add more functionality to C++ interface - dMass, dSpace, dGeom there should be functions to delete groups of bodies/joints in one go - this will be more efficient than deleting them one at a time, because less partitioning tests will be needed. should we expose body and joint object structures so that the user can explicitly allocate them locally, or e.g. on the stack? makes allocating temporary contact constraints easier. NO --> helps data hiding and therefore library binary compatability. joints: hinge & slider - DONE measure angle, rate - DONE power - DONE joint limits - DONE mixed powered+limited joints, powering away from limit - DONE hinge2 - DONE steering angle and rate measurement - DONE steering limits - DONE steering motor - DONE wheel motor - DONE wheel angle rate measurement - DONE optional hinge2 suspension: - DONE alignment of B&S part to given axis - DONE global framework for giving epsilon and gamma - DONE toss away r-motor, make power & stuff specific to joint - DONE it's just easier that way joint code reuse: - DONE use standard functions to set velocity (c), limits (lo,hi), spongyness (epsilon) etc, this prevents these functions from proliferating implicit spring framework - actually allow joints to return a value `k' such that J*vnew = c + k*f, where f = force needed to achieve vnew - DONE contact slip - DONE contact erp & cfm parameters (not just "softness") - DONE hinge2: when we lock back wheels along the steering axis, there is no error correction if they get out of alignment - DONE, just use high and low limits. joint limit spongyness: erp and cfm for joint set from world (global) values when joint created. - DONE joint limit restitution - DONE check inertia transformations, e.g. by applying steering torque to a thin wheel --> actually, i made test_I more comprehensive random number comparisons between slow and fast methods. - random PD inertia (not just diagonal). - random velocity - random joint error (make joints then move bodies a bit) check that J*vnew=c (slow step already does this, but it doesn't equal zero for some reason! - actually, when LCP constraint limits are reached, it wont!) tons of things in lcp.cpp (@@@), especially speed optimizations. also, we wanted to do index block switching and index block updates to take advantage of the outer product trick ... but this is not worth the effort i think. lcp.cpp: if lo=hi=0, check operation. can we switch from NL <-> NH without going through C? --> done. andy says: still having trouble with those resource files.. drawstuff.res doesn't seem to build or be found under cygwin gcc. DOC how bodies and geoms associated then resolved in contact callback ... not really necessary. fix the "memory leak" in geom.cpp library should have no global constructors, as it might be used with C linkage. --> as long as test_chain1 works, there are none. DOC cfm, the derivation and what it means. --> partially done, could be better joint "get type" function andy says: in ode/src/error.cpp _snprintf() and _vsnprintf() are missing in testode: finite and isnan are missing. copysign is missing russ: okay here's the problem: i have Makefile.platform files for VC++, MinGW, but not Cygwin. Cygwin uses the unix-like functions for everything, but the VC++/MinGW configs assumes the MS C-runtime functions. this is easy to fix, except i need to install Cygwin which is a pain to do over MinGW. argh. build on linux - assumptions made about location of X11 lib, opengl etc. implement: dBodyAddForceAtPos,dBodyAddRelForceAtPos,dBodyAddRelForceAtRelPos, dBodyGetPointPos,dBodyGetPointVel,dBodyGetPointRelVel dJointAttach(), allow both bodies to be 0 to put the joint into limbo. space near-callback should be given potentially intersecting objects 100 at a time instead of 1 at a time, to save on calling costs ... which are trivial, so we don't bother to do this. doccer: @func{} also refs second etc function in function *list*. make sure joints can return 0 from GetInfo1, i.e. no constraints or "inactive" joint, and the step functions will handle it. when attaching contact with (0,body), instead of setting the reverse flag on the joint and checking it in getInfo2(), we should just reverse the normal straight away ... ? --> trouble is, dJointAttach() knows nothing about what kind of joint it is attaching. hinge2 needs to be attached to two bodies for it to work, make sure this is always the case. --> assertion added in dJointAttach(). if two joints connect to the same two bodies, check that the fast solver works! -> it should. functions to get all the joints/bodies a body/joint is connected to. If I don't have the GCC libraries installed, HUGE_VALF is undefined. fix capped cylinder - capped cylinder collision so that two contacts can be generated. transformation geometry object. joint groups should also be destroyed by destroying the world --> naaahhh. DONT DO THIS: body/joint creators with world = 0 --> not inserted into any world. allow bodies/joints to be detached from a world (this is what happens to grouped joints when a world is destroyed). can bodies and joints be linked together when not attached to world?? what happens when we have an island of b/j, some of which are not in world? soln: dont keep lists of b/j in the world, just infer it from the islands? body & joint disabling / enabling start a change log. collision flags - 0xffff mask. dBodyGetFiniteRotationMode() / ...Axis() dBodyAddForceAtRelPos() ball & socket joint limits and motors. auto-build env on windows: 3 compilers, debug/release, short/double = 12 combinations --> auto logs. handle infinities better: HUGE_VALF is not commanly defined, it seems. get rid of the __USE_ISOC9X macro in common.h perhaps just use a "big" number instead of the actual IEEE infinity, it's more portable anyway. --> new config system dCloseODE() - tidy up *all* allocated memory, esp in geom.cpp. used to keep leak detectors happy. extra API to get lambda and J'*lambda from last timestep. better stack implementation that is not so system dependent. but how will we do dynamic page allocation? do we even need to? all collision files will now be collision_*, not geom_* check exported global symbols - no C++ mangling. rename dSphere etc to dxSphere etc. C interface support for making new classes. make sure DLL-ized stuff preserved ... but class numbers should no longer be exported. point geom ( = sphere of radius 0 ) geoms stored in doubly linked lists in space (fast removal). bodies need to keep geoms pointers and call dGeomMoved() in dBodySetPosition() etc and world step. PROBLEM: links dynamics and collision together too much, makes it hard to extract ODE collision ... unless we say: dGeomMoved() and dGeomID must be supplied by the new collision library! dCollide() should take spaces as arguments - it should call dSpaceCollide2() with its own callback that puts all found contacts in the array, stopping when there is no more space left in the array. dxSpace::getGeom() - the geom numbers will change as geoms are dirtied - find some other numbering scheme, or document this behavior. the 'placeable' property - objects that should not ever be attached to bodies should flag an error when setBody etc are called. dGeomSetBody(0) - DOC: the position and orientation of the body will be preserved. in this case the geom should NOT be dirtied (dGeomMoved() should not be called). DOC: dGeomGetBodyNext() as part of dynamics/collision interface groups/spaces are subclasses of geom. groups/spaces can contain other groups/spaces. geom can be owned by a group/space. collision handling: geom-geom : standard collision function geom-group : special space code group-group : n^2 tests (or n space tests) - hard to optimize because of disjoint space representations. group internal : normal space internal-collision code groups/spaces can be told that some objects never move, i.e. that the objects are locked. should we lock the whole space? locking: the AABB for the object is not recalculated groups/spaces can be told that the internal contents self-intersect or not. actually an old ODE group is the equivalent of an old ODE simple space. - just call dCollide() or not. the group doesn't get passed to the space callback any more ... only the intersecting geoms get passed? maybe the callback can initiate the extra intersection tests itself? (because we want programmable flexibility to determine what gets intersected and what doesn't) - NO infrastructure to indicate when an object has moved (and thus its AABB needs to be recalculated) space enumeration functions. make sure that there are no additions or deletions while enumeration is taking place. - documented the behavior, didn't disallow it cache the AABB in the dxGeom? (for non-moving objects) - perhaps keep a pointer to separately allocated space? ... no DOC: dGeomGetClass() is a first-class geom function, not in the "User defined classes" section. it returns a constant that can be checked against dSphereClass etc. remove dxGeom dependence on dBodyID? ... not yet dBase -> dxBase allow a geom to be inserted into multiple spaces? need this to optimize some kinds of tests ... no update docs. make CHECK_NOT_LOCKED an assert. DOC: "Calling these functions on a non-placeable geom results in a runtime error." ...in the debug build only? non-placeable geoms should not allocate dxPosR. perhaps pass a dGeom constructor arg that says 'placeable' or not - this also sets the GEOM_PLACEABLE flag. GeomTransform: final_pos and final_R valid if no GEOM_AABB_BAD flag!!! fix up this code, esp use of ComputeTX(). Space incompatibilities: no dSpaceDestroy(), dGeomDestroy() does not take a dSpaceID ... dSpaceDestroy() added. GeomGroup incompatibilities: dCollide() used to take a GeomGroup and would return all the contact points for all the intersecting objects. now you have to call dSpaceCollide2() and get a callback for each one. need to provide old behavior. simple space optimization: we should keep the precomputed AABB for the non-moving geoms around, so that when the other geoms move we can just compute the AABBs for those geoms and then combine it with the non-moving AABB. --> too hard! collision build options: old and new tidyups for collision: * rationalize what stuff goes in what source files, and file names * minimize set of header files that all collision* sources use - after all changes. * update ode-cpp stuff (C++ interface header files). porting guide: ODE list email dGeomGetSpaceAABB() deleted dGeomGetClass (geom_group); used to return a unique type for GeomGroups, but now it returns dSimpleSpaceID. tidyups: update DLL declarations.