-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[core] Add Perlin ground profile generators. #799
Conversation
What do you mean ? |
To be able to get this type of terrain: |
I see. It looks like a quantisation based on the vertical value only. Something like I think |
Are you planning to work on it ? If not, then I suggest closing this issue because I'm not planning to work on it either. |
Yes, I did a bit more work on it but didn’t push anything yet. I’m planning to work on/finish it in a couple of weeks. |
Ok perfect ! Let's keep it open then :) |
5167e9f
to
75575c6
Compare
Apparently you made good progress ! Nice :) What is your future plan ? You want to add quantisation ? Can you add a unit test checking if the gradient is right ? |
The problem is not that it asserts to false because asserts are disabled for release build type. The issue is rather the contrary, we should systematically check this condition and raise an exception if not satisfying this condition causes segfault. I will issue a fix for this. |
Yes, I still need to do :
|
Nope it is fine :)
I'm afraid doing this is not straightforward. It has been a long-lasting issue as you know. Once everything else is working, I could help you on this part to improve the current heuristic that has not sufficient in many cases. |
To many code duplication. There should be no need to implement anything specific for the 2D scenario. |
I'm going to help you on this, so that we can close this long-lasting PR. |
If you have time for it, I'm pretty happy to get your help. I didn't have much time to work on it the last few weeks, but hoping to finish it this week. |
Ok I skimmed through the code. Now I remember. Since those processes at not used for anything inside core itself, I'm going to refactor them a bit. In particular to replace |
Since you're taking over for the PerlinNoise part, I started creating some unit tests (using the current methods' name) and fixed a typo in the 1D gradient computation. There is also a bug in the 2D gradient computation. |
Ok nice, so far I have been working on adding the gradient feature on all the other random processes so as to provide a unified API for all of them, without slowing down computations. I have also fixed stuff like negative time, and fixed bugs on non-perlin processes. |
I will commit something this morning. |
… differentiable. Fix negative time support.
Can you try creating a periodic_perlin_ground on your side ? I am having a bit of trouble doing so:
|
Also, I had started working on sample_state and added: gym_jiminy/common/envs/locomotion.py, line 239..
gym_jiminy/common/envs/generic.py, line 1398
Either there is a bug in this code or there is something that I've been missing because it's not working as expected. |
No need to make two branches based on the sign of # Get ground profile
ground_profile = self.simulator.get_options()["world"]["groundProfile"]
# Lowest contact point from ground
contact_frames_xy_positions = np.stack([
self.robot.pinocchio_model.frames[frame_index].placement.translation[:2]
for frame_index in self.robot.contact_frame_indices])
contact_frames_z_positions = np.stack([
self.robot.pinocchio_model.frames[frame_index].placement.translation[2]
for frame_index in self.robot.contact_frame_indices])
ground_height_contact_frames = np.zeros((len(self.robot.contact_frame_indices),))
query_heightmap(ground_profile, contact_frames_xy_positions, ground_height_contact_frames)
delta_height_from_ground = contact_frames_z_positions - ground_height_contact_frames
# Make sure that there is exactly one point in contact with the ground,
# all the others being above the ground
q[2] -= min(delta_height_from_ground) Apart from that, it looks good. What is the issue ? |
It is expected, but the error message is misleading. I will fix it. In fact, each octave has a larger wavelength than the "previous" one, so if you add too many octaves, at some point it can exceed the period. |
Is it standard implementation or some implementation use the other convention (each octave has a higher frequency) ? |
Did you updated the forward kinematic by calling # Set robot in neutral configuration
q = self._neutral()
pin.framesForwardKinematics(self.robot.pinocchio_model, self.robot.pinocchio_data, q) |
It is standard, look for Perlin Noise "persistence" and "lacunarity". |
It shouldn't be needed since it is already called after
|
Yes, it changes for leveraging vectorisation more efficiently and hence improve performance. |
Indeed. If you called refresh afterward then there is something very strange happening. |
Here is the code snippet I use. I simply call import numpy as np
from gym_jiminy.envs.anymal import ANYmalPDControlJiminyEnv
from jiminy_py import tree
from jiminy_py.core import periodic_perlin_ground, random_perlin_ground
if __name__ == '__main__':
env = ANYmalPDControlJiminyEnv()
engine_options = env.simulator.get_options()
orientation = 0.0
wavelength= 1.0
num_octaves = 8
seed = 42
engine_options["world"]["groundProfile"] = random_perlin_ground(wavelength, num_octaves, seed)
env.simulator.set_options(engine_options)
for i in range(5):
obs, _ = env.reset(seed = i)
terminated, truncated = False, False
while not (terminated or truncated):
assert not any(np.isnan(e).any() for e in tree.flatten(obs)), "Nan in observation"
obs, _, terminated, truncated, _ = env.step(0.0*env.action_space.sample())
breakpoint()
if terminated or truncated:
print(f"terminated: {terminated}, truncated: {truncated}")
env.replay(backed="panda3d")
env.stop() |
Here is your issue: contact_positions = np.stack([
self.robot.pinocchio_data.oMf[frame_index].translation
for frame_index in self.robot.contact_frame_indices], -1)
|
I can confirm it is working with: engine_options = self.simulator.get_options()
ground_fun = engine_options['world']['groundProfile']
# Lowest contact point from ground
contact_positions = np.stack([
self.robot.pinocchio_data.oMf[frame_index].translation
for frame_index in self.robot.contact_frame_indices], -1)
contact_heights = np.zeros((contact_positions.shape[-1],))
jiminy.query_heightmap(
ground_fun, contact_positions[:2], contact_heights)
delta_height_from_ground = contact_positions[2] - contact_heights
# Make sure that there is exactly one point in contact with the
# ground, all the others being above the ground.
q[2] -= delta_height_from_ground.min() |
Oh yes, that's a nice catch. It is still floating in the air on my end.. |
It is fine on my side ! (I mean with "your" patch to make the robot touch the ground, it is not merged for now as it is not generic enough, it should also consider collision bodies, even if they are not properly supported at the time being that are used in ant environment for instance). Ideally, |
I need to profile this code, because I'm not happy at all with the performance: import numpy as np
from jiminy_py.core import random_perlin_ground, query_heightmap
ground_fun = random_perlin_ground(wavelength=1.0, num_octaves=8, seed=42)
positions = np.random.rand(3, 100)
%timeit query_heightmap(ground_fun, positions[:2], positions[2])
76.1 µs ± 680 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each) I consider this as extremely bad. I would expect something like 5us at max. There is a lot of redundant computations everywhere: the gradient is computed independently from the height, and the gradient at knots is never cached even if the query point is only shifted by 1mm. |
* [core] Fix robot serialization issue. (#821) * [core] Minor improvement periodic Perlin process and periodic stair ground. (#799) * [core] 'PeriodicGaussianProcess' and 'PeriodicFourierProcess' are now differentiable. (#799) * [core] Fix negative time support for all existing random processes. (#799) * [core] Add N-dimension Perlin processes. (#799) (#823) * [core] Add gradient computation for all Perlin processes. (#799) (#823) (#825) * [core] Make all Perlin processes faster and copy-able. (#799) * [core] Add Perlin ground generators. (#799) * [core] Replace MurmurHash3 by xxHash32 which is faster. (#824) * [core] Make gradient computation optional for heightmap functions. (#824) * [jiminy_py] Fix 'tree.unflatten_as' mixing up key order for 'gym.spaces.Dict'. (#819) * [python/simulator] Consistent keyword arguments between 'Simulator.build' and 'Simulator.add_robot'. (#821) * [python/viewer] Fix MacOS support. (#822) * [python/viewer] Add support of user-specified extra cameras (rgb and depth). (#826) * [python/viewer] Significantly speed-up both offscreen and onscreen rendering for Panda3D. (#826) * [gym/common] More generic stacking quantity. (#812) * [gym/common] Add termination condition abstraction. (#812) * [gym/common] Add quantity shift and drift tracking termination conditions. (#812) * [gym/common] Add support of termination composition in pipeline environments. (#812) * [gym/common] Add base roll/pitch termination condition. (#813) * [gym/common] Add base relative height termination condition. (#813) * [gym/common] Add foot collision termination condition. (#813) * [gym/common] More generic actuated joint kinematic quantity. (#814) * [gym/common] Add multi-ary operator quantity. (#814) * [gym/common] Add safety limits termination condition. (#814) * [gym/common] Add robot flying termination condition. (#815) * [gym/common] Add power consumption termination condition. (#816) * [gym/common] Add ground impact force termination condition. (#816) * [gym/common] Add base odometry pose drift tracking termination condition. (#817) * [gym/common] Add motor positions shift tracking termination condition. (#817) * [gym/common] Add relative foot odometry pose shift tracking termination conditions. (#820) * [gym/common] Add unit test checking that observation wrappers preserve key ordering. (#820) * [gym/common] Fix quantity hash collision issue in quantity manager. (#821) * [gym/common] Refactor quantity management to dramatically improve its performance. (#821) * [gym/common] Add 'order' option to 'AdditiveReward'. (#821) * [misc] Fix missing compositions documentation. (#812) --------- Co-authored-by: Mathias Wulfman <101942083+mwulfman@users.noreply.github.com>
I am proposing to add a unidirection Perlin ground
HeightmapFunction
, 2D Perlin groundHeightmapFunction
and a quantization methods to quantize any ground to certain z-values.