/// <summary> /// An override of the Subsystem CanPerform method /// </summary> /// <param name="proposedEvent"></param> /// <param name="environment"></param> /// <returns></returns> public override bool CanPerform(Event proposedEvent, Universe environment) { if (base.CanPerform( proposedEvent, environment) == false) return false; //double timetoslew = (rand()%5)+8; double timetoslew = _timetoslew; double es = proposedEvent.GetEventStart(Asset); double ts = proposedEvent.GetTaskStart(Asset); double te = proposedEvent.GetTaskEnd(Asset); if (es + timetoslew > ts) { if (es + timetoslew > te) { // TODO: Change this to Logger //Console.WriteLine("ADCS: Not enough time to slew event start: "+ es + "task end" + te); return false; } else ts = es + timetoslew; } // from Brown, Pp. 99 DynamicState position = Asset.AssetDynamicState; Matrix<double> m_SC_pos_at_ts_ECI = position.PositionECI(ts); Matrix<double> m_target_pos_at_ts_ECI = _task.Target.DynamicState.PositionECI(ts); Matrix<double> m_pv = m_target_pos_at_ts_ECI - m_SC_pos_at_ts_ECI; // set state data _newState.SetProfile(POINTVEC_KEY, new HSFProfile<Matrix<double>>(ts, m_pv)); proposedEvent.SetTaskStart(Asset, ts); return true; }
public override bool CanPerform( Event proposedEvent, Universe environment) { if (!base.CanPerform( proposedEvent, environment)) return false; DynamicState position = Asset.AssetDynamicState; Matrix<double> assetPosECI = position.PositionECI(proposedEvent.GetTaskStart(Asset)); Matrix<double> targetPosECI = _task.Target.DynamicState.PositionECI(proposedEvent.GetTaskStart(Asset)); return GeometryUtilities.hasLOS(assetPosECI, targetPosECI); }
/// <summary> /// Constructor for the system class /// </summary> /// <param name="assets"></param> /// <param name="subsystems"></param> /// <param name="constraints"></param> /// <param name="environment"></param> public SystemClass(List<Asset> assets, List<Subsystem> subsystems, List<Constraint> constraints, Universe environment) { Assets = assets; Constraints = constraints; Environment = environment; Subsystems = new List<Subsystem>(); foreach (Subsystem nIt in subsystems) { Subsystems.Add(nIt); } }
/// <summary> /// The default canPerform method. /// Should be used to check if all dependent subsystems can perform and extended by subsystem implementations. /// </summary> /// <param name="oldState"></param> /// <param name="newState"></param> /// <param name="tasks"></param> /// <param name="environment"></param> /// <returns></returns> public virtual bool CanPerform(Event proposedEvent, Universe environment) { foreach (var sub in DependentSubsystems) { if (!sub.IsEvaluated)// && !sub.GetType().Equals(typeof(ScriptedSubsystem))) if (sub.CanPerform(proposedEvent, environment) == false) return false; } _task = proposedEvent.GetAssetTask(Asset); //Find the correct task for the subsystem _newState = proposedEvent.State; IsEvaluated = true; return true; }
/// <summary> /// An override of the Subsystem CanPerform method /// </summary> /// <param name="proposedEvent"></param> /// <param name="environment"></param> /// <returns></returns> public override bool CanPerform(Event proposedEvent, Universe environment) { IsEvaluated = true; if (!base.CanPerform(proposedEvent, environment)) return false; if (_task.Type == TaskType.COMM) { HSFProfile<double> newProf = DependencyCollector(proposedEvent); if (!newProf.Empty()) proposedEvent.State.SetProfile(DATARATE_KEY, newProf); } return true; }
/// <summary> /// An override of the Subsystem CanPerform method /// </summary> /// <param name="proposedEvent"></param> /// <param name="environment"></param> /// <returns></returns> public override bool CanPerform(Event proposedEvent, Universe environment) { if (!base.CanPerform(proposedEvent, environment)) return false; if (_task.Type == TaskType.IMAGING) { double ts = proposedEvent.GetTaskStart(Asset); double te = proposedEvent.GetTaskEnd(Asset); double oldbufferratio = _newState.GetLastValue(Dkeys[0]).Value; Delegate DepCollector; SubsystemDependencyFunctions.TryGetValue("DepCollector", out DepCollector); HSFProfile<double> newdataratein = ((HSFProfile<double>)DepCollector.DynamicInvoke(proposedEvent) / _bufferSize); bool exceeded = false; HSFProfile<double> newdataratio = newdataratein.upperLimitIntegrateToProf(ts, te, 1, 1, ref exceeded, 0, oldbufferratio); if (!exceeded) { _newState.AddValue(DATABUFFERRATIO_KEY, newdataratio); return true; } // TODO: Change to logger Console.WriteLine("SSDR buffer full"); return false; } else if (_task.Type == TaskType.COMM) { double ts = proposedEvent.GetTaskStart(Asset); proposedEvent.SetTaskEnd(Asset, ts + 60.0); double te = proposedEvent.GetTaskEnd(Asset); double data = _bufferSize * _newState.GetLastValue(Dkeys.First()).Value; double dataqueout = data / 2 > 50 ? data / 2 : data; if (data - dataqueout < 0) dataqueout = data; if (dataqueout > 0) _newState.AddValue(DATABUFFERRATIO_KEY, new KeyValuePair<double, double>(te, (data - dataqueout) / _bufferSize)); return true; } return true; }
/// <summary> /// Method to check if the subsystem can perform the most recent task that was added to the schedule /// </summary> /// <param name="subsystem"></param> /// <param name="proposedSchedule"></param> /// <param name="environment"></param> /// <returns></returns> private static bool checkSub(Subsystem subsystem, SystemSchedule proposedSchedule, Universe environment) { if (subsystem.IsEvaluated) return true; var events = proposedSchedule.AllStates.Events; if (events.Count != 0) { //if (events.Count > 1) // subsystem._oldState = events.ElementAt(events.Count - 2).State; //else // subsystem._oldState = null; if (!subsystem.CanPerform(events.Peek(), environment)) return false; events.Peek().isEvaluated +=1; } return true; }
public override bool CanPerform(Event proposedEvent, Universe environment) { if (IsEvaluated) return true; // Check all dependent subsystems foreach (var sub in DependentSubsystems) { if (!sub.IsEvaluated) if (sub.CanPerform(proposedEvent, environment) == false) return false; } _task = proposedEvent.GetAssetTask(Asset); //Find the correct task for the subsystem _newState = proposedEvent.State; IsEvaluated = true; // Call the can perform method that is in the python class dynamic perform = _pythonInstance.CanPerform(proposedEvent, environment); return (bool)perform; }
static int Main(string[] args) { // Begin the Logger ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); log.Info("STARTING HSF RUN"); //Do not delete // Set Defaults var simulationInputFilePath = @"..\..\..\SimulationInput.XML"; var targetDeckFilePath = @"..\..\..\v2.2-300targets.xml"; var modelInputFilePath = @"..\..\..\DSAC_Static.xml"; bool simulationSet = false, targetSet = false, modelSet = false; // Get the input filenames int i = 0; foreach(var input in args) { i++; switch (input) { case "-s": simulationInputFilePath = args[i]; simulationSet = true; break; case "-t": targetDeckFilePath = args[i]; targetSet = true; break; case "-m": modelInputFilePath = args[i]; modelSet = true; break; } } ///add usage statement if (!simulationSet) { log.Info("Using Default Simulation File"); } if (!targetSet) { log.Info("Using Default Target File"); } if (!modelSet) { log.Info("Using Default Model File"); } // Initialize Output File var outputFileName = string.Format("output-{0:yyyy-MM-dd}-*", DateTime.Now); var outputPath = @"C:\HorizonLog\"; var txt = ".txt"; string[] fileNames = System.IO.Directory.GetFiles(outputPath, outputFileName, System.IO.SearchOption.TopDirectoryOnly); double number = 0; foreach (var fileName in fileNames) { char version = fileName[fileName.Length - txt.Length-1]; if(number < Char.GetNumericValue(version)) number = Char.GetNumericValue(version); } number++; outputFileName = outputFileName.Remove(outputFileName.Length - 1) + number; outputPath += outputFileName + txt; // Find the main input node from the XML input files XmlNode evaluatorNode = XmlParser.ParseSimulationInput(simulationInputFilePath); // Load the target deck into the targets list from the XML target deck input file Stack<Task> systemTasks = new Stack<Task>(); bool targetsLoaded = Task.loadTargetsIntoTaskList(XmlParser.GetTargetNode(targetDeckFilePath), systemTasks); if (!targetsLoaded) { return 1; } // Find the main model node from the XML model input file var modelInputXMLNode = XmlParser.GetModelNode(modelInputFilePath); // Load the environment. First check if there is an ENVIRONMENT XMLNode in the input file Universe SystemUniverse = null; //Create singleton dependency dictionary Dependency dependencies = Dependency.Instance; // Initialize List to hold assets and subsystem nodes List<Asset> assetList = new List<Asset>(); List<Subsystem> subList = new List<Subsystem>(); // Maps used to set up preceeding nodes Dictionary<ISubsystem, XmlNode> subsystemXMLNodeMap = new Dictionary<ISubsystem, XmlNode>(); Dictionary<string, Subsystem> subsystemMap = new Dictionary<string, Subsystem>(); List<KeyValuePair<string, string>> dependencyMap = new List<KeyValuePair<string, string>>(); List<KeyValuePair<string, string>> dependencyFcnMap = new List<KeyValuePair<string, string>>(); // Dictionary<string, ScriptedSubsystem> scriptedSubNames = new Dictionary<string, ScriptedSubsystem>(); // Create Constraint list List<Constraint> constraintsList = new List<Constraint>(); //Create Lists to hold all the initial condition and dependency nodes to be parsed later List<XmlNode> ICNodes = new List<XmlNode>(); List<XmlNode> DepNodes = new List<XmlNode>(); SystemState initialSysState = new SystemState(); // Set up Subsystem Nodes, first loop through the assets in the XML model input file foreach (XmlNode modelChildNode in modelInputXMLNode.ChildNodes) { if (modelChildNode.Name.Equals("ENVIRONMENT")) { // Create the Environment based on the XMLNode SystemUniverse = new Universe(modelChildNode); } if (modelChildNode.Name.Equals("ASSET")) { Asset asset = new Asset(modelChildNode); assetList.Add(asset); // Loop through all the of the ChildNodess for this Asset foreach (XmlNode childNode in modelChildNode.ChildNodes) { // Get the current Subsystem XML Node, and create it using the SubsystemFactory if (childNode.Name.Equals("SUBSYSTEM")) { //is this how we want to do this? // Check if the type of the Subsystem is scripted, networked, or other string subName = SubsystemFactory.GetSubsystem(childNode, dependencies, asset, subsystemMap); foreach (XmlNode ICorDepNode in childNode.ChildNodes) { if(ICorDepNode.Name.Equals("IC")) ICNodes.Add(ICorDepNode); if (ICorDepNode.Name.Equals("DEPENDENCY")) { string depSubName = "", depFunc = ""; depSubName = Subsystem.parseNameFromXmlNode(ICorDepNode, asset.Name) ; dependencyMap.Add(new KeyValuePair<string, string>(subName, depSubName)); if (ICorDepNode.Attributes["fcnName"] != null) { depFunc = ICorDepNode.Attributes["fcnName"].Value.ToString(); dependencyFcnMap.Add(new KeyValuePair<string, string>(subName, depFunc)); } } } } //Create a new Constraint if (childNode.Name.Equals("CONSTRAINT")) { constraintsList.Add(ConstraintFactory.GetConstraint(childNode, subsystemMap, asset)); } } if (ICNodes.Count > 0) initialSysState.Add(SystemState.setInitialSystemState(ICNodes, asset)); ICNodes.Clear(); } } if (SystemUniverse == null) SystemUniverse = new Universe(); foreach (KeyValuePair<string, Subsystem> sub in subsystemMap) { if(!sub.Value.GetType().Equals(typeof(ScriptedSubsystem)))//let the scripted subsystems add their own dependency collector sub.Value.AddDependencyCollector(); subList.Add(sub.Value); } log.Info("Subsystems and Constraints Loaded"); //Add all the dependent subsystems to the dependent subsystem list of the subsystems foreach (KeyValuePair<string, string> depSubPair in dependencyMap) { Subsystem subToAddDep, depSub; subsystemMap.TryGetValue(depSubPair.Key, out subToAddDep); subsystemMap.TryGetValue(depSubPair.Value, out depSub); subToAddDep.DependentSubsystems.Add(depSub); } //give the dependency functions to all the subsytems that need them foreach (KeyValuePair<string, string> depFunc in dependencyFcnMap) { Subsystem subToAddDep; subsystemMap.TryGetValue(depFunc.Key, out subToAddDep); subToAddDep.SubsystemDependencyFunctions.Add(depFunc.Value, dependencies.GetDependencyFunc(depFunc.Value)); } log.Info("Dependencies Loaded"); SystemClass simSystem = new SystemClass(assetList, subList, constraintsList, SystemUniverse); if (simSystem.CheckForCircularDependencies()) throw new NotFiniteNumberException("System has circular dependencies! Please correct then try again."); Evaluator schedEvaluator = EvaluatorFactory.GetEvaluator(evaluatorNode, dependencies); Scheduler scheduler = new Scheduler(schedEvaluator); List<SystemSchedule> schedules = scheduler.GenerateSchedules(simSystem, systemTasks, initialSysState); // Evaluate the schedules and set their values foreach (SystemSchedule systemSchedule in schedules) { systemSchedule.ScheduleValue = schedEvaluator.Evaluate(systemSchedule); bool canExtendUntilEnd = true; // Extend the subsystem states to the end of the simulation foreach (var subsystem in simSystem.Subsystems) { if(systemSchedule.AllStates.Events.Count >0) if (!subsystem.CanExtend(systemSchedule.AllStates.Events.Peek(), simSystem.Environment, SimParameters.SimEndSeconds)) log.Error("Cannot Extend " + subsystem.Name + " to end of simulation"); } } // Sort the sysScheds by their values schedules.Sort((x, y) => x.ScheduleValue.CompareTo(y.ScheduleValue)); schedules.Reverse(); double maxSched = schedules[0].ScheduleValue; i = 0; //Morgan's Way using (StreamWriter sw = File.CreateText(outputPath)) { foreach (SystemSchedule sched in schedules) { sw.WriteLine("Schedule Number: " + i + "Schedule Value: " + schedules[i].ScheduleValue); foreach (var eit in sched.AllStates.Events) { if (i < 5)//just compare the first 5 schedules for now { sw.WriteLine(eit.ToString()); } } i++; } log.Info("Max Schedule Value: " + maxSched); } // Mehiel's way string stateDataFilePath = @"C:\HorizonLog\" + string.Format("output-{0:yyyy-MM-dd-hh-mm-ss}", DateTime.Now); SystemSchedule.WriteSchedule(schedules[0], stateDataFilePath); var csv = new StringBuilder(); csv.Clear(); foreach (var asset in simSystem.Assets) { File.WriteAllText(@"..\..\..\" + asset.Name + "_dynamicStateData.csv", asset.AssetDynamicState.ToString()); } return 0; // Console.ReadKey(); }
/// <summary> /// The default canExtend function. May be over written for additional functionality. /// </summary> /// <param name="newState"></param> /// <param name="position"></param> /// <param name="environment"></param> /// <param name="evalToTime"></param> /// <returns></returns> public virtual bool CanExtend(Event proposedEvent, Universe environment, double evalToTime) { if (proposedEvent.GetEventEnd(Asset) < evalToTime) proposedEvent.SetEventEnd(Asset, evalToTime); return true; }
/// <summary> /// Override of the canExtend method for the power subsystem /// </summary> /// <param name="newState"></param> /// <param name="universe"></param> /// <param name="evalToTime"></param> /// <returns></returns> public override bool CanExtend(Event proposedEvent, Universe universe, double evalToTime) { double ee = proposedEvent.GetEventEnd(Asset); if (ee > SimParameters.SimEndSeconds) return false; Sun sun = universe.Sun; double te = proposedEvent.State.GetLastValue(DOD_KEY).Key; if (proposedEvent.GetEventEnd(Asset) < evalToTime) proposedEvent.SetEventEnd(Asset, evalToTime); // get the dod initial conditions double olddod = proposedEvent.State.GetValueAtTime(DOD_KEY, te).Value; // collect power profile out Delegate DepCollector; SubsystemDependencyFunctions.TryGetValue("DepCollector", out DepCollector); HSFProfile<double> powerOut = (HSFProfile<double>)DepCollector.DynamicInvoke(proposedEvent); // deps->callDoubleDependency("POWERSUB_getPowerProfile"); // collect power profile in DynamicState position = Asset.AssetDynamicState; HSFProfile<double> powerIn = CalcSolarPanelPowerProfile(te, ee, proposedEvent.State, position, universe); // calculate dod rate HSFProfile<double> dodrateofchange = ((powerOut - powerIn) / _batterySize); bool exceeded_lower = false, exceeded_upper = false; double freq = 1.0; HSFProfile<double> dodProf = dodrateofchange.limitIntegrateToProf(te, ee, freq, 0.0, 1.0, ref exceeded_lower, ref exceeded_upper, 0, olddod); if (exceeded_upper) return false; if(dodProf.LastTime() != ee && ee == SimParameters.SimEndSeconds) { dodProf[ee] = dodProf.LastValue(); } proposedEvent.State.AddValue(DOD_KEY, dodProf); return true; }
/// <summary> /// Override of the canPerform method for the power subsystem /// </summary> /// <param name="oldState"></param> /// <param name="newState"></param> /// <param name="tasks"></param> /// <param name="universe"></param> /// <returns></returns> public override bool CanPerform(Event proposedEvent, Universe universe) { //Make sure all dependent subsystems have been evaluated if (!base.CanPerform(proposedEvent, universe)) return false; double es = proposedEvent.GetEventStart(Asset); double te = proposedEvent.GetTaskEnd(Asset); double ee = proposedEvent.GetEventEnd(Asset); double powerSubPowerOut = 10; if (ee > SimParameters.SimEndSeconds) { Console.WriteLine("Simulation ended"); return false; } // get the old DOD double olddod = _newState.GetLastValue(Dkeys.First()).Value; // collect power profile out Delegate DepCollector; SubsystemDependencyFunctions.TryGetValue("DepCollector", out DepCollector); HSFProfile<double> powerOut = (HSFProfile<double>)DepCollector.DynamicInvoke(proposedEvent); // deps->callDoubleDependency("POWERSUB_getPowerProfile"); powerOut = powerOut + powerSubPowerOut; // collect power profile in DynamicState position = Asset.AssetDynamicState; HSFProfile<double> powerIn = CalcSolarPanelPowerProfile(es, te, _newState, position, universe); // calculate dod rate HSFProfile<double> dodrateofchange = ((powerOut - powerIn) / _batterySize); bool exceeded= false ; double freq = 1.0; HSFProfile<double> dodProf = dodrateofchange.lowerLimitIntegrateToProf(es, te, freq, 0.0, ref exceeded, 0, olddod); _newState.AddValue(DOD_KEY, dodProf); return true; }
/// <summary> /// Calculate the solar panel power in over the time of the task /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <param name="state"></param> /// <param name="position"></param> /// <param name="universe"></param> /// <returns></returns> protected HSFProfile<double> CalcSolarPanelPowerProfile(double start, double end, SystemState state, DynamicState position, Universe universe) { // create solar panel profile for this event double freq = 5; ShadowState lastShadow = universe.Sun.castShadowOnPos(position, start); HSFProfile<double> solarPanelPowerProfile = new HSFProfile<double>(start, GetSolarPanelPower(lastShadow)); for (double time = start + freq; time <= end; time += freq) { ShadowState shadow = universe.Sun.castShadowOnPos(position, time); // if the shadow state changes during this step, save the power data if (shadow != lastShadow) { solarPanelPowerProfile[time] = GetSolarPanelPower(shadow); lastShadow = shadow; } } state.AddValue(POWIN_KEY, solarPanelPowerProfile); return solarPanelPowerProfile; }
public override bool CanExtend(Event proposedEvent, Universe environment, double evalToTime) { dynamic extend = _pythonInstance.CanExtend(proposedEvent, environment, evalToTime); return (bool)extend; }
/// <summary> /// An override of the Subsystem CanPerform method /// </summary> /// <param name="proposedEvent"></param> /// <param name="environment"></param> /// <returns></returns> public override bool CanPerform(Event proposedEvent, Universe environment) { if (!base.CanPerform(proposedEvent, environment)) return false; if (_task.Type == TaskType.IMAGING) { //set pixels and time to caputre based on target value int value = _task.Target.Value; double pixels = _lowQualityPixels; double timetocapture = _lowQualityTime; if (value <= _highQualityTime && value >= _midQualityTime) //Morgan took out magic numbers { pixels = _midQualityPixels; timetocapture = _midQualityTime; } if (value > _highQualityTime) { pixels = _highQualityPixels; timetocapture = _highQualityTime; } // get event start and task start times double es = proposedEvent.GetEventStart(Asset); double ts = proposedEvent.GetTaskStart(Asset); double te = proposedEvent.GetTaskEnd(Asset); if (ts > te) { // TODO: Change this to Logger Console.WriteLine("EOSensor lost access"); return false; } // set task end based upon time to capture te = ts + timetocapture; proposedEvent.SetTaskEnd(Asset, te); // calculate incidence angle // from Brown, Pp. 99 DynamicState position = Asset.AssetDynamicState; double timage = ts + timetocapture / 2; Matrix<double> m_SC_pos_at_tf_ECI = position.PositionECI(timage); Matrix<double> m_target_pos_at_tf_ECI = _task.Target.DynamicState.PositionECI(timage); Matrix<double> m_pv = m_target_pos_at_tf_ECI - m_SC_pos_at_tf_ECI; Matrix<double> pos_norm = -m_SC_pos_at_tf_ECI / Matrix<double>.Norm(-m_SC_pos_at_tf_ECI); Matrix<double> pv_norm = m_pv / Matrix<double>.Norm(m_pv); double incidenceang = 90 - 180 / Math.PI * Math.Acos(Matrix<double>.Dot(pos_norm, pv_norm)); // set state data _newState.AddValue(INCIDENCE_KEY, new KeyValuePair<double, double>(timage, incidenceang)); _newState.AddValue(INCIDENCE_KEY, new KeyValuePair<double, double>(timage + 1, 0.0)); _newState.AddValue(PIXELS_KEY, new KeyValuePair<double, double>(timage, pixels)); _newState.AddValue(PIXELS_KEY, new KeyValuePair<double, double>(timage + 1, 0.0)); _newState.AddValue(EOON_KEY, new KeyValuePair<double, bool>(ts, true)); _newState.AddValue(EOON_KEY, new KeyValuePair<double, bool>(te, false)); } return true; }
/// <summary> /// See if all the subsystems can perform the most recent task that was added to the schedule /// </summary> /// <param name="subsystems"></param> /// <param name="proposedSchedule"></param> /// <param name="environment"></param> /// <returns></returns> private static bool checkSubs(List<Subsystem> subsystems, SystemSchedule proposedSchedule, Universe environment) { foreach (var sub in subsystems) { if (!sub.IsEvaluated && !checkSub(sub, proposedSchedule, environment)) return false; } return true; }