JamieMair / MuJoCo.jl

Julia bindings and visualiser for the MuJoCo physics engine.
https://jamiemair.github.io/MuJoCo.jl/
MIT License
57 stars 4 forks source link

[Ask] Is there any method to modify mjuiState_ 's rect mutable ? #114

Open kshfire opened 4 months ago

kshfire commented 4 months ago

First of all, thank you for developing MuJoCo.jl !!!

I'm a beginner in Julia. I'm trying to re-implement original MuJoCo's simulate.cc by Julia with MuJoCo.jl. However, I've encountered a big problem: I found that mjuiState_'s rect type is NTuple{25, mjrRect} : it is immutable (I'm supprised and frustrated)

For example, I've tried to re-implement below codes, but I found that MuJoCo.jl's mjuiState_ 's rect type is immutable.

simulate.cc : void Simulate::RenderLoop() auto [buf_width, buf_height] = this->platform_ui->GetFramebufferSize(); this->uistate.nrect = 1; this->uistate.rect[0].width = buf_width; this->uistate.rect[0].height = buf_height;

I wonder that is there any method to modify mjuiState_'s rect type to mutable type ?

I tried to replace NTuple by SVector (StaticArrays), but MuJoCo.jl package was not worked. If I can't find a solution to this, I may have to give up. (very sad)

If there is a solution, I'd appreciate it if you could let me know.

kshfire commented 4 months ago

Since reallocation of NTuple is working, as a temporary method I use this method to modify uistate.rect values. I wonder if there is a better way.

JamieMair commented 4 months ago

Thanks @kshfire for the question, and it's great that you are trying to replicate the simulate.cc functionality. This should be fairly similar to what we have in the Visualiser extension, if you want to take a look there for reference.

Most of the underlying bindings to the C library (meaning in the LibMuJoCo module) are auto-generated and essentially map 1 to 1 with the C equivalent. There are good reasons for not making everything mutable by default. In other cases, we have friendly Julia wrappers for the most common structs (mjData, mjModel etc), but we don't have this for the visualisation internals.

You should still be able to do everything you can in C, albeit in a less ergonomic way. One option to make it a bit less painful is to use the Setfield.jl package, which gives you a macro to let you write "pseudo-mutating" code. As an example:

using Setfield, MuJoCo
s = MuJoCo.LibMuJoCo.mjuiState();

# Set nested fields one at a time
s = @set s.rect[1].width = Int32(100)
s = @set s.rect[1].height = Int32(50)
s = @set s.rect[1].left = Int32(0)
s = @set s.rect[1].bottom = Int32(0)
# OR: Set the entire rect at once
s = @set s.rect[1] = mjrRect(Int32(0), Int32(0), Int32(100), Int32(50))

println(s.rect[1]) # MuJoCo.LibMuJoCo.mjrRect_(0, 0, 100, 50)

Unfortunately, the underlying type is a Cint (Int32), so the conversions to Int32 are necessary at the moment, but this would change when we get around to wrapping the structs.

I hope this helps for now, but I think it would be beneficial to add an issue to wrap more of the internals in a Julia friendly way so that making visualisation extensions is easier in the future. I've opened - https://github.com/JamieMair/MuJoCo.jl/issues/115 for when we have some time to implement this.