Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
56d2ee7
Added headlamp state and action.
schmerl Aug 27, 2021
db47b29
Hooked Headlamp into the model
schmerl Aug 27, 2021
63e4fc3
Added headlamp on precondition for move in dark corridors
schmerl Aug 27, 2021
e00cc90
Added toString
schmerl Aug 27, 2021
d09ff20
Added darkness to the environment and loading
schmerl Aug 27, 2021
30d168f
Set up initial state for headlamp.
schmerl Aug 27, 2021
c52dca3
Parsing of darkness
schmerl Aug 27, 2021
918fc8b
Added some dark corridors and a preference for number of headlamp
schmerl Aug 31, 2021
a9b5e4b
Added headlamp domain and event
schmerl Aug 31, 2021
faa951e
Added rendering of dark places on the map
schmerl Sep 8, 2021
ef1e4eb
Added action for headlamp turning on
schmerl Sep 8, 2021
f903724
Added output of dark places on the map
schmerl Sep 8, 2021
412433c
Removed change headlamp from list of qualities.
schmerl Sep 8, 2021
cd5fc42
Removed change headlamp from list of qualities.
schmerl Sep 8, 2021
cf0b50c
Removed change headlamp from list of qualities.
schmerl Sep 8, 2021
200ed9a
Added all the places for considering headlamps and moves.
schmerl Sep 8, 2021
feadda8
Merge pull request #9 from cmu-able/headlamp-wo-qualities
schmerl Sep 8, 2021
39fd939
Updated mission file to change weightings
schmerl Sep 8, 2021
2f354d1
Updated mission file to change weightings
schmerl Sep 8, 2021
4113bc6
Merge branch 'headlamp' of https://github.com/cmu-able/explainable-pl…
schmerl Sep 8, 2021
c77e9a3
Updated mission file to change weightings
schmerl Sep 8, 2021
013646b
Changes to line spacing.
schmerl Sep 8, 2021
c8c46c6
Removed dead code
schmerl Sep 8, 2021
491f0e6
Added headlamp to legend.
schmerl Sep 8, 2021
0829979
Reverted to previous
schmerl Sep 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion XPlanning/data/mobilerobot/maps/GHC7-map0.json
Original file line number Diff line number Diff line change
Expand Up @@ -548,5 +548,22 @@
"to-id": "L22",
"from-id": "L18"
}
]
],
"lighting": [
{
"dark": true,
"to-id": "L22",
"from-id": "L18"
},
{
"dark": true,
"to-id": "L21",
"from-id": "L17"
},
{
"dark": true,
"to-id": "L24",
"from-id": "L27"
}
]
}
2 changes: 1 addition & 1 deletion XPlanning/data/mobilerobot/missions/mission0.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"objective": "energyConsumption",
"scaling-const": 0.3,
"min-step-value": 0.0,
"max-step-value": 2525
"max-step-value": 4185.0

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to change to cater for added energy along the longest path if the headlamp was turned on.

}
],
"start-id": "L1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
import examples.mobilerobot.dsm.Mission;
import examples.mobilerobot.dsm.MobileRobotXMDPBuilder;
import examples.mobilerobot.dsm.parser.AreaParser;
import examples.mobilerobot.dsm.parser.DarknessParser;
import examples.mobilerobot.dsm.parser.IEdgeAttributeParser;
import examples.mobilerobot.dsm.parser.INodeAttributeParser;
import examples.mobilerobot.dsm.parser.MapTopologyReader;
import examples.mobilerobot.dsm.parser.MissionReader;
import examples.mobilerobot.dsm.parser.OcclusionParser;
import examples.mobilerobot.models.Area;
import examples.mobilerobot.models.Darkness;
import examples.mobilerobot.models.Occlusion;
import language.exceptions.XMDPException;
import language.mdp.XMDP;
Expand All @@ -44,15 +46,18 @@ public MobileRobotXMDPLoader(File mapsJsonDir) {
mMapsJsonDir = mapsJsonDir;
AreaParser areaParser = new AreaParser();
OcclusionParser occlusionParser = new OcclusionParser();
DarknessParser darknessParser = new DarknessParser();
Set<INodeAttributeParser<? extends INodeAttribute>> nodeAttributeParsers = new HashSet<>();
nodeAttributeParsers.add(areaParser);
Set<IEdgeAttributeParser<? extends IEdgeAttribute>> edgeAttributeParsers = new HashSet<>();
edgeAttributeParsers.add(occlusionParser);
edgeAttributeParsers.add(darknessParser);
mMapReader = new MapTopologyReader(nodeAttributeParsers, edgeAttributeParsers);

// Default node/edge attribute values
mDefaultNodeAttributes.put(areaParser.getAttributeName(), DEFAULT_AREA);
mDefaultEdgeAttributes.put(occlusionParser.getAttributeName(), DEFAULT_OCCLUSION);
mDefaultEdgeAttributes.put(darknessParser.getAttributeName(), Darkness.LIGHT);
}

