cartographer/common/lua_parameter_dictionary.h

Overview

LuaParameterDictionary provides a hierarchical configuration system using Lua scripts. It parses Lua files into a dictionary tree, supporting nested tables, type-safe value extraction, and file includes.

Class: cartographer::common::LuaParameterDictionary

Construction

// From Lua code string
static std::unique_ptr<LuaParameterDictionary> MakeLuaParameterDictionary(
    const std::string& code, const std::string& filename = "");

// From file (resolves includes)
static std::unique_ptr<LuaParameterDictionary> MakeLuaParameterDictionary(
    const std::string& filename,
    const std::vector<std::string>& search_paths);

Value Extraction

// Primitive types
bool GetBool(const std::string& key) const;
int GetInt(const std::string& key) const;
double GetDouble(const std::string& key) const;
std::string GetString(const std::string& key) const;

// Nested dictionary
std::unique_ptr<LuaParameterDictionary> GetDictionary(const std::string& key) const;

// Array of dictionaries
std::vector<std::unique_ptr<LuaParameterDictionary>> GetArray(
    const std::string& key) const;

// Check existence
bool HasKey(const std::string& key) const;

Iteration

// Get all keys
std::vector<std::string> GetKeys() const;

// For each key-value pair
void ForEach(const std::function<void(const std::string&, 
                                      LuaParameterDictionary*)>& callback) const;

Lua Configuration Format

Basic Values

-- config.lua
resolution = 0.05
max_range = 30.0
use_imu = true
sensor_frame = "laser"

Tables (Nested Dictionaries)

scan_matcher = {
  translation_weight = 10.0,
  rotation_weight = 40.0,
  ceres_solver_options = {
    max_num_iterations = 20,
    num_threads = 1,
  },
}

Arrays

-- Array of values
sensor_ids = {"laser", "imu", "odometry"}

-- Array of tables
trajectories = {
  {id = 1, sensor = "laser"},
  {id = 2, sensor = "velodyne"},
}

Includes

-- base.lua
common_params = {resolution = 0.05}

-- config.lua
include "base.lua"

MAP_BUILDER = {
  use_trajectory_builder_2d = true,
  pose_graph = POSE_GRAPH,  -- from included file
}

Configuration File Resolver

ConfigurationFileResolver handles file search paths and includes:

class ConfigurationFileResolver {
 public:
  explicit ConfigurationFileResolver(
      const std::vector<std::string>& configuration_files_directories);
  
  std::string GetFileContentOrDie(const std::string& filename);
  std::string GetFullPathOrDie(const std::string& filename);
};

Usage

// Set up resolver with config directories
std::vector<std::string> config_dirs = {"/etc/cartographer", "./config"};
auto resolver = std::make_unique<ConfigurationFileResolver>(config_dirs);

// Load main config file (resolves includes)
std::string lua_code = resolver->GetFileContentOrDie("my_robot.lua");

// Parse to dictionary
auto lua_dict = common::MakeLuaParameterDictionary(lua_code);

// Extract MapBuilder options
auto options = mapping::CreateMapBuilderOptions(lua_dict.get());

Type Conversion to Protobuf

Helper functions convert Lua dictionaries to protobuf options:

// In mapping/proto/*.proto options
proto::MapBuilderOptions CreateMapBuilderOptions(
    common::LuaParameterDictionary* parameter_dictionary);

proto::TrajectoryBuilderOptions CreateTrajectoryBuilderOptions(
    common::LuaParameterDictionary* parameter_dictionary);

proto::PoseGraphOptions CreatePoseGraphOptions(
    common::LuaParameterDictionary* parameter_dictionary);

These are defined in *_options.proto and implemented in corresponding *_options.cc files.

Error Handling

  • Missing keys → CHECK failure (crash)

  • Type mismatch → CHECK failure

  • File not found → CHECK failure in GetFileContentOrDie

Best practice: Provide all required keys with sensible defaults in base config files.

Example: Complete Configuration

-- my_robot.lua
include "trajectory_builder_2d.lua"
include "pose_graph.lua"

MAP_BUILDER = {
  use_trajectory_builder_2d = true,
  num_background_threads = 4,
  pose_graph = POSE_GRAPH,
}

TRAJECTORY_BUILDER_2D = {
  min_range = 0.1,
  max_range = 50.0,
  voxel_filter_size = 0.02,
  ceres_scan_matcher = {
    occupied_space_weight = 1.0,
    translation_weight = 10.0,
    rotation_weight = 40.0,
  },
}

See Also