Skip to content
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

rendering #92

Merged
merged 42 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a64cb49
create rendering module with pyglet, pygame renderer
luigiberducci Jul 24, 2023
d397039
setting up pygame renderer, too slow
luigiberducci Jul 24, 2023
31c3a07
add scaling resolution
luigiberducci Aug 31, 2023
beef2d5
add rendering config file,
luigiberducci Aug 31, 2023
dc99ed1
add rendering fps, not centered yet
luigiberducci Aug 31, 2023
bf7951c
create map renderer object,
luigiberducci Sep 1, 2023
f0891fd
add example with video recording,
luigiberducci Sep 1, 2023
bac7281
increase font size,
luigiberducci Sep 1, 2023
3eec14b
add rendering simulation timer, add zooming also in rgb_array mode
luigiberducci Sep 1, 2023
5bbd209
add info txt and parametrize agent to follow
luigiberducci Sep 1, 2023
a15f49c
update state of cars
luigiberducci Sep 1, 2023
179a099
use gymnasium wrapper to save video instead of moviepy,
luigiberducci Sep 1, 2023
f9e8c05
implement callbacks,
luigiberducci Sep 14, 2023
93ba5d8
black
luigiberducci Sep 14, 2023
d34a50f
remove dependency pyglet,
luigiberducci Sep 15, 2023
a1bfc46
create rendering module with pyglet, pygame renderer
luigiberducci Jul 24, 2023
24ab1f0
setting up pygame renderer, too slow
luigiberducci Jul 24, 2023
b2b0faf
add scaling resolution
luigiberducci Aug 31, 2023
4c4b25e
add rendering config file,
luigiberducci Aug 31, 2023
2c6f935
add rendering fps, not centered yet
luigiberducci Aug 31, 2023
8b5fb9f
create map renderer object,
luigiberducci Sep 1, 2023
b612133
add example with video recording,
luigiberducci Sep 1, 2023
90bf6a6
increase font size,
luigiberducci Sep 1, 2023
aa9d6f8
add rendering simulation timer, add zooming also in rgb_array mode
luigiberducci Sep 1, 2023
defb89f
add info txt and parametrize agent to follow
luigiberducci Sep 1, 2023
a7dea40
update state of cars
luigiberducci Sep 1, 2023
2fd4940
use gymnasium wrapper to save video instead of moviepy,
luigiberducci Sep 1, 2023
61b2b0f
implement callbacks,
luigiberducci Sep 14, 2023
935e447
black
luigiberducci Sep 14, 2023
3e80cd8
remove dependency pyglet,
luigiberducci Sep 15, 2023
5ef9428
complete rendering: add change pov, instructions, refactoring config …
luigiberducci Nov 24, 2023
0af1699
blackify
luigiberducci Nov 24, 2023
cacc6db
refactoring, typing, comments
luigiberducci Nov 24, 2023
28a9c2b
Merge remote-tracking branch 'origin/dev_rendering' into dev_rendering
luigiberducci Nov 24, 2023
7392f7e
example: close env in video recording to save trigger saving video.
luigiberducci Nov 24, 2023
f2b0c5f
remove dependency matplotlib
luigiberducci Nov 30, 2023
099cb86
remove dependency matplotlib
luigiberducci Nov 30, 2023
4f90fee
correct import pp,
luigiberducci Dec 15, 2023
979f3f2
remove print laptime, clean import, black
luigiberducci Dec 15, 2023
af0bb64
refactoring text objects
luigiberducci Dec 19, 2023
0dfa9a2
bugfix: video_recording.py, fix wrong order steer, speed action.
luigiberducci Dec 19, 2023
0540d83
Merge branch 'v1.0.0' into dev_rendering
luigiberducci Dec 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/random_trackgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def create_track():
assert i1 != -1
assert i2 != -1

track = track[i1: 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)
Expand Down
78 changes: 78 additions & 0 deletions examples/video_recording.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import time
import gymnasium as gym
import gymnasium.wrappers
import numpy as np

from waypoint_follow import PurePursuitPlanner


def main():
work = {
"mass": 3.463388126201571,
"lf": 0.15597534362552312,
"tlad": 0.82461887897713965,
"vgain": 1,
}

env = gym.make(
"f110_gym:f110-v0",
config={
"map": "Spielberg",
"num_agents": 1,
"timestep": 0.01,
"integrator": "rk4",
"control_input": "speed",
"model": "st",
"observation_config": {"type": "kinematic_state"},
"params": {"mu": 1.0},
},
render_mode="rgb_array",
)
env = gymnasium.wrappers.RecordVideo(env, f"video_{time.time()}")
track = env.unwrapped.track

planner = PurePursuitPlanner(track=track, wb=0.17145 + 0.15875)

poses = np.array(
[
[
track.raceline.xs[0],
track.raceline.ys[0],
track.raceline.yaws[0],
]
]
)

obs, info = env.reset(options={"poses": poses})
done = False

laptime = 0.0
start = time.time()

