A Cartpole `Task` to balance the pole. State is initialized either close to the target configuration or at a random configuration.
| 149 | |
| 150 | |
| 151 | class Balance(base.Task): |
| 152 | """A Cartpole `Task` to balance the pole. |
| 153 | |
| 154 | State is initialized either close to the target configuration or at a random |
| 155 | configuration. |
| 156 | """ |
| 157 | _CART_RANGE = (-.25, .25) |
| 158 | _ANGLE_COSINE_RANGE = (.995, 1) |
| 159 | |
| 160 | def __init__(self, swing_up, sparse, random=None): |
| 161 | """Initializes an instance of `Balance`. |
| 162 | |
| 163 | Args: |
| 164 | swing_up: A `bool`, which if `True` sets the cart to the middle of the |
| 165 | slider and the pole pointing towards the ground. Otherwise, sets the |
| 166 | cart to a random position on the slider and the pole to a random |
| 167 | near-vertical position. |
| 168 | sparse: A `bool`, whether to return a sparse or a smooth reward. |
| 169 | random: Optional, either a `numpy.random.RandomState` instance, an |
| 170 | integer seed for creating a new `RandomState`, or None to select a seed |
| 171 | automatically (default). |
| 172 | """ |
| 173 | self._sparse = sparse |
| 174 | self._swing_up = swing_up |
| 175 | super().__init__(random=random) |
| 176 | |
| 177 | def initialize_episode(self, physics): |
| 178 | """Sets the state of the environment at the start of each episode. |
| 179 | |
| 180 | Initializes the cart and pole according to `swing_up`, and in both cases |
| 181 | adds a small random initial velocity to break symmetry. |
| 182 | |
| 183 | Args: |
| 184 | physics: An instance of `Physics`. |
| 185 | """ |
| 186 | nv = physics.model.nv |
| 187 | if self._swing_up: |
| 188 | physics.named.data.qpos['slider'] = .01*self.random.randn() |
| 189 | physics.named.data.qpos['hinge_1'] = np.pi + .01*self.random.randn() |
| 190 | physics.named.data.qpos[2:] = .1*self.random.randn(nv - 2) |
| 191 | else: |
| 192 | physics.named.data.qpos['slider'] = self.random.uniform(-.1, .1) |
| 193 | physics.named.data.qpos[1:] = self.random.uniform(-.034, .034, nv - 1) |
| 194 | physics.named.data.qvel[:] = 0.01 * self.random.randn(physics.model.nv) |
| 195 | super().initialize_episode(physics) |
| 196 | |
| 197 | def get_observation(self, physics): |
| 198 | """Returns an observation of the (bounded) physics state.""" |
| 199 | obs = collections.OrderedDict() |
| 200 | obs['position'] = physics.bounded_position() |
| 201 | obs['velocity'] = physics.velocity() |
| 202 | return obs |
| 203 | |
| 204 | def _get_reward(self, physics, sparse): |
| 205 | if sparse: |
| 206 | cart_in_bounds = rewards.tolerance(physics.cart_position(), |
| 207 | self._CART_RANGE) |
| 208 | angle_in_bounds = rewards.tolerance(physics.pole_angle_cosine(), |
no outgoing calls
no test coverage detected
searching dependent graphs…