RVO2 Library

repository·main·Indexed 21 days ago

https://github.com/snape/rvo2

A C++98 implementation of the Optimal Reciprocal Collision Avoidance (ORCA) algorithm for 2D environments. RVO2 enables smooth, collision-free motion for large groups of independent agents and static obstacles without explicit communication. The library features OpenMP parallelization for high-performance simulations and provides a public API via RVOSimulator, Vector2, and Line classes.

Tokens
3.9K
Snippets
9
Records
22
Agent score
76%

What's inside RVO2

  1. Overview of the RVO2 Library

    main

    RVO2 is a C++98 implementation of the Optimal Reciprocal Collision Avoidance (ORCA) algorithm in two dimensions. It is designed for scenarios where multiple independent mobile agents (like robots) must avoid collisions with each other and static obstacles in a shared workspace without explicit communication.

    Key features include:

    • ORCA Algorithm: Provides collision-free motion by assigning half the responsibility of avoiding pairwise collisions to each agent.
    • Efficiency: Reduces optimal action selection to solving low-dimensional linear programs, capable of handling thousands of agents in milliseconds.
    • Parallelization: Uses OpenMP to exploit multiple processors for efficient simulation.
    • Dynamic Control: The simulation is fully accessible and manipulable during runtime, allowing users to specify obstacles, agents, and preferred velocities step-by-step.
  2. How to use the RVO2 Library API

    main

    The RVO2 library provides a simple API for integration into third-party applications. To perform a simulation, a developer follows these conceptual steps:

    1. Define the Environment: Specify static obstacles in the workspace.
    2. Initialize Agents: Add agents to the simulation.
    3. Set Intentions: Specify the preferred velocities for each agent (the velocity the agent wants to have if no collisions were present).
    4. Step the Simulation: Perform the simulation step-by-step via library calls. The library computes collision-free velocities based on the current state and preferred velocities.
  3. Use OpenMP for parallel simulation

    main
    The RVO2 Library has optional support for OpenMP, an API for shared-memory parallel computing. Enabling OpenMP allows the library to parallelize simulation steps across available processors, improving performance.
  4. Identify the public API of RVO2 Library

    main

    The public API of the RVO2 Library is defined exclusively by the symbols declared in the src/RVO.h header file. This header provides the interfaces for the following core components:

    • RVOSimulator: The main simulation engine.
    • Vector2: A 2D vector class.
    • Line: A line segment class.

    Internal implementation details, such as Agent, KdTree, and Obstacle, are not part of the public API and should not be relied upon for direct integration.

  5. Understand RVO2 Library versioning and stability

    main

    The library follows Semantic Versioning 2.0.0.

    • API Stability: The public API is stable across patch and minor versions. Breaking changes are only introduced in new major versions.
    • ABI Stability: ABI compatibility is maintained across patch versions within the same major.minor release series. New major or minor versions may introduce ABI-breaking changes.
  6. Access RVO2 Library documentation

    main

    Documentation is available in several formats:

    • In-code Documentation: All features, parameters, and usage guides are documented using Doxygen markup within src/RVO.h and related headers.
    • Example Code: Three annotated example programs demonstrate typical usage patterns (agents, obstacles, and step-wise simulation):
      • examples/Blocks.cc
      • examples/Circle.cc
      • examples/Roadmap.cc
    • HTML Documentation: Can be generated from the source headers using CMake by setting the -DBUILD_DOCUMENTATION=ON flag.
  7. Configure the RVO2 development environment with Docker Compose

    main

    The compose.yaml file defines a dev service used to set up a development environment for the RVO2 library using Docker. It builds an image from the local Dockerfile and mounts the current directory to /workspace inside the container with a cached volume flag to optimize performance.

    services:
      dev:
        build:
          context: .
          dockerfile: Dockerfile
        volumes:
          - .:/workspace:cached
  8. Add agents to the simulation

    main

    You can add agents to the simulation using addAgent. If you use the version without specific parameters, the agent will inherit the default properties set during the RVOSimulator construction or via setAgentDefaults.

    Returns:

    • The unique number (ID) of the agent.
    • RVO::RVO_ERROR if the agent defaults have not been set or if an error occurs.

    Overloads:

    1. addAgent(const Vector2 &position)
    2. addAgent(const Vector2 &position, float neighborDist, std::size_t maxNeighbors, float timeHorizon, float timeHorizonObst, float radius, float maxSpeed)
    3. addAgent(const Vector2 &position, float neighborDist, std::size_t maxNeighbors, float timeHorizon, float timeHorizonObst, float radius, float maxSpeed, const Vector2 &velocity)
    // Add agent with default properties
    std::size_t agentId = sim.addAgent(RVO::Vector2(0, 0));
    
    // Add agent with specific properties
    std::size_t agentIdCustom = sim.addAgent(RVO::Vector2(5, 5), 10.0f, 10, 1.0f, 1.0f, 1.0f, 5.0f);
  9. Step the simulation

    main

    To advance the simulation in time, call doStep(). This updates the two-dimensional position and velocity of every agent in the simulation based on the current time step.

    // In your simulation loop
    while (running) {
        sim.doStep();
        // Update your visual representation using sim.getAgentPosition(id)
    }
  10. Query visibility between points

    main

    The queryVisibility method checks if two points are mutually visible given the current obstacles in the simulation.

    Overloads:

    1. queryVisibility(const Vector2 &point1, const Vector2 &point2): Returns true if the line segment between the points does not intersect any obstacles.
    2. queryVisibility(const Vector2 &point1, const Vector2 &point2, float radius): Returns true if the line segment between the points maintains at least the specified radius distance from all obstacles.

    Note: If processObstacles() has not been called yet, these methods return true by default.

    RVO::Vector2 p1(0, 0);
    RVO::Vector2 p2(10, 10);
    
    if (sim.queryVisibility(p1, p2)) {
        // Path is clear
    }
    
    if (sim.queryVisibility(p1, p2, 0.5f)) {
        // Path is clear with a safety buffer of 0.5 units
    }
  11. Add and process obstacles

    main

    Obstacles are defined by a list of vertices in a polygon.

    Adding Obstacles: Use addObstacle(const std::vector<Vector2> &vertices).

    • For a standard obstacle, list vertices in counterclockwise order.
    • To create a "negative" obstacle (like a bounding box for the environment), list vertices in clockwise order.
    • Returns the index of the first vertex, or RVO::RVO_ERROR if fewer than two vertices are provided.

    Crucial Step: After adding obstacles, you must call processObstacles() before the simulation will account for them in agent navigation.

    std::vector<RVO::Vector2> vertices;
    vertices.push_back(RVO::Vector2(10, 10));
    vertices.push_back(RVO::Vector2(10, 20));
    vertices.push_back(RVO::Vector2(20, 20));
    vertices.push_back(RVO::Vector2(20, 10));
    
    std::size_t obstacleId = sim.addObstacle(vertices);
    
    // Must call this to make obstacles active!
    sim.processObstacles();
  12. Use the Vector2 class for 2D math

    main
    The RVO::Vector2 class provides a standard implementation for 2D vectors, used for representing positions and velocities within the RVO2 library. It supports common vector arithmetic including addition, subtraction, scalar multiplication, and division, as well as dot products and normalization.