frames = [env.render()]
while not done and laptime < 15.0:
action = env.action_space.sample()
for i, agent_id in enumerate(obs.keys()):
speed, steer = planner.plan(
obs[agent_id]["pose_x"],
obs[agent_id]["pose_y"],
obs[agent_id]["pose_theta"],
work["tlad"],
work["vgain"],
)
action[i] = [steer, speed]

obs, step_reward, done, truncated, info = env.step(action)
laptime += step_reward

frame = env.render()
frames.append(frame)

print("Sim elapsed time:", laptime, "Real elapsed time:", time.time() - start)

# close env to trigger video saving
env.close()


if __name__ == "__main__":
main()
162 changes: 74 additions & 88 deletions examples/waypoint_follow.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import time
from typing import Tuple

import gymnasium as gym
import numpy as np
from numba import njit
from pyglet.gl import GL_POINTS


"""
Planner Helpers
Expand Down Expand Up @@ -183,6 +184,8 @@ def __init__(self, track, wb):
self.max_reacquire = 20.0

self.drawn_waypoints = []
self.lookahead_point = None
self.current_index = None

def load_waypoints(self, conf):
"""
Expand All @@ -195,32 +198,42 @@ def load_waypoints(self, conf):

def render_waypoints(self, e):
"""
update waypoints being drawn by EnvRenderer
Callback to render waypoints.
"""
points = self.waypoints[:, :2]
e.render_closed_lines(points, color=(128, 0, 0), size=1)

def render_lookahead_point(self, e):
"""
Callback to render the lookahead point.
"""
if self.lookahead_point is not None:
points = self.lookahead_point[:2][None] # shape (1, 2)
e.render_points(points, color=(0, 0, 128), size=2)

def render_local_plan(self, e):
"""
update waypoints being drawn by EnvRenderer
"""
if self.current_index is not None:
points = self.waypoints[self.current_index : self.current_index + 10, :2]
e.render_lines(points, color=(0, 128, 0), size=1)

scaled_points = 50.0 * points

for i in range(points.shape[0]):
if len(self.drawn_waypoints) < points.shape[0]:
b = e.batch.add(
1,
GL_POINTS,
None,
("v3f/stream", [scaled_points[i, 0], scaled_points[i, 1], 0.0]),
("c3B/stream", [183, 193, 222]),
)
self.drawn_waypoints.append(b)
else:
self.drawn_waypoints[i].vertices = [
scaled_points[i, 0],
scaled_points[i, 1],
0.0,
]

def _get_current_waypoint(self, waypoints, lookahead_distance, position, theta):
def _get_current_waypoint(
self, waypoints, lookahead_distance, position, theta
) -> Tuple[np.ndarray, int]:
"""
gets the current waypoint to follow
Returns the current waypoint to follow given the current pose.

Args:
waypoints: The waypoints to follow (Nx3 array)
lookahead_distance: The lookahead distance [m]
position: The current position (2D array)
theta: The current heading [rad]

Returns:
waypoint: The current waypoint to follow (x, y, speed)
i: The index of the current waypoint
"""
wpts = waypoints[:, :2]
lookahead_distance = np.float32(lookahead_distance)
Expand All @@ -231,61 +244,48 @@ def _get_current_waypoint(self, waypoints, lookahead_distance, position, theta):
position, lookahead_distance, wpts, t1, wrap=True
)
if i2 is None:
return None
return None, None
current_waypoint = np.empty((3,), dtype=np.float32)
# x, y
current_waypoint[0:2] = wpts[i2, :]
# speed
current_waypoint[2] = waypoints[i, -1]
return current_waypoint
return current_waypoint, i
elif nearest_dist < self.max_reacquire:
# NOTE: specify type or numba complains
return wpts[i, :]
return wpts[i, :], i
else:
return None
return None, None

