diff --git a/XPlanning/data/mobilerobot/missions/mission0.json b/XPlanning/data/mobilerobot/missions/mission0.json index 5c980c9a..9c396be6 100644 --- a/XPlanning/data/mobilerobot/missions/mission0.json +++ b/XPlanning/data/mobilerobot/missions/mission0.json @@ -3,23 +3,29 @@ "map-file": "GHC7-map0.json", "preference-info": [ { - "scaling-const": 34.38082047198017, + "scaling-const": 0.3, "min-step-value": 0.0, "max-step-value": 34.38082047198017, "objective": "travelTime" }, { - "scaling-const": 100.0, + "scaling-const": 0.2, "min-step-value": 0.0, "max-step-value": 1.0, "objective": "collision" }, { - "scaling-const": 33.0, + "scaling-const": 0.2, "min-step-value": 0.0, "max-step-value": 3.0, "objective": "intrusiveness" - } + }, + { + "objective": "energyConsumption", + "scaling-const": 0.3, + "min-step-value": 0.0, + "max-step-value": 2525 + } ], "start-id": "L1" } \ No newline at end of file diff --git a/XPlanning/src/examples/mobilerobot/demo/MobileRobotXPlanner.java b/XPlanning/src/examples/mobilerobot/demo/MobileRobotXPlanner.java index 2c8d6916..1a092d55 100644 --- a/XPlanning/src/examples/mobilerobot/demo/MobileRobotXPlanner.java +++ b/XPlanning/src/examples/mobilerobot/demo/MobileRobotXPlanner.java @@ -14,6 +14,7 @@ import examples.common.XPlanner; import examples.common.XPlannerOutDirectories; import examples.mobilerobot.metrics.CollisionEvent; +import examples.mobilerobot.metrics.EnergyConsumptionQFunction; import examples.mobilerobot.metrics.IntrusiveMoveEvent; import examples.mobilerobot.metrics.TravelTimeQFunction; import examples.mobilerobot.viz.MapBasedPolicyRenderer; @@ -107,6 +108,10 @@ public static Vocabulary getVocabulary() { "very-intrusive"); vocab.putPreposition(IntrusiveMoveEvent.NAME, "at"); vocab.putUnit(IntrusiveMoveEvent.NAME, "location", "locations"); + + vocab.putNoun(EnergyConsumptionQFunction.NAME, "energy"); + vocab.putVerb(EnergyConsumptionQFunction.NAME, "consumes"); + vocab.putUnit(EnergyConsumptionQFunction.NAME, "milliwatt", "milliwatts"); return vocab; } @@ -115,6 +120,7 @@ public static QADecimalFormatter getQADecimalFormatter() { decimalFormatter.putDecimalFormat(TravelTimeQFunction.NAME, "#"); decimalFormatter.putDecimalFormat(CollisionEvent.NAME, "#.#"); decimalFormatter.putDecimalFormat(IntrusiveMoveEvent.NAME, "#"); + decimalFormatter.putDecimalFormat(EnergyConsumptionQFunction.NAME, "#"); return decimalFormatter; } @@ -122,6 +128,8 @@ public static void setVerbalizerOrdering(VerbalizerSettings verbalizerSettings) verbalizerSettings.appendQFunctionName(TravelTimeQFunction.NAME); verbalizerSettings.appendQFunctionName(CollisionEvent.NAME); verbalizerSettings.appendQFunctionName(IntrusiveMoveEvent.NAME); + verbalizerSettings.appendQFunctionName(EnergyConsumptionQFunction.NAME); + verbalizerSettings.appendEventName(IntrusiveMoveEvent.NAME, IntrusiveMoveEvent.NON_INTRUSIVE_EVENT_NAME); verbalizerSettings.appendEventName(IntrusiveMoveEvent.NAME, IntrusiveMoveEvent.SOMEWHAT_INTRUSIVE_EVENT_NAME); verbalizerSettings.appendEventName(IntrusiveMoveEvent.NAME, IntrusiveMoveEvent.VERY_INTRUSIVE_EVENT_NAME); diff --git a/XPlanning/src/examples/mobilerobot/dsm/MobileRobotXMDPBuilder.java b/XPlanning/src/examples/mobilerobot/dsm/MobileRobotXMDPBuilder.java index 95628724..974ba98c 100644 --- a/XPlanning/src/examples/mobilerobot/dsm/MobileRobotXMDPBuilder.java +++ b/XPlanning/src/examples/mobilerobot/dsm/MobileRobotXMDPBuilder.java @@ -9,6 +9,8 @@ import examples.mobilerobot.dsm.exceptions.NodeAttributeNotFoundException; import examples.mobilerobot.metrics.CollisionDomain; import examples.mobilerobot.metrics.CollisionEvent; +import examples.mobilerobot.metrics.EnergyConsumptionDomain; +import examples.mobilerobot.metrics.EnergyConsumptionQFunction; import examples.mobilerobot.metrics.IntrusiveMoveEvent; import examples.mobilerobot.metrics.IntrusivenessDomain; import examples.mobilerobot.metrics.TravelTimeDomain; @@ -252,11 +254,16 @@ private QSpace buildQFunctions() { metric.putEventValue(veryIntrusive, VERY_INTRUSIVE_PENALTY); NonStandardMetricQFunction intrusiveQFunction = new NonStandardMetricQFunction<>( metric); + + // Energy Consumption + EnergyConsumptionDomain energyDomain = new EnergyConsumptionDomain(rLocDef, rSpeedDef, moveToDef); + EnergyConsumptionQFunction energyQFunction = new EnergyConsumptionQFunction(energyDomain); QSpace qSpace = new QSpace(); qSpace.addQFunction(timeQFunction); qSpace.addQFunction(collisionQFunction); qSpace.addQFunction(intrusiveQFunction); + qSpace.addQFunction(energyQFunction); return qSpace; } diff --git a/XPlanning/src/examples/mobilerobot/metrics/EnergyConsumptionDomain.java b/XPlanning/src/examples/mobilerobot/metrics/EnergyConsumptionDomain.java new file mode 100644 index 00000000..b2ae879a --- /dev/null +++ b/XPlanning/src/examples/mobilerobot/metrics/EnergyConsumptionDomain.java @@ -0,0 +1,44 @@ +package examples.mobilerobot.metrics; + +import examples.mobilerobot.models.Location; +import examples.mobilerobot.models.MoveToAction; +import examples.mobilerobot.models.RobotSpeed; +import language.domain.metrics.TransitionStructure; +import language.domain.models.ActionDefinition; +import language.domain.models.StateVarDefinition; +/** + * Defines the domain for the energy quality domain + * + * The energy consumption quality is calculated based on the robot's location and speed, + * gets information from the MoveToAction, and effects the robot's location (because MoveToAction does) + * + * + */ +public class EnergyConsumptionDomain extends TransitionStructure { + + + private StateVarDefinition mrLocDef; + private StateVarDefinition mrSpeedDef; + + public EnergyConsumptionDomain(StateVarDefinition rLocDef, StateVarDefinition rSpeedDef, + ActionDefinition moveToDef) { + + this.mrLocDef = rLocDef; + this.mrSpeedDef = rSpeedDef; + addSrcStateVarDef(rLocDef); + addSrcStateVarDef(rSpeedDef); + + setActionDef(moveToDef); + + addDestStateVarDef(rLocDef); + } + + public StateVarDefinition getLocationStateVar() { + return mrLocDef; + } + + public StateVarDefinition getSpeedStateVar() { + return mrSpeedDef; + } + +} diff --git a/XPlanning/src/examples/mobilerobot/metrics/EnergyConsumptionQFunction.java b/XPlanning/src/examples/mobilerobot/metrics/EnergyConsumptionQFunction.java new file mode 100644 index 00000000..60c98654 --- /dev/null +++ b/XPlanning/src/examples/mobilerobot/metrics/EnergyConsumptionQFunction.java @@ -0,0 +1,89 @@ +package examples.mobilerobot.metrics; + +import examples.mobilerobot.models.Distance; +import examples.mobilerobot.models.Location; +import examples.mobilerobot.models.MoveToAction; +import examples.mobilerobot.models.RobotSpeed; +import language.domain.metrics.IStandardMetricQFunction; +import language.domain.metrics.Transition; +import language.exceptions.AttributeNameNotFoundException; +import language.exceptions.VarNotFoundException; +/** + * Calculates the energy consumption of the robot on a single transition. For now, + * let's keep this simple. Let's assume the robot has a constant consumption rate based on the + * time to traverse the segment, which is calculated from the speed and the distance traveled by + * the MovetoAction. + * + * Let's assume it consumes 20mw per hour when stationary and increases by 1.5mw per hour for + * every 0.1m/s increase in speed. + * + */ +public class EnergyConsumptionQFunction implements IStandardMetricQFunction { + + public static final String NAME = "energyConsumption"; + + public static final double BASE_DISCHARGE_RATE = 20.0; + public static final double SPEED_INCREASE_DISCHARGE_RATE = 1.5; + + private EnergyConsumptionDomain mDomain; + + public EnergyConsumptionQFunction(EnergyConsumptionDomain domain) { + this.mDomain = domain; + + } + + @Override + public String getName() { + return NAME; + } + + @Override + public EnergyConsumptionDomain getTransitionStructure() { + return mDomain; + } + + @Override + public double getValue(Transition transition) + throws VarNotFoundException, AttributeNameNotFoundException { + // Calculate the distance based on the location and the movetoaction + MoveToAction moveTo = transition.getAction(); + Location comingFrom = transition.getSrcStateVarValue(Location.class, mDomain.getLocationStateVar()); + Distance distance = moveTo.getDistance(mDomain.getLocationStateVar().getStateVar(comingFrom)); + + RobotSpeed speed = transition.getSrcStateVarValue(RobotSpeed.class, mDomain.getSpeedStateVar()); + + double consumption = distance.getDistance() / speed.getSpeed() * + (BASE_DISCHARGE_RATE + speed.getSpeed() * SPEED_INCREASE_DISCHARGE_RATE * 10); + + return consumption; + } + + /* + * Cached hashCode -- Effective Java + */ + private volatile int hashCode; + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof EnergyConsumptionQFunction)) { + return false; + } + EnergyConsumptionQFunction qFunction = (EnergyConsumptionQFunction) obj; + return qFunction.mDomain.equals(mDomain); + } + + @Override + public int hashCode() { + int result = hashCode; + if (result == 0) { + result = 17; + result = 31 * result + mDomain.hashCode(); + hashCode = result; + } + return result; + } + +}