Skip to content

Commit

Permalink
Add nav_types.py and extract GlobalRoute class
Browse files Browse the repository at this point in the history
  • Loading branch information
ll7 committed Mar 25, 2024
1 parent 9c62038 commit b121981
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 112 deletions.
99 changes: 99 additions & 0 deletions robot_sf/nav/gloabal_route.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@

from typing import List, Tuple
from math import dist


from dataclasses import dataclass

from robot_sf.nav.nav_types import Vec2D, Rect

@dataclass
class GlobalRoute:
"""
A class to represent a global route.
Attributes
----------
spawn_id : int
The id of the spawn point.
goal_id : int
The id of the goal point.
waypoints : List[Vec2D]
The waypoints of the route.
spawn_zone : Rect
The spawn zone of the route.
goal_zone : Rect
The goal zone of the route.
Methods
-------
__post_init__():
Validates the spawn_id, goal_id, and waypoints.
sections():
Returns the sections of the route.
section_lengths():
Returns the lengths of the sections.
section_offsets():
Returns the offsets of the sections.
total_length():
Returns the total length of the route.
"""

spawn_id: int
goal_id: int
waypoints: List[Vec2D]
spawn_zone: Rect
goal_zone: Rect

def __post_init__(self):
"""
Validates the spawn_id, goal_id, and waypoints.
Raises a ValueError if spawn_id or goal_id is less than 0 or if waypoints is empty.
"""

if self.spawn_id < 0:
raise ValueError('Spawn id needs to be an integer >= 0!')
if self.goal_id < 0:
raise ValueError('Goal id needs to be an integer >= 0!')
if len(self.waypoints) < 1:
raise ValueError(f'Route {self.spawn_id} -> {self.goal_id} contains no waypoints!')

@property
def sections(self) -> List[Tuple[Vec2D, Vec2D]]:
"""
Returns the sections of the route as a list of tuples, where each tuple
contains two Vec2D objects
representing the start and end points of the section.
"""

return [] if len(self.waypoints) < 2 else list(zip(self.waypoints[:-1], self.waypoints[1:]))

@property
def section_lengths(self) -> List[float]:
"""
Returns the lengths of the sections as a list of floats.
"""

return [dist(p1, p2) for p1, p2 in self.sections]

@property
def section_offsets(self) -> List[float]:
"""
Returns the offsets of the sections as a list of floats.
"""

lengths = self.section_lengths
offsets = []
temp_offset = 0.0
for section_length in lengths:
offsets.append(temp_offset)
temp_offset += section_length
return offsets

@property
def total_length(self) -> float:
"""
Returns the total length of the route as a float.
"""

return 0 if len(self.waypoints) < 2 else sum(self.section_lengths)
104 changes: 6 additions & 98 deletions robot_sf/nav/map_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
import os
import json
import random
from math import sqrt, dist
from typing import List, Tuple, Union, Dict
from math import sqrt
from typing import List, Union, Dict
from dataclasses import dataclass, field

import numpy as np

Vec2D = Tuple[float, float]
Line2D = Tuple[float, float, float, float]
Rect = Tuple[Vec2D, Vec2D, Vec2D]
from robot_sf.nav.gloabal_route import GlobalRoute
from robot_sf.nav.nav_types import Vec2D, Line2D, Rect


@dataclass
Expand Down Expand Up @@ -41,7 +40,8 @@ class Obstacle:

def __post_init__(self):
"""
Validates and processes the vertices to create the lines and vertices_np attributes.
Validates and processes the vertices to create the lines and vertices_np
attributes.
Raises a ValueError if no vertices are specified.
"""

Expand All @@ -66,98 +66,6 @@ def __post_init__(self):
print('WARNING: obstacle is just a single point that cannot collide!')


@dataclass
class GlobalRoute:
"""
A class to represent a global route.
Attributes
----------
spawn_id : int
The id of the spawn point.
goal_id : int
The id of the goal point.
waypoints : List[Vec2D]
The waypoints of the route.
spawn_zone : Rect
The spawn zone of the route.
goal_zone : Rect
The goal zone of the route.
Methods
-------
__post_init__():
Validates the spawn_id, goal_id, and waypoints.
sections():
Returns the sections of the route.
section_lengths():
Returns the lengths of the sections.
section_offsets():
Returns the offsets of the sections.
total_length():
Returns the total length of the route.
"""

spawn_id: int
goal_id: int
waypoints: List[Vec2D]
spawn_zone: Rect
goal_zone: Rect