def plan(self, pose_x, pose_y, pose_theta, lookahead_distance, vgain):
"""
gives actuation given observation
"""
position = np.array([pose_x, pose_y])
lookahead_point = self._get_current_waypoint(
lookahead_point, i = self._get_current_waypoint(
self.waypoints, lookahead_distance, position, pose_theta
)

if lookahead_point is None:
return 4.0, 0.0

# for rendering
self.lookahead_point = lookahead_point
self.current_index = i

# actuation
speed, steering_angle = get_actuation(
pose_theta, lookahead_point, position, lookahead_distance, self.wheelbase
pose_theta,
self.lookahead_point,
position,
lookahead_distance,
self.wheelbase,
)
speed = vgain * speed

return speed, steering_angle


class FlippyPlanner:
"""
Planner designed to exploit integration methods and dynamics.
For testing only. To observe this error, use single track dynamics for all velocities >0.1
"""

def __init__(self, speed=1, flip_every=1, steer=2):
self.speed = speed
self.flip_every = flip_every
self.counter = 0
self.steer = steer

def render_waypoints(self, *args, **kwargs):
pass

def plan(self, *args, **kwargs):
if self.counter % self.flip_every == 0:
self.counter = 0
self.steer *= -1
return self.speed, self.steer


def main():
"""
main entry point
Expand All @@ -296,7 +296,7 @@ def main():
"lf": 0.15597534362552312,
"tlad": 0.82461887897713965,
"vgain": 1,
} # 0.90338203837889}
}

env = gym.make(
"f110_gym:f110-v0",
Expand All @@ -312,40 +312,23 @@ def main():
},
render_mode="human",
)
track = env.unwrapped.track

planner = PurePursuitPlanner(
track=env.track, wb=0.17145 + 0.15875
) # FlippyPlanner(speed=0.2, flip_every=1, steer=10)

def render_callback(env_renderer):
# custom extra drawing function

e = env_renderer

# update camera to follow car
x = e.cars[0].vertices[::2]
y = e.cars[0].vertices[1::2]
top, bottom, left, right = max(y), min(y), min(x), max(x)
e.score_label.x = left
e.score_label.y = top - 700
e.left = left - 800
e.right = right + 800
e.top = top + 800
e.bottom = bottom - 800

planner.render_waypoints(env_renderer)

env.add_render_callback(render_callback)
planner = PurePursuitPlanner(track=track, wb=0.17145 + 0.15875)

poses = np.array(
[
[
env.track.raceline.xs[0],
env.track.raceline.ys[0],
env.track.raceline.yaws[0],
track.raceline.xs[0],
track.raceline.ys[0],
track.raceline.yaws[0],
]
]
)
env.unwrapped.add_render_callback(planner.render_waypoints)
env.unwrapped.add_render_callback(planner.render_local_plan)
env.unwrapped.add_render_callback(planner.render_lookahead_point)

obs, info = env.reset(options={"poses": poses})
done = False
env.render()
Expand All @@ -354,17 +337,20 @@ def render_callback(env_renderer):
start = time.time()

while not done:
agent_id = env.agent_ids[0]
speed, steer = planner.plan(
obs[agent_id]["pose_x"],
obs[agent_id]["pose_y"],
obs[agent_id]["pose_theta"],
work["tlad"],
work["vgain"],
)
obs, step_reward, done, truncated, info = env.step(np.array([[steer, speed]]))
action = env.action_space.sample()
for i, agent_id in enumerate(obs.keys()):
speed, steer = planner.plan(
obs[agent_id]["pose_x"],
obs[agent_id]["pose_y"],
obs[agent_id]["pose_theta"],
work["tlad"],
work["vgain"],
)
action[i] = np.array([steer, speed])

obs, step_reward, done, truncated, info = env.step(action)
laptime += step_reward
env.render()
frame = env.render()

print("Sim elapsed time:", laptime, "Real elapsed time:", time.time() - start)

Expand Down
3 changes: 1 addition & 2 deletions gym/f110_gym/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import gymnasium as gym

gym.register(
id="f110-v0",
entry_point="f110_gym.envs:F110Env",
id="f110-v0", entry_point="f110_gym.envs:F110Env",
)
2 changes: 2 additions & 0 deletions gym/f110_gym/envs/base_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ def __init__(
self.ego_idx = ego_idx
self.params = params
self.agent_poses = np.empty((self.num_agents, 3))
self.agent_steerings = np.empty((self.num_agents,))
self.agents = []
self.collisions = np.zeros((self.num_agents,))
self.collision_idx = -1 * np.ones((self.num_agents,))
Expand Down Expand Up @@ -503,6 +504,7 @@ def step(self, control_inputs):

# update sim's information of agent poses
self.agent_poses[i, :] = np.append(agent.state[0:2], agent.state[4])
self.agent_steerings[i] = agent.state[2]

# check collisions between all agents
self.check_collision()
Expand Down
6 changes: 3 additions & 3 deletions gym/f110_gym/envs/cubic_spline.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def calc_position(self, x):
i = self.__search_index(x)
dx = x - self.x[i]
position = (
self.a[i] + self.b[i] * dx + self.c[i] * dx**2.0 + self.d[i] * dx**3.0
self.a[i] + self.b[i] * dx + self.c[i] * dx ** 2.0 + self.d[i] * dx ** 3.0
)

return position
Expand All @@ -86,7 +86,7 @@ def calc_first_derivative(self, x):

i = self.__search_index(x)
dx = x - self.x[i]
dy = self.b[i] + 2.0 * self.c[i] * dx + 3.0 * self.d[i] * dx**2.0
dy = self.b[i] + 2.0 * self.c[i] * dx + 3.0 * self.d[i] * dx ** 2.0
return dy

def calc_second_derivative(self, x):
Expand Down Expand Up @@ -205,7 +205,7 @@ def calc_curvature(self, s):
ddx = self.sx.calc_second_derivative(s)
dy = self.sy.calc_first_derivative(s)
ddy = self.sy.calc_second_derivative(s)
k = (ddy * dx - ddx * dy) / ((dx**2 + dy**2) ** (3 / 2))
k = (ddy * dx - ddx * dy) / ((dx ** 2 + dy ** 2) ** (3 / 2))
return k

def calc_yaw(self, s):
Expand Down
Loading
Loading