I’ve been doing RL research recently using the Mujoco physics engine as my robotics simulator. Up until now I’ve just written my own library that exposed just the functionality I needed as a subset of all that Mujoco can do, but I figure it may be a good time to do a re-write with all functionality exposed for the community. The issue I’m trying to wrap around is Mujoco contains all its information in two structs, mjModel and mjData, and how to efficiently interact with the values they contain when they are both pointers. The following is a example of what they look like, but there are a few hundred fields in each struct in the actual library:
// in C:
struct _mjModelExample {
int nposition;
int nvelocity;
mjOption opt; // other c struct
mjVis vis; // other c struct
}
struct _mjDataExample {
int nbuffer;
double* time;
void* buffer;
double* positions; // pointers into the void* buffer field
double* velocity;
}
mjModel* m = mj_loadXML("file.xml");
mjData* d = mj_makeData(m);
mj_step(m, d); // advance the model one time-step; values are stored in d
I can get around the struct-within-struct issue of mjModel by making everything immutable and not changing fields for the time being, but the bigger issue is accessing and swapping values in mjData’s fields, as Julia seems them as Ptr{Cdouble}
types. What I’ve thought about doing is replicating the struct’s structure as a Julia type and start doing unsafe_wraps to access the fields.
type mjDataJulia
nbuffer::Integer
time::Float64
positions::Vector{Float64}
velocity::Vector{Float64}
end
d = unsafe_load(d_pointer_from_c)
m = unsafe_load(m_pointer_from_c)
j_d = mjDataJulia(0, 0.0,
unsafe_wrap(Array, d.positions, m.npositions),
unsafe_wrap(Array, d.velocity, m.nvelocity))
j_d.positions = j_d.positions .* 0.5
mj_step(m_pointer_from_c, d_pointer_from_c) // Advance time; fields in mjData can be modified and accessed
This way I could ‘write’ into positions
and velocity
without having to do unsafe_wraps later on, but doesn’t address how the non-pointer fields could be mirrored. The structs are too large to always do copies whenever I need values, so having direct memory access is ideal.
I feel like there’s something I’m missing, however, in that there’s a simple solution staring me in the face that I’m not seeing. Any advice from folks that have encountered these kinds of data structures or this situation before would be tremendously appreciated!