def __post_init__(self):
"""
Validates the spawn_id, goal_id, and waypoints.
Raises a ValueError if spawn_id or goal_id is less than 0 or if waypoints is empty.
"""

if self.spawn_id < 0:
raise ValueError('Spawn id needs to be an integer >= 0!')
if self.goal_id < 0:
raise ValueError('Goal id needs to be an integer >= 0!')
if len(self.waypoints) < 1:
raise ValueError(f'Route {self.spawn_id} -> {self.goal_id} contains no waypoints!')

@property
def sections(self) -> List[Tuple[Vec2D, Vec2D]]:
"""
Returns the sections of the route as a list of tuples, where each tuple
contains two Vec2D objects
representing the start and end points of the section.
"""

return [] if len(self.waypoints) < 2 else list(zip(self.waypoints[:-1], self.waypoints[1:]))

@property
def section_lengths(self) -> List[float]:
"""
Returns the lengths of the sections as a list of floats.
"""

return [dist(p1, p2) for p1, p2 in self.sections]

@property
def section_offsets(self) -> List[float]:
"""
Returns the offsets of the sections as a list of floats.
"""

lengths = self.section_lengths
offsets = []
temp_offset = 0.0
for section_length in lengths:
offsets.append(temp_offset)
temp_offset += section_length
return offsets

@property
def total_length(self) -> float:
"""
Returns the total length of the route as a float.
"""

return 0 if len(self.waypoints) < 2 else sum(self.section_lengths)


@dataclass
class MapDefinition:
"""
Expand Down
8 changes: 8 additions & 0 deletions robot_sf/nav/nav_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from typing import Tuple

Vec2D = Tuple[float, float]
Line2D = Tuple[float, float, float, float]
Rect = Tuple[Vec2D, Vec2D, Vec2D]
# TODO: Is there a difference between a Rect and a Zone?
# rect ABC with sides |A B|, |B C| and diagonal |A C|
Zone = Tuple[Vec2D, Vec2D, Vec2D]
6 changes: 2 additions & 4 deletions robot_sf/nav/navigation.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
from random import sample, randint
from math import dist, atan2
from dataclasses import dataclass, field
from typing import List, Tuple, Optional
from typing import List, Optional

from robot_sf.nav.map_config import MapDefinition
from robot_sf.ped_npc.ped_zone import sample_zone

Vec2D = Tuple[float, float]
Zone = Tuple[Vec2D, Vec2D, Vec2D]
from robot_sf.nav.nav_types import Vec2D


@dataclass
Expand Down
6 changes: 2 additions & 4 deletions robot_sf/ped_npc/ped_behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@
- Pedestrian groups can be assigned to follow a route or to move around a crowded zone
"""
from math import dist
from typing import List, Dict, Tuple, Protocol
from typing import List, Dict, Protocol
from dataclasses import dataclass, field

from robot_sf.nav.map_config import GlobalRoute
from robot_sf.nav.navigation import RouteNavigator
from robot_sf.ped_npc.ped_zone import sample_zone
from robot_sf.ped_npc.ped_grouping import PedestrianGroupings

Vec2D = Tuple[float, float]
Zone = Tuple[Vec2D, Vec2D, Vec2D]
from robot_sf.nav.nav_types import Zone


class PedestrianBehavior(Protocol):
Expand Down
3 changes: 1 addition & 2 deletions robot_sf/ped_npc/ped_population.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
from robot_sf.ped_npc.ped_behavior import \
PedestrianBehavior, CrowdedZoneBehavior, FollowRouteBehavior
from robot_sf.ped_npc.ped_zone import sample_zone
from robot_sf.nav.nav_types import Vec2D, Zone

PedState = np.ndarray
PedGrouping = Set[int]
Vec2D = Tuple[float, float]
Zone = Tuple[Vec2D, Vec2D, Vec2D] # rect ABC with sides |A B|, |B C| and diagonal |A C|
ZoneAssignments = Dict[int, int]


Expand Down
6 changes: 2 additions & 4 deletions robot_sf/ped_npc/ped_zone.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from typing import List, Tuple
from typing import List
import numpy as np

Vec2D = Tuple[float, float]
Zone = Tuple[Vec2D, Vec2D, Vec2D] # rect ABC with sides |A B|, |B C| and diagonal |A C|

from robot_sf.nav.nav_types import Vec2D, Zone

def sample_zone(zone: Zone, num_samples: int) -> List[Vec2D]:
"""
Expand Down

0 comments on commit b121981

Please sign in to comment.