menu
info Documentation

Custom Model Example

The complete code description of the generic ElectricalPowerSystem is shown below. It shows all the basic structural components used to create a custom component.

namespace D2S2.Model.Satellite
{
    public class ElectricalPowerSystem : SatellitePhysicalComponent, IInitialisable
    {
        private double powerIn = 0.0;
        private double powerOut = 0.0;

        private double currentBatteryPower = 0.0;
        private double initialBatteryPower = 0.0;
        private double maximumPowerStorage = 22.5;
        private double powUsage = 0;

        // ---------- array properties for dependent object binding --------------
        private ModelList<D2S2.Model.Satellite.SolarPanel> solarPanels;
        private ModelList<D2S2.Model.Satellite.SatelliteElectricalComponent> consumers;
 
        [ModelDependency(DependencyType.Link, false)]
        [Description("List of all power generating components")]
        public ModelList<D2S2.Model.Satellite.SolarPanel> SolarPanels { get { return solarPanels; } }

        [ModelDependency(DependencyType.Link, false)]
        [Description("List of all power consuming components")]
        public ModelList<D2S2.Model.Satellite.SatelliteElectricalComponent> PowerConsumers { get { return consumers; } }

        // ------------- read-only properties for exposing model state -----------------
        [ModelValue(ModelValueType.State)]
        [DisplayName("Generated Power")]
        [Description("Total power generated [W]")]
        [Category("Measurement")]
        public UDouble<W> PowerInUnit { get { return new UDouble<W>(powerIn); } }

        [ModelValue(ModelValueType.State)]
        [DisplayName("Consumed Power")]
        [Description("Total power consumption [W]")]
        [Category("Measurement")]
        public UDouble<W> PowerOutUnit { get { return new UDouble<W>(powerOut); } }

        [ModelValue(ModelValueType.State)]
        [DisplayName("Battery Capacity")]
        [Description("Current capacity of the battery [W.hr]")]
        [Category("Measurement")]
        public UDouble<Whr> CurrentBatteryPower { get { return new UDouble<Whr>(currentBatteryPower); } }

        // ------------- adjustable/input properties -----------------

        [ModelValue(ModelValueType.Initial)]
        [DisplayName("Maximum Energy Storage")]
        [Category("Battery Settings")]
        [Description("Maximum energy storage capacity of batteries [W.hr]")]
        public double MaximumPowerStorage 
        { 
            get 
            { 
                return maximumPowerStorage; 
            }
            set
            {
                maximumPowerStorage = value; 
                OnPropertyValueChanged(GetProperty((ElectricalPowerSystem m) => m.MaximumPowerStorage)); 
            }
        }

        [ModelValue(ModelValueType.Initial)]
        [DisplayName("Initial Battery Energy")]
        [Category("Battery Settings")]
        [Description("Initial energy stored in batteries [W.hr]")]
        public double InitialPowerStorage
        { 
            get 
            { 
                return initialBatteryPower; 
            }
            set
            {
                initialBatteryPower = value; 
                OnPropertyValueChanged(GetProperty((ElectricalPowerSystem m) => m.InitialPowerStorage)); 
            }
        }

        [ModelValue(ModelValueType.Initial)]
        [Category("Parameters")]
        [DisplayName("Power Usage")]
        [Description("Power usage [W]")]
        public double PowerUsage
        { 
            get 
            { 
                return powUsage; 
            }
            set
            {
                powUsage = value; 
                OnPropertyValueChanged(GetProperty((ElectricalPowerSystem m) => m.PowerUsage)); 
            }
        }

        public ElectricalPowerSystem()
        {
            solarPanels = new ModelList<SolarPanel>(OnLinkDependencyChanged, GetProperty((ElectricalPowerSystem m) => m.SolarPanels));
            consumers = new ModelList<SatelliteElectricalComponent>(OnLinkDependencyChanged, GetProperty((ElectricalPowerSystem m) => m.PowerConsumers));
        }

        public void Initialise(DateTime time)
        {
            currentBatteryPower = initialBatteryPower;
            if (currentBatteryPower > maximumPowerStorage)
                currentBatteryPower = maximumPowerStorage;

            powerIn = 0;
            powerOut = 0;
        }

        public override Vector3d GetForce(SatelliteEnvironmentState environment)
        {
            return Vector3d.Zero;
        }

        public override Vector3d GetTorque(SatelliteEnvironmentState environment)
        {
            return Vector3d.Zero;
        }

        public override void UpdateEnvironment(DateTime time, SatelliteEnvironmentState environment, SatelliteKinematicState state, SurfaceModel surfaceModel)
        {
            base.UpdateEnvironment(time, environment, state, surfaceModel);

            // if satellite is in sunlit part of orbit query the current power generated by all connected solar panels
            if (!environment.SunLit)
            {
                powerIn = 0;
            }
            else
            {
                powerIn = 0;
                for (int i = 0; i < SolarPanels.Count; i++)
                {
                    powerIn += SolarPanels[i].GetPowerGenerated();
                }
            }

            // power consumption of EPS itself
            powerOut = PowerUsage;
            // Go through all satellite components and request their power usage (have a list of all power consumers, electrical satellite components)
            for (int i = 0; i < PowerConsumers.Count; i++)
            {
                powerOut += PowerConsumers[i].GetPowerConsumption();
            }
        }

        public override void UpdateEnd(TimeSpan timeDelta)
        {
            base.UpdateEnd(timeDelta);

            // Simplified battery model, simply determine the maximum power density, use simple integration
            currentBatteryPower += timeDelta.TotalHours * (powerIn - powerOut);

            // Set battery storage limits
            if (currentBatteryPower > maximumPowerStorage)
            {
                currentBatteryPower = maximumPowerStorage;
            }
            else if (currentBatteryPower < 0)
            {
                currentBatteryPower = 0;
            }
        }
    }
}