Search code examples
ranimationaccelerometerrgl

How to rotate hand object with accelerometer data using `rgl` and `animation`


Let's say I had a wireframe, 3D object such as https://free3d.com/3d-model/freerealsichand-85561.html

Let's say I wanted to fix the wrist of said object to be the readout of an accelerometer wrist watch (e.g., get position via dead-reckoning).

How can I plot a 3-D image like this in rgl?

How can I rotate / translate said image based on changes to accelerometer data?

Bonus for: how can I play an animation of this activity. (e.g., library animation)

The accelerometer is 3-DOF: x-acc, y-acc, z-acc without any other data.


Solution

  • That link includes the hand in several formats, but rgl can't currently read them. It comes closest with the .OBJ format, but can't read the normals or textures that are recorded in that file, so it fails. You might want to try updating readOBJ to support more of the OBJ format; alternatively, you can remove that information like this:

    hand <- readLines("hand.OBJ")
    poly <- grepl("^f ", hand)
    hand[poly] <- gsub("/[^ ]+", "", hand[poly])
    handmesh <- readOBJ(textConnection(hand))
    

    This will give some warnings because it ignores some other parts of that file, but it results in an object that rgl can handle. You can plot it like this:

    shade3d(handmesh, col = "pink")
    

    To translate and rotate the shape, use the translate3d and rotate3d functions on the userMatrix e.g.

    par3d(userMatrix = rotate3d(par3d("userMatrix"), 0.1, 1,0,0))
    

    to rotate the hand by 0.1 radians around the x axis. (You could also rotate the handmesh itself if you want a permanent change.)

    You'll need to spend some time figuring out what are the coordinates of the wrist, and translating your 3-DOF data into the right coordinate system.

    You don't need animation for an animation; see the examples in ?rgl::play3d. For example, to spin the hand around the x axis, you could use

    open3d()
    shade3d(handmesh, col = "pink")
    play3d(spin3d(axis = c(1, 0, 0)))