Create dynamic virtual force impulse source at a point (apply force at a point)

Discussion in 'Simulation' started by Artem, Dec 28, 2016.

  1. Copying my question from (in case it got missed):
    http://www.mujoco.org/forum/index.php?threads/applying-external-force-at-a-position.2199/

    given a selected point in Cartesian space (not associated with a particular body) I would like to apply a force impulse (or apply a force during a short period of time) to a body which this point collides with, in other words, create a temporary virtual point-source of impulse which I can randomly create, remove and change during simulation that would only affect an object that occupies the space of the point.
    How should I approach this problem ? Any code examples would be very useful.
    Thank you in advance and Happy New Year to everyone! :)
     
  2. Emo Todorov

    Emo Todorov Administrator Staff Member

    You have to specify a body to which the force/torque will be applied. The body can be anywhere (i.e. the point of application does not need to be inside the body) but unless you specify the body, there is no way for MuJoCo to figure out what you want to do.

    So you need to do two things at each simulation step:

    (1) Use MuJoCo's collision detection mechanism to find out which body is colliding with the point of interest (and make sure this does not trigger a built-in contact force);

    (2) Specify the desired force once you know the body.


    (1) can be done by defining a small sphere at the virtual point of interest, and also defining the "gap" attribute for that geom to be very large. Contacts with the sphere will be detected and included in mjData.contact but will not be used by the contact force solver, because they fall in the gap. This is precisely why the gap parameter was introduced - so that users can implement custom forces for contacts.

    (2) is done with the function mj_applyFT. The arguments include the 3D force and torque you want to apply (expressed in the world frame), the index of the body to which the force/torque will be applied, and there is also a gfrc_target parameter where the result is added. Normally you should pass mjData.qfrc_applied, unless you want to compose applied forces into your own buffer and then copy them into qfrc_applied.

    It is important to clear qfrc_applied after every time step. MuJoCo will not to do this for you automatically, because in some scenarios you may want to leave the forces there over time (but not in the scenario you are describing).
     
  3. Thanks a lot for the quick response !
    Could you clarify few more questions:
    - what would be the best way to dynamically create and remove such "virtual" sphere during the simulation ?
    - would this sphere generate multiple contacts with the same body on the scene or a single contact, given it has non zero spatial size (vs. true point source having a zero volume) ?
    - what would be the best way to visualize force vector (at its origin in the "sphere") I am applying using this approach ?
     
    Last edited: Dec 28, 2016
  4. Emo Todorov

    Emo Todorov Administrator Staff Member

    You could attach the sphere geom to a mocap body, which is intended to be moved by user code (while the simulator treats it as stationary). The mocap body position and orientation are in mjData.mocap_pos and mjData.mocap_quat. If you want to disable the extra forces on a given timestep, just don't generate them in your code.

    The sphere will only generate a single contact with any other geom, but if you have multiple geoms attached to the same body, then you could have multiple contacts. You can detect this in your code: find all contacts on the same body and average their positions for example.

    As for visualization, you can add abstract geoms (including arrows) to mjvScene, just before calling the low-level OpenGL render function mjr_render. Look at the VR code sample, it shows how to do that in the function v_update:

    http://www.mujoco.org/book/source/mjvive.cpp
     
  5. Thanks a lot ! It is very helpful !
     
  6. @Emo Todorov Will it be possible to do the things you mentioned in the 131 version as well ?
     
  7. Emo Todorov

    Emo Todorov Administrator Staff Member

    Yes you can do all of this in 1.31, but the code will be somewhat different because the abstract visualizer was upgraded in 1.40 and in particular mjvScene was added to collect all relevant objects in one place. You can look at the simulate.cpp code sample included in the 1.31 release; it should be clear where to add the custom geoms for rendering.
     
  8. I tried creating a default geom(with geom type mjGEOM_CAPSULE) like shown in the http://www.mujoco.org/book/source/mjvive.cpp and adding it to the mjvObjects object after the mjv_makeGeoms call. But calling mjr_render doesn't render the new geom in the scene. Am I missing something ?
     
    Last edited: Jan 18, 2017
  9. Emo Todorov

    Emo Todorov Administrator Staff Member

    Did you increase the geom counter mjvScene.ngeom? If you did, that means some property of your new geom is causing it to be invisible...
     
  10. Thanks, that helped.