@Override
Expand Down
91 changes: 70 additions & 21 deletions XPlanning/src/examples/mobilerobot/dsm/MobileRobotXMDPBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@
import examples.mobilerobot.metrics.TravelTimeDomain;
import examples.mobilerobot.metrics.TravelTimeQFunction;
import examples.mobilerobot.models.Area;
import examples.mobilerobot.models.Darkness;
import examples.mobilerobot.models.Distance;
import examples.mobilerobot.models.HeadlampActionDescription;
import examples.mobilerobot.models.HeadlampState;
import examples.mobilerobot.models.Location;
import examples.mobilerobot.models.MoveToAction;
import examples.mobilerobot.models.Occlusion;
import examples.mobilerobot.models.RobotLocationActionDescription;
import examples.mobilerobot.models.RobotSpeed;
import examples.mobilerobot.models.RobotSpeedActionDescription;
import examples.mobilerobot.models.SetHeadlampAction;
import examples.mobilerobot.models.SetSpeedAction;
import language.domain.metrics.CountQFunction;
import language.domain.metrics.EventBasedMetric;
Expand Down Expand Up @@ -78,6 +82,20 @@ public class MobileRobotXMDPBuilder {
// SetSpeed action definition
private ActionDefinition<SetSpeedAction> setSpeedDef = new ActionDefinition<>("setSpeed", setSpeedHalf,
setSpeedFull);

// --- Headlamp setting --- //
private HeadlampState headlampOn = new HeadlampState(true);
private HeadlampState headlampOff = new HeadlampState(false);

// Robot's headlamp state variable
private StateVarDefinition<HeadlampState> rHeadlampDef = new StateVarDefinition<>("rHeadlamp", headlampOn, headlampOff);

// Headlamp-setting actions
private SetHeadlampAction setHeadlampOff = new SetHeadlampAction(rHeadlampDef.getStateVar(headlampOff));
private SetHeadlampAction setHeadlampOn = new SetHeadlampAction(rHeadlampDef.getStateVar(headlampOn));

// SetHeadlamp action defintion
private ActionDefinition<SetHeadlampAction> setHeadlampDef = new ActionDefinition<>("setHeadlamp", setHeadlampOff, setHeadlampOn);
// ------ //

// --- QA functions --- //
Expand Down Expand Up @@ -130,6 +148,7 @@ private StateSpace buildStateSpace(MapTopology map) throws NodeAttributeNotFound
StateSpace stateSpace = new StateSpace();
stateSpace.addStateVarDefinition(rLocDef);
stateSpace.addStateVarDefinition(rSpeedDef);
stateSpace.addStateVarDefinition(rHeadlampDef);
return stateSpace;
}

Expand All @@ -139,24 +158,29 @@ private ActionSpace buildActionSpace(MapTopology map) throws MapTopologyExceptio

// Assume that all locations are reachable
for (Location locDest : rLocDef.getPossibleValues()) {
MoveToAction moveTo = new MoveToAction(rLocDef.getStateVar(locDest));

// Derived attributes for each move action are obtained from edges in the map
LocationNode node = map.lookUpLocationNode(locDest.getId());
Set<Connection> connections = map.getConnections(node);
for (Connection conn : connections) {
Location locSrc = mLocMap.get(conn.getOtherNode(node));

// Distance
Distance distance = new Distance(conn.getDistance());
moveTo.putDistanceValue(distance, rLocDef.getStateVar(locSrc));

// Occlusion
Occlusion occlusion = conn.getConnectionAttribute(Occlusion.class, "occlusion");
moveTo.putOcclusionValue(occlusion, rLocDef.getStateVar(locSrc));
for (HeadlampState hlState : rHeadlampDef.getPossibleValues()) {
MoveToAction moveTo = new MoveToAction(rLocDef.getStateVar(locDest), rHeadlampDef.getStateVar(hlState));

// Derived attributes for each move action are obtained from edges in the map
LocationNode node = map.lookUpLocationNode(locDest.getId());
Set<Connection> connections = map.getConnections(node);
for (Connection conn : connections) {
Location locSrc = mLocMap.get(conn.getOtherNode(node));

// Distance
Distance distance = new Distance(conn.getDistance());
moveTo.putDistanceValue(distance, rLocDef.getStateVar(locSrc));

// Occlusion
Occlusion occlusion = conn.getConnectionAttribute(Occlusion.class, "occlusion");
moveTo.putOcclusionValue(occlusion, rLocDef.getStateVar(locSrc));

Darkness darkness = conn.getConnectionAttribute(Darkness.class, "lighting");
moveTo.putDarknessValue(darkness, rLocDef.getStateVar(locSrc));
}

moveTos.add(moveTo);
}

moveTos.add(moveTo);
}

// MoveTo action definition
Expand All @@ -165,6 +189,7 @@ private ActionSpace buildActionSpace(MapTopology map) throws MapTopologyExceptio
ActionSpace actionSpace = new ActionSpace();
actionSpace.addActionDefinition(moveToDef);
actionSpace.addActionDefinition(setSpeedDef);
actionSpace.addActionDefinition(setHeadlampDef);
return actionSpace;
}

