Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
ba54e75
intial commit
bridgesign Jul 20, 2025
db649e8
Typing extension and ranged lookup
bridgesign Jul 21, 2025
06da5df
Bug in agent delete in record and logging. Add test to ensure coverage
bridgesign Jul 21, 2025
8e701c2
Changed sensors to accomodate sqlite engine
bridgesign Jul 21, 2025
a96ceb7
Added tests and updated failing scenarios
bridgesign Jul 23, 2025
2e61447
Update gamms/GraphEngine/graph_engine.py
bridgesign Jul 23, 2025
8c768cd
Update gamms/GraphEngine/graph_engine.py
bridgesign Jul 23, 2025
9ca8c49
Update gamms/GraphEngine/graph_engine.py
bridgesign Jul 23, 2025
114875b
No error raise. Use deafult error in sqlite del. Corrected angle wrap…
bridgesign Jul 23, 2025
8ec30df
Update gamms/SensorEngine/sensor_engine.py
bridgesign Jul 23, 2025
45ac621
Update gamms/SensorEngine/sensor_engine.py
bridgesign Jul 23, 2025
828c218
Revert agent sensor calculation. It was correct
bridgesign Jul 23, 2025
5bb91e4
Added tests. Corrected sensor engine "create_sensor" method
bridgesign Jul 28, 2025
bda2935
Extended agent to have custom orientation and added checks on imprope…
bridgesign Jul 31, 2025
518f329
Aerial agent with recording update. Extension in IAgent interface and…
bridgesign Jul 31, 2025
cb2ab50
three sensors for drones
jmalegaonkar Aug 1, 2025
3cf0bab
Sqlite graph (#63)
bridgesign Aug 2, 2025
fb674bc
sensors untested
jmalegaonkar Aug 3, 2025
b9597f7
Added tests. Corrected sensor engine "create_sensor" method
bridgesign Jul 28, 2025
68491fd
Merge branch 'unittest-dev' of https://github.com/GAMMSim/gamms into …
bridgesign Aug 3, 2025
acb71a5
Merge branch 'dev' into unittest-dev
bridgesign Aug 3, 2025
a4de747
Sqlite graph (#63)
bridgesign Aug 2, 2025
f63a48b
Merge branch 'unittest-dev' of https://github.com/GAMMSim/gamms into …
bridgesign Aug 3, 2025
77cc406
Repetition due to commit merge mess up
bridgesign Aug 3, 2025
359374e
Remove repetition
bridgesign Aug 3, 2025
51d9b59
Update tests/sensor_test.py
bridgesign Aug 3, 2025
3eb6ba9
Max_d should be infinity when failing to find close enough nodes
bridgesign Aug 4, 2025
8b8c6b3
Merge pull request #64 from GAMMSim/unittest-dev
jmalegaonkar Aug 8, 2025
ebf940a
Aerial agent visual (#65)
Brian-Jiang Aug 8, 2025
f458b2e
Aerial agent visual (#66)
Brian-Jiang Aug 14, 2025
ca6a257
No / in path. Windows issue
bridgesign Aug 22, 2025
405d950
Corrected Aerial Sensor typing and implementation. Testing remaining
bridgesign Aug 22, 2025
39ae4a0
Update of human input handling and aerial sensor default drawers
bridgesign Aug 22, 2025
dfc7750
Add agent before registering sensors. Otherwise error on aerial sensors
bridgesign Aug 25, 2025
52ac88d
Agent test suite and corrections in agent implementations or document…
bridgesign Sep 4, 2025
0abb314
Corrections is direction and cosine clipping
bridgesign Sep 4, 2025
113b367
Corrected tests for aerial agents
bridgesign Sep 4, 2025
254b161
Updated docs
bridgesign Sep 4, 2025
68d9e20
Merge branch 'dev' into aerial-agent
bridgesign Sep 4, 2025
c4110fe
wrong plugin option
bridgesign Sep 5, 2025
156d365
Agent orientation needs to be normalized before setting
bridgesign Sep 15, 2025
a16f7ed
Linetrsing creation isi pretty heavy. Optimize if it is not required.…
bridgesign Sep 16, 2025
fa39cda
Only warn when redefining custom sensor type. Change it in future ver…
bridgesign Sep 17, 2025
21f746a
Added license
bridgesign Sep 17, 2025
a00f26e
Merge branch 'main' into dev
bridgesign Sep 27, 2025
bcc9085
Deprecated setup.py
bridgesign Sep 27, 2025
4cc1137
Changes for release
bridgesign Sep 27, 2025
415c162
Added workflow
bridgesign Sep 27, 2025
a77057a
No branch required
bridgesign Sep 27, 2025
d971213
Remove setup.py
bridgesign Sep 27, 2025
28350ca
Merge branch 'main' into dev
bridgesign Sep 27, 2025
8a5898b
for vis
jmalegaonkar Oct 2, 2025
55c04b2
Merge branch 'dev' of https://github.com/GAMMSim/gamms into dev
jmalegaonkar Oct 2, 2025
21ecf13
Added artist API in docs
bridgesign Oct 7, 2025
6066e1c
Changed tempfile to dir for windows issue
bridgesign Oct 7, 2025
325ee65
Added font size for render_text
bridgesign Oct 7, 2025
fbeb1fb
Remove temp files
bridgesign Oct 7, 2025
ff975cd
Updated outdated parts in snippets
bridgesign Oct 8, 2025
80a6bb9
Correct async issue (#69)
bridgesign Oct 14, 2025
9e25f4d
Merge direct hot fixes from main to dev (#73)
bridgesign Feb 21, 2026
0cda5c4
Fix for graph cleanup. Patch update. cbor2 dependency changed
bridgesign Feb 21, 2026
e947abb
Enable WAL model sqlite. Optimize commits during adds
bridgesign Feb 21, 2026
5b6d954
Remove unrequired class vars
bridgesign Feb 21, 2026
4e40b61
Merge branch 'main' into dev
bridgesign Feb 24, 2026
8822e48
Artist updates #79 (#80)
mehulsinha73 Apr 24, 2026
ab2f770
Rendering optimization #78 (#81)
jinmin111 May 14, 2026
c6d118d
render images (#90)
mehulsinha73 May 19, 2026
881b053
memory engine occlusion (#83)
jmalegaonkar May 29, 2026
761f2ff
Release br (#91)
bridgesign May 29, 2026
f9dfe1e
Refactor GitHub Actions workflow for Python package
bridgesign May 29, 2026
bd4cb5c
dev based tests
bridgesign May 29, 2026
9e99e74
Install for testing
bridgesign May 29, 2026
7573524
Issue with dependency resolv
bridgesign May 29, 2026
287c3ed
Removed deprecated test API
bridgesign May 29, 2026
5effda0
I hatre python module loading
bridgesign May 29, 2026
a3c2d2c
Artist update (#92)
mehulsinha73 Jun 1, 2026
e7ee6e9
Refactor lazy loading function in __init__.py
bridgesign Jun 6, 2026
d51b29e
Merge branch 'main' into dev
bridgesign Jun 9, 2026
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
46 changes: 46 additions & 0 deletions .github/workflows/dev-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Dev Branch Test

on:
workflow_dispatch:
push:
branches:
- dev

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build
python -m pip install .

- name: Run tests
run: |
for file in tests/*_test.py; do python "$file"; done

- name: Build distributions
if: matrix.python-version == '3.13'
run: python -m build

- name: Upload build artifacts
if: matrix.python-version == '3.13'
uses: actions/upload-artifact@v4
with:
name: dev-dists
path: dist/
50 changes: 23 additions & 27 deletions .github/workflows/workflow.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
# This workflow will upload a Python Package to PyPI when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Upload Python Package

on:
Expand All @@ -16,55 +8,59 @@ permissions:
contents: read

jobs:
release-build:
test-and-build:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.x"
python-version: ${{ matrix.python-version }}

- name: Build release distributions
- name: Install build tools
run: |
# NOTE: put your own distribution build steps here.
python -m pip install --upgrade pip
python -m pip install build
python -m build
python -m pip install .

- name: Run tests
run: |
for file in tests/*_test.py; do python "$file"; done

- name: Build distributions
if: matrix.python-version == '3.13'
run: python -m build

- name: Upload distributions
if: matrix.python-version == '3.13'
uses: actions/upload-artifact@v4
with:
name: release-dists
path: dist/

pypi-publish:
runs-on: ubuntu-latest
needs:
- release-build
needs: test-and-build

permissions:
# IMPORTANT: this permission is mandatory for trusted publishing
id-token: write

# Dedicated environments with protections for publishing are strongly recommended.
# For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
environment:
name: pypi
# OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
# url: https://pypi.org/p/YOURPROJECT
#
# ALTERNATIVE: if your GitHub Release name is the PyPI project version string
# ALTERNATIVE: exactly, uncomment the following line instead:
# url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }}

steps:
- name: Retrieve release distributions
- name: Download distributions
uses: actions/download-artifact@v4
with:
name: release-dists
path: dist/

- name: Publish release distributions to PyPI
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
packages-dir: dist/
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,8 @@ cython_debug/

# Profile files
*.prof

# OS files
.DS_Store

.claude/
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# GAMMS v0.2.7
# GAMMS v1.0.0

GAMMS (Graph based Adversarial Multiagent Modelling Simulator) is a Python library designed for simulating large scale multi-agent scenarios on environments represented as graphs. The library is a framework which focuses on providing a flexible and extensible architecture to facilitate implementing interactions between agents and the environment as well as controlling the information flow between them. The library is geared towards easing development of high level scenario dynamics and testing agent behaviours rather than low level details like the actual physics of real world interactions. GAMMS tries to solve the following problems:

Expand Down Expand Up @@ -45,4 +45,17 @@ Detailed installation and setup instructions are available in the [Installation

# Documentation

The documentation is available at [GAMMS Documentation](https://gammsim.github.io/gamms/stable/). The documentation is generated using [mkdocs-materials](https://squidfunk.github.io/mkdocs-material/) with mike for versioning. You can do a local build by cloning the repository and serving the documentation using mkdocs. For new users, [Tutorials](https://gammsim.github.io/gamms/stable/tutorials) is a good place to start.
The documentation is available at [GAMMS Documentation](https://gammsim.github.io/gamms/stable/). The documentation is generated using [mkdocs-materials](https://squidfunk.github.io/mkdocs-material/) with mike for versioning. You can do a local build by cloning the repository and serving the documentation using mkdocs. For new users, [Tutorials](https://gammsim.github.io/gamms/stable/tutorials) is a good place to start.

# Citation

If you use GAMMS in your work, please cite the paper:

```bibtex
@article{patil2026gamms,
title={GAMMS: Graph based Adversarial Multiagent Modeling Simulator},
author={Patil, Rohan and Malegaonkar, Jai and Jiang, Xiao and Dion, Andre and Sukhatme, Gaurav S and Christensen, Henrik I},
journal={arXiv preprint arXiv:2602.05105},
year={2026}
}
```
4 changes: 2 additions & 2 deletions examples/base/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import math

# Visualization
vis_engine = gamms.visual.Engine.PYGAME
vis_engine = gamms.visual.Engine.NO_VIS

# The path to the graph file
location = "West Point, New York, USA"
location = "La Jolla, CA, USA"
resolution = 10.0
graph_path = 'graph.pkl'

Expand Down
93 changes: 93 additions & 0 deletions examples/moving_dot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""Minimal example of a non-agent dynamic artist moving between two fixed points."""

import gamms
from gamms.VisualizationEngine import Color, Shape
from gamms.VisualizationEngine.artist import Artist
from gamms.typing import ArtistType, IContext


START_POINT = (-8.0, 0.0)
END_POINT = (8.0, 0.0)
VIS_KWARGS = {}


def draw_moving_dot(ctx: IContext, data: dict):
start_x, start_y = data["start"]
end_x, end_y = data["end"]
alpha = data.get("_alpha")

x = (1.0 - alpha) * start_x + alpha * end_x
y = (1.0 - alpha) * start_y + alpha * end_y

ctx.visual.render_circle(
x,
y,
data.get("radius", 0.9),
data.get("color", Color.Red),
)


def draw_path_line(ctx: IContext, data: dict):
start_x, start_y = data["start"]
end_x, end_y = data["end"]
ctx.visual.render_line(
start_x,
start_y,
end_x,
end_y,
data.get("path_color", Color.LightGray),
width=data.get("width", 2),
)


def add_anchor(ctx: IContext, name: str, x: float, y: float, color):
anchor = Artist(ctx, Shape.Circle, 5)
anchor.data["x"] = x
anchor.data["y"] = y
anchor.data["radius"] = 0.6
anchor.data["color"] = color
anchor.set_artist_type(ArtistType.STATIC)
ctx.visual.add_artist(name, anchor)
return anchor


def add_path_line(ctx: IContext, name: str, start: tuple[float, float], end: tuple[float, float]):
path = Artist(ctx, draw_path_line, 15)
path.data["start"] = start
path.data["end"] = end
path.data["path_color"] = Color.LightGray
path.data["width"] = 2
path.set_artist_type(ArtistType.STATIC)
ctx.visual.add_artist(name, path)
return path


def main() -> None:
ctx = gamms.create_context(
vis_engine=gamms.visual.Engine.PYGAME,
vis_kwargs=VIS_KWARGS,
)

add_anchor(ctx, "start_anchor", START_POINT[0], START_POINT[1], Color.Blue)
add_anchor(ctx, "end_anchor", END_POINT[0], END_POINT[1], Color.Green)
add_path_line(ctx, "moving_dot_path", START_POINT, END_POINT)

moving_dot = Artist(ctx, draw_moving_dot, 20)
moving_dot.set_artist_type(ArtistType.DYNAMIC)
moving_dot.data["start"] = START_POINT
moving_dot.data["end"] = END_POINT
moving_dot.data["radius"] = 0.9
moving_dot.data["color"] = Color.Red
moving_dot.data["path_color"] = Color.LightGray
ctx.visual.add_artist("moving_dot", moving_dot)

while not ctx.is_terminated():
ctx.visual.simulate()
moving_dot.data["start"], moving_dot.data["end"] = moving_dot.data["end"], moving_dot.data["start"]

ctx.terminate()


if __name__ == "__main__":
main()

106 changes: 106 additions & 0 deletions examples/occlusion_game/ucsd_game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import gamms
from gamms import osm as gamms_osm

import math

LOCATION = "University of California San Diego, La Jolla, CA, USA"
RESOLUTION = 10.0
SENSOR_RANGE = 80.0
SENSOR_FOV = math.radians(360) # 120° cone

# ---------------------------------------------------------------------------
# Load graph
# ---------------------------------------------------------------------------
print("Fetching UCSD walk graph from OSM...")
G = gamms_osm.create_osm_graph(LOCATION, gamms_osm.OSMType.WALK, resolution=RESOLUTION)
print(f" {G.number_of_nodes()} nodes, {G.number_of_edges()} edges")

# ---------------------------------------------------------------------------
# Create context and attach graph
# ---------------------------------------------------------------------------
ctx = gamms.create_context(
graph_engine=gamms.graph.Engine.MEMORY,
vis_engine=gamms.visual.Engine.PYGAME,
vis_kwargs={"width": 1600, "height": 900},
)
ctx.graph.attach_networkx_graph(G)

# ---------------------------------------------------------------------------
# Load buildings
# ---------------------------------------------------------------------------
print("Fetching UCSD buildings from OSM (may take ~30s)...")
face_count = 0
for face in gamms_osm.obstacle_from_osm(LOCATION):
ctx.graph.add_obstacle_face(
face["face_id"],
tr=face["tr"],
tl=face["tl"],
br=face["br"],
bl=face["bl"],
type=face["type"],
)
face_count += 1
print(f" {face_count} building wall faces loaded")

# ---------------------------------------------------------------------------
# Sensors + agent
# ---------------------------------------------------------------------------
start_node = next(ctx.graph.graph.get_nodes())

ctx.sensor.create_sensor("neighbor", gamms.sensor.SensorType.NEIGHBOR)
ctx.sensor.create_sensor(
"arc",
gamms.sensor.SensorType.ARC,
sensor_range=SENSOR_RANGE,
fov=SENSOR_FOV,
)
ctx.sensor.create_sensor(
"occ_map",
gamms.sensor.SensorType.OCCLUDED_MAP,
sensor_range=SENSOR_RANGE,
fov=SENSOR_FOV,
)

ctx.agent.create_agent("player", sensors=["neighbor", "arc", "occ_map"], start_node_id=start_node)
ctx.sensor.get_sensor("arc").set_owner("player")
ctx.sensor.get_sensor("occ_map").set_owner("player")

# ---------------------------------------------------------------------------
# Visuals
# ---------------------------------------------------------------------------
ctx.visual.set_graph_visual()
ctx.visual.set_obstacle_visual()
ctx.visual.set_agent_visual("player", color="blue", size=10)
ctx.visual.set_sensor_visual("arc", node_color=(255, 200, 0), edge_color=(200, 160, 0))
ctx.visual.set_sensor_visual("occ_map", node_color=(0, 220, 220), edge_color=(0, 180, 180))

# ---------------------------------------------------------------------------
# Game loop
# ---------------------------------------------------------------------------
print("\n=== Game started ===\n")

turn = 0
while not ctx.is_terminated():
agent = ctx.agent.get_agent("player")
state = agent.get_state()

arc_data = state["sensor"]["arc"][1]
occ = state["sensor"]["occ_map"][1]
arc_nodes = arc_data.get("nodes", {})
vis_nodes = occ.get("nodes", {})
neighbors = state["sensor"]["neighbor"][1]
hidden = len(arc_nodes) - len(vis_nodes)

turn += 1
print(f"Turn {turn:>3} | node {agent.current_node_id:>6} "
f"| arc: {len(arc_nodes):>4} occluded: {len(vis_nodes):>4} hidden by buildings: {hidden:>4} "
f"| neighbors: {sorted(neighbors)}")

next_node = ctx.visual.human_input("player", state)
state["action"] = next_node
agent.set_state()

ctx.visual.simulate()

ctx.terminate()
print("Game over.")
Loading
Loading