All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.massisframework.massis.ai.sposh.SPOSHLogicController Maven / Gradle / Ivy

package com.massisframework.massis.ai.sposh;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.massisframework.massis.ai.sposh.actions.SimulationAction;
import com.massisframework.massis.ai.sposh.senses.SimulationSense;
import com.massisframework.massis.model.agents.HighLevelController;
import com.massisframework.massis.model.agents.LowLevelAgent;
import com.massisframework.massis.util.SimObjectProperty;

import cz.cuni.amis.pogamut.sposh.elements.ParseException;
import cz.cuni.amis.pogamut.sposh.elements.PoshParser;
import cz.cuni.amis.pogamut.sposh.elements.PoshPlan;
import cz.cuni.amis.pogamut.sposh.engine.FireResult;
import cz.cuni.amis.pogamut.sposh.engine.PoshEngine;
import cz.cuni.amis.pogamut.sposh.engine.PoshEngine.EvaluationResultInfo;
import cz.cuni.amis.pogamut.sposh.engine.timer.SystemClockTimer;
import cz.cuni.amis.pogamut.sposh.executor.StateWorkExecutor;

/**
 * SPOSH Logic controller in MASSIS. Based in Pogamut's Logic Controller
 *
 * @author rpax
 *
 * @param 
 */
@SuppressWarnings({ "rawtypes", "serial" })
public class SPOSHLogicController extends HighLevelController  {

    private final Logger logger;
    @SuppressWarnings("unused")
	private static final Map cachedPlans = new HashMap<>();
    /**
     * Posh engine that is evaluating the plan.
     */
    private final PoshEngine engine;
    /**
     * Primitive executor that is executing the primitves when engine requests
     * it, passes the variables and returns the value of executed primitive.
     */
    private final StateWorkExecutor workExecutor;
    private final SimulationContext context;

    /**
     * Main constructor. Loads a plan and attaches its logic to the agent
     *
     * @param agent the agent
     * @param planFilePath the path of the sposh plan
     */
    public SPOSHLogicController(LowLevelAgent agent,
            Map metadata,
            String resourcesFolder)
    {
        super(agent, metadata, resourcesFolder);
        
        this.logger = Logger.getLogger(
                agent.getClass().getName() + "#" + agent.getID());
        this.logger.setLevel(Level.WARNING);
        final String planPathRelative = metadata.get(SimObjectProperty.PLANFILE.toString());
        final String planPathAbsolute = Paths.get(resourcesFolder,
                planPathRelative).toString();
        final PoshPlan poshPlan = loadPoshPlanFromFile(planPathAbsolute);
        // Creation of the context
        this.context = new SimulationContext(agent);
        
        agent.setHighLevelData(this.context);
        
        this.workExecutor = new StateWorkExecutor(this.logger);
        // Creation of the actions of the plan, done by reflection
        for (final String actionClassName : poshPlan.getActionsNames())
        {
            try
            {

                final SimulationAction action = (SimulationAction) Class
                        .forName(actionClassName)
                        .getConstructor(SimulationContext.class)
                        .newInstance(this.context);
                this.workExecutor
                        .addAction(action.getClass().getName(), action);
            } catch (final Exception ex)
            {
                this.logger.log(Level.SEVERE, null, ex);
            }
        }
        // the same its done with the senses
        for (final String actionClassName : poshPlan.getSensesNames())
        {
            try
            {
                final SimulationSense sense = (SimulationSense) Class
                        .forName(actionClassName)
                        .getConstructor(SimulationContext.class)
                        .newInstance(this.context);
                this.workExecutor.addSense(sense.getClass().getName(), sense);
            } catch (final Exception ex)
            {
                this.logger.log(Level.SEVERE, null, ex);
            }
        }
        
        // creation of the engine
        this.engine = new PoshEngine(agent.getID(), poshPlan,
                new SystemClockTimer(),
                Logger.getLogger(SPOSHLogicController.class.getName()));
        // tenemos el contexto ya.

    }