Expand All @@ -173,6 +198,7 @@ private StateVarTuple buildInitialState(LocationNode startNode) {
StateVarTuple initialState = new StateVarTuple();
initialState.addStateVar(rLocDef.getStateVar(loc));
initialState.addStateVar(rSpeedDef.getStateVar(DEFAULT_SPEED));
initialState.addStateVar(rHeadlampDef.getStateVar(headlampOff));
return initialState;
}

Expand All @@ -182,6 +208,10 @@ private StateVarTuple buildGoal(LocationNode goalNode) {
goal.addStateVar(rLocDef.getStateVar(loc));
return goal;
}

private boolean isDark(Connection conn) throws MapTopologyException{
return conn.getConnectionAttribute(Darkness.class, "lighting") == Darkness.DARK;
}

private TransitionFunction buildTransitionFunction(MapTopology map) throws XMDPException, MapTopologyException {
// MoveTo:
Expand All @@ -190,19 +220,23 @@ private TransitionFunction buildTransitionFunction(MapTopology map) throws XMDPE

for (MoveToAction moveTo : moveToDef.getActions()) {
Location locDest = moveTo.getDestination();
HeadlampState hlState = moveTo.getHeadlampState();

// Source location for each move action from the map
LocationNode node = map.lookUpLocationNode(locDest.getId());
Set<Connection> connections = map.getConnections(node);
for (Connection conn : connections) {
Location locSrc = mLocMap.get(conn.getOtherNode(node));
preMoveTo.add(moveTo, rLocDef, locSrc);
if (isDark(conn) && !hlState.getValue()) {
preMoveTo.add(moveTo, rHeadlampDef, headlampOn);
}
}
}

// Action description for rLoc
RobotLocationActionDescription rLocActionDesc = new RobotLocationActionDescription(moveToDef, preMoveTo,
rLocDef);
rLocDef, rHeadlampDef);

// PSO
FactoredPSO<MoveToAction> moveToPSO = new FactoredPSO<>(moveToDef, preMoveTo);
Expand All @@ -217,14 +251,28 @@ private TransitionFunction buildTransitionFunction(MapTopology map) throws XMDPE
// Action description for rSpeed
RobotSpeedActionDescription rSpeedActionDesc = new RobotSpeedActionDescription(setSpeedDef, preSetSpeed,
rSpeedDef);

// PSO
FactoredPSO<SetSpeedAction> setSpeedPSO = new FactoredPSO<>(setSpeedDef, preSetSpeed);
setSpeedPSO.addActionDescription(rSpeedActionDesc);

// SetHeadlamp
// Precondition
Precondition<SetHeadlampAction> preSetHeadlamp = new Precondition<>(setHeadlampDef);
preSetHeadlamp.add(setHeadlampOn, rHeadlampDef, headlampOff);
preSetHeadlamp.add(setHeadlampOff, rHeadlampDef, headlampOn);

// Action description for rHeadlamp
HeadlampActionDescription rHeadlampActionDesc = new HeadlampActionDescription(setHeadlampDef, preSetHeadlamp, rHeadlampDef);

// PSO
FactoredPSO<SetHeadlampAction> setHeadlampPSO = new FactoredPSO<>(setHeadlampDef, preSetHeadlamp);
setHeadlampPSO.addActionDescription(rHeadlampActionDesc);

TransitionFunction transFunction = new TransitionFunction();
transFunction.add(moveToPSO);
transFunction.add(setSpeedPSO);
transFunction.add(setHeadlampPSO);
return transFunction;
}

Expand Down Expand Up @@ -256,9 +304,10 @@ private QSpace buildQFunctions() {
metric);

