1 /************************************************************************* 2 * D bindings for ODE * 3 * * 4 * C header port by Daniel "q66" Kolesa <quaker66@gmail.com> * 5 * * 6 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith. * 7 * All rights reserved. Email: russ@q12.org Web: www.q12.org * 8 * * 9 * This library is free software; you can redistribute it and/or * 10 * modify it under the terms of EITHER: * 11 * (1) The GNU Lesser General Public License as published by the Free * 12 * Software Foundation; either version 2.1 of the License, or (at * 13 * your option) any later version. The text of the GNU Lesser * 14 * General Public License is included with this library in the * 15 * file LICENSE.TXT. * 16 * (2) The BSD-style license that is included with this library in * 17 * the file LICENSE-BSD.TXT. * 18 * * 19 * This library is distributed in the hope that it will be useful, * 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * 22 * LICENSE.TXT and LICENSE-BSD.TXT for more details. * 23 * * 24 *************************************************************************/ 25 26 module deimos.ode.objects; 27 28 private 29 { 30 import deimos.ode.common; 31 import deimos.ode.mass; 32 import deimos.ode.contact; 33 } 34 35 extern (C): 36 nothrow: 37 38 /** 39 * @defgroup world World 40 * 41 * The world object is a container for rigid bodies and joints. Objects in 42 * different worlds can not interact, for example rigid bodies from two 43 * different worlds can not collide. 44 * 45 * All the objects in a world exist at the same point in time, thus one 46 * reason to use separate worlds is to simulate systems at different rates. 47 * Most applications will only need one world. 48 */ 49 50 /** 51 * @brief Create a new, empty world and return its ID number. 52 * @return an identifier 53 * @ingroup world 54 */ 55 dWorldID dWorldCreate(); 56 57 /** 58 * @brief Destroy a world and everything in it. 59 * 60 * This includes all bodies, and all joints that are not part of a joint 61 * group. Joints that are part of a joint group will be deactivated, and 62 * can be destroyed by calling, for example, dJointGroupEmpty(). 63 * @ingroup world 64 * @param world the identifier for the world the be destroyed. 65 */ 66 void dWorldDestroy(dWorldID world); 67 68 69 /** 70 * @brief Set the world's global gravity vector. 71 * 72 * The units are m/s^2, so Earth's gravity vector would be (0,0,-9.81), 73 * assuming that +z is up. The default is no gravity, i.e. (0,0,0). 74 * 75 * @ingroup world 76 */ 77 void dWorldSetGravity(dWorldID, dReal x, dReal y, dReal z); 78 79 80 /** 81 * @brief Get the gravity vector for a given world. 82 * @ingroup world 83 */ 84 void dWorldGetGravity(dWorldID, dVector3 gravity); 85 86 87 /** 88 * @brief Set the global ERP value, that controls how much error 89 * correction is performed in each time step. 90 * @ingroup world 91 * @param dWorldID the identifier of the world. 92 * @param erp Typical values are in the range 0.1--0.8. The default is 0.2. 93 */ 94 void dWorldSetERP(dWorldID, dReal erp); 95 96 /** 97 * @brief Get the error reduction parameter. 98 * @ingroup world 99 * @return ERP value 100 */ 101 dReal dWorldGetERP(dWorldID); 102 103 104 /** 105 * @brief Set the global CFM (constraint force mixing) value. 106 * @ingroup world 107 * @param cfm Typical values are in the range @m{10^{-9}} -- 1. 108 * The default is 10^-5 if single precision is being used, or 10^-10 109 * if double precision is being used. 110 */ 111 void dWorldSetCFM(dWorldID, dReal cfm); 112 113 /** 114 * @brief Get the constraint force mixing value. 115 * @ingroup world 116 * @return CFM value 117 */ 118 dReal dWorldGetCFM(dWorldID); 119 120 121 /** 122 * @brief Set the world to use shared working memory along with another world. 123 * 124 * The worlds allocate working memory internally for simulation stepping. This 125 * memory is cached among the calls to @c dWordStep and @c dWorldQuickStep. 126 * Similarly, several worlds can be set up to share this memory caches thus 127 * reducing overall memory usage by cost of making worlds inappropriate for 128 * simultaneous simulation in multiple threads. 129 * 130 * If null value is passed for @a from_world parameter the world is detached from 131 * sharing and returns to defaults for working memory, reservation policy and 132 * memory manager as if just created. This can also be used to enable use of shared 133 * memory for a world that has already had working memory allocated privately. 134 * Normally using shared memory after a world has its private working memory allocated 135 * is prohibited. 136 * 137 * Allocation policy used can only increase world's internal reserved memory size 138 * and never decreases it. @c dWorldCleanupWorkingMemory can be used to release 139 * working memory for a world in case if number of objects/joint decreases 140 * significantly in it. 141 * 142 * With sharing working memory worlds also automatically share memory reservation 143 * policy and memory manager. Thus, these parameters need to be customized for 144 * initial world to be used as sharing source only. 145 * 146 * Failure result status means a memory allocation failure. 147 * 148 * @param w The world to use the shared memory with. 149 * @param from_world Null or the world the shared memory is to be used from. 150 * @returns 1 for success and 0 for failure. 151 * 152 * @ingroup world 153 * @see dWorldCleanupWorkingMemory 154 * @see dWorldSetStepMemoryReservationPolicy 155 * @see dWorldSetStepMemoryManager 156 */ 157 int dWorldUseSharedWorkingMemory(dWorldID w, dWorldID from_world/*=NULL*/); 158 159 /** 160 * @brief Release internal working memory allocated for world 161 * 162 * The worlds allocate working memory internally for simulation stepping. This 163 * function can be used to free world's internal memory cache in case if number of 164 * objects/joints in the world decreases significantly. By default, internal 165 * allocation policy is used to only increase cache size as necessary and never 166 * decrease it. 167 * 168 * If a world shares its working memory with other worlds the cache deletion 169 * affects all the linked worlds. However the shared status itself remains intact. 170 * 171 * The function call does affect neither memory reservation policy nor memory manager. 172 * 173 * @param w The world to release working memory for. 174 * 175 * @ingroup world 176 * @see dWorldUseSharedWorkingMemory 177 * @see dWorldSetStepMemoryReservationPolicy 178 * @see dWorldSetStepMemoryManager 179 */ 180 void dWorldCleanupWorkingMemory(dWorldID w); 181 182 enum dWORLDSTEP_RESERVEFACTOR_DEFAULT = 1.2f; 183 enum dWORLDSTEP_RESERVESIZE_DEFAULT = 65536U; 184 185 /** 186 * @struct dWorldStepReserveInfo 187 * @brief Memory reservation policy descriptor structure for world stepping functions. 188 * 189 * @c struct_size should be assigned the size of the structure. 190 * 191 * @c reserve_factor is a quotient that is multiplied by required memory size 192 * to allocate extra reserve whenever reallocation is needed. 193 * 194 * @c reserve_minimum is a minimum size that is checked against whenever reallocation 195 * is needed to allocate expected working memory minimum at once without extra 196 * reallocations as number of bodies/joints grows. 197 * 198 * @ingroup world 199 * @see dWorldSetStepMemoryReservationPolicy 200 */ 201 struct dWorldStepReserveInfo 202 { 203 uint struct_size; 204 205 float reserve_factor; // Use float as precision does not matter here 206 uint reserve_minimum; 207 } 208 209 /** 210 * @brief Set memory reservation policy for world to be used with simulation stepping functions 211 * 212 * The function allows to customize reservation policy to be used for internal 213 * memory which is allocated to aid simulation for a world. By default, values 214 * of @c dWORLDSTEP_RESERVEFACTOR_DEFAULT and @c dWORLDSTEP_RESERVESIZE_DEFAULT 215 * are used. 216 * 217 * Passing @a policyinfo argument as NULL results in reservation policy being 218 * reset to defaults as if the world has been just created. The content of 219 * @a policyinfo structure is copied internally and does not need to remain valid 220 * after the call returns. 221 * 222 * If the world uses working memory sharing, changing memory reservation policy 223 * affects all the worlds linked together. 224 * 225 * Failure result status means a memory allocation failure. 226 * 227 * @param w The world to change memory reservation policy for. 228 * @param policyinfo Null or a pointer to policy descriptor structure. 229 * @returns 1 for success and 0 for failure. 230 * 231 * @ingroup world 232 * @see dWorldUseSharedWorkingMemory 233 */ 234 int dWorldSetStepMemoryReservationPolicy(dWorldID w, in dWorldStepReserveInfo* policyinfo/*=NULL*/); 235 236 /** 237 * @struct dWorldStepMemoryFunctionsInfo 238 * @brief World stepping memory manager descriptor structure 239 * 240 * This structure is intended to define the functions of memory manager to be used 241 * with world stepping functions. 242 * 243 * @c struct_size should be assigned the size of the structure 244 * 245 * @c alloc_block is a function to allocate memory block of given size. 246 * 247 * @c shrink_block is a function to shrink existing memory block to a smaller size. 248 * It must preserve the contents of block head while shrinking. The new block size 249 * is guaranteed to be always less than the existing one. 250 * 251 * @c free_block is a function to delete existing memory block. 252 * 253 * @ingroup init 254 * @see dWorldSetStepMemoryManager 255 */ 256 struct dWorldStepMemoryFunctionsInfo 257 { 258 uint struct_size; 259 260 void* function(size_t block_size) alloc_block; 261 void* function( 262 void* block_pointer, 263 size_t block_current_size, 264 size_t block_smaller_size 265 ) shrink_block; 266 void function(void* block_pointer, size_t block_current_size) free_block; 267 } 268 269 /** 270 * @brief Set memory manager for world to be used with simulation stepping functions 271 * 272 * The function allows to customize memory manager to be used for internal 273 * memory allocation during simulation for a world. By default, @c dAlloc/@c dRealloc/@c dFree 274 * based memory manager is used. 275 * 276 * Passing @a memfuncs argument as NULL results in memory manager being 277 * reset to default one as if the world has been just created. The content of 278 * @a memfuncs structure is copied internally and does not need to remain valid 279 * after the call returns. 280 * 281 * If the world uses working memory sharing, changing memory manager 282 * affects all the worlds linked together. 283 * 284 * Failure result status means a memory allocation failure. 285 * 286 * @param w The world to change memory reservation policy for. 287 * @param memfuncs Null or a pointer to memory manager descriptor structure. 288 * @returns 1 for success and 0 for failure. 289 * 290 * @ingroup world 291 * @see dWorldUseSharedWorkingMemory 292 */ 293 int dWorldSetStepMemoryManager(dWorldID w, in dWorldStepMemoryFunctionsInfo* memfuncs); 294 295 /** 296 * @brief Step the world. 297 * 298 * This uses a "big matrix" method that takes time on the order of m^3 299 * and memory on the order of m^2, where m is the total number of constraint 300 * rows. For large systems this will use a lot of memory and can be very slow, 301 * but this is currently the most accurate method. 302 * 303 * Failure result status means that the memory allocation has failed for operation. 304 * In such a case all the objects remain in unchanged state and simulation can be 305 * retried as soon as more memory is available. 306 * 307 * @param w The world to be stepped 308 * @param stepsize The number of seconds that the simulation has to advance. 309 * @returns 1 for success and 0 for failure 310 * 311 * @ingroup world 312 */ 313 int dWorldStep(dWorldID w, dReal stepsize); 314 315 /** 316 * @brief Quick-step the world. 317 * 318 * This uses an iterative method that takes time on the order of m*N 319 * and memory on the order of m, where m is the total number of constraint 320 * rows N is the number of iterations. 321 * For large systems this is a lot faster than dWorldStep(), 322 * but it is less accurate. 323 * 324 * QuickStep is great for stacks of objects especially when the 325 * auto-disable feature is used as well. 326 * However, it has poor accuracy for near-singular systems. 327 * Near-singular systems can occur when using high-friction contacts, motors, 328 * or certain articulated structures. For example, a robot with multiple legs 329 * sitting on the ground may be near-singular. 330 * 331 * There are ways to help overcome QuickStep's inaccuracy problems: 332 * 333 * \li Increase CFM. 334 * \li Reduce the number of contacts in your system (e.g. use the minimum 335 * number of contacts for the feet of a robot or creature). 336 * \li Don't use excessive friction in the contacts. 337 * \li Use contact slip if appropriate 338 * \li Avoid kinematic loops (however, kinematic loops are inevitable in 339 * legged creatures). 340 * \li Don't use excessive motor strength. 341 * \liUse force-based motors instead of velocity-based motors. 342 * 343 * Increasing the number of QuickStep iterations may help a little bit, but 344 * it is not going to help much if your system is really near singular. 345 * 346 * Failure result status means that the memory allocation has failed for operation. 347 * In such a case all the objects remain in unchanged state and simulation can be 348 * retried as soon as more memory is available. 349 * 350 * @param w The world to be stepped 351 * @param stepsize The number of seconds that the simulation has to advance. 352 * @returns 1 for success and 0 for failure 353 * 354 * @ingroup world 355 */ 356 int dWorldQuickStep(dWorldID w, dReal stepsize); 357 358 359 /** 360 * @brief Converts an impulse to a force. 361 * @ingroup world 362 * @remarks 363 * If you want to apply a linear or angular impulse to a rigid body, 364 * instead of a force or a torque, then you can use this function to convert 365 * the desired impulse into a force/torque vector before calling the 366 * BodyAdd... function. 367 * The current algorithm simply scales the impulse by 1/stepsize, 368 * where stepsize is the step size for the next step that will be taken. 369 * This function is given a dWorldID because, in the future, the force 370 * computation may depend on integrator parameters that are set as 371 * properties of the world. 372 */ 373 void dWorldImpulseToForce( 374 dWorldID, dReal stepsize, dReal ix, dReal iy, dReal iz, dVector3 force 375 ); 376 377 378 /** 379 * @brief Set the number of iterations that the QuickStep method performs per 380 * step. 381 * @ingroup world 382 * @remarks 383 * More iterations will give a more accurate solution, but will take 384 * longer to compute. 385 * @param num The default is 20 iterations. 386 */ 387 void dWorldSetQuickStepNumIterations(dWorldID, int num); 388 389 390 /** 391 * @brief Get the number of iterations that the QuickStep method performs per 392 * step. 393 * @ingroup world 394 * @return nr of iterations 395 */ 396 int dWorldGetQuickStepNumIterations(dWorldID); 397 398 /** 399 * @brief Set the SOR over-relaxation parameter 400 * @ingroup world 401 * @param over_relaxation value to use by SOR 402 */ 403 void dWorldSetQuickStepW(dWorldID, dReal over_relaxation); 404 405 /** 406 * @brief Get the SOR over-relaxation parameter 407 * @ingroup world 408 * @returns the over-relaxation setting 409 */ 410 dReal dWorldGetQuickStepW(dWorldID); 411 412 /* World contact parameter functions */ 413 414 /** 415 * @brief Set the maximum correcting velocity that contacts are allowed 416 * to generate. 417 * @ingroup world 418 * @param vel The default value is infinity (i.e. no limit). 419 * @remarks 420 * Reducing this value can help prevent "popping" of deeply embedded objects. 421 */ 422 void dWorldSetContactMaxCorrectingVel(dWorldID, dReal vel); 423 424 /** 425 * @brief Get the maximum correcting velocity that contacts are allowed 426 * to generated. 427 * @ingroup world 428 */ 429 dReal dWorldGetContactMaxCorrectingVel(dWorldID); 430 431 /** 432 * @brief Set the depth of the surface layer around all geometry objects. 433 * @ingroup world 434 * @remarks 435 * Contacts are allowed to sink into the surface layer up to the given 436 * depth before coming to rest. 437 * @param depth The default value is zero. 438 * @remarks 439 * Increasing this to some small value (e.g. 0.001) can help prevent 440 * jittering problems due to contacts being repeatedly made and broken. 441 */ 442 void dWorldSetContactSurfaceLayer(dWorldID, dReal depth); 443 444 /** 445 * @brief Get the depth of the surface layer around all geometry objects. 446 * @ingroup world 447 * @returns the depth 448 */ 449 dReal dWorldGetContactSurfaceLayer(dWorldID); 450 451 452 /** 453 * @defgroup disable Automatic Enabling and Disabling 454 * @ingroup world bodies 455 * 456 * Every body can be enabled or disabled. Enabled bodies participate in the 457 * simulation, while disabled bodies are turned off and do not get updated 458 * during a simulation step. New bodies are always created in the enabled state. 459 * 460 * A disabled body that is connected through a joint to an enabled body will be 461 * automatically re-enabled at the next simulation step. 462 * 463 * Disabled bodies do not consume CPU time, therefore to speed up the simulation 464 * bodies should be disabled when they come to rest. This can be done automatically 465 * with the auto-disable feature. 466 * 467 * If a body has its auto-disable flag turned on, it will automatically disable 468 * itself when 469 * @li It has been idle for a given number of simulation steps. 470 * @li It has also been idle for a given amount of simulation time. 471 * 472 * A body is considered to be idle when the magnitudes of both its 473 * linear average velocity and angular average velocity are below given thresholds. 474 * The sample size for the average defaults to one and can be disabled by setting 475 * to zero with 476 * 477 * Thus, every body has six auto-disable parameters: an enabled flag, a idle step 478 * count, an idle time, linear/angular average velocity thresholds, and the 479 * average samples count. 480 * 481 * Newly created bodies get these parameters from world. 482 */ 483 484 /** 485 * @brief Get auto disable linear threshold for newly created bodies. 486 * @ingroup disable 487 * @return the threshold 488 */ 489 dReal dWorldGetAutoDisableLinearThreshold(dWorldID); 490 491 /** 492 * @brief Set auto disable linear threshold for newly created bodies. 493 * @param linear_threshold default is 0.01 494 * @ingroup disable 495 */ 496 void dWorldSetAutoDisableLinearThreshold(dWorldID, dReal linear_threshold); 497 498 /** 499 * @brief Get auto disable angular threshold for newly created bodies. 500 * @ingroup disable 501 * @return the threshold 502 */ 503 dReal dWorldGetAutoDisableAngularThreshold(dWorldID); 504 505 /** 506 * @brief Set auto disable angular threshold for newly created bodies. 507 * @param linear_threshold default is 0.01 508 * @ingroup disable 509 */ 510 void dWorldSetAutoDisableAngularThreshold(dWorldID, dReal angular_threshold); 511 512 /** 513 * @brief Get auto disable linear average threshold for newly created bodies. 514 * @ingroup disable 515 * @return the threshold 516 */ 517 dReal dWorldGetAutoDisableLinearAverageThreshold(dWorldID); 518 519 /** 520 * @brief Set auto disable linear average threshold for newly created bodies. 521 * @param linear_average_threshold default is 0.01 522 * @ingroup disable 523 */ 524 void dWorldSetAutoDisableLinearAverageThreshold(dWorldID, dReal linear_average_threshold); 525 526 /** 527 * @brief Get auto disable angular average threshold for newly created bodies. 528 * @ingroup disable 529 * @return the threshold 530 */ 531 dReal dWorldGetAutoDisableAngularAverageThreshold(dWorldID); 532 533 /** 534 * @brief Set auto disable angular average threshold for newly created bodies. 535 * @param linear_average_threshold default is 0.01 536 * @ingroup disable 537 */ 538 void dWorldSetAutoDisableAngularAverageThreshold(dWorldID, dReal angular_average_threshold); 539 540 /** 541 * @brief Get auto disable sample count for newly created bodies. 542 * @ingroup disable 543 * @return number of samples used 544 */ 545 int dWorldGetAutoDisableAverageSamplesCount(dWorldID); 546 547 /** 548 * @brief Set auto disable average sample count for newly created bodies. 549 * @ingroup disable 550 * @param average_samples_count Default is 1, meaning only instantaneous velocity is used. 551 * Set to zero to disable sampling and thus prevent any body from auto-disabling. 552 */ 553 void dWorldSetAutoDisableAverageSamplesCount(dWorldID, uint average_samples_count); 554 555 /** 556 * @brief Get auto disable steps for newly created bodies. 557 * @ingroup disable 558 * @return nr of steps 559 */ 560 int dWorldGetAutoDisableSteps(dWorldID); 561 562 /** 563 * @brief Set auto disable steps for newly created bodies. 564 * @ingroup disable 565 * @param steps default is 10 566 */ 567 void dWorldSetAutoDisableSteps(dWorldID, int steps); 568 569 /** 570 * @brief Get auto disable time for newly created bodies. 571 * @ingroup disable 572 * @return nr of seconds 573 */ 574 dReal dWorldGetAutoDisableTime(dWorldID); 575 576 /** 577 * @brief Set auto disable time for newly created bodies. 578 * @ingroup disable 579 * @param time default is 0 seconds 580 */ 581 void dWorldSetAutoDisableTime(dWorldID, dReal time); 582 583 /** 584 * @brief Get auto disable flag for newly created bodies. 585 * @ingroup disable 586 * @return 0 or 1 587 */ 588 int dWorldGetAutoDisableFlag(dWorldID); 589 590 /** 591 * @brief Set auto disable flag for newly created bodies. 592 * @ingroup disable 593 * @param do_auto_disable default is false. 594 */ 595 void dWorldSetAutoDisableFlag(dWorldID, int do_auto_disable); 596 597 598 /** 599 * @defgroup damping Damping 600 * @ingroup bodies world 601 * 602 * Damping serves two purposes: reduce simulation instability, and to allow 603 * the bodies to come to rest (and possibly auto-disabling them). 604 * 605 * Bodies are constructed using the world's current damping parameters. Setting 606 * the scales to 0 disables the damping. 607 * 608 * Here is how it is done: after every time step linear and angular 609 * velocities are tested against the corresponding thresholds. If they 610 * are above, they are multiplied by (1 - scale). So a negative scale value 611 * will actually increase the speed, and values greater than one will 612 * make the object oscillate every step; both can make the simulation unstable. 613 * 614 * To disable damping just set the damping scale to zero. 615 * 616 * You can also limit the maximum angular velocity. In contrast to the damping 617 * functions, the angular velocity is affected before the body is moved. 618 * This means that it will introduce errors in joints that are forcing the body 619 * to rotate too fast. Some bodies have naturally high angular velocities 620 * (like cars' wheels), so you may want to give them a very high (like the default, 621 * dInfinity) limit. 622 * 623 * @note The velocities are damped after the stepper function has moved the 624 * object. Otherwise the damping could introduce errors in joints. First the 625 * joint constraints are processed by the stepper (moving the body), then 626 * the damping is applied. 627 * 628 * @note The damping happens right after the moved callback is called; this way 629 * it still possible use the exact velocities the body has acquired during the 630 * step. You can even use the callback to create your own customized damping. 631 */ 632 633 /** 634 * @brief Get the world's linear damping threshold. 635 * @ingroup damping 636 */ 637 dReal dWorldGetLinearDampingThreshold(dWorldID w); 638 639 /** 640 * @brief Set the world's linear damping threshold. 641 * @param threshold The damping won't be applied if the linear speed is 642 * below this threshold. Default is 0.01. 643 * @ingroup damping 644 */ 645 void dWorldSetLinearDampingThreshold(dWorldID w, dReal threshold); 646 647 /** 648 * @brief Get the world's angular damping threshold. 649 * @ingroup damping 650 */ 651 dReal dWorldGetAngularDampingThreshold(dWorldID w); 652 653 /** 654 * @brief Set the world's angular damping threshold. 655 * @param threshold The damping won't be applied if the angular speed is 656 * below this threshold. Default is 0.01. 657 * @ingroup damping 658 */ 659 void dWorldSetAngularDampingThreshold(dWorldID w, dReal threshold); 660 661 /** 662 * @brief Get the world's linear damping scale. 663 * @ingroup damping 664 */ 665 dReal dWorldGetLinearDamping(dWorldID w); 666 667 /** 668 * @brief Set the world's linear damping scale. 669 * @param scale The linear damping scale that is to be applied to bodies. 670 * Default is 0 (no damping). Should be in the interval [0, 1]. 671 * @ingroup damping 672 */ 673 void dWorldSetLinearDamping(dWorldID w, dReal scale); 674 675 /** 676 * @brief Get the world's angular damping scale. 677 * @ingroup damping 678 */ 679 dReal dWorldGetAngularDamping(dWorldID w); 680 681 /** 682 * @brief Set the world's angular damping scale. 683 * @param scale The angular damping scale that is to be applied to bodies. 684 * Default is 0 (no damping). Should be in the interval [0, 1]. 685 * @ingroup damping 686 */ 687 void dWorldSetAngularDamping(dWorldID w, dReal scale); 688 689 /** 690 * @brief Convenience function to set body linear and angular scales. 691 * @param linear_scale The linear damping scale that is to be applied to bodies. 692 * @param angular_scale The angular damping scale that is to be applied to bodies. 693 * @ingroup damping 694 */ 695 void dWorldSetDamping(dWorldID w, dReal linear_scale, dReal angular_scale); 696 697 /** 698 * @brief Get the default maximum angular speed. 699 * @ingroup damping 700 * @sa dBodyGetMaxAngularSpeed() 701 */ 702 dReal dWorldGetMaxAngularSpeed(dWorldID w); 703 704 705 /** 706 * @brief Set the default maximum angular speed for new bodies. 707 * @ingroup damping 708 * @sa dBodySetMaxAngularSpeed() 709 */ 710 void dWorldSetMaxAngularSpeed(dWorldID w, dReal max_speed); 711 712 713 714 /** 715 * @defgroup bodies Rigid Bodies 716 * 717 * A rigid body has various properties from the point of view of the 718 * simulation. Some properties change over time: 719 * 720 * @li Position vector (x,y,z) of the body's point of reference. 721 * Currently the point of reference must correspond to the body's center of mass. 722 * @li Linear velocity of the point of reference, a vector (vx,vy,vz). 723 * @li Orientation of a body, represented by a quaternion (qs,qx,qy,qz) or 724 * a 3x3 rotation matrix. 725 * @li Angular velocity vector (wx,wy,wz) which describes how the orientation 726 * changes over time. 727 * 728 * Other body properties are usually constant over time: 729 * 730 * @li Mass of the body. 731 * @li Position of the center of mass with respect to the point of reference. 732 * In the current implementation the center of mass and the point of 733 * reference must coincide. 734 * @li Inertia matrix. This is a 3x3 matrix that describes how the body's mass 735 * is distributed around the center of mass. Conceptually each body has an 736 * x-y-z coordinate frame embedded in it that moves and rotates with the body. 737 * 738 * The origin of this coordinate frame is the body's point of reference. Some values 739 * in ODE (vectors, matrices etc) are relative to the body coordinate frame, and others 740 * are relative to the global coordinate frame. 741 * 742 * Note that the shape of a rigid body is not a dynamical property (except insofar as 743 * it influences the various mass properties). It is only collision detection that cares 744 * about the detailed shape of the body. 745 */ 746 747 748 /** 749 * @brief Get auto disable linear average threshold. 750 * @ingroup bodies disable 751 * @return the threshold 752 */ 753 dReal dBodyGetAutoDisableLinearThreshold(dBodyID); 754 755 /** 756 * @brief Set auto disable linear average threshold. 757 * @ingroup bodies disable 758 * @return the threshold 759 */ 760 void dBodySetAutoDisableLinearThreshold(dBodyID, dReal linear_average_threshold); 761 762 /** 763 * @brief Get auto disable angular average threshold. 764 * @ingroup bodies disable 765 * @return the threshold 766 */ 767 dReal dBodyGetAutoDisableAngularThreshold(dBodyID); 768 769 /** 770 * @brief Set auto disable angular average threshold. 771 * @ingroup bodies disable 772 * @return the threshold 773 */ 774 void dBodySetAutoDisableAngularThreshold(dBodyID, dReal angular_average_threshold); 775 776 /** 777 * @brief Get auto disable average size (samples count). 778 * @ingroup bodies disable 779 * @return the nr of steps/size. 780 */ 781 int dBodyGetAutoDisableAverageSamplesCount(dBodyID); 782 783 /** 784 * @brief Set auto disable average buffer size (average steps). 785 * @ingroup bodies disable 786 * @param average_samples_count the nr of samples to review. 787 */ 788 void dBodySetAutoDisableAverageSamplesCount(dBodyID, uint average_samples_count); 789 790 791 /** 792 * @brief Get auto steps a body must be thought of as idle to disable 793 * @ingroup bodies disable 794 * @return the nr of steps 795 */ 796 int dBodyGetAutoDisableSteps(dBodyID); 797 798 /** 799 * @brief Set auto disable steps. 800 * @ingroup bodies disable 801 * @param steps the nr of steps. 802 */ 803 void dBodySetAutoDisableSteps(dBodyID, int steps); 804 805 /** 806 * @brief Get auto disable time. 807 * @ingroup bodies disable 808 * @return nr of seconds 809 */ 810 dReal dBodyGetAutoDisableTime(dBodyID); 811 812 /** 813 * @brief Set auto disable time. 814 * @ingroup bodies disable 815 * @param time nr of seconds. 816 */ 817 void dBodySetAutoDisableTime(dBodyID, dReal time); 818 819 /** 820 * @brief Get auto disable flag. 821 * @ingroup bodies disable 822 * @return 0 or 1 823 */ 824 int dBodyGetAutoDisableFlag(dBodyID); 825 826 /** 827 * @brief Set auto disable flag. 828 * @ingroup bodies disable 829 * @param do_auto_disable 0 or 1 830 */ 831 void dBodySetAutoDisableFlag(dBodyID, int do_auto_disable); 832 833 /** 834 * @brief Set auto disable defaults. 835 * @remarks 836 * Set the values for the body to those set as default for the world. 837 * @ingroup bodies disable 838 */ 839 void dBodySetAutoDisableDefaults(dBodyID); 840 841 842 /** 843 * @brief Retrieves the world attached to te given body. 844 * @remarks 845 * 846 * @ingroup bodies 847 */ 848 dWorldID dBodyGetWorld(dBodyID); 849 850 /** 851 * @brief Create a body in given world. 852 * @remarks 853 * Default mass parameters are at position (0,0,0). 854 * @ingroup bodies 855 */ 856 dBodyID dBodyCreate(dWorldID); 857 858 /** 859 * @brief Destroy a body. 860 * @remarks 861 * All joints that are attached to this body will be put into limbo: 862 * i.e. unattached and not affecting the simulation, but they will NOT be 863 * deleted. 864 * @ingroup bodies 865 */ 866 void dBodyDestroy(dBodyID); 867 868 /** 869 * @brief Set the body's user-data pointer. 870 * @ingroup bodies 871 * @param data arbitraty pointer 872 */ 873 void dBodySetData(dBodyID, void* data); 874 875 /** 876 * @brief Get the body's user-data pointer. 877 * @ingroup bodies 878 * @return a pointer to the user's data. 879 */ 880 void* dBodyGetData(dBodyID); 881 882 /** 883 * @brief Set position of a body. 884 * @remarks 885 * After setting, the outcome of the simulation is undefined 886 * if the new configuration is inconsistent with the joints/constraints 887 * that are present. 888 * @ingroup bodies 889 */ 890 void dBodySetPosition(dBodyID, dReal x, dReal y, dReal z); 891 892 /** 893 * @brief Set the orientation of a body. 894 * @ingroup bodies 895 * @remarks 896 * After setting, the outcome of the simulation is undefined 897 * if the new configuration is inconsistent with the joints/constraints 898 * that are present. 899 */ 900 void dBodySetRotation(dBodyID, in dMatrix3 R); 901 902 /** 903 * @brief Set the orientation of a body. 904 * @ingroup bodies 905 * @remarks 906 * After setting, the outcome of the simulation is undefined 907 * if the new configuration is inconsistent with the joints/constraints 908 * that are present. 909 */ 910 void dBodySetQuaternion(dBodyID, in dQuaternion q); 911 912 /** 913 * @brief Set the linear velocity of a body. 914 * @ingroup bodies 915 */ 916 void dBodySetLinearVel(dBodyID, dReal x, dReal y, dReal z); 917 918 /** 919 * @brief Set the angular velocity of a body. 920 * @ingroup bodies 921 */ 922 void dBodySetAngularVel(dBodyID, dReal x, dReal y, dReal z); 923 924 /** 925 * @brief Get the position of a body. 926 * @ingroup bodies 927 * @remarks 928 * When getting, the returned values are pointers to internal data structures, 929 * so the vectors are valid until any changes are made to the rigid body 930 * system structure. 931 * @sa dBodyCopyPosition 932 */ 933 const(dReal)* dBodyGetPosition(dBodyID); 934 935 936 /** 937 * @brief Copy the position of a body into a vector. 938 * @ingroup bodies 939 * @param body the body to query 940 * @param pos a copy of the body position 941 * @sa dBodyGetPosition 942 */ 943 void dBodyCopyPosition(dBodyID dbody, dVector3 pos); 944 945 946 /** 947 * @brief Get the rotation of a body. 948 * @ingroup bodies 949 * @return pointer to a 4x3 rotation matrix. 950 */ 951 const(dReal)* dBodyGetRotation(dBodyID); 952 953 954 /** 955 * @brief Copy the rotation of a body. 956 * @ingroup bodies 957 * @param body the body to query 958 * @param R a copy of the rotation matrix 959 * @sa dBodyGetRotation 960 */ 961 void dBodyCopyRotation(dBodyID, dMatrix3 R); 962 963 964 /** 965 * @brief Get the rotation of a body. 966 * @ingroup bodies 967 * @return pointer to 4 scalars that represent the quaternion. 968 */ 969 const(dReal)* dBodyGetQuaternion(dBodyID); 970 971 972 /** 973 * @brief Copy the orientation of a body into a quaternion. 974 * @ingroup bodies 975 * @param body the body to query 976 * @param quat a copy of the orientation quaternion 977 * @sa dBodyGetQuaternion 978 */ 979 void dBodyCopyQuaternion(dBodyID dbody, dQuaternion quat); 980 981 982 /** 983 * @brief Get the linear velocity of a body. 984 * @ingroup bodies 985 */ 986 const(dReal)* dBodyGetLinearVel(dBodyID); 987 988 /** 989 * @brief Get the angular velocity of a body. 990 * @ingroup bodies 991 */ 992 const(dReal)* dBodyGetAngularVel(dBodyID); 993 994 /** 995 * @brief Set the mass of a body. 996 * @ingroup bodies 997 */ 998 void dBodySetMass(dBodyID, in dMass* mass); 999 1000 /** 1001 * @brief Get the mass of a body. 1002 * @ingroup bodies 1003 */ 1004 void dBodyGetMass(dBodyID, dMass* mass); 1005 1006 /** 1007 * @brief Add force at centre of mass of body in absolute coordinates. 1008 * @ingroup bodies 1009 */ 1010 void dBodyAddForce(dBodyID, dReal fx, dReal fy, dReal fz); 1011 1012 /** 1013 * @brief Add torque at centre of mass of body in absolute coordinates. 1014 * @ingroup bodies 1015 */ 1016 void dBodyAddTorque(dBodyID, dReal fx, dReal fy, dReal fz); 1017 1018 /** 1019 * @brief Add force at centre of mass of body in coordinates relative to body. 1020 * @ingroup bodies 1021 */ 1022 void dBodyAddRelForce(dBodyID, dReal fx, dReal fy, dReal fz); 1023 1024 /** 1025 * @brief Add torque at centre of mass of body in coordinates relative to body. 1026 * @ingroup bodies 1027 */ 1028 void dBodyAddRelTorque(dBodyID, dReal fx, dReal fy, dReal fz); 1029 1030 /** 1031 * @brief Add force at specified point in body in global coordinates. 1032 * @ingroup bodies 1033 */ 1034 void dBodyAddForceAtPos( 1035 dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz 1036 ); 1037 /** 1038 * @brief Add force at specified point in body in local coordinates. 1039 * @ingroup bodies 1040 */ 1041 void dBodyAddForceAtRelPos( 1042 dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz 1043 ); 1044 /** 1045 * @brief Add force at specified point in body in global coordinates. 1046 * @ingroup bodies 1047 */ 1048 void dBodyAddRelForceAtPos( 1049 dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz 1050 ); 1051 /** 1052 * @brief Add force at specified point in body in local coordinates. 1053 * @ingroup bodies 1054 */ 1055 void dBodyAddRelForceAtRelPos( 1056 dBodyID, dReal fx, dReal fy, dReal fz, dReal px, dReal py, dReal pz 1057 ); 1058 1059 /** 1060 * @brief Return the current accumulated force vector. 1061 * @return points to an array of 3 reals. 1062 * @remarks 1063 * The returned values are pointers to internal data structures, so 1064 * the vectors are only valid until any changes are made to the rigid 1065 * body system. 1066 * @ingroup bodies 1067 */ 1068 const(dReal)* dBodyGetForce(dBodyID); 1069 1070 /** 1071 * @brief Return the current accumulated torque vector. 1072 * @return points to an array of 3 reals. 1073 * @remarks 1074 * The returned values are pointers to internal data structures, so 1075 * the vectors are only valid until any changes are made to the rigid 1076 * body system. 1077 * @ingroup bodies 1078 */ 1079 const(dReal)* dBodyGetTorque(dBodyID); 1080 1081 /** 1082 * @brief Set the body force accumulation vector. 1083 * @remarks 1084 * This is mostly useful to zero the force and torque for deactivated bodies 1085 * before they are reactivated, in the case where the force-adding functions 1086 * were called on them while they were deactivated. 1087 * @ingroup bodies 1088 */ 1089 void dBodySetForce(dBodyID b, dReal x, dReal y, dReal z); 1090 1091 /** 1092 * @brief Set the body torque accumulation vector. 1093 * @remarks 1094 * This is mostly useful to zero the force and torque for deactivated bodies 1095 * before they are reactivated, in the case where the force-adding functions 1096 * were called on them while they were deactivated. 1097 * @ingroup bodies 1098 */ 1099 void dBodySetTorque(dBodyID b, dReal x, dReal y, dReal z); 1100 1101 /** 1102 * @brief Get world position of a relative point on body. 1103 * @ingroup bodies 1104 * @param result will contain the result. 1105 */ 1106 void dBodyGetRelPointPos(dBodyID, dReal px, dReal py, dReal pz,dVector3 result); 1107 1108 /** 1109 * @brief Get velocity vector in global coords of a relative point on body. 1110 * @ingroup bodies 1111 * @param result will contain the result. 1112 */ 1113 void dBodyGetRelPointVel(dBodyID, dReal px, dReal py, dReal pz, dVector3 result); 1114 1115 /** 1116 * @brief Get velocity vector in global coords of a globally 1117 * specified point on a body. 1118 * @ingroup bodies 1119 * @param result will contain the result. 1120 */ 1121 void dBodyGetPointVel(dBodyID, dReal px, dReal py, dReal pz, dVector3 result); 1122 1123 /** 1124 * @brief takes a point in global coordinates and returns 1125 * the point's position in body-relative coordinates. 1126 * @remarks 1127 * This is the inverse of dBodyGetRelPointPos() 1128 * @ingroup bodies 1129 * @param result will contain the result. 1130 */ 1131 void dBodyGetPosRelPoint(dBodyID, dReal px, dReal py, dReal pz, dVector3 result); 1132 1133 /** 1134 * @brief Convert from local to world coordinates. 1135 * @ingroup bodies 1136 * @param result will contain the result. 1137 */ 1138 void dBodyVectorToWorld(dBodyID, dReal px, dReal py, dReal pz, dVector3 result); 1139 1140 /** 1141 * @brief Convert from world to local coordinates. 1142 * @ingroup bodies 1143 * @param result will contain the result. 1144 */ 1145 void dBodyVectorFromWorld(dBodyID, dReal px, dReal py, dReal pz, dVector3 result); 1146 1147 /** 1148 * @brief controls the way a body's orientation is updated at each timestep. 1149 * @ingroup bodies 1150 * @param mode can be 0 or 1: 1151 * \li 0: An ``infinitesimal'' orientation update is used. 1152 * This is fast to compute, but it can occasionally cause inaccuracies 1153 * for bodies that are rotating at high speed, especially when those 1154 * bodies are joined to other bodies. 1155 * This is the default for every new body that is created. 1156 * \li 1: A ``finite'' orientation update is used. 1157 * This is more costly to compute, but will be more accurate for high 1158 * speed rotations. 1159 * @remarks 1160 * Note however that high speed rotations can result in many types of 1161 * error in a simulation, and the finite mode will only fix one of those 1162 * sources of error. 1163 */ 1164 void dBodySetFiniteRotationMode(dBodyID, int mode); 1165 1166 /** 1167 * @brief sets the finite rotation axis for a body. 1168 * @ingroup bodies 1169 * @remarks 1170 * This is axis only has meaning when the finite rotation mode is set 1171 * If this axis is zero (0,0,0), full finite rotations are performed on 1172 * the body. 1173 * If this axis is nonzero, the body is rotated by performing a partial finite 1174 * rotation along the axis direction followed by an infinitesimal rotation 1175 * along an orthogonal direction. 1176 * @remarks 1177 * This can be useful to alleviate certain sources of error caused by quickly 1178 * spinning bodies. For example, if a car wheel is rotating at high speed 1179 * you can call this function with the wheel's hinge axis as the argument to 1180 * try and improve its behavior. 1181 */ 1182 void dBodySetFiniteRotationAxis(dBodyID, dReal x, dReal y, dReal z); 1183 1184 /** 1185 * @brief Get the way a body's orientation is updated each timestep. 1186 * @ingroup bodies 1187 * @return the mode 0 (infitesimal) or 1 (finite). 1188 */ 1189 int dBodyGetFiniteRotationMode(dBodyID); 1190 1191 /** 1192 * @brief Get the finite rotation axis. 1193 * @param result will contain the axis. 1194 * @ingroup bodies 1195 */ 1196 void dBodyGetFiniteRotationAxis(dBodyID, dVector3 result); 1197 1198 /** 1199 * @brief Get the number of joints that are attached to this body. 1200 * @ingroup bodies 1201 * @return nr of joints 1202 */ 1203 int dBodyGetNumJoints(dBodyID b); 1204 1205 /** 1206 * @brief Return a joint attached to this body, given by index. 1207 * @ingroup bodies 1208 * @param index valid range is 0 to n-1 where n is the value returned by 1209 * dBodyGetNumJoints(). 1210 */ 1211 dJointID dBodyGetJoint(dBodyID, int index); 1212 1213 1214 1215 1216 /** 1217 * @brief Set rigid body to dynamic state (default). 1218 * @param dBodyID identification of body. 1219 * @ingroup bodies 1220 */ 1221 void dBodySetDynamic(dBodyID); 1222 1223 /** 1224 * @brief Set rigid body to kinematic state. 1225 * When in kinematic state the body isn't simulated as a dynamic 1226 * body (it's "unstoppable", doesn't respond to forces), 1227 * but can still affect dynamic bodies (e.g. in joints). 1228 * Kinematic bodies can be controlled by position and velocity. 1229 * @note A kinematic body has infinite mass. If you set its mass 1230 * to something else, it loses the kinematic state and behaves 1231 * as a normal dynamic body. 1232 * @param dBodyID identification of body. 1233 * @ingroup bodies 1234 */ 1235 void dBodySetKinematic(dBodyID); 1236 1237 /** 1238 * @brief Check wether a body is in kinematic state. 1239 * @ingroup bodies 1240 * @return 1 if a body is kinematic or 0 if it is dynamic. 1241 */ 1242 int dBodyIsKinematic(dBodyID); 1243 1244 /** 1245 * @brief Manually enable a body. 1246 * @param dBodyID identification of body. 1247 * @ingroup bodies 1248 */ 1249 void dBodyEnable(dBodyID); 1250 1251 /** 1252 * @brief Manually disable a body. 1253 * @ingroup bodies 1254 * @remarks 1255 * A disabled body that is connected through a joint to an enabled body will 1256 * be automatically re-enabled at the next simulation step. 1257 */ 1258 void dBodyDisable(dBodyID); 1259 1260 /** 1261 * @brief Check wether a body is enabled. 1262 * @ingroup bodies 1263 * @return 1 if a body is currently enabled or 0 if it is disabled. 1264 */ 1265 int dBodyIsEnabled(dBodyID); 1266 1267 /** 1268 * @brief Set whether the body is influenced by the world's gravity or not. 1269 * @ingroup bodies 1270 * @param mode when nonzero gravity affects this body. 1271 * @remarks 1272 * Newly created bodies are always influenced by the world's gravity. 1273 */ 1274 void dBodySetGravityMode(dBodyID b, int mode); 1275 1276 /** 1277 * @brief Get whether the body is influenced by the world's gravity or not. 1278 * @ingroup bodies 1279 * @return nonzero means gravity affects this body. 1280 */ 1281 int dBodyGetGravityMode(dBodyID b); 1282 1283 /** 1284 * @brief Set the 'moved' callback of a body. 1285 * 1286 * Whenever a body has its position or rotation changed during the 1287 * timestep, the callback will be called (with body as the argument). 1288 * Use it to know which body may need an update in an external 1289 * structure (like a 3D engine). 1290 * 1291 * @param b the body that needs to be watched. 1292 * @param callback the callback to be invoked when the body moves. Set to zero 1293 * to disable. 1294 * @ingroup bodies 1295 */ 1296 void dBodySetMovedCallback(dBodyID b, void function(dBodyID) callback); 1297 1298 1299 /** 1300 * @brief Return the first geom associated with the body. 1301 * 1302 * You can traverse through the geoms by repeatedly calling 1303 * dBodyGetNextGeom(). 1304 * 1305 * @return the first geom attached to this body, or 0. 1306 * @ingroup bodies 1307 */ 1308 dGeomID dBodyGetFirstGeom(dBodyID b); 1309 1310 1311 /** 1312 * @brief returns the next geom associated with the same body. 1313 * @param g a geom attached to some body. 1314 * @return the next geom attached to the same body, or 0. 1315 * @sa dBodyGetFirstGeom 1316 * @ingroup bodies 1317 */ 1318 dGeomID dBodyGetNextGeom(dGeomID g); 1319 1320 1321 /** 1322 * @brief Resets the damping settings to the current world's settings. 1323 * @ingroup bodies damping 1324 */ 1325 void dBodySetDampingDefaults(dBodyID b); 1326 1327 /** 1328 * @brief Get the body's linear damping scale. 1329 * @ingroup bodies damping 1330 */ 1331 dReal dBodyGetLinearDamping(dBodyID b); 1332 1333 /** 1334 * @brief Set the body's linear damping scale. 1335 * @param scale The linear damping scale. Should be in the interval [0, 1]. 1336 * @ingroup bodies damping 1337 * @remarks From now on the body will not use the world's linear damping 1338 * scale until dBodySetDampingDefaults() is called. 1339 * @sa dBodySetDampingDefaults() 1340 */ 1341 void dBodySetLinearDamping(dBodyID b, dReal scale); 1342 1343 /** 1344 * @brief Get the body's angular damping scale. 1345 * @ingroup bodies damping 1346 * @remarks If the body's angular damping scale was not set, this function 1347 * returns the world's angular damping scale. 1348 */ 1349 dReal dBodyGetAngularDamping(dBodyID b); 1350 1351 /** 1352 * @brief Set the body's angular damping scale. 1353 * @param scale The angular damping scale. Should be in the interval [0, 1]. 1354 * @ingroup bodies damping 1355 * @remarks From now on the body will not use the world's angular damping 1356 * scale until dBodyResetAngularDamping() is called. 1357 * @sa dBodyResetAngularDamping() 1358 */ 1359 void dBodySetAngularDamping(dBodyID b, dReal scale); 1360 1361 /** 1362 * @brief Convenience function to set linear and angular scales at once. 1363 * @param linear_scale The linear damping scale. Should be in the interval [0, 1]. 1364 * @param angular_scale The angular damping scale. Should be in the interval [0, 1]. 1365 * @ingroup bodies damping 1366 * @sa dBodySetLinearDamping() dBodySetAngularDamping() 1367 */ 1368 void dBodySetDamping(dBodyID b, dReal linear_scale, dReal angular_scale); 1369 1370 /** 1371 * @brief Get the body's linear damping threshold. 1372 * @ingroup bodies damping 1373 */ 1374 dReal dBodyGetLinearDampingThreshold(dBodyID b); 1375 1376 /** 1377 * @brief Set the body's linear damping threshold. 1378 * @param threshold The linear threshold to be used. Damping 1379 * is only applied if the linear speed is above this limit. 1380 * @ingroup bodies damping 1381 */ 1382 void dBodySetLinearDampingThreshold(dBodyID b, dReal threshold); 1383 1384 /** 1385 * @brief Get the body's angular damping threshold. 1386 * @ingroup bodies damping 1387 */ 1388 dReal dBodyGetAngularDampingThreshold(dBodyID b); 1389 1390 /** 1391 * @brief Set the body's angular damping threshold. 1392 * @param threshold The angular threshold to be used. Damping is 1393 * only used if the angular speed is above this limit. 1394 * @ingroup bodies damping 1395 */ 1396 void dBodySetAngularDampingThreshold(dBodyID b, dReal threshold); 1397 1398 /** 1399 * @brief Get the body's maximum angular speed. 1400 * @ingroup damping bodies 1401 * @sa dWorldGetMaxAngularSpeed() 1402 */ 1403 dReal dBodyGetMaxAngularSpeed(dBodyID b); 1404 1405 /** 1406 * @brief Set the body's maximum angular speed. 1407 * @ingroup damping bodies 1408 * @sa dWorldSetMaxAngularSpeed() dBodyResetMaxAngularSpeed() 1409 * The default value is dInfinity, but it's a good idea to limit 1410 * it at less than 500 if the body has the gyroscopic term 1411 * enabled. 1412 */ 1413 void dBodySetMaxAngularSpeed(dBodyID b, dReal max_speed); 1414 1415 1416 1417 /** 1418 * @brief Get the body's gyroscopic state. 1419 * 1420 * @return nonzero if gyroscopic term computation is enabled (default), 1421 * zero otherwise. 1422 * @ingroup bodies 1423 */ 1424 int dBodyGetGyroscopicMode(dBodyID b); 1425 1426 1427 /** 1428 * @brief Enable/disable the body's gyroscopic term. 1429 * 1430 * Disabling the gyroscopic term of a body usually improves 1431 * stability. It also helps turning spining objects, like cars' 1432 * wheels. 1433 * 1434 * @param enabled nonzero (default) to enable gyroscopic term, 0 1435 * to disable. 1436 * @ingroup bodies 1437 */ 1438 void dBodySetGyroscopicMode(dBodyID b, int enabled); 1439 1440 1441 1442 1443 /** 1444 * @defgroup joints Joints 1445 * 1446 * In real life a joint is something like a hinge, that is used to connect two 1447 * objects. 1448 * In ODE a joint is very similar: It is a relationship that is enforced between 1449 * two bodies so that they can only have certain positions and orientations 1450 * relative to each other. 1451 * This relationship is called a constraint -- the words joint and 1452 * constraint are often used interchangeably. 1453 * 1454 * A joint has a set of parameters that can be set. These include: 1455 * 1456 * 1457 * \li dParamLoStop Low stop angle or position. Setting this to 1458 * -dInfinity (the default value) turns off the low stop. 1459 * For rotational joints, this stop must be greater than -pi to be 1460 * effective. 1461 * \li dParamHiStop High stop angle or position. Setting this to 1462 * dInfinity (the default value) turns off the high stop. 1463 * For rotational joints, this stop must be less than pi to be 1464 * effective. 1465 * If the high stop is less than the low stop then both stops will 1466 * be ineffective. 1467 * \li dParamVel Desired motor velocity (this will be an angular or 1468 * linear velocity). 1469 * \li dParamFMax The maximum force or torque that the motor will use to 1470 * achieve the desired velocity. 1471 * This must always be greater than or equal to zero. 1472 * Setting this to zero (the default value) turns off the motor. 1473 * \li dParamFudgeFactor The current joint stop/motor implementation has 1474 * a small problem: 1475 * when the joint is at one stop and the motor is set to move it away 1476 * from the stop, too much force may be applied for one time step, 1477 * causing a ``jumping'' motion. 1478 * This fudge factor is used to scale this excess force. 1479 * It should have a value between zero and one (the default value). 1480 * If the jumping motion is too visible in a joint, the value can be 1481 * reduced. 1482 * Making this value too small can prevent the motor from being able to 1483 * move the joint away from a stop. 1484 * \li dParamBounce The bouncyness of the stops. 1485 * This is a restitution parameter in the range 0..1. 1486 * 0 means the stops are not bouncy at all, 1 means maximum bouncyness. 1487 * \li dParamCFM The constraint force mixing (CFM) value used when not 1488 * at a stop. 1489 * \li dParamStopERP The error reduction parameter (ERP) used by the 1490 * stops. 1491 * \li dParamStopCFM The constraint force mixing (CFM) value used by the 1492 * stops. Together with the ERP value this can be used to get spongy or 1493 * soft stops. 1494 * Note that this is intended for unpowered joints, it does not really 1495 * work as expected when a powered joint reaches its limit. 1496 * \li dParamSuspensionERP Suspension error reduction parameter (ERP). 1497 * Currently this is only implemented on the hinge-2 joint. 1498 * \li dParamSuspensionCFM Suspension constraint force mixing (CFM) value. 1499 * Currently this is only implemented on the hinge-2 joint. 1500 * 1501 * If a particular parameter is not implemented by a given joint, setting it 1502 * will have no effect. 1503 * These parameter names can be optionally followed by a digit (2 or 3) 1504 * to indicate the second or third set of parameters, e.g. for the second axis 1505 * in a hinge-2 joint, or the third axis in an AMotor joint. 1506 */ 1507 1508 1509 /** 1510 * @brief Create a new joint of the ball type. 1511 * @ingroup joints 1512 * @remarks 1513 * The joint is initially in "limbo" (i.e. it has no effect on the simulation) 1514 * because it does not connect to any bodies. 1515 * @param dJointGroupID set to 0 to allocate the joint normally. 1516 * If it is nonzero the joint is allocated in the given joint group. 1517 */ 1518 dJointID dJointCreateBall(dWorldID, dJointGroupID); 1519 1520 /** 1521 * @brief Create a new joint of the hinge type. 1522 * @ingroup joints 1523 * @param dJointGroupID set to 0 to allocate the joint normally. 1524 * If it is nonzero the joint is allocated in the given joint group. 1525 */ 1526 dJointID dJointCreateHinge(dWorldID, dJointGroupID); 1527 1528 /** 1529 * @brief Create a new joint of the slider type. 1530 * @ingroup joints 1531 * @param dJointGroupID set to 0 to allocate the joint normally. 1532 * If it is nonzero the joint is allocated in the given joint group. 1533 */ 1534 dJointID dJointCreateSlider(dWorldID, dJointGroupID); 1535 1536 /** 1537 * @brief Create a new joint of the contact type. 1538 * @ingroup joints 1539 * @param dJointGroupID set to 0 to allocate the joint normally. 1540 * If it is nonzero the joint is allocated in the given joint group. 1541 */ 1542 dJointID dJointCreateContact(dWorldID, dJointGroupID, in dContact *); 1543 1544 /** 1545 * @brief Create a new joint of the hinge2 type. 1546 * @ingroup joints 1547 * @param dJointGroupID set to 0 to allocate the joint normally. 1548 * If it is nonzero the joint is allocated in the given joint group. 1549 */ 1550 dJointID dJointCreateHinge2(dWorldID, dJointGroupID); 1551 1552 /** 1553 * @brief Create a new joint of the universal type. 1554 * @ingroup joints 1555 * @param dJointGroupID set to 0 to allocate the joint normally. 1556 * If it is nonzero the joint is allocated in the given joint group. 1557 */ 1558 dJointID dJointCreateUniversal(dWorldID, dJointGroupID); 1559 1560 /** 1561 * @brief Create a new joint of the PR (Prismatic and Rotoide) type. 1562 * @ingroup joints 1563 * @param dJointGroupID set to 0 to allocate the joint normally. 1564 * If it is nonzero the joint is allocated in the given joint group. 1565 */ 1566 dJointID dJointCreatePR(dWorldID, dJointGroupID); 1567 1568 /** 1569 * @brief Create a new joint of the PU (Prismatic and Universal) type. 1570 * @ingroup joints 1571 * @param dJointGroupID set to 0 to allocate the joint normally. 1572 * If it is nonzero the joint is allocated in the given joint group. 1573 */ 1574 dJointID dJointCreatePU(dWorldID, dJointGroupID); 1575 1576 /** 1577 * @brief Create a new joint of the Piston type. 1578 * @ingroup joints 1579 * @param dJointGroupID set to 0 to allocate the joint normally. 1580 * If it is nonzero the joint is allocated in the given 1581 * joint group. 1582 */ 1583 dJointID dJointCreatePiston(dWorldID, dJointGroupID); 1584 1585 /** 1586 * @brief Create a new joint of the fixed type. 1587 * @ingroup joints 1588 * @param dJointGroupID set to 0 to allocate the joint normally. 1589 * If it is nonzero the joint is allocated in the given joint group. 1590 */ 1591 dJointID dJointCreateFixed(dWorldID, dJointGroupID); 1592 1593 dJointID dJointCreateNull(dWorldID, dJointGroupID); 1594 1595 /** 1596 * @brief Create a new joint of the A-motor type. 1597 * @ingroup joints 1598 * @param dJointGroupID set to 0 to allocate the joint normally. 1599 * If it is nonzero the joint is allocated in the given joint group. 1600 */ 1601 dJointID dJointCreateAMotor(dWorldID, dJointGroupID); 1602 1603 /** 1604 * @brief Create a new joint of the L-motor type. 1605 * @ingroup joints 1606 * @param dJointGroupID set to 0 to allocate the joint normally. 1607 * If it is nonzero the joint is allocated in the given joint group. 1608 */ 1609 dJointID dJointCreateLMotor(dWorldID, dJointGroupID); 1610 1611 /** 1612 * @brief Create a new joint of the plane-2d type. 1613 * @ingroup joints 1614 * @param dJointGroupID set to 0 to allocate the joint normally. 1615 * If it is nonzero the joint is allocated in the given joint group. 1616 */ 1617 dJointID dJointCreatePlane2D(dWorldID, dJointGroupID); 1618 1619 /** 1620 * @brief Destroy a joint. 1621 * @ingroup joints 1622 * 1623 * disconnects it from its attached bodies and removing it from the world. 1624 * However, if the joint is a member of a group then this function has no 1625 * effect - to destroy that joint the group must be emptied or destroyed. 1626 */ 1627 void dJointDestroy(dJointID); 1628 1629 1630 /** 1631 * @brief Create a joint group 1632 * @ingroup joints 1633 * @param max_size deprecated. Set to 0. 1634 */ 1635 dJointGroupID dJointGroupCreate(int max_size); 1636 1637 /** 1638 * @brief Destroy a joint group. 1639 * @ingroup joints 1640 * 1641 * All joints in the joint group will be destroyed. 1642 */ 1643 void dJointGroupDestroy(dJointGroupID); 1644 1645 /** 1646 * @brief Empty a joint group. 1647 * @ingroup joints 1648 * 1649 * All joints in the joint group will be destroyed, 1650 * but the joint group itself will not be destroyed. 1651 */ 1652 void dJointGroupEmpty(dJointGroupID); 1653 1654 /** 1655 * @brief Return the number of bodies attached to the joint 1656 * @ingroup joints 1657 */ 1658 int dJointGetNumBodies(dJointID); 1659 1660 /** 1661 * @brief Attach the joint to some new bodies. 1662 * @ingroup joints 1663 * 1664 * If the joint is already attached, it will be detached from the old bodies 1665 * first. 1666 * To attach this joint to only one body, set body1 or body2 to zero - a zero 1667 * body refers to the static environment. 1668 * Setting both bodies to zero puts the joint into "limbo", i.e. it will 1669 * have no effect on the simulation. 1670 * @remarks 1671 * Some joints, like hinge-2 need to be attached to two bodies to work. 1672 */ 1673 void dJointAttach(dJointID, dBodyID body1, dBodyID body2); 1674 1675 /** 1676 * @brief Manually enable a joint. 1677 * @param dJointID identification of joint. 1678 * @ingroup joints 1679 */ 1680 void dJointEnable(dJointID); 1681 1682 /** 1683 * @brief Manually disable a joint. 1684 * @ingroup joints 1685 * @remarks 1686 * A disabled joint will not affect the simulation, but will maintain the anchors and 1687 * axes so it can be enabled later. 1688 */ 1689 void dJointDisable(dJointID); 1690 1691 /** 1692 * @brief Check wether a joint is enabled. 1693 * @ingroup joints 1694 * @return 1 if a joint is currently enabled or 0 if it is disabled. 1695 */ 1696 int dJointIsEnabled(dJointID); 1697 1698 /** 1699 * @brief Set the user-data pointer 1700 * @ingroup joints 1701 */ 1702 void dJointSetData(dJointID, void* data); 1703 1704 /** 1705 * @brief Get the user-data pointer 1706 * @ingroup joints 1707 */ 1708 void* dJointGetData(dJointID); 1709 1710 /** 1711 * @brief Get the type of the joint 1712 * @ingroup joints 1713 * @return the type, being one of these: 1714 * \li dJointTypeBall 1715 * \li dJointTypeHinge 1716 * \li dJointTypeSlider 1717 * \li dJointTypeContact 1718 * \li dJointTypeUniversal 1719 * \li dJointTypeHinge2 1720 * \li dJointTypeFixed 1721 * \li dJointTypeNull 1722 * \li dJointTypeAMotor 1723 * \li dJointTypeLMotor 1724 * \li dJointTypePlane2D 1725 * \li dJointTypePR 1726 * \li dJointTypePU 1727 * \li dJointTypePiston 1728 */ 1729 dJointType dJointGetType(dJointID); 1730 1731 /** 1732 * @brief Return the bodies that this joint connects. 1733 * @ingroup joints 1734 * @param index return the first (0) or second (1) body. 1735 * @remarks 1736 * If one of these returned body IDs is zero, the joint connects the other body 1737 * to the static environment. 1738 * If both body IDs are zero, the joint is in ``limbo'' and has no effect on 1739 * the simulation. 1740 */ 1741 dBodyID dJointGetBody(dJointID, int index); 1742 1743 /** 1744 * @brief Sets the datastructure that is to receive the feedback. 1745 * 1746 * The feedback can be used by the user, so that it is known how 1747 * much force an individual joint exerts. 1748 * @ingroup joints 1749 */ 1750 void dJointSetFeedback(dJointID, dJointFeedback*); 1751 1752 /** 1753 * @brief Gets the datastructure that is to receive the feedback. 1754 * @ingroup joints 1755 */ 1756 dJointFeedback* dJointGetFeedback(dJointID); 1757 1758 /** 1759 * @brief Set the joint anchor point. 1760 * @ingroup joints 1761 * 1762 * The joint will try to keep this point on each body 1763 * together. The input is specified in world coordinates. 1764 */ 1765 void dJointSetBallAnchor(dJointID, dReal x, dReal y, dReal z); 1766 1767 /** 1768 * @brief Set the joint anchor point. 1769 * @ingroup joints 1770 */ 1771 void dJointSetBallAnchor2(dJointID, dReal x, dReal y, dReal z); 1772 1773 /** 1774 * @brief Param setting for Ball joints 1775 * @ingroup joints 1776 */ 1777 void dJointSetBallParam(dJointID, int parameter, dReal value); 1778 1779 /** 1780 * @brief Set hinge anchor parameter. 1781 * @ingroup joints 1782 */ 1783 void dJointSetHingeAnchor(dJointID, dReal x, dReal y, dReal z); 1784 1785 void dJointSetHingeAnchorDelta( 1786 dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az 1787 ); 1788 1789 /** 1790 * @brief Set hinge axis. 1791 * @ingroup joints 1792 */ 1793 void dJointSetHingeAxis(dJointID, dReal x, dReal y, dReal z); 1794 1795 /** 1796 * @brief Set the Hinge axis as if the 2 bodies were already at angle appart. 1797 * @ingroup joints 1798 * 1799 * This function initialize the Axis and the relative orientation of each body 1800 * as if body1 was rotated around the axis by the angle value. \br 1801 * Ex: 1802 * <PRE> 1803 * dJointSetHingeAxis(jId, 1, 0, 0); 1804 * // If you request the position you will have: dJointGetHingeAngle(jId) == 0 1805 * dJointSetHingeAxisDelta(jId, 1, 0, 0, 0.23); 1806 * // If you request the position you will have: dJointGetHingeAngle(jId) == 0.23 1807 * </PRE> 1808 1809 * @param j The Hinge joint ID for which the axis will be set 1810 * @param x The X component of the axis in world frame 1811 * @param y The Y component of the axis in world frame 1812 * @param z The Z component of the axis in world frame 1813 * @param angle The angle for the offset of the relative orientation. 1814 * As if body1 was rotated by angle when the Axis was set (see below). 1815 * The rotation is around the new Hinge axis. 1816 * 1817 * @note Usually the function dJointSetHingeAxis set the current position of body1 1818 * and body2 as the zero angle position. This function set the current position 1819 * as the if the 2 bodies where \b angle appart. 1820 * @warning Calling dJointSetHingeAnchor or dJointSetHingeAxis will reset the "zero" 1821 * angle position. 1822 */ 1823 void dJointSetHingeAxisOffset(dJointID j, dReal x, dReal y, dReal z, dReal angle); 1824 1825 /** 1826 * @brief set joint parameter 1827 * @ingroup joints 1828 */ 1829 void dJointSetHingeParam(dJointID, int parameter, dReal value); 1830 1831 /** 1832 * @brief Applies the torque about the hinge axis. 1833 * 1834 * That is, it applies a torque with specified magnitude in the direction 1835 * of the hinge axis, to body 1, and with the same magnitude but in opposite 1836 * direction to body 2. This function is just a wrapper for dBodyAddTorque()} 1837 * @ingroup joints 1838 */ 1839 void dJointAddHingeTorque(dJointID joint, dReal torque); 1840 1841 /** 1842 * @brief set the joint axis 1843 * @ingroup joints 1844 */ 1845 void dJointSetSliderAxis(dJointID, dReal x, dReal y, dReal z); 1846 1847 /** 1848 * @ingroup joints 1849 */ 1850 void dJointSetSliderAxisDelta(dJointID, dReal x, dReal y, dReal z, dReal ax, dReal ay, dReal az); 1851 1852 /** 1853 * @brief set joint parameter 1854 * @ingroup joints 1855 */ 1856 void dJointSetSliderParam(dJointID, int parameter, dReal value); 1857 1858 /** 1859 * @brief Applies the given force in the slider's direction. 1860 * 1861 * That is, it applies a force with specified magnitude, in the direction of 1862 * slider's axis, to body1, and with the same magnitude but opposite 1863 * direction to body2. This function is just a wrapper for dBodyAddForce(). 1864 * @ingroup joints 1865 */ 1866 void dJointAddSliderForce(dJointID joint, dReal force); 1867 1868 /** 1869 * @brief set anchor 1870 * @ingroup joints 1871 */ 1872 void dJointSetHinge2Anchor(dJointID, dReal x, dReal y, dReal z); 1873 1874 /** 1875 * @brief set axis 1876 * @ingroup joints 1877 */ 1878 void dJointSetHinge2Axis1(dJointID, dReal x, dReal y, dReal z); 1879 1880 /** 1881 * @brief set axis 1882 * @ingroup joints 1883 */ 1884 void dJointSetHinge2Axis2(dJointID, dReal x, dReal y, dReal z); 1885 1886 /** 1887 * @brief set joint parameter 1888 * @ingroup joints 1889 */ 1890 void dJointSetHinge2Param(dJointID, int parameter, dReal value); 1891 1892 /** 1893 * @brief Applies torque1 about the hinge2's axis 1, torque2 about the 1894 * hinge2's axis 2. 1895 * @remarks This function is just a wrapper for dBodyAddTorque(). 1896 * @ingroup joints 1897 */ 1898 void dJointAddHinge2Torques(dJointID joint, dReal torque1, dReal torque2); 1899 1900 /** 1901 * @brief set anchor 1902 * @ingroup joints 1903 */ 1904 void dJointSetUniversalAnchor(dJointID, dReal x, dReal y, dReal z); 1905 1906 /** 1907 * @brief set axis 1908 * @ingroup joints 1909 */ 1910 void dJointSetUniversalAxis1(dJointID, dReal x, dReal y, dReal z); 1911 1912 /** 1913 * @brief Set the Universal axis1 as if the 2 bodies were already at 1914 * offset1 and offset2 appart with respect to axis1 and axis2. 1915 * @ingroup joints 1916 * 1917 * This function initialize the axis1 and the relative orientation of 1918 * each body as if body1 was rotated around the new axis1 by the offset1 1919 * value and as if body2 was rotated around the axis2 by offset2. \br 1920 * Ex: 1921 * <PRE> 1922 * dJointSetHuniversalAxis1(jId, 1, 0, 0); 1923 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0 1924 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0 1925 * dJointSetHuniversalAxis1Offset(jId, 1, 0, 0, 0.2, 0.17); 1926 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0.2 1927 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0.17 1928 * </PRE> 1929 * 1930 * @param j The Hinge joint ID for which the axis will be set 1931 * @param x The X component of the axis in world frame 1932 * @param y The Y component of the axis in world frame 1933 * @param z The Z component of the axis in world frame 1934 * @param angle The angle for the offset of the relative orientation. 1935 * As if body1 was rotated by angle when the Axis was set (see below). 1936 * The rotation is around the new Hinge axis. 1937 * 1938 * @note Usually the function dJointSetHingeAxis set the current position of body1 1939 * and body2 as the zero angle position. This function set the current position 1940 * as the if the 2 bodies where \b offsets appart. 1941 * 1942 * @note Any previous offsets are erased. 1943 * 1944 * @warning Calling dJointSetUniversalAnchor, dJointSetUnivesalAxis1, 1945 * dJointSetUniversalAxis2, dJointSetUniversalAxis2Offset 1946 * will reset the "zero" angle position. 1947 */ 1948 void dJointSetUniversalAxis1Offset( 1949 dJointID, dReal x, dReal y, dReal z, dReal offset1, dReal offset2 1950 ); 1951 1952 /** 1953 * @brief set axis 1954 * @ingroup joints 1955 */ 1956 void dJointSetUniversalAxis2(dJointID, dReal x, dReal y, dReal z); 1957 1958 /** 1959 * @brief Set the Universal axis2 as if the 2 bodies were already at 1960 * offset1 and offset2 appart with respect to axis1 and axis2. 1961 * @ingroup joints 1962 * 1963 * This function initialize the axis2 and the relative orientation of 1964 * each body as if body1 was rotated around the axis1 by the offset1 1965 * value and as if body2 was rotated around the new axis2 by offset2. \br 1966 * Ex: 1967 * <PRE> 1968 * dJointSetHuniversalAxis2(jId, 0, 1, 0); 1969 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0 1970 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0 1971 * dJointSetHuniversalAxis2Offset(jId, 0, 1, 0, 0.2, 0.17); 1972 * // If you request the position you will have: dJointGetUniversalAngle1(jId) == 0.2 1973 * // If you request the position you will have: dJointGetUniversalAngle2(jId) == 0.17 1974 * </PRE> 1975 1976 * @param j The Hinge joint ID for which the axis will be set 1977 * @param x The X component of the axis in world frame 1978 * @param y The Y component of the axis in world frame 1979 * @param z The Z component of the axis in world frame 1980 * @param angle The angle for the offset of the relative orientation. 1981 * As if body1 was rotated by angle when the Axis was set (see below). 1982 * The rotation is around the new Hinge axis. 1983 * 1984 * @note Usually the function dJointSetHingeAxis set the current position of body1 1985 * and body2 as the zero angle position. This function set the current position 1986 * as the if the 2 bodies where \b offsets appart. 1987 * 1988 * @note Any previous offsets are erased. 1989 * 1990 * @warning Calling dJointSetUniversalAnchor, dJointSetUnivesalAxis1, 1991 * dJointSetUniversalAxis2, dJointSetUniversalAxis2Offset 1992 * will reset the "zero" angle position. 1993 */ 1994 1995 1996 void dJointSetUniversalAxis2Offset( 1997 dJointID, dReal x, dReal y, dReal z, dReal offset1, dReal offset2 1998 ); 1999 2000 /** 2001 * @brief set joint parameter 2002 * @ingroup joints 2003 */ 2004 void dJointSetUniversalParam(dJointID, int parameter, dReal value); 2005 2006 /** 2007 * @brief Applies torque1 about the universal's axis 1, torque2 about the 2008 * universal's axis 2. 2009 * @remarks This function is just a wrapper for dBodyAddTorque(). 2010 * @ingroup joints 2011 */ 2012 void dJointAddUniversalTorques(dJointID joint, dReal torque1, dReal torque2); 2013 2014 2015 /** 2016 * @brief set anchor 2017 * @ingroup joints 2018 */ 2019 void dJointSetPRAnchor(dJointID, dReal x, dReal y, dReal z); 2020 2021 /** 2022 * @brief set the axis for the prismatic articulation 2023 * @ingroup joints 2024 */ 2025 void dJointSetPRAxis1(dJointID, dReal x, dReal y, dReal z); 2026 2027 /** 2028 * @brief set the axis for the rotoide articulation 2029 * @ingroup joints 2030 */ 2031 void dJointSetPRAxis2(dJointID, dReal x, dReal y, dReal z); 2032 2033 /** 2034 * @brief set joint parameter 2035 * @ingroup joints 2036 * 2037 * @note parameterX where X equal 2 refer to parameter for the rotoide articulation 2038 */ 2039 void dJointSetPRParam(dJointID, int parameter, dReal value); 2040 2041 /** 2042 * @brief Applies the torque about the rotoide axis of the PR joint 2043 * 2044 * That is, it applies a torque with specified magnitude in the direction 2045 * of the rotoide axis, to body 1, and with the same magnitude but in opposite 2046 * direction to body 2. This function is just a wrapper for dBodyAddTorque()} 2047 * @ingroup joints 2048 */ 2049 void dJointAddPRTorque(dJointID j, dReal torque); 2050 2051 2052 /** 2053 * @brief set anchor 2054 * @ingroup joints 2055 */ 2056 void dJointSetPUAnchor(dJointID, dReal x, dReal y, dReal z); 2057 2058 /** 2059 * @brief Set the PU anchor as if the 2 bodies were already at [dx, dy, dz] appart. 2060 * @ingroup joints 2061 * 2062 * This function initialize the anchor and the relative position of each body 2063 * as if the position between body1 and body2 was already the projection of [dx, dy, dz] 2064 * along the Piston axis. (i.e as if the body1 was at its current position - [dx,dy,dy] when the 2065 * axis is set). 2066 * Ex: 2067 * <PRE> 2068 * dReal offset = 3; 2069 * dVector3 axis; 2070 * dJointGetPUAxis(jId, axis); 2071 * dJointSetPUAnchor(jId, 0, 0, 0); 2072 * // If you request the position you will have: dJointGetPUPosition(jId) == 0 2073 * dJointSetPUAnchorOffset(jId, 0, 0, 0, axis[X]*offset, axis[Y]*offset, axis[Z]*offset); 2074 * // If you request the position you will have: dJointGetPUPosition(jId) == offset 2075 * </PRE> 2076 * @param j The PU joint for which the anchor point will be set 2077 * @param x The X position of the anchor point in world frame 2078 * @param y The Y position of the anchor point in world frame 2079 * @param z The Z position of the anchor point in world frame 2080 * @param dx A delta to be substracted to the X position as if the anchor was set 2081 * when body1 was at current_position[X] - dx 2082 * @param dx A delta to be substracted to the Y position as if the anchor was set 2083 * when body1 was at current_position[Y] - dy 2084 * @param dx A delta to be substracted to the Z position as if the anchor was set 2085 * when body1 was at current_position[Z] - dz 2086 */ 2087 void dJointSetPUAnchorOffset( 2088 dJointID, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz 2089 ); 2090 2091 /** 2092 * @brief set the axis for the first axis or the universal articulation 2093 * @ingroup joints 2094 */ 2095 void dJointSetPUAxis1(dJointID, dReal x, dReal y, dReal z); 2096 2097 /** 2098 * @brief set the axis for the second axis or the universal articulation 2099 * @ingroup joints 2100 */ 2101 void dJointSetPUAxis2(dJointID, dReal x, dReal y, dReal z); 2102 2103 /** 2104 * @brief set the axis for the prismatic articulation 2105 * @ingroup joints 2106 */ 2107 void dJointSetPUAxis3(dJointID, dReal x, dReal y, dReal z); 2108 2109 /** 2110 * @brief set the axis for the prismatic articulation 2111 * @ingroup joints 2112 * @note This function was added for convenience it is the same as 2113 * dJointSetPUAxis3 2114 */ 2115 void dJointSetPUAxisP(dJointID id, dReal x, dReal y, dReal z); 2116 2117 2118 2119 /** 2120 * @brief set joint parameter 2121 * @ingroup joints 2122 * 2123 * @note parameterX where X equal 2 refer to parameter for second axis of the 2124 * universal articulation 2125 * @note parameterX where X equal 3 refer to parameter for prismatic 2126 * articulation 2127 */ 2128 void dJointSetPUParam(dJointID, int parameter, dReal value); 2129 2130 /** 2131 * @brief Applies the torque about the rotoide axis of the PU joint 2132 * 2133 * That is, it applies a torque with specified magnitude in the direction 2134 * of the rotoide axis, to body 1, and with the same magnitude but in opposite 2135 * direction to body 2. This function is just a wrapper for dBodyAddTorque()} 2136 * @ingroup joints 2137 */ 2138 void dJointAddPUTorque(dJointID j, dReal torque); 2139 2140 2141 2142 2143 /** 2144 * @brief set the joint anchor 2145 * @ingroup joints 2146 */ 2147 void dJointSetPistonAnchor(dJointID, dReal x, dReal y, dReal z); 2148 2149 /** 2150 * @brief Set the Piston anchor as if the 2 bodies were already at [dx,dy, dz] appart. 2151 * @ingroup joints 2152 * 2153 * This function initialize the anchor and the relative position of each body 2154 * as if the position between body1 and body2 was already the projection of [dx, dy, dz] 2155 * along the Piston axis. (i.e as if the body1 was at its current position - [dx,dy,dy] when the 2156 * axis is set). 2157 * Ex: 2158 * <PRE> 2159 * dReal offset = 3; 2160 * dVector3 axis; 2161 * dJointGetPistonAxis(jId, axis); 2162 * dJointSetPistonAnchor(jId, 0, 0, 0); 2163 * // If you request the position you will have: dJointGetPistonPosition(jId) == 0 2164 * dJointSetPistonAnchorOffset(jId, 0, 0, 0, axis[X]*offset, axis[Y]*offset, axis[Z]*offset); 2165 * // If you request the position you will have: dJointGetPistonPosition(jId) == offset 2166 * </PRE> 2167 * @param j The Piston joint for which the anchor point will be set 2168 * @param x The X position of the anchor point in world frame 2169 * @param y The Y position of the anchor point in world frame 2170 * @param z The Z position of the anchor point in world frame 2171 * @param dx A delta to be substracted to the X position as if the anchor was set 2172 * when body1 was at current_position[X] - dx 2173 * @param dx A delta to be substracted to the Y position as if the anchor was set 2174 * when body1 was at current_position[Y] - dy 2175 * @param dx A delta to be substracted to the Z position as if the anchor was set 2176 * when body1 was at current_position[Z] - dz 2177 */ 2178 void dJointSetPistonAnchorOffset( 2179 dJointID j, dReal x, dReal y, dReal z, dReal dx, dReal dy, dReal dz 2180 ); 2181 2182 /** 2183 * @brief set the joint axis 2184 * @ingroup joints 2185 */ 2186 void dJointSetPistonAxis(dJointID, dReal x, dReal y, dReal z); 2187 2188 /** 2189 * @brief set joint parameter 2190 * @ingroup joints 2191 */ 2192 void dJointSetPistonParam(dJointID, int parameter, dReal value); 2193 2194 /** 2195 * @brief Applies the given force in the slider's direction. 2196 * 2197 * That is, it applies a force with specified magnitude, in the direction of 2198 * prismatic's axis, to body1, and with the same magnitude but opposite 2199 * direction to body2. This function is just a wrapper for dBodyAddForce(). 2200 * @ingroup joints 2201 */ 2202 void dJointAddPistonForce(dJointID joint, dReal force); 2203 2204 2205 /** 2206 * @brief Call this on the fixed joint after it has been attached to 2207 * remember the current desired relative offset and desired relative 2208 * rotation between the bodies. 2209 * @ingroup joints 2210 */ 2211 void dJointSetFixed(dJointID); 2212 2213 /* 2214 * @brief Sets joint parameter 2215 * 2216 * @ingroup joints 2217 */ 2218 void dJointSetFixedParam(dJointID, int parameter, dReal value); 2219 2220 /** 2221 * @brief set the nr of axes 2222 * @param num 0..3 2223 * @ingroup joints 2224 */ 2225 void dJointSetAMotorNumAxes(dJointID, int num); 2226 2227 /** 2228 * @brief set axis 2229 * @ingroup joints 2230 */ 2231 void dJointSetAMotorAxis(dJointID, int anum, int rel, 2232 dReal x, dReal y, dReal z); 2233 2234 /** 2235 * @brief Tell the AMotor what the current angle is along axis anum. 2236 * 2237 * This function should only be called in dAMotorUser mode, because in this 2238 * mode the AMotor has no other way of knowing the joint angles. 2239 * The angle information is needed if stops have been set along the axis, 2240 * but it is not needed for axis motors. 2241 * @ingroup joints 2242 */ 2243 void dJointSetAMotorAngle(dJointID, int anum, dReal angle); 2244 2245 /** 2246 * @brief set joint parameter 2247 * @ingroup joints 2248 */ 2249 void dJointSetAMotorParam(dJointID, int parameter, dReal value); 2250 2251 /** 2252 * @brief set mode 2253 * @ingroup joints 2254 */ 2255 void dJointSetAMotorMode(dJointID, int mode); 2256 2257 /** 2258 * @brief Applies torque0 about the AMotor's axis 0, torque1 about the 2259 * AMotor's axis 1, and torque2 about the AMotor's axis 2. 2260 * @remarks 2261 * If the motor has fewer than three axes, the higher torques are ignored. 2262 * This function is just a wrapper for dBodyAddTorque(). 2263 * @ingroup joints 2264 */ 2265 void dJointAddAMotorTorques(dJointID, dReal torque1, dReal torque2, dReal torque3); 2266 2267 /** 2268 * @brief Set the number of axes that will be controlled by the LMotor. 2269 * @param num can range from 0 (which effectively deactivates the joint) to 3. 2270 * @ingroup joints 2271 */ 2272 void dJointSetLMotorNumAxes(dJointID, int num); 2273 2274 /** 2275 * @brief Set the AMotor axes. 2276 * @param anum selects the axis to change (0,1 or 2). 2277 * @param rel Each axis can have one of three ``relative orientation'' modes 2278 * \li 0: The axis is anchored to the global frame. 2279 * \li 1: The axis is anchored to the first body. 2280 * \li 2: The axis is anchored to the second body. 2281 * @remarks The axis vector is always specified in global coordinates 2282 * regardless of the setting of rel. 2283 * @ingroup joints 2284 */ 2285 void dJointSetLMotorAxis(dJointID, int anum, int rel, dReal x, dReal y, dReal z); 2286 2287 /** 2288 * @brief set joint parameter 2289 * @ingroup joints 2290 */ 2291 void dJointSetLMotorParam(dJointID, int parameter, dReal value); 2292 2293 /** 2294 * @ingroup joints 2295 */ 2296 void dJointSetPlane2DXParam(dJointID, int parameter, dReal value); 2297 2298 /** 2299 * @ingroup joints 2300 */ 2301 2302 void dJointSetPlane2DYParam(dJointID, int parameter, dReal value); 2303 2304 /** 2305 * @ingroup joints 2306 */ 2307 void dJointSetPlane2DAngleParam(dJointID, int parameter, dReal value); 2308 2309 /** 2310 * @brief Get the joint anchor point, in world coordinates. 2311 * 2312 * This returns the point on body 1. If the joint is perfectly satisfied, 2313 * this will be the same as the point on body 2. 2314 */ 2315 void dJointGetBallAnchor(dJointID, dVector3 result); 2316 2317 /** 2318 * @brief Get the joint anchor point, in world coordinates. 2319 * 2320 * This returns the point on body 2. You can think of a ball and socket 2321 * joint as trying to keep the result of dJointGetBallAnchor() and 2322 * dJointGetBallAnchor2() the same. If the joint is perfectly satisfied, 2323 * this function will return the same value as dJointGetBallAnchor() to 2324 * within roundoff errors. dJointGetBallAnchor2() can be used, along with 2325 * dJointGetBallAnchor(), to see how far the joint has come apart. 2326 */ 2327 void dJointGetBallAnchor2(dJointID, dVector3 result); 2328 2329 /** 2330 * @brief get joint parameter 2331 * @ingroup joints 2332 */ 2333 dReal dJointGetBallParam(dJointID, int parameter); 2334 2335 /** 2336 * @brief Get the hinge anchor point, in world coordinates. 2337 * 2338 * This returns the point on body 1. If the joint is perfectly satisfied, 2339 * this will be the same as the point on body 2. 2340 * @ingroup joints 2341 */ 2342 void dJointGetHingeAnchor(dJointID, dVector3 result); 2343 2344 /** 2345 * @brief Get the joint anchor point, in world coordinates. 2346 * @return The point on body 2. If the joint is perfectly satisfied, 2347 * this will return the same value as dJointGetHingeAnchor(). 2348 * If not, this value will be slightly different. 2349 * This can be used, for example, to see how far the joint has come apart. 2350 * @ingroup joints 2351 */ 2352 void dJointGetHingeAnchor2(dJointID, dVector3 result); 2353 2354 /** 2355 * @brief get axis 2356 * @ingroup joints 2357 */ 2358 void dJointGetHingeAxis(dJointID, dVector3 result); 2359 2360 /** 2361 * @brief get joint parameter 2362 * @ingroup joints 2363 */ 2364 dReal dJointGetHingeParam(dJointID, int parameter); 2365 2366 /** 2367 * @brief Get the hinge angle. 2368 * 2369 * The angle is measured between the two bodies, or between the body and 2370 * the static environment. 2371 * The angle will be between -pi..pi. 2372 * Give the relative rotation with respect to the Hinge axis of Body 1 with 2373 * respect to Body 2. 2374 * When the hinge anchor or axis is set, the current position of the attached 2375 * bodies is examined and that position will be the zero angle. 2376 * @ingroup joints 2377 */ 2378 dReal dJointGetHingeAngle(dJointID); 2379 2380 /** 2381 * @brief Get the hinge angle time derivative. 2382 * @ingroup joints 2383 */ 2384 dReal dJointGetHingeAngleRate(dJointID); 2385 2386 /** 2387 * @brief Get the slider linear position (i.e. the slider's extension) 2388 * 2389 * When the axis is set, the current position of the attached bodies is 2390 * examined and that position will be the zero position. 2391 2392 * The position is the distance, with respect to the zero position, 2393 * along the slider axis of body 1 with respect to 2394 * body 2. (A NULL body is replaced by the world). 2395 * @ingroup joints 2396 */ 2397 dReal dJointGetSliderPosition(dJointID); 2398 2399 /** 2400 * @brief Get the slider linear position's time derivative. 2401 * @ingroup joints 2402 */ 2403 dReal dJointGetSliderPositionRate(dJointID); 2404 2405 /** 2406 * @brief Get the slider axis 2407 * @ingroup joints 2408 */ 2409 void dJointGetSliderAxis(dJointID, dVector3 result); 2410 2411 /** 2412 * @brief get joint parameter 2413 * @ingroup joints 2414 */ 2415 dReal dJointGetSliderParam(dJointID, int parameter); 2416 2417 /** 2418 * @brief Get the joint anchor point, in world coordinates. 2419 * @return the point on body 1. If the joint is perfectly satisfied, 2420 * this will be the same as the point on body 2. 2421 * @ingroup joints 2422 */ 2423 void dJointGetHinge2Anchor(dJointID, dVector3 result); 2424 2425 /** 2426 * @brief Get the joint anchor point, in world coordinates. 2427 * This returns the point on body 2. If the joint is perfectly satisfied, 2428 * this will return the same value as dJointGetHinge2Anchor. 2429 * If not, this value will be slightly different. 2430 * This can be used, for example, to see how far the joint has come apart. 2431 * @ingroup joints 2432 */ 2433 void dJointGetHinge2Anchor2(dJointID, dVector3 result); 2434 2435 /** 2436 * @brief Get joint axis 2437 * @ingroup joints 2438 */ 2439 void dJointGetHinge2Axis1(dJointID, dVector3 result); 2440 2441 /** 2442 * @brief Get joint axis 2443 * @ingroup joints 2444 */ 2445 void dJointGetHinge2Axis2(dJointID, dVector3 result); 2446 2447 /** 2448 * @brief get joint parameter 2449 * @ingroup joints 2450 */ 2451 dReal dJointGetHinge2Param(dJointID, int parameter); 2452 2453 /** 2454 * @brief Get angle 2455 * @ingroup joints 2456 */ 2457 dReal dJointGetHinge2Angle1(dJointID); 2458 2459 /** 2460 * @brief Get time derivative of angle 2461 * @ingroup joints 2462 */ 2463 dReal dJointGetHinge2Angle1Rate(dJointID); 2464 2465 /** 2466 * @brief Get time derivative of angle 2467 * @ingroup joints 2468 */ 2469 dReal dJointGetHinge2Angle2Rate(dJointID); 2470 2471 /** 2472 * @brief Get the joint anchor point, in world coordinates. 2473 * @return the point on body 1. If the joint is perfectly satisfied, 2474 * this will be the same as the point on body 2. 2475 * @ingroup joints 2476 */ 2477 void dJointGetUniversalAnchor(dJointID, dVector3 result); 2478 2479 /** 2480 * @brief Get the joint anchor point, in world coordinates. 2481 * @return This returns the point on body 2. 2482 * @remarks 2483 * You can think of the ball and socket part of a universal joint as 2484 * trying to keep the result of dJointGetBallAnchor() and 2485 * dJointGetBallAnchor2() the same. If the joint is 2486 * perfectly satisfied, this function will return the same value 2487 * as dJointGetUniversalAnchor() to within roundoff errors. 2488 * dJointGetUniversalAnchor2() can be used, along with 2489 * dJointGetUniversalAnchor(), to see how far the joint has come apart. 2490 * @ingroup joints 2491 */ 2492 void dJointGetUniversalAnchor2(dJointID, dVector3 result); 2493 2494 /** 2495 * @brief Get axis 2496 * @ingroup joints 2497 */ 2498 void dJointGetUniversalAxis1(dJointID, dVector3 result); 2499 2500 /** 2501 * @brief Get axis 2502 * @ingroup joints 2503 */ 2504 void dJointGetUniversalAxis2(dJointID, dVector3 result); 2505 2506 2507 /** 2508 * @brief get joint parameter 2509 * @ingroup joints 2510 */ 2511 dReal dJointGetUniversalParam(dJointID, int parameter); 2512 2513 /** 2514 * @brief Get both angles at the same time. 2515 * @ingroup joints 2516 * 2517 * @param joint The universal joint for which we want to calculate the angles 2518 * @param angle1 The angle between the body1 and the axis 1 2519 * @param angle2 The angle between the body2 and the axis 2 2520 * 2521 * @note This function combine getUniversalAngle1 and getUniversalAngle2 together 2522 * and try to avoid redundant calculation 2523 */ 2524 void dJointGetUniversalAngles(dJointID, dReal* angle1, dReal* angle2); 2525 2526 /** 2527 * @brief Get angle 2528 * @ingroup joints 2529 */ 2530 dReal dJointGetUniversalAngle1(dJointID); 2531 2532 /** 2533 * @brief Get angle 2534 * @ingroup joints 2535 */ 2536 dReal dJointGetUniversalAngle2(dJointID); 2537 2538 /** 2539 * @brief Get time derivative of angle 2540 * @ingroup joints 2541 */ 2542 dReal dJointGetUniversalAngle1Rate(dJointID); 2543 2544 /** 2545 * @brief Get time derivative of angle 2546 * @ingroup joints 2547 */ 2548 dReal dJointGetUniversalAngle2Rate(dJointID); 2549 2550 2551 2552 /** 2553 * @brief Get the joint anchor point, in world coordinates. 2554 * @return the point on body 1. If the joint is perfectly satisfied, 2555 * this will be the same as the point on body 2. 2556 * @ingroup joints 2557 */ 2558 void dJointGetPRAnchor(dJointID, dVector3 result); 2559 2560 /** 2561 * @brief Get the PR linear position (i.e. the prismatic's extension) 2562 * 2563 * When the axis is set, the current position of the attached bodies is 2564 * examined and that position will be the zero position. 2565 * 2566 * The position is the "oriented" length between the 2567 * position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)] 2568 * 2569 * @ingroup joints 2570 */ 2571 dReal dJointGetPRPosition(dJointID); 2572 2573 /** 2574 * @brief Get the PR linear position's time derivative 2575 * 2576 * @ingroup joints 2577 */ 2578 dReal dJointGetPRPositionRate(dJointID); 2579 2580 2581 /** 2582 * @brief Get the PR angular position (i.e. the twist between the 2 bodies) 2583 * 2584 * When the axis is set, the current position of the attached bodies is 2585 * examined and that position will be the zero position. 2586 * @ingroup joints 2587 */ 2588 dReal dJointGetPRAngle(dJointID); 2589 2590 /** 2591 * @brief Get the PR angular position's time derivative 2592 * 2593 * @ingroup joints 2594 */ 2595 dReal dJointGetPRAngleRate(dJointID); 2596 2597 2598 /** 2599 * @brief Get the prismatic axis 2600 * @ingroup joints 2601 */ 2602 void dJointGetPRAxis1(dJointID, dVector3 result); 2603 2604 /** 2605 * @brief Get the Rotoide axis 2606 * @ingroup joints 2607 */ 2608 void dJointGetPRAxis2(dJointID, dVector3 result); 2609 2610 /** 2611 * @brief get joint parameter 2612 * @ingroup joints 2613 */ 2614 dReal dJointGetPRParam(dJointID, int parameter); 2615 2616 2617 2618 /** 2619 * @brief Get the joint anchor point, in world coordinates. 2620 * @return the point on body 1. If the joint is perfectly satisfied, 2621 * this will be the same as the point on body 2. 2622 * @ingroup joints 2623 */ 2624 void dJointGetPUAnchor(dJointID, dVector3 result); 2625 2626 /** 2627 * @brief Get the PU linear position (i.e. the prismatic's extension) 2628 * 2629 * When the axis is set, the current position of the attached bodies is 2630 * examined and that position will be the zero position. 2631 * 2632 * The position is the "oriented" length between the 2633 * position = (Prismatic axis) dot_product [(body1 + offset) - (body2 + anchor2)] 2634 * 2635 * @ingroup joints 2636 */ 2637 dReal dJointGetPUPosition(dJointID); 2638 2639 /** 2640 * @brief Get the PR linear position's time derivative 2641 * 2642 * @ingroup joints 2643 */ 2644 dReal dJointGetPUPositionRate(dJointID); 2645 2646 /** 2647 * @brief Get the first axis of the universal component of the joint 2648 * @ingroup joints 2649 */ 2650 void dJointGetPUAxis1(dJointID, dVector3 result); 2651 2652 /** 2653 * @brief Get the second axis of the Universal component of the joint 2654 * @ingroup joints 2655 */ 2656 void dJointGetPUAxis2(dJointID, dVector3 result); 2657 2658 /** 2659 * @brief Get the prismatic axis 2660 * @ingroup joints 2661 */ 2662 void dJointGetPUAxis3(dJointID, dVector3 result); 2663 2664 /** 2665 * @brief Get the prismatic axis 2666 * @ingroup joints 2667 * 2668 * @note This function was added for convenience it is the same as 2669 * dJointGetPUAxis3 2670 */ 2671 void dJointGetPUAxisP(dJointID id, dVector3 result); 2672 2673 2674 2675 2676 /** 2677 * @brief Get both angles at the same time. 2678 * @ingroup joints 2679 * 2680 * @param joint The Prismatic universal joint for which we want to calculate the angles 2681 * @param angle1 The angle between the body1 and the axis 1 2682 * @param angle2 The angle between the body2 and the axis 2 2683 * 2684 * @note This function combine dJointGetPUAngle1 and dJointGetPUAngle2 together 2685 * and try to avoid redundant calculation 2686 */ 2687 void dJointGetPUAngles(dJointID, dReal* angle1, dReal* angle2); 2688 2689 /** 2690 * @brief Get angle 2691 * @ingroup joints 2692 */ 2693 dReal dJointGetPUAngle1(dJointID); 2694 2695 /** 2696 * @brief * @brief Get time derivative of angle1 2697 * 2698 * @ingroup joints 2699 */ 2700 dReal dJointGetPUAngle1Rate(dJointID); 2701 2702 2703 /** 2704 * @brief Get angle 2705 * @ingroup joints 2706 */ 2707 dReal dJointGetPUAngle2(dJointID); 2708 2709 /** 2710 * @brief * @brief Get time derivative of angle2 2711 * 2712 * @ingroup joints 2713 */ 2714 dReal dJointGetPUAngle2Rate(dJointID); 2715 2716 /** 2717 * @brief get joint parameter 2718 * @ingroup joints 2719 */ 2720 dReal dJointGetPUParam(dJointID, int parameter); 2721 2722 2723 2724 2725 2726 /** 2727 * @brief Get the Piston linear position (i.e. the piston's extension) 2728 * 2729 * When the axis is set, the current position of the attached bodies is 2730 * examined and that position will be the zero position. 2731 * @ingroup joints 2732 */ 2733 dReal dJointGetPistonPosition(dJointID); 2734 2735 /** 2736 * @brief Get the piston linear position's time derivative. 2737 * @ingroup joints 2738 */ 2739 dReal dJointGetPistonPositionRate(dJointID); 2740 2741 /** 2742 * @brief Get the Piston angular position (i.e. the twist between the 2 bodies) 2743 * 2744 * When the axis is set, the current position of the attached bodies is 2745 * examined and that position will be the zero position. 2746 * @ingroup joints 2747 */ 2748 dReal dJointGetPistonAngle(dJointID); 2749 2750 /** 2751 * @brief Get the piston angular position's time derivative. 2752 * @ingroup joints 2753 */ 2754 dReal dJointGetPistonAngleRate(dJointID); 2755 2756 2757 /** 2758 * @brief Get the joint anchor 2759 * 2760 * This returns the point on body 1. If the joint is perfectly satisfied, 2761 * this will be the same as the point on body 2 in direction perpendicular 2762 * to the prismatic axis. 2763 * 2764 * @ingroup joints 2765 */ 2766 void dJointGetPistonAnchor(dJointID, dVector3 result); 2767 2768 /** 2769 * @brief Get the joint anchor w.r.t. body 2 2770 * 2771 * This returns the point on body 2. You can think of a Piston 2772 * joint as trying to keep the result of dJointGetPistonAnchor() and 2773 * dJointGetPistonAnchor2() the same in the direction perpendicular to the 2774 * pirsmatic axis. If the joint is perfectly satisfied, 2775 * this function will return the same value as dJointGetPistonAnchor() to 2776 * within roundoff errors. dJointGetPistonAnchor2() can be used, along with 2777 * dJointGetPistonAnchor(), to see how far the joint has come apart. 2778 * 2779 * @ingroup joints 2780 */ 2781 void dJointGetPistonAnchor2(dJointID, dVector3 result); 2782 2783 /** 2784 * @brief Get the prismatic axis (This is also the rotoide axis. 2785 * @ingroup joints 2786 */ 2787 void dJointGetPistonAxis(dJointID, dVector3 result); 2788 2789 /** 2790 * @brief get joint parameter 2791 * @ingroup joints 2792 */ 2793 dReal dJointGetPistonParam(dJointID, int parameter); 2794 2795 2796 /** 2797 * @brief Get the number of angular axes that will be controlled by the 2798 * AMotor. 2799 * @param num can range from 0 (which effectively deactivates the 2800 * joint) to 3. 2801 * This is automatically set to 3 in dAMotorEuler mode. 2802 * @ingroup joints 2803 */ 2804 int dJointGetAMotorNumAxes(dJointID); 2805 2806 /** 2807 * @brief Get the AMotor axes. 2808 * @param anum selects the axis to change (0,1 or 2). 2809 * @param rel Each axis can have one of three ``relative orientation'' modes. 2810 * \li 0: The axis is anchored to the global frame. 2811 * \li 1: The axis is anchored to the first body. 2812 * \li 2: The axis is anchored to the second body. 2813 * @ingroup joints 2814 */ 2815 void dJointGetAMotorAxis(dJointID, int anum, dVector3 result); 2816 2817 /** 2818 * @brief Get axis 2819 * @remarks 2820 * The axis vector is always specified in global coordinates regardless 2821 * of the setting of rel. 2822 * There are two GetAMotorAxis functions, one to return the axis and one to 2823 * return the relative mode. 2824 * 2825 * For dAMotorEuler mode: 2826 * \li Only axes 0 and 2 need to be set. Axis 1 will be determined 2827 automatically at each time step. 2828 * \li Axes 0 and 2 must be perpendicular to each other. 2829 * \li Axis 0 must be anchored to the first body, axis 2 must be anchored 2830 to the second body. 2831 * @ingroup joints 2832 */ 2833 int dJointGetAMotorAxisRel(dJointID, int anum); 2834 2835 /** 2836 * @brief Get the current angle for axis. 2837 * @remarks 2838 * In dAMotorUser mode this is simply the value that was set with 2839 * dJointSetAMotorAngle(). 2840 * In dAMotorEuler mode this is the corresponding euler angle. 2841 * @ingroup joints 2842 */ 2843 dReal dJointGetAMotorAngle(dJointID, int anum); 2844 2845 /** 2846 * @brief Get the current angle rate for axis anum. 2847 * @remarks 2848 * In dAMotorUser mode this is always zero, as not enough information is 2849 * available. 2850 * In dAMotorEuler mode this is the corresponding euler angle rate. 2851 * @ingroup joints 2852 */ 2853 dReal dJointGetAMotorAngleRate(dJointID, int anum); 2854 2855 /** 2856 * @brief get joint parameter 2857 * @ingroup joints 2858 */ 2859 dReal dJointGetAMotorParam(dJointID, int parameter); 2860 2861 /** 2862 * @brief Get the angular motor mode. 2863 * @param mode must be one of the following constants: 2864 * \li dAMotorUser The AMotor axes and joint angle settings are entirely 2865 * controlled by the user. This is the default mode. 2866 * \li dAMotorEuler Euler angles are automatically computed. 2867 * The axis a1 is also automatically computed. 2868 * The AMotor axes must be set correctly when in this mode, 2869 * as described below. 2870 * When this mode is initially set the current relative orientations 2871 * of the bodies will correspond to all euler angles at zero. 2872 * @ingroup joints 2873 */ 2874 int dJointGetAMotorMode(dJointID); 2875 2876 /** 2877 * @brief Get nr of axes. 2878 * @ingroup joints 2879 */ 2880 int dJointGetLMotorNumAxes(dJointID); 2881 2882 /** 2883 * @brief Get axis. 2884 * @ingroup joints 2885 */ 2886 void dJointGetLMotorAxis(dJointID, int anum, dVector3 result); 2887 2888 /** 2889 * @brief get joint parameter 2890 * @ingroup joints 2891 */ 2892 dReal dJointGetLMotorParam(dJointID, int parameter); 2893 2894 /** 2895 * @brief get joint parameter 2896 * @ingroup joints 2897 */ 2898 dReal dJointGetFixedParam(dJointID, int parameter); 2899 2900 2901 /** 2902 * @ingroup joints 2903 */ 2904 dJointID dConnectingJoint(dBodyID, dBodyID); 2905 2906 /** 2907 * @ingroup joints 2908 */ 2909 int dConnectingJointList(dBodyID, dBodyID, dJointID*); 2910 2911 /** 2912 * @brief Utility function 2913 * @return 1 if the two bodies are connected together by 2914 * a joint, otherwise return 0. 2915 * @ingroup joints 2916 */ 2917 int dAreConnected(dBodyID, dBodyID); 2918 2919 /** 2920 * @brief Utility function 2921 * @return 1 if the two bodies are connected together by 2922 * a joint that does not have type @arg{joint_type}, otherwise return 0. 2923 * @param body1 A body to check. 2924 * @param body2 A body to check. 2925 * @param joint_type is a dJointTypeXXX constant. 2926 * This is useful for deciding whether to add contact joints between two bodies: 2927 * if they are already connected by non-contact joints then it may not be 2928 * appropriate to add contacts, however it is okay to add more contact between- 2929 * bodies that already have contacts. 2930 * @ingroup joints 2931 */ 2932 int dAreConnectedExcluding(dBodyID body1, dBodyID body2, int joint_type);