Skip to content

Commit

Permalink
Merged develop into branch
Browse files Browse the repository at this point in the history
  • Loading branch information
Kieran Ratcliffe committed Jan 9, 2024
2 parents 9cd9c22 + b98927f commit 37e916f
Show file tree
Hide file tree
Showing 58 changed files with 4,595 additions and 2,150 deletions.
44 changes: 44 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CI

on:
push:
branches:
- master
- develop
pull_request:
branches:
- "*"
types:
- opened
- reopened
- synchronize
- ready_for_review

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
- name: Install dependencies
run: |
$HOME/.local/bin/poetry install --without dev
- name: Run tests
env:
IAI_API_KEY: ${{ secrets.IAI_API_KEY }}
run: |
$HOME/.local/bin/poetry run pytest tests/
2 changes: 1 addition & 1 deletion .github/workflows/publish-to-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ jobs:
if: startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_API_TOKEN }}
password: ${{ secrets.PYPI_API_TOKEN }}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[pypi-badge]: https://badge.fury.io/py/invertedai.svg
[pypi-link]: https://pypi.org/project/invertedai/
[colab-badge]: https://colab.research.google.com/assets/colab-badge.svg
[colab-link]: https://colab.research.google.com/github/inverted-ai/invertedai/blob/develop/examples/IAI_demo.ipynb
[colab-link]: https://colab.research.google.com/github/inverted-ai/invertedai/blob/develop/examples/IAI_full_demo.ipynb
[rest-link]: https://app.swaggerhub.com/apis-docs/InvertedAI/InvertedAI
[examples-link]: https://github.com/inverted-ai/invertedai/tree/master/examples