// Energy Consumption
EnergyConsumptionDomain energyDomain = new EnergyConsumptionDomain(rLocDef, rSpeedDef, moveToDef);
EnergyConsumptionDomain energyDomain = new EnergyConsumptionDomain(rLocDef, rSpeedDef, rHeadlampDef, moveToDef);
EnergyConsumptionQFunction energyQFunction = new EnergyConsumptionQFunction(energyDomain);



QSpace qSpace = new QSpace();
qSpace.addQFunction(timeQFunction);
qSpace.addQFunction(collisionQFunction);
Expand Down
25 changes: 25 additions & 0 deletions XPlanning/src/examples/mobilerobot/dsm/parser/DarknessParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package examples.mobilerobot.dsm.parser;

import org.json.simple.JSONObject;

import examples.mobilerobot.models.Darkness;

public class DarknessParser implements IEdgeAttributeParser<Darkness> {

@Override
public String getAttributeName() {
return "lighting";
}

@Override
public String getJSONObjectKey() {
return "lighting";
}

@Override
public Darkness parseAttribute(JSONObject edgeObject) {
Boolean dark = (Boolean )edgeObject.getOrDefault("dark", false);
return dark ? Darkness.DARK : Darkness.LIGHT;
}

}
Original file line number Diff line number Diff line change
@@ -1,44 +1,52 @@
package examples.mobilerobot.metrics;

import examples.mobilerobot.models.HeadlampState;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnergyConsumption now depends on headlamp state, so add that here.

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)
* 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<MoveToAction> {


private StateVarDefinition<Location> mrLocDef;
private StateVarDefinition<RobotSpeed> mrSpeedDef;
private StateVarDefinition<HeadlampState> mrHeadlampDef;

public EnergyConsumptionDomain(StateVarDefinition<Location> rLocDef, StateVarDefinition<RobotSpeed> rSpeedDef,
ActionDefinition<MoveToAction> moveToDef) {
StateVarDefinition<HeadlampState> rHeadlampDef, ActionDefinition<MoveToAction> moveToDef) {

this.mrLocDef = rLocDef;
this.mrSpeedDef = rSpeedDef;
this.mrHeadlampDef = rHeadlampDef;
addSrcStateVarDef(rLocDef);
addSrcStateVarDef(rSpeedDef);

addSrcStateVarDef(rHeadlampDef);

setActionDef(moveToDef);

addDestStateVarDef(rLocDef);
}

public StateVarDefinition<Location> getLocationStateVar() {
return mrLocDef;
}

public StateVarDefinition<RobotSpeed> getSpeedStateVar() {
return mrSpeedDef;
}

public StateVarDefinition<HeadlampState> getHeadlampStateVar() {
return mrHeadlampDef;
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package examples.mobilerobot.metrics;

import examples.mobilerobot.models.Distance;
import examples.mobilerobot.models.HeadlampState;
import examples.mobilerobot.models.Location;
import examples.mobilerobot.models.MoveToAction;
import examples.mobilerobot.models.RobotSpeed;
Expand All @@ -24,6 +25,7 @@ public class EnergyConsumptionQFunction implements IStandardMetricQFunction<Move

public static final double BASE_DISCHARGE_RATE = 20.0;
public static final double SPEED_INCREASE_DISCHARGE_RATE = 1.5;
public static final double HEADLAMP_DISCHARGE_RATE = 20.0;

private EnergyConsumptionDomain mDomain;

Expand Down Expand Up @@ -52,8 +54,13 @@ public double getValue(Transition<MoveToAction, EnergyConsumptionDomain> transit

RobotSpeed speed = transition.getSrcStateVarValue(RobotSpeed.class, mDomain.getSpeedStateVar());

// If the headlamp is on, then need to discharge at a higher rate
HeadlampState hl = transition.getSrcStateVarValue(HeadlampState.class, mDomain.getHeadlampStateVar());

double consumption = distance.getDistance() / speed.getSpeed() *
(BASE_DISCHARGE_RATE + speed.getSpeed() * SPEED_INCREASE_DISCHARGE_RATE * 10);
(BASE_DISCHARGE_RATE
+ speed.getSpeed() * SPEED_INCREASE_DISCHARGE_RATE * 10
+ (hl.getValue() ? HEADLAMP_DISCHARGE_RATE : 0));

return consumption;
}
Expand Down
8 changes: 8 additions & 0 deletions XPlanning/src/examples/mobilerobot/models/Darkness.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package examples.mobilerobot.models;

import examples.mobilerobot.dsm.IEdgeAttribute;
import language.domain.models.IActionAttribute;

public enum Darkness implements IEdgeAttribute, IActionAttribute {
LIGHT, DARK
}
Loading