Skip to content

Instantly share code, notes, and snippets.

@Arth-ur
Created May 9, 2018 11:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Arth-ur/ad295b251c4664565741fb18b5ad4724 to your computer and use it in GitHub Desktop.
Save Arth-ur/ad295b251c4664565741fb18b5ad4724 to your computer and use it in GitHub Desktop.
from PIL import Image
import random
# size of one pixel
PIXEL_SIZE = 0.2
# the scale is computed by dividing HEIGHT_RANGE by 128
HEIGHT_RANGE = 0.4
# the minimum height
HEIGHT_OFFSET = 0.01
# should we inverse greyscale ?
INVERSE = False
# Dimensions
WIDTH = 16
HEIGHT = 16
# Top left position inside the image
ORIGINX = 90
ORIGINY = 7
# number of rocks
NROCKS = 50
# number of pebbles
NPEBBLES = 50
# a fraction of the area where the pebbles are located
PEBBLE_REGION=0.2
if __name__ == '__main__':
# convert image to 8-bit grayscale
img = Image.open('noise.png').convert('L')
# crop image according to WIDTH and HEIGHT
img = img.crop((ORIGINX, ORIGINY, WIDTH + ORIGINX, HEIGHT + ORIGINY))
# convert image to 2D array
data = list(img.getdata())
# inverse grescale if needed
if INVERSE:
data = [ 128 - p for p in data]
# map greyscale to heights
heights = [p * (HEIGHT_RANGE / 128.0) for p in data]
# lower to map to minimum
min_height = min(heights)
heights = [height - min_height + HEIGHT_OFFSET for height in heights]
# create 2d heightmap
heightmap = [heights[offset:offset+WIDTH]
for offset in range(0, WIDTH*HEIGHT, WIDTH)]
# output map
for i in range(0, WIDTH):
for j in range(0, HEIGHT):
# compute coordinates
x = i * PIXEL_SIZE - WIDTH / 2 * PIXEL_SIZE
y = j * PIXEL_SIZE - WIDTH / 2 * PIXEL_SIZE
# retrieve height
height = heightmap[i][j]
# print obstacle
print('{x} {y} {sx} {sy} {sz} {d}'.format(
x=x,
y=y,
sx=PIXEL_SIZE,
sy=PIXEL_SIZE,
sz=height,
d=0.0 # infinite density
))
# a list of tuples (x, y, z, sx, sy, sz, angle)
obstacles = []
# add rocks
for i in range(0, NROCKS):
s = round(random.uniform(0.05, 0.2), 5)
while True:
x = round(random.uniform(-WIDTH/2.0+1, WIDTH/2.0-1) * PIXEL_SIZE, 5)
y = round(random.uniform(-HEIGHT/2.0+1, HEIGHT/2.0-1) * PIXEL_SIZE, 5)
# Safe zone
if abs(x) > 0.3 or abs(y) > 0.3:
break
z = max([
heightmap[int(x / PIXEL_SIZE + WIDTH / 2.0)][int(y / PIXEL_SIZE + HEIGHT / 2.0)],
heightmap[int((x + s) / PIXEL_SIZE + WIDTH / 2.0)][int(y / PIXEL_SIZE + HEIGHT / 2.0)],
heightmap[int((x - s) / PIXEL_SIZE + WIDTH / 2.0)][int(y / PIXEL_SIZE + HEIGHT / 2.0)],
heightmap[int(x / PIXEL_SIZE + WIDTH / 2.0)][int((y + s) / PIXEL_SIZE + HEIGHT / 2.0)],
heightmap[int(x / PIXEL_SIZE + WIDTH / 2.0)][int((y + s) / PIXEL_SIZE + HEIGHT / 2.0)],
]) + s / 2.0 - 0.1
# rocks are allowed to collide with other rocks
# add rock to obstacles list
obstacles.append({'x': x, 'y': y, 'z': z, 'sx': s, 'sy': s, 'sz': s, 'a': 0.0})
print('{x} {y} {z} {sx} {sy} {sz} {d}'.format(
x=x,
y=y,
z=z,
sx=s,
sy=s,
sz=s,
d=0.0
))
# add pebbles
for i in range(0, NPEBBLES):
while True:
s = round(random.uniform(0.02, 0.05), 5)
while True:
# pebbles are generated inside a pixel and at the center of the arena
xi = random.randint(int(PEBBLE_REGION*WIDTH) + 1, int((1-PEBBLE_REGION)*WIDTH-1))
yi = random.randint(int(PEBBLE_REGION*HEIGHT) + 1, int((1-PEBBLE_REGION)*HEIGHT-1))
x = round((xi - WIDTH/2) * PIXEL_SIZE + random.uniform(-PIXEL_SIZE/2+s, PIXEL_SIZE/2-s), 5)
y = round((yi - HEIGHT/2) * PIXEL_SIZE + random.uniform(-PIXEL_SIZE/2+s, PIXEL_SIZE/2-s), 5)
# Safe zone around robot
if abs(x) > 0.3 or abs(y) > 0.3:
break
z = heightmap[xi][int(yi)] + s / 2.0
# pebbles are not allowed to collide with rocks or other pebbles
colliding = False
for obstacle in obstacles:
if ((x - obstacle['x'])**2 + (y - obstacle['y'])**2) <= (s / 2.0 + obstacle['sx'] / 2.0)**2:
colliding = True
break
if not colliding: break
# add pebbles to obstacles list
obstacles.append({'x': x, 'y': y, 'z': z, 'sx': s, 'sy': s, 'sz': s, 'a': 0.0})
print('{x} {y} {z} {sx} {sy} {sz} {d}'.format(
x=x,
y=y,
z=z,
sx=s,
sy=s,
sz=s,
d=110.0
))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment