001: /*
002: * <copyright>
003: *
004: * Copyright 2001-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.logistics.plugin.trans;
027:
028: import org.cougaar.planning.ldm.asset.AggregateAsset;
029: import org.cougaar.planning.ldm.asset.Asset;
030: import org.cougaar.planning.ldm.asset.AssetGroup;
031:
032: import org.cougaar.planning.ldm.plan.MPTask;
033: import org.cougaar.planning.ldm.plan.PlanElement;
034: import org.cougaar.planning.ldm.plan.Task;
035:
036: import org.cougaar.planning.ldm.plan.AspectType;
037: import org.cougaar.planning.ldm.plan.AspectValue;
038:
039: import org.cougaar.lib.filter.UTILSingleTaskAllocatorPlugin;
040:
041: import java.util.Date;
042:
043: import org.cougaar.logistics.ldm.Constants;
044: import org.cougaar.glm.ldm.asset.Organization;
045: import org.cougaar.glm.ldm.asset.GLMAsset;
046: import org.cougaar.glm.ldm.asset.MovabilityPG;
047:
048: import org.cougaar.glm.ldm.plan.GeolocLocation;
049:
050: import org.cougaar.lib.callback.UTILExpandableTaskCallback;
051: import org.cougaar.lib.callback.UTILFilterCallback;
052: import org.cougaar.lib.callback.UTILGenericListener;
053:
054: import org.cougaar.glm.util.GLMMeasure;
055: import org.cougaar.glm.util.GLMPrepPhrase;
056:
057: /**
058: * <pre>
059: * Plugin that looks for TRANSIT or TRANSPORT tasks.
060: *
061: * In general, like it's super class, TransportAllocatorPlugin,
062: * BUT if the asset is self-propelled, short-circuits the process
063: * by assigning the task to its direct object. This follows the simple
064: * idea that to deploy a truck, you have it move itself.
065: *
066: * </pre>
067: */
068: public class GroundTransportAllocatorPlugin extends
069: TransportAllocatorPlugin {
070:
071: /** creates GLMMeasure and GLMPrepPhrase helper classes */
072: public void localSetup() {
073: super .localSetup();
074: measureHelper = new GLMMeasure(logger);
075: glmPrepHelper = new GLMPrepPhrase(logger);
076: }
077:
078: /**
079: * <pre>
080: * This plugin is interested in tasks with verb TRANSIT or TRANSPORT
081: * The task must also have the VISHNU prep attached, indicating that the Vishnu
082: * plugin upstream has created the task.
083: *
084: * BUT if the task is to move a self-transportable item, just go ahead, be
085: * interested in it, and allocate it. These tasks will never go to the Vishnu
086: * Aggregator.
087: * </pre>
088: * @param t task to check to see if it is an input task to this plugin
089: */
090: public boolean interestingTask(Task t) {
091: boolean hasTransitVerb = t.getVerb().equals(
092: Constants.Verb.TRANSIT);
093: boolean hasTransportVerb = t.getVerb().equals(
094: Constants.Verb.TRANSPORT);
095:
096: if (!(hasTransitVerb || hasTransportVerb))
097: return false;
098:
099: boolean hasVishnu = prepHelper.hasPrepNamed(t, "VISHNU");
100:
101: if (hasTransitVerb && hasVishnu) {
102: if (isDebugEnabled())
103: debug(getName()
104: + ".interestingTask - interested in TRANSIT task "
105: + t.getUID());
106: return true;
107: }
108:
109: if (hasTransportVerb && hasVishnu) {
110: if (isDebugEnabled())
111: debug(getName()
112: + ".interestingTask - interested in TRANSPORT task "
113: + t.getUID());
114: return true;
115: }
116:
117: boolean isSelfPropelled = isSelf(t);
118:
119: if (hasTransportVerb && !hasVishnu && isSelfPropelled) {
120: if (isDebugEnabled())
121: debug(getName()
122: + ".interestingTask - interested in self-propelled task "
123: + t.getUID());
124: return true;
125: }
126:
127: if (isDebugEnabled() && !isSelfPropelled)
128: debug(getName() + ".interestingTask - NOT interested in "
129: + t.getUID());
130:
131: return isSelfPropelled;
132: }
133:
134: /** checks to see if the the task is to move a self-propelled item */
135: protected boolean isSelf(Task t) {
136: boolean isSelfPropelled = false;
137:
138: Asset directObject = t.getDirectObject();
139: if (!(directObject instanceof AssetGroup))
140: isSelfPropelled = isSelfPropelled(t, directObject);
141:
142: return isSelfPropelled;
143: }
144:
145: /**
146: * <pre>
147: * Checks to see if the the task is to move a self-propelled item, given the direct object
148: *
149: * Determines the nature of the direct object by examining its Cargo Category Code on its
150: * movability property group.
151: *
152: * If an asset doesn't have a movability PG, returns false.
153: * </pre>
154: * @param t just passed in so we can report which task has a missing movability PG.
155: * @param directObject asset to examine
156: */
157: protected boolean isSelfPropelled(Task t, Asset directObject) {
158: GLMAsset baseAsset = (directObject instanceof AggregateAsset) ? (GLMAsset) ((AggregateAsset) directObject)
159: .getAsset()
160: : (GLMAsset) directObject;
161:
162: MovabilityPG move_prop = baseAsset.getMovabilityPG();
163:
164: if (move_prop != null) {
165: String cargocatcode = move_prop.getCargoCategoryCode();
166: if (cargocatcode == null) {
167: if (isWarnEnabled())
168: warn(getName()
169: + ".isSelfPropelled - found task "
170: + t.getUID()
171: + "\nwith d.o. "
172: + directObject
173: + "\nthat had a movabilityPG but no cargo cat code?");
174: } else if (cargocatcode.charAt(0) == 'R') {
175: if (isDebugEnabled())
176: debug(getName()
177: + ".isSelfPropelled - found self-propelled vehicle on task "
178: + t.getUID());
179: return true;
180: }
181: } else {
182: if (isInfoEnabled())
183: info(getName() + ".isSelfPropelled - asset "
184: + baseAsset + " for task " + t
185: + " is missing its movability PG.");
186: }
187:
188: return false;
189: }
190:
191: /**
192: * <pre>
193: * determines the asset that is allocated to
194: *
195: * Allocate to self (=direct object) if self propelled.
196: *
197: * Otherwise grab asset from WITH prep.
198: * </pre>
199: **/
200: public Asset findAsset(Task t) {
201: if (isSelf(t)) {
202: return t.getDirectObject();
203: } else {
204: return super .findAsset(t);
205: }
206: }
207:
208: /**
209: * <pre>
210: * Do the actual allocation here
211: *
212: * If self propelled, do simple great circle calculations based on the speed
213: * of the asset to determine START and END aspect values.
214: *
215: * Calls <tt>getSpeed</tt> to determine asset (vehicle) speed.
216: *
217: * Otherwise, use super's createAllocation.
218: * <pre>
219: * @see #isSelf
220: * @see org.cougaar.glm.util.GLMMeasure#distanceBetween
221: * @see #getSpeed
222: * @param t the task to allocate
223: * @param a the asset to allocate to
224: * @return the allocation
225: */
226: public PlanElement createAllocation(Task t, Asset a) {
227: try {
228: if (isSelf(t)) {
229: Date to = prefHelper.getBestDate(t);
230: Date from = to;
231: GeolocLocation poe = glmPrepHelper.getFromLocation(t);
232: GeolocLocation pod = glmPrepHelper.getToLocation(t);
233:
234: double distance = measureHelper.distanceBetween(poe,
235: pod).getMiles();
236: double speed = getSpeed((GLMAsset) a);
237: long time = (long) ((distance / speed) * 60.0d * 60.0d * 1000.0d); // millis
238:
239: from = new Date(to.getTime() - time);
240: double confidence = allocHelper.HIGHEST_CONFIDENCE;
241:
242: if (isDebugEnabled())
243: debug(".createAllocation - for self propelled "
244: + t.getUID() + " , ready at " + from
245: + " - best " + to + " confidence "
246: + confidence);
247:
248: AspectValue[] values = new AspectValue[2];
249: values[0] = AspectValue.newAspectValue(
250: AspectType.START_TIME, from.getTime());
251: values[1] = AspectValue.newAspectValue(
252: AspectType.END_TIME, to.getTime());
253:
254: PlanElement pe = allocHelper.makeAllocation(this , ldmf,
255: realityPlan, t, a, values, confidence,
256: Constants.Role.TRANSPORTER);
257: return pe;
258: } else
259: return super .createAllocation(t, a);
260: } catch (Exception e) {
261: error(getName() + ".createAllocation - for task "
262: + t.getUID() + " the asset allocated was " + a
263: + " which is NOT a GLMAsset. How strange.");
264: return null;
265: }
266: }
267:
268: /**
269: * Examines GroundSelfPropulsionPG to determine speed of asset
270: *
271: * @see org.cougaar.glm.ldm.asset.GroundSelfPropulsionPG#getCruiseSpeed
272: **/
273: protected double getSpeed(GLMAsset asset) {
274: double speed = 55;
275:
276: try {
277: speed = asset.getGroundSelfPropulsionPG().getCruiseSpeed()
278: .getMilesPerHour();
279: } catch (Exception e) {
280: try {
281: speed = asset.getAirSelfPropulsionPG().getCruiseSpeed()
282: .getMilesPerHour();
283: } catch (Exception ee) {
284: try {
285: speed = asset.getWaterSelfPropulsionPG()
286: .getCruiseSpeed().getMilesPerHour();
287: } catch (Exception eee) {
288: if (isDebugEnabled())
289: debug(getName()
290: + ".getSpeed - WARNING - Could not determine"
291: + " resource speed for "
292: + asset.getUID());
293: }
294: }
295: }
296:
297: return speed;
298: }
299:
300: protected GLMMeasure measureHelper;
301: protected GLMPrepPhrase glmPrepHelper;
302: }
|