    /**
     * Logic method evaluates the posh plan every time it is called.
     */
    @Override
    public final void step()
    {

        if (getEngine().getLog() != null)
        {
            // getEngine().getLog().info("Invoking SPOSH engine.");
        }
        // LoggableWorkExecutor loggableWorkExecutor = new LoggableWorkExecutor(
        // workExecutor);
        while (true)
        {
            // EvaluationResultInfo result = getEngine().evaluatePlan(
            // loggableWorkExecutor);
            final EvaluationResultInfo result = getEngine()
                    .evaluatePlan(this.workExecutor);
            // String lastPrimitive =
            // loggableWorkExecutor.getLastExecutedPrimitive();
            if (result.type != null
                    && (result.type == FireResult.Type.CONTINUE
                    || result.type == FireResult.Type.FOLLOW
                    || result.type == FireResult.Type.FULFILLED
                    || result.type == FireResult.Type.SURFACE_CONTINUE || result.type == FireResult.Type.FAILED))
            {
                if (getEngine().getLog() != null)
                {
                    // getEngine().getLog().info("Plan evaluation continues...");
                }
                continue;
            }
            break;
        }
        if (getEngine().getLog() != null)
        {
            // getEngine().getLog().info("Plan evaluation end.");
        }

    }

    public static synchronized PoshPlan loadPoshPlanFromFile(String planFilePath)
    {
        try
        {
            return parsePlan(getPlanFromFile(planFilePath));
        } catch (IOException | ParseException ex)
        {
            Logger.getLogger(SPOSHLogicController.class.getName()).log(
                    Level.SEVERE, null, ex);
            throw new RuntimeException(ex);
        }
        /*
         * if (!cachedPlans.containsKey(planFilePath)) {
         * 
         * try { cachedPlans.put(planFilePath, ); } catch (IOException |
         * ParseException ex) { logger.log( Level.SEVERE, null, ex); throw new
         * RuntimeException(ex); }
         * 
         * } return cachedPlans.get(planFilePath);
         */
    }

    /**
     * Parse the supplied plan.
     *
     * @param planSource plan source to be parsed
     * @return parsed plan
     * @throws ParseException if there is an syntax error in the plan.
     */
    public static PoshPlan parsePlan(String planSource) throws ParseException
    {
        final StringReader planReader = new StringReader(planSource);
        final PoshParser parser = new PoshParser(planReader);
        return parser.parsePlan();
    }

    /**
     * Get sposh engine for this logic
     *
     * @return null if engine wasn't yet created(is created in
	 *         {@link SposhLogicController#initializeController(UT2004Bot) } ) or the
     * engine.
     */
    protected final PoshEngine getEngine()
    {
        return this.engine;
    }

    /**
     * Read POSH plan from the stream and return it. Close the stream.
     *
     * @param in Input stream from which the plan is going to be read
     * @return Text of the plan, basically content of the stream
     * @throws IOException If there is some error while reading the stream
     */
    public static String getPlanFromStream(InputStream in) throws IOException
    {
        final BufferedReader br = new BufferedReader(new InputStreamReader(in));

        final StringBuilder plan = new StringBuilder();
        String line;
        try
        {
            while ((line = br.readLine()) != null)
            {
                plan.append(line);
            }
        } finally
        {
            br.close();
        }

        return plan.toString();
    }

    /**
     * Read POSH plan from the file and return it.
     *
     * @param filename Path to the file that contains the POSH plan.
     * @return Text of the plan, basically content of the file
     * @throws IOException If there is some error while reading the stream
     */
    public static String getPlanFromFile(String filename) throws IOException
    {
        final FileInputStream f = new FileInputStream(filename);
        return getPlanFromStream(f);
    }

    /**
     * Get POSh plan from resource int the same jar as the class.
     * 

* *

     * // Plan is stored in package cz.cuni.amis.pogamut.testbot under name
     * // poshPlan.lap
     * // This can get the file from .jar or package structure
     * getPlanFromResource("cz/cuni/amis/pogamut/testbot/poshPlan.lap");
     * 
* * @param resourcePath Path to the plan in some package * @return Content of the plan. * @throws IOException if something goes wrong, like file is missing, * hardisk has blown up ect. */ protected final String getPlanFromResource(String resourcePath) throws IOException { final ClassLoader cl = this.getClass().getClassLoader(); return getPlanFromStream(cl.getResourceAsStream(resourcePath)); } public SimulationContext getContext() { return this.context; } @Override public void stop() { } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy