Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
// 4. source ~/.scrimmage/setup.bash
// 5. scrimmage missions/straight-no-gui.xml
//
// To persist keys across reboots:
// macOS: ssh-add --apple-use-keychain ~/.ssh/id_rsa
// Linux: Add `AddKeysToAgent yes` to ~/.ssh/config
// Windows (PowerShell as Admin):
// Get-Service ssh-agent | Set-Service -StartupType Automatic -PassThru | Start-Service
// ssh-add $HOME\.ssh\id_rsa
//
{
"name": "SCRIMMAGE Dev Container",
"build": {
Expand All @@ -22,6 +29,11 @@
"containerEnv": {
"DISPLAY": "${localEnv:DISPLAY}"
},
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/sshd:1": {}
},
"initializeCommand": "ssh-add -l || true",
"customizations": {
"vscode": {
"extensions": [
Expand Down
61 changes: 25 additions & 36 deletions docs/source/tutorials/gen-entities.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,52 +99,41 @@ by adding an entity block key-value pair to the ``GenerateEntity`` message:
// Publish the GenerateEntity message
pub_gen_ents_->publish(msg);

Modify Plugin Parameters
------------------------

Before publishing the message, you can modify the XML attributes of specific plugins
by adding an entity plugin key-value-attr block to the ``GenerateEntity`` message:
Plugin-Specific Overrides Removed
---------------------------------

.. code-block:: c++
``GenerateEntity`` no longer supports overriding plugin XML attributes at runtime.
That API was removed as a breaking change because it encouraged external mutation of
parsed mission templates and made entity generation behavior hard to reason about.

// Modify the entity's plugin speed
auto autonomy_speed = msg->data.add_plugin_param();
autonomy_speed->set_plugin_type("autonomy0");
autonomy_speed->set_tag_name("speed");
autonomy_speed->set_tag_value("100")

Here the ``plugin_type`` represents the type of plugin, like ``motion_model``, ``autonomy`` (Note the
autonomy plugin is referenced as ``autonomy#`` by the GUI, where ``autonomy0`` is the first instance
and increments if there are multiple autonomy plugins in one entity), or ``controller``. The ``tag_name``
represents the plugin specific tag that should be updated, like ``speed`` for the Straight ``autonomy``
plugin. The ``tag_value`` represents the value of the corresponding plugin specific tag.

The above change in the plugin parameter for the ``GenerateEntity`` message does not affect
the stored parsed Mission XML plugin attribute value used by ``SimControl.cpp``. For example,
if the above block was only executed for a given conditional, entities without a block changing
their speed would default to the Mission XML defined speed.

Another way to generate entities with different plugin parameters involves either using multiple entity
blocks with different entity ``tags`` or creating new plugin XML files that have differently
configured default parameters. For example, you could copy and rename the ``Straight.xml`` file to
``MyStraight.xml`` and then modify the plugin parameters in ``MyStraight.xml``.
In your entity, you can load the ``MyStraight`` autonomy plugin by referencing it directly as long
as it is in your ``SCRIMMAGE_PLUGIN_PATH``:
If you need different plugin configurations at runtime, define separate entity
templates with different ``tag`` values. For example:

.. code-block:: xml

<entity tag="gen_my_straight">
<!-- Entity with default autonomy -->
<entity tag="gen_straight">
<count>0</count>
<autonomy>Straight</autonomy>
...
<autonomy>MyStraight</autonomy>
</entity>

<!-- Entity with custom autonomy -->
<entity tag="gen_my_straight">
<count>0</count>
<autonomy speed="30">MyStraight</autonomy>
...
</entity>

In your entity generation plugin, you can modify the ``autonomy`` tag before
publishing the ``GenerateEntity`` message:
Then select the appropriate template by setting ``entity_tag`` in your
``GenerateEntity`` message:

.. code-block:: c++

auto kv_autonomy = msg->data.add_entity_param();
kv_autonomy->set_key("autonomy");
kv_autonomy->set_value("MyStraight2"); // Load parameters from MyStraight2.xml
msg->data.set_entity_tag("gen_my_straight"); // Uses MyStraight autonomy

.. warning::

Attempting to override plugin names (``autonomy``, ``controller``,
``motion_model``, ``sensor``) via ``entity_param`` will be ignored and
produce a warning. Plugins are determined at mission parse time, not runtime.
6 changes: 1 addition & 5 deletions include/scrimmage/entity/Entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,8 @@ namespace scrimmage {

using Service = std::function<bool(scrimmage::MessageBasePtr, scrimmage::MessageBasePtr&)>;

typedef std::map<std::string, std::map<std::string, std::string>> AttributeMap;

struct EntityInitParams {
EntityInitParams() {};
AttributeMap overrides;
GPUControllerPtr gpu_controller;
GPUMotionModelPtr gpu_motion_model;
std::map<std::string, std::string> info;
Expand All @@ -87,8 +84,7 @@ class Entity : public std::enable_shared_from_this<Entity> {

bool parse_visual(
std::map<std::string, std::string>& info,
MissionParsePtr mp,
std::map<std::string, std::string>& overrides);
MissionParsePtr mp);

void close(double t);
void collision();
Expand Down
2 changes: 1 addition & 1 deletion include/scrimmage/entity/EntityPluginHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ template <class T>
boost::optional<std::shared_ptr<T>> make_autonomy(
const std::string& autonomy_name,
PluginManagerPtr plugin_manager,
std::map<std::string, std::string>& overrides,
const std::map<std::string, std::string>& overrides,
EntityPtr parent,
StatePtr state,
std::shared_ptr<std::unordered_map<int, int>>& id_to_team_map,
Expand Down
33 changes: 25 additions & 8 deletions include/scrimmage/parse/MissionParse.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@
#include "scrimmage/proto/Color.pb.h"
#include "scrimmage/proto/Visual.pb.h"

namespace sp = scrimmage_proto;

namespace scrimmage {

// Key 1: Entity Description XML ID
Expand Down Expand Up @@ -77,6 +75,20 @@ struct GenerateInfo {
double time_variance;
};

/// Structured metadata for entity plugins (autonomy, controller, sensor, motion_model)
struct EntityPluginInfo {
std::string name; ///< Actual plugin name (e.g., "Straight", "MotorSchemas")
std::string type; ///< Plugin type: "autonomy", "controller", "motion_model", "sensor"
int order = 0; ///< Execution order (0, 1, 2 for multiple plugins of same type)

/// Parameters from mission XML inline attributes (e.g., speed="21")
std::map<std::string, std::string> params;

int entity_block_id = -1; ///< Which entity block this came from
std::string entity_name; ///< <name>uav_entity</name> if present
std::string entity_tag; ///< tag="gen_straight" if present
};

class MissionParse {
public:
bool create_log_dir();
Expand Down Expand Up @@ -105,14 +117,18 @@ class MissionParse {
std::string log_dir();
std::string root_log_dir();

std::map<int, AttributeMap>& entity_attributes();

std::map<int, std::map<std::string, std::string>>& entity_params();

std::map<int, int>& ent_id_to_block_id();

EntityDesc_t& entity_descriptions();

/// Returns map<entity_block_id, map<plugin_key, EntityPluginInfo>> for all entity blocks
const std::map<int, std::map<std::string, EntityPluginInfo>>& all_entity_plugins() const;

/// Get plugins by type, ordered by execution order
std::vector<EntityPluginInfo> get_plugins_by_type(int entity_block_id, const std::string& type) const;

std::map<std::string, int>& entity_tag_to_id();

bool enable_gui();
Expand Down Expand Up @@ -190,17 +206,18 @@ class MissionParse {

std::map<int, TeamInfo> team_info_;

std::map<int, AttributeMap> entity_attributes_;
std::map<int, std::map<std::string, std::string>> entity_params_;

// Key: Entity ID
// Value: XML "entity" block used to create entity
// This can be used to find the key for which entity_attributes_ maps to
// the entity XML block.
// Value: XML "entity" block ID used to create entity
// Maps runtime entity IDs to their source entity_plugins_ block ID.
std::map<int, int> ent_id_to_block_id_;

EntityDesc_t entity_descs_;

/// Key: entity block ID, Value: map of plugin key (type:name) to EntityPluginInfo
std::map<int, std::map<std::string, EntityPluginInfo>> entity_plugins_;

bool use_exact_log_path_;
std::string root_log_dir_;
std::string log_dir_;
Expand Down
130 changes: 130 additions & 0 deletions include/scrimmage/parse/MissionValidation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*!
* @file
*
* @section LICENSE
*
* Copyright (C) 2017 by the Georgia Tech Research Institute (GTRI)
*
* This file is part of SCRIMMAGE.
*
* SCRIMMAGE is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* SCRIMMAGE is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SCRIMMAGE. If not, see <http://www.gnu.org/licenses/>.
*
* @author Ethan M Boos <[email protected]>
* @date 06 April 2026
* @version 0.1.0
* @brief Brief file description.
* @section DESCRIPTION
* A Long description goes here.
*
*/

#ifndef INCLUDE_SCRIMMAGE_PARSE_MISSIONVALIDATION_H_
#define INCLUDE_SCRIMMAGE_PARSE_MISSIONVALIDATION_H_

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

namespace scrimmage {

// Maps plugin directory names to internal type names.
// Update here if plugin types are added or renamed.
inline const std::map<std::string, std::string> kPluginDirToType = {
{"autonomy", "autonomy"},
{"controller", "controller"},
{"motion", "motion_model"},
{"sensor", "sensor"},
{"interaction", "entity_interaction"},
{"metrics", "metrics"},
{"network", "network"}
};

// Entity-level plugin types (attached to specific entities, not global).
inline const std::set<std::string> kEntityPluginTypes = {
"autonomy", "controller", "motion_model", "sensor"
};

class FileSearch;
class MissionParse;

struct ValidationError {
enum class Type {
PLUGIN_CONFIG_NOT_FOUND,
PLUGIN_LIBRARY_NOT_FOUND,
PLUGIN_LIBRARY_INVALID,
UNKNOWN_PLUGIN_TYPE
};

Type type;
std::string plugin_name;
std::string plugin_type; // autonomy, controller, motion_model, etc.
std::string context; // location in mission file (entity block index or "global")
std::string message;
std::vector<std::string> suggestions;
};

struct PluginValidationInfo {
enum class Status {
unknown,
valid,
config_not_found,
};

Status status = Status::unknown;
std::string config_xml_path;
std::vector<std::string> suggestions;
};

struct ValidationResult {
bool valid() const { return errors.empty(); }
std::vector<ValidationError> errors;
std::map<std::string, std::set<std::string>> available_plugins;
std::map<int, std::map<std::string, PluginValidationInfo>> entity_plugin_diagnostics;
};

class MissionValidation {
public:
ValidationResult validate(
const std::shared_ptr<MissionParse>& mp,
FileSearch& file_search);

void print_errors(
const ValidationResult& result,
const std::string& mission_filename) const;

void set_verbose(bool verbose) { verbose_ = verbose; }

protected:
std::map<std::string, std::set<std::string>> discover_plugins_by_type(
const std::string& env_var,
FileSearch& file_search);

std::vector<std::string> find_similar(
const std::string& name,
const std::set<std::string>& available,
size_t max_suggestions = 3) const;

size_t levenshtein_distance(
const std::string& s1,
const std::string& s2) const;

private:
bool verbose_ = false;
};

} // namespace scrimmage

#endif // INCLUDE_SCRIMMAGE_PARSE_MISSIONVALIDATION_H_
59 changes: 0 additions & 59 deletions include/scrimmage/plugins/metrics/OpenAIRewards/OpenAIRewards.h

This file was deleted.

Loading