Expand All @@ -15,7 +15,7 @@
<!-- start elevator-pitch -->
Inverted AI provides an API for controlling non-playable characters (NPCs) in autonomous driving simulations,
available as either a [REST API][rest-link] or a [Python SDK](https://docs.inverted.ai/en/latest/pythonapi/index.html), (and [C++ SDK](https://docs.inverted.ai/en/latest/cppapi/index.html)) built on top of it. Using the API requires an access key -
[contact us](mailto:sales@inverted.ai) to get yours. This page describes how to get started quickly. For more in-depth understanding,
create an account on our [user portal](https://www.inverted.ai/portal/login) to get one. New users are given keys preloaded with an API access budget; researcher users affiliated to academic institutions generally receive a sufficient amount of credits to conduct their research for free. This page describes how to get started quickly. For more in-depth understanding,
see the [API usage guide](https://docs.inverted.ai/en/latest/userguide.html), and detailed documentation for the [REST API][rest-link],
the [Python SDK](https://docs.inverted.ai/en/latest/pythonapi/index.html), and the [C++ SDK](https://docs.inverted.ai/en/latest/cppapi/index.html).
To understand the underlying technology and why it's necessary for autonomous driving simulations, visit the
Expand Down
11 changes: 7 additions & 4 deletions examples/carla/region_drive.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import sys
sys.path.append('../')

import argparse
import invertedai as iai
from invertedai.simulation.simulator import Simulation, SimulationConfig
from simulation.simulator import Simulation, SimulationConfig
import pathlib
import pygame
from tqdm import tqdm
Expand All @@ -17,7 +20,7 @@
parser.add_argument("-cap", "--quadtree_capacity", type=int, default=15)
parser.add_argument("-ad", "--agent_density", type=int, default=10)
parser.add_argument("-ri", "--re_initialization", type=int, default=30)
parser.add_argument("-len", "--simulation_length", type=int, default=10000)
parser.add_argument("-len", "--simulation_length", type=int, default=600)
args = parser.parse_args()


Expand All @@ -29,12 +32,12 @@

cfg = SimulationConfig(location=args.location, map_center=(response.map_center.x, response.map_center.y),
map_fov=response.map_fov, rendered_static_map=rendered_static_map,
map_width=response.map_fov+200, map_height=response.map_fov+200, agent_density=args.agent_density,
map_width=response.map_fov, map_height=response.map_fov, agent_density=args.agent_density,
initialize_stride=50, quadtree_capacity=args.quadtree_capacity,
re_initialization_period=args.re_initialization)
simulation = Simulation(cfg=cfg)

fps = 100
fps = 60
clock = pygame.time.Clock()
run = True
start = perf_counter()
Expand Down
2 changes: 1 addition & 1 deletion examples/simulation/regions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from simulation.utils import Rectangle, RE_INITIALIZATION_PERIOD, DEBUG
from typing import List, Optional, Callable
from random import randint
from invertedai import drive, async_drive
from invertedai.api.drive import drive, async_drive
from simulation.car import Car


Expand Down
7 changes: 6 additions & 1 deletion invertedai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@
dev = strtobool(os.environ.get("IAI_DEV", "false"))
if dev:
dev_url = os.environ.get("IAI_DEV_URL", "http://localhost:8000")
commercial_url = "https://api.inverted.ai/v0/aws/m1"
academic_url = "https://api.inverted.ai/v0/academic/m1"

log_level = os.environ.get("IAI_LOG_LEVEL", "WARNING")
log_console = strtobool(os.environ.get("IAI_LOG_CONSOLE", "true"))
log_file = strtobool(os.environ.get("IAI_LOG_FILE", "false"))
api_key = os.environ.get("IAI_API_KEY", "")


logger = IAILogger(level=log_level, consoel=bool(log_console), log_file=bool(log_file))

session = Session(api_key)
session = Session()
if api_key:
session.add_apikey(api_key)
add_apikey = session.add_apikey
use_mock_api = session.use_mock_api

Expand Down
63 changes: 35 additions & 28 deletions invertedai/api/drive.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,22 @@ class DriveResponse(BaseModel):
is_inside_supported_area: List[
bool
] #: For each agent, indicates whether the predicted state is inside supported area.
model_version: str # Model version used for this API call


@validate_arguments
def drive(
location: str,
agent_states: List[AgentState],
agent_attributes: List[AgentAttributes],
recurrent_states: List[RecurrentState],
traffic_lights_states: Optional[TrafficLightStatesDict] = None,
get_birdview: bool = False,
rendering_center: Optional[Tuple[float, float]] = None,
rendering_fov: Optional[float] = None,
get_infractions: bool = False,
random_seed: Optional[int] = None,
location: str,
agent_states: List[AgentState],
agent_attributes: List[AgentAttributes],
recurrent_states: List[RecurrentState],
traffic_lights_states: Optional[TrafficLightStatesDict] = None,
get_birdview: bool = False,
rendering_center: Optional[Tuple[float, float]] = None,
rendering_fov: Optional[float] = None,
get_infractions: bool = False,
random_seed: Optional[int] = None,
model_version: Optional[str] = None
) -> DriveResponse:
"""
Parameters
Expand All @@ -71,7 +73,8 @@ def drive(
agent_attributes:
Static attributes of all agents.
List of agent attributes. Each agent requires, length: [float]
width: [float] and rear_axis_offset: [float] all in meters.
width: [float] and rear_axis_offset: [float] all in meters. agent_type: [str],
currently supports 'car' and 'pedestrian'.
recurrent_states:
Recurrent states for all agents, obtained from the previous call to
Expand Down Expand Up @@ -99,17 +102,15 @@ def drive(
random_seed:
Controls the stochastic aspects of agent behavior for reproducibility.
model_version:
Optionally specify the version of the model. If None is passed which is by default, the best model will be used.
See Also
--------
:func:`initialize`
:func:`location_info`
:func:`light`
:func:`blame`
"""
if len(agent_states) != len(agent_attributes):
raise InvalidInput("Incompatible Number of Agents in either 'agent_states' or 'agent_attributes'.")
if len(agent_states) != len(recurrent_states):
raise InvalidInput("Incompatible Number of Agents in either 'agent_states' or 'recurrent_states'.")

if should_use_mock_api():
agent_states = [mock_update_agent_state(s) for s in agent_states]
Expand Down Expand Up @@ -144,7 +145,8 @@ def _tolist(input_data: List):
get_infractions=get_infractions,
random_seed=random_seed,
rendering_center=rendering_center,
rendering_fov=rendering_fov
rendering_fov=rendering_fov,
model_version=model_version
)
start = time.time()
timeout = TIMEOUT
Expand All @@ -170,33 +172,36 @@ def _tolist(input_data: List):
if response["infraction_indicators"]
else [],
is_inside_supported_area=response["is_inside_supported_area"],
model_version=response["model_version"]
)

return response
except APIConnectionError as e:
iai.logger.warning("Retrying")
if (
timeout is not None and time.time() > start + timeout
timeout is not None and time.time() > start + timeout
) or not e.should_retry:
raise e


@validate_arguments
async def async_drive(
location: str,
agent_states: List[AgentState],
agent_attributes: List[AgentAttributes],
recurrent_states: List[RecurrentState],
traffic_lights_states: Optional[TrafficLightStatesDict] = None,
get_birdview: bool = False,
rendering_center: Optional[Tuple[float, float]] = None,
rendering_fov: Optional[float] = None,
get_infractions: bool = False,
random_seed: Optional[int] = None,
location: str,
agent_states: List[AgentState],
agent_attributes: List[AgentAttributes],
recurrent_states: List[RecurrentState],
traffic_lights_states: Optional[TrafficLightStatesDict] = None,
get_birdview: bool = False,
rendering_center: Optional[Tuple[float, float]] = None,
rendering_fov: Optional[float] = None,
get_infractions: bool = False,
random_seed: Optional[int] = None,
model_version: Optional[str] = None
) -> DriveResponse:
"""
A light async version of :func:`drive`
"""

def _tolist(input_data: List):
if not isinstance(input_data, list):
return input_data.tolist()
Expand All @@ -216,7 +221,8 @@ def _tolist(input_data: List):
get_infractions=get_infractions,
random_seed=random_seed,
rendering_center=rendering_center,
rendering_fov=rendering_fov
rendering_fov=rendering_fov,
model_version=model_version,
)
response = await iai.session.async_request(model="drive", data=model_inputs)

Expand All @@ -237,6 +243,7 @@ def _tolist(input_data: List):
if response["infraction_indicators"]
else [],
is_inside_supported_area=response["is_inside_supported_area"],
model_version=response["model_version"]
)

return response

0 comments on commit 37e916f

Please sign in to comment.