Access config from within an attribute set in an option

I have some config options and some default values in them. Some of the default values depend on other options, like context depends on mmsi. For the context option this works fine, but I also want to use the same trick with the revolution and torque option. These are part of an attribute set and I don’t know how to reference the values they depend on. Any ideas how to achieve this?

{ config, lib, ... }:
let
  cfg = config.vessel;
  pi = 3.14159265359;
  engine = with lib.types;
    submodule {
      options = {
        power = lib.mkOption {
          type = with lib.types; ints.unsigned;
          default = 0;
          example = 800000;
          description = "Maximum power [W] on the output shaft of the engine.";
        };
        rpm = lib.mkOption {
          type = with lib.types; ints.unsigned;
          default = 0;
          example = 1800;
          description =
            "Maximum rotations per minute [rpm] on the output shaft of the engine. If this value is greater than 0 it will be used to calculate revolutions.";
        };
        revolutions = lib.mkOption {
          type = with lib.types; float;
          default = cfg.engines.dontknow.speed / 60.0; # this is not working
          example = 30.0;
          description =
            "Maximum revolutions [Hz] on the output shaft of the engine.";
        };
        reduction = lib.mkOption {
          type = with lib.types; float;
          default = 1.0;
          example = 4.5;
          description = "Reduction of the gearbox.";
        };
        torque = lib.mkOption {
          type = with lib.types; float;
          default = cfg.engines.dontknow.power / ((cfg.engines.dontknow.revolutions / cfg.engines.dontknow.reduction) * 2 * pi); # this is not working
          example = 0.0;
          description =
            "Torque [Nm] on the shaft after the gearbox reduction. If not specified this value is calculated from power, revolutions and reduction.";
        };
        inverseDirection =
          lib.mkEnableOption "Inverse the direction of the rotation.";
      };
    };
in {
  options.vessel = rec {
    mmsi = lib.mkOption {
      type = with lib.types; str;
      example = "244770688";
      description = "The MMSI number of the vessel.";
    };
    context = lib.mkOption {
      type = with lib.types; str;
      example = "vessels.urn:mrn:imo:mmsi:244770688";
      default = "vessels.urn:mrn:imo:mmsi:${cfg.mmsi}";
      description = "The context for SignalK.";
    };
    engines = lib.mkOption {
      type = with lib.types; attrsOf engine;
      default = { };
      example = lib.literalExpression ''
        {
          "propulsion.mainEnginePort" = {
            power = 1400000;
            rpm = 1800;
            reduction = 5.2;
          };
          "propulsion.mainEngineStarboard" = {
            power = 1175000;
            rpm = 1600;
            reduction = 5.2;
          };
        };      
      '';
      description = "Attribute set with engine names and their specs.";
    };
  };
}

The actual config will look like this:

  vessel = {
    mmsi = "245231000";
    engines = {
      "propulsion.mainEnginePort" = {
        power = 1400000;
        rpm = 1800;
        reduction = 5.2;
      };
      "propulsion.mainEngineStarboard" = {
        power = 1175000;
        rpm = 1600;
        reduction = 5.2;
      };
    };
  };

Any module can be either an attribute set (as in your code) or a function returning an attribute set, this way you can use:

submodule({config, ...}: {
   options = {
      // you can use config here to refer to this submodule values.
   };
})

Thanks, works like a charm!