Source code for rofunc.learning.RofuncRL.tasks.isaacgymenv.base.dr_utils

# Copyright (c) 2018-2022, NVIDIA Corporation
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


import numpy as np
from bisect import bisect
from isaacgym import gymapi 


[docs]def get_property_setter_map(gym): property_to_setters = { "dof_properties": gym.set_actor_dof_properties, "tendon_properties": gym.set_actor_tendon_properties, "rigid_body_properties": gym.set_actor_rigid_body_properties, "rigid_shape_properties": gym.set_actor_rigid_shape_properties, "sim_params": gym.set_sim_params, } return property_to_setters
[docs]def get_property_getter_map(gym): property_to_getters = { "dof_properties": gym.get_actor_dof_properties, "tendon_properties": gym.get_actor_tendon_properties, "rigid_body_properties": gym.get_actor_rigid_body_properties, "rigid_shape_properties": gym.get_actor_rigid_shape_properties, "sim_params": gym.get_sim_params, } return property_to_getters
[docs]def get_default_setter_args(gym): property_to_setter_args = { "dof_properties": [], "tendon_properties": [], "rigid_body_properties": [True], "rigid_shape_properties": [], "sim_params": [], } return property_to_setter_args
[docs]def generate_random_samples(attr_randomization_params, shape, curr_gym_step_count, extern_sample=None): rand_range = attr_randomization_params['range'] distribution = attr_randomization_params['distribution'] sched_type = attr_randomization_params['schedule'] if 'schedule' in attr_randomization_params else None sched_step = attr_randomization_params['schedule_steps'] if 'schedule' in attr_randomization_params else None operation = attr_randomization_params['operation'] if sched_type == 'linear': sched_scaling = 1 / sched_step * min(curr_gym_step_count, sched_step) elif sched_type == 'constant': sched_scaling = 0 if curr_gym_step_count < sched_step else 1 else: sched_scaling = 1 if extern_sample is not None: sample = extern_sample if operation == 'additive': sample *= sched_scaling elif operation == 'scaling': sample = sample * sched_scaling + 1 * (1 - sched_scaling) elif distribution == "gaussian": mu, var = rand_range if operation == 'additive': mu *= sched_scaling var *= sched_scaling elif operation == 'scaling': var = var * sched_scaling # scale up var over time mu = mu * sched_scaling + 1 * (1 - sched_scaling) # linearly interpolate sample = np.random.normal(mu, var, shape) elif distribution == "loguniform": lo, hi = rand_range if operation == 'additive': lo *= sched_scaling hi *= sched_scaling elif operation == 'scaling': lo = lo * sched_scaling + 1 * (1 - sched_scaling) hi = hi * sched_scaling + 1 * (1 - sched_scaling) sample = np.exp(np.random.uniform(np.log(lo), np.log(hi), shape)) elif distribution == "uniform": lo, hi = rand_range if operation == 'additive': lo *= sched_scaling hi *= sched_scaling elif operation == 'scaling': lo = lo * sched_scaling + 1 * (1 - sched_scaling) hi = hi * sched_scaling + 1 * (1 - sched_scaling) sample = np.random.uniform(lo, hi, shape) return sample
[docs]def get_bucketed_val(new_prop_val, attr_randomization_params): if attr_randomization_params['distribution'] == 'uniform': # range of buckets defined by uniform distribution lo, hi = attr_randomization_params['range'][0], attr_randomization_params['range'][1] else: # for gaussian, set range of buckets to be 2 stddev away from mean lo = attr_randomization_params['range'][0] - 2 * np.sqrt(attr_randomization_params['range'][1]) hi = attr_randomization_params['range'][0] + 2 * np.sqrt(attr_randomization_params['range'][1]) num_buckets = attr_randomization_params['num_buckets'] buckets = [(hi - lo) * i / num_buckets + lo for i in range(num_buckets)] return buckets[bisect(buckets, new_prop_val) - 1]
[docs]def apply_random_samples(prop, og_prop, attr, attr_randomization_params, curr_gym_step_count, extern_sample=None): """ @params: prop: property we want to randomise og_prop: the original property and its value attr: which particular attribute we want to randomise e.g. damping, stiffness attr_randomization_params: the attribute randomisation meta-data e.g. distr, range, schedule curr_gym_step_count: gym steps so far """ if isinstance(prop, gymapi.SimParams): if attr == 'gravity': sample = generate_random_samples(attr_randomization_params, 3, curr_gym_step_count) if attr_randomization_params['operation'] == 'scaling': prop.gravity.x = og_prop['gravity'].x * sample[0] prop.gravity.y = og_prop['gravity'].y * sample[1] prop.gravity.z = og_prop['gravity'].z * sample[2] elif attr_randomization_params['operation'] == 'additive': prop.gravity.x = og_prop['gravity'].x + sample[0] prop.gravity.y = og_prop['gravity'].y + sample[1] prop.gravity.z = og_prop['gravity'].z + sample[2] if attr == 'rest_offset': sample = generate_random_samples(attr_randomization_params, 1, curr_gym_step_count) prop.physx.rest_offset = sample elif isinstance(prop, np.ndarray): sample = generate_random_samples(attr_randomization_params, prop[attr].shape, curr_gym_step_count, extern_sample) if attr_randomization_params['operation'] == 'scaling': new_prop_val = og_prop[attr] * sample elif attr_randomization_params['operation'] == 'additive': new_prop_val = og_prop[attr] + sample if 'num_buckets' in attr_randomization_params and attr_randomization_params['num_buckets'] > 0: new_prop_val = get_bucketed_val(new_prop_val, attr_randomization_params) prop[attr] = new_prop_val else: sample = generate_random_samples(attr_randomization_params, 1, curr_gym_step_count, extern_sample) cur_attr_val = og_prop[attr] if attr_randomization_params['operation'] == 'scaling': new_prop_val = cur_attr_val * sample elif attr_randomization_params['operation'] == 'additive': new_prop_val = cur_attr_val + sample if 'num_buckets' in attr_randomization_params and attr_randomization_params['num_buckets'] > 0: new_prop_val = get_bucketed_val(new_prop_val, attr_randomization_params) setattr(prop, attr, new_prop_val)
[docs]def check_buckets(gym, envs, dr_params): total_num_buckets = 0 for actor, actor_properties in dr_params["actor_params"].items(): cur_num_buckets = 0 if 'rigid_shape_properties' in actor_properties.keys(): prop_attrs = actor_properties['rigid_shape_properties'] if 'restitution' in prop_attrs and 'num_buckets' in prop_attrs['restitution']: cur_num_buckets = prop_attrs['restitution']['num_buckets'] if 'friction' in prop_attrs and 'num_buckets' in prop_attrs['friction']: if cur_num_buckets > 0: cur_num_buckets *= prop_attrs['friction']['num_buckets'] else: cur_num_buckets = prop_attrs['friction']['num_buckets'] total_num_buckets += cur_num_buckets assert total_num_buckets <= 64000, 'Explicit material bucketing has been specified, but the provided total bucket count exceeds 64K: {} specified buckets'.format( total_num_buckets) shape_ct = 0 # Separate loop because we should not assume that each actor is present in each env for env in envs: for i in range(gym.get_actor_count(env)): actor_handle = gym.get_actor_handle(env, i) actor_name = gym.get_actor_name(env, actor_handle) if actor_name in dr_params["actor_params"] and 'rigid_shape_properties' in dr_params["actor_params"][actor_name]: shape_ct += gym.get_actor_rigid_shape_count(env, actor_handle) assert shape_ct <= 64000 or total_num_buckets > 0, 'Explicit material bucketing is not used but the total number of shapes exceeds material limit. Please specify bucketing to limit material count.'