class_docstr: ### Description
  The easiest control task to learn from pixels - a top-down
  racing environment. The generated track is random every episode.
  
  Some indicators are shown at the bottom of the window along with the
  state RGB buffer. From left to right: true speed, four ABS sensors,
  steering wheel position, and gyroscope.
  To play yourself (it's rather fast for humans), type:
  ```
  python gym/envs/box2d/car_racing.py
  ```
  Remember: it's a powerful rear-wheel drive car - don't press the accelerator
  and turn at the same time.
  
  ### Action Space
  If continuous:
      There are 3 actions: steering (-1 is full left, +1 is full right), gas, and breaking.
  If discrete:
      There are 5 actions: do nothing, steer left, steer right, gas, brake.
  
  ### Observation Space
  State consists of 96x96 pixels.
  
  ### Rewards
  The reward is -0.1 every frame and +1000/N for every track tile visited,
  where N is the total number of tiles visited in the track. For example,
  if you have finished in 732 frames, your reward is
  1000 - 0.1*732 = 926.8 points.
  
  ### Starting State
  The car starts at rest in the center of the road.
  
  ### Episode Termination
  The episode finishes when all of the tiles are visited. The car can also go
  outside of the playfield - that is, far off the track, in which case it will
  receive -100 reward and die.
  
  ### Arguments
  `lap_complete_percent` dictates the percentage of tiles that must be visited by
  the agent before a lap is considered complete.
  
  Passing `domain_randomize=True` enables the domain randomized variant of the environment.
  In this scenario, the background and track colours are different on every reset.
  
  Passing `continuous=False` converts the environment to use discrete action space.
  The discrete action space has 5 actions: [do nothing, left, right, gas, brake].
  
  ### Reset Arguments
  Passing the option `options["randomize"] = True` will change the current colour of the environment on demand.
  Correspondingly, passing the option `options["randomize"] = False` will not change the current colour of the environment.
  `domain_randomize` must be `True` on init for this argument to work.
  Example usage:
  ```py
      env = gym.make("CarRacing-v1", domain_randomize=True)
  
      # normal reset, this changes the colour scheme by default
      env.reset()
  
      # reset with colour scheme change
      env.reset(options={"randomize": True})
  
      # reset with no colour scheme change
      env.reset(options={"randomize": False})
  ```
  
  ### Version History
  - v1: Change track completion logic and add domain randomization (0.24.0)
  - v0: Original version
  
  ### References
  - Chris Campbell (2014), http://www.iforce2d.net/b2dtut/top-down-car.
  
  ### Credits
  Created by Oleg Klimov
code: def _create_track(self):
      CHECKPOINTS = 12
  
      # Create checkpoints
      checkpoints = []
      for c in range(CHECKPOINTS):
          noise = self.np_random.uniform(
              0, 2 * math.pi * 1 / CHECKPOINTS
          )
          alpha = 2 * math.pi * c / CHECKPOINTS + noise
          rad = self.np_random.uniform(TRACK_RAD / 3, TRACK_RAD)
  
          if c == 0:
              alpha = 0
              rad = 1.5 * TRACK_RAD
          if c == CHECKPOINTS - 1:
              alpha = 2 * math.pi * c / CHECKPOINTS
              self.start_alpha = 2 * math.pi * (-0.5) / CHECKPOINTS
              rad = 1.5 * TRACK_RAD
  
          checkpoints.append(
              (alpha, rad * math.cos(alpha), rad * math.sin(alpha))
          )
      self.road = []
  
      # Go from one checkpoint to another to create track
      x, y, beta = 1.5 * TRACK_RAD, 0, 0
      dest_i = 0
      laps = 0
      track = []
      no_freeze = 2500
      visited_other_side = False
      while True:
          alpha = math.atan2(y, x)
          if visited_other_side and alpha > 0:
              laps += 1
              visited_other_side = False
          if alpha < 0:
              visited_other_side = True
              alpha += 2 * math.pi
  
          while True:  # Find destination from checkpoints
              failed = True
  
              while True:
                  dest_alpha, dest_x, dest_y = checkpoints[
                      dest_i % len(checkpoints)
                  ]
                  if alpha <= dest_alpha:
                      failed = False
                      break
                  dest_i += 1
                  if dest_i % len(checkpoints) == 0:
                      break
  
              if not failed:
                  break
  
              alpha -= 2 * math.pi
              continue
  
          r1x = math.cos(beta)
          r1y = math.sin(beta)
          p1x = -r1y
          p1y = r1x
          dest_dx = dest_x - x  # vector towards destination
          dest_dy = dest_y - y
          # destination vector projected on rad:
          proj = r1x * dest_dx + r1y * dest_dy
          while beta - alpha > 1.5 * math.pi:
              beta -= 2 * math.pi
          while beta - alpha < -1.5 * math.pi:
              beta += 2 * math.pi
          prev_beta = beta
          proj *= SCALE
          if proj > 0.3:
              beta -= min(TRACK_TURN_RATE, abs(0.001 * proj))
          if proj < -0.3:
              beta += min(TRACK_TURN_RATE, abs(0.001 * proj))
          x += p1x * TRACK_DETAIL_STEP
          y += p1y * TRACK_DETAIL_STEP
          track.append((alpha, prev_beta * 0.5 + beta * 0.5, x, y))
          if laps > 4:
              break
          no_freeze -= 1
          if no_freeze == 0:
              break
  
      # Find closed loop range i1..i2, first loop should be ignored, second is OK
      i1, i2 = -1, -1
      i = len(track)
      while True:
          i -= 1
          if i == 0:
              return False  # Failed
          pass_through_start = (
              track[i][0] > self.start_alpha
              and track[i - 1][0] <= self.start_alpha
          )
          if pass_through_start and i2 == -1:
              i2 = i
          elif pass_through_start and i1 == -1:
              i1 = i
              break
      if self.verbose:
          print(
              "Track generation: %i..%i -> %i-tiles track"
              % (i1, i2, i2 - i1)
          )
      assert i1 != -1
      assert i2 != -1
  
      track = track[i1 : i2 - 1]
  
      first_beta = track[0][1]
      first_perp_x = math.cos(first_beta)
      first_perp_y = math.sin(first_beta)
      # Length of perpendicular jump to put together head and tail
      well_glued_together = np.sqrt(
          np.square(first_perp_x * (track[0][2] - track[-1][2]))
          + np.square(first_perp_y * (track[0][3] - track[-1][3]))
      )
      if well_glued_together > TRACK_DETAIL_STEP:
          return False
  
      # Red-white border on hard turns
      border = [False] * len(track)
      for i in range(len(track)):
          good = True
          oneside = 0
          for neg in range(BORDER_MIN_COUNT):
              beta1 = track[i - neg - 0][1]
              beta2 = track[i - neg - 1][1]
              good &= abs(beta1 - beta2) > TRACK_TURN_RATE * 0.2
              oneside += np.sign(beta1 - beta2)
          good &= abs(oneside) == BORDER_MIN_COUNT
          border[i] = good
      for i in range(len(track)):
          for neg in range(BORDER_MIN_COUNT):
              border[i - neg] |= border[i]
  
      # Create tiles
      for i in range(len(track)):
          alpha1, beta1, x1, y1 = track[i]
          alpha2, beta2, x2, y2 = track[i - 1]
          road1_l = (
              x1 - TRACK_WIDTH * math.cos(beta1),
              y1 - TRACK_WIDTH * math.sin(beta1),
          )
          road1_r = (
              x1 + TRACK_WIDTH * math.cos(beta1),
              y1 + TRACK_WIDTH * math.sin(beta1),
          )
          road2_l = (
              x2 - TRACK_WIDTH * math.cos(beta2),
              y2 - TRACK_WIDTH * math.sin(beta2),
          )
          road2_r = (
              x2 + TRACK_WIDTH * math.cos(beta2),
              y2 + TRACK_WIDTH * math.sin(beta2),
          )
          vertices = [road1_l, road1_r, road2_r, road2_l]
          self.fd_tile.shape.vertices = vertices
          t = self.world.CreateStaticBody(fixtures=self.fd_tile)
          t.userData = t
          c = 0.01 * (i % 3) * 255
          t.color = self.road_color + c
          t.road_visited = False
          t.road_friction = 1.0
          t.idx = i
          t.fixtures[0].sensor = True
          self.road_poly.append(
              ([road1_l, road1_r, road2_r, road2_l], t.color)
          )
          self.road.append(t)
          if border[i]:
              side = np.sign(beta2 - beta1)
              b1_l = (
                  x1 + side * TRACK_WIDTH * math.cos(beta1),
                  y1 + side * TRACK_WIDTH * math.sin(beta1),
              )
              b1_r = (
                  x1 + side * (TRACK_WIDTH + BORDER) * math.cos(beta1),
                  y1 + side * (TRACK_WIDTH + BORDER) * math.sin(beta1),
              )
              b2_l = (
                  x2 + side * TRACK_WIDTH * math.cos(beta2),
                  y2 + side * TRACK_WIDTH * math.sin(beta2),
              )
              b2_r = (
                  x2 + side * (TRACK_WIDTH + BORDER) * math.cos(beta2),
                  y2 + side * (TRACK_WIDTH + BORDER) * math.sin(beta2),
              )
              self.road_poly.append(
                  (
                      [b1_l, b1_r, b2_r, b2_l],
                      (255, 255, 255) if i % 2 == 0 else (255, 0, 0),
                  )
              )
      self.track = track
      return True
  
imports: import math
  from typing import Optional, Union
  import numpy
  import gym
  from gym import spaces
  from gym.envs.box2d.car_dynamics import Car
  from gym.error import DependencyNotInstalled, InvalidAction
  from gym.utils import EzPickle
label_desc: Use image node_id 5 for calling the CarRacing obj's underlying member method code with example usage: obj._create_track() and returns: True, False, False