com.github.rinde.rinsim.examples.demo.factory.FactoryExample.java Source code

Java tutorial

Introduction

Here is the source code for com.github.rinde.rinsim.examples.demo.factory.FactoryExample.java

Source

/*
 * Copyright (C) 2011-2016 Rinde van Lon, iMinds-DistriNet, KU Leuven
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.rinde.rinsim.examples.demo.factory;

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Arrays.asList;

import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.Set;

import javax.annotation.Nullable;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;

import org.apache.commons.math3.random.MersenneTwister;
import org.apache.commons.math3.random.RandomGenerator;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Monitor;

import com.github.rinde.rinsim.core.Simulator;
import com.github.rinde.rinsim.core.model.pdp.DefaultPDPModel;
import com.github.rinde.rinsim.core.model.time.TickListener;
import com.github.rinde.rinsim.core.model.time.TimeLapse;
import com.github.rinde.rinsim.event.Listener;
import com.github.rinde.rinsim.examples.demo.swarm.SwarmDemo;
import com.github.rinde.rinsim.geom.Graph;
import com.github.rinde.rinsim.geom.Graphs;
import com.github.rinde.rinsim.geom.LengthData;
import com.github.rinde.rinsim.geom.MultimapGraph;
import com.github.rinde.rinsim.geom.Point;
import com.github.rinde.rinsim.ui.View;
import com.github.rinde.rinsim.ui.renderers.GraphRoadModelRenderer;
import com.github.rinde.rinsim.ui.renderers.RoadUserRenderer;
import com.google.common.collect.ImmutableList;
import com.google.common.math.DoubleMath;

/**
 * @author Rinde van Lon
 *
 */
public final class FactoryExample {

    static final double POINT_DISTANCE = 5d;
    static final long SERVICE_DURATION = 120000;
    static final double AGV_SPEED = 10;
    static final int CANVAS_MARGIN = 30;

    static final int FONT_SIZE = 10;

    static final int VERTICAL_LINE_SPACING = 6;
    static final int NUM_VEHICLES = 12;
    static final int FULL_HD_W = 1920;
    static final int SPEED_UP = 4;
    static final long RANDOM_SEED = 123L;

    // spacing between text pixels
    static final double SPACING = 30d;

    private FactoryExample() {
    }

    /**
     * Starts the example.
     * @param args One optional argument specifying the simulation end time is
     *          supported.
     */
    public static void main(@Nullable String[] args) {
        final long endTime = args != null && args.length >= 1 ? Long.parseLong(args[0]) : Long.MAX_VALUE;

        final Display d = new Display();
        @Nullable
        Monitor sec = null;
        for (final Monitor m : d.getMonitors()) {
            if (d.getPrimaryMonitor() != m) {
                sec = m;
                break;
            }
        }
        run(endTime, d, sec, null);
    }

    /**
     * Run the example.
     * @param endTime The time to stop.
     * @param display The display to show it on.
     * @param m The monitor to show it on.
     * @param list Listener for events.
     * @return The simulator used in the example.
     */
    public static Simulator run(final long endTime, Display display, @Nullable Monitor m, @Nullable Listener list) {

        final Rectangle rect;
        if (m != null) {
            if (list != null) {
                rect = m.getClientArea();
            } else {
                // full screen
                rect = m.getBounds();
            }
        } else {
            rect = display.getPrimaryMonitor().getClientArea();
        }

        List<String> words = asList(" BioCo3 \nDistriNet");
        // spacing between vertical lines in line units

        // screen
        if (rect.width == FULL_HD_W) {
            // AgentWise\nKU Leuven", "iMinds\nDistriNet"
            // " Agent \n Wise ", " Distri \n Net "
            words = asList(" iMinds \nDistriNet");
        }

        final ImmutableList<ImmutableList<Point>> points = createPoints(words);
        final Graph<?> g = createGraph(points);

        final List<Point> borderNodes = newArrayList(getBorderNodes(g));
        Collections.shuffle(borderNodes, new Random(RANDOM_SEED));

        View.Builder view = View.builder().with(GraphRoadModelRenderer.builder().withMargin(CANVAS_MARGIN))
                .with(BoxRenderer.builder())
                .with(RoadUserRenderer.builder().withImageAssociation(AGV.class, "/graphics/flat/forklift2.png"))
                .withTitleAppendix("Factory Demo").withAutoPlay().withAutoClose().withSpeedUp(SPEED_UP);

        if (m != null) {
            view = view.withMonitor(m).withResolution(m.getClientArea().width, m.getClientArea().height)
                    .withDisplay(display);

            if (list != null) {
                view = view.withCallback(list).withAsync();
            } else {
                view = view.withFullScreen();
            }
        }

        final RandomGenerator rng = new MersenneTwister(RANDOM_SEED);
        final Simulator simulator = Simulator.builder().setRandomGenerator(rng)
                .addModel(BlockingGraphRoadModel
                        .blockingBuilder(g).withDistanceUnit(SI.METER).withSpeedUnit(NonSI.KILOMETERS_PER_HOUR))
                .addModel(DefaultPDPModel.builder())
                .addModel(AgvModel.builder()
                        .withPoints(ImmutableList.<ImmutableList<Point>>builder().addAll(points)
                                .add(ImmutableList.copyOf(borderNodes)).build(), getBorderNodes(g)))
                .addModel(view).build();

        for (int i = 0; i < NUM_VEHICLES; i++) {
            final List<Point> l = points.get(rng.nextInt(points.size()));
            final Point p = l.get(rng.nextInt(l.size()));
            simulator.register(new AGV(p));
        }

        simulator.addTickListener(new TickListener() {
            @Override
            public void tick(TimeLapse time) {
                if (time.getStartTime() > endTime) {
                    simulator.stop();
                }
            }

            @Override
            public void afterTick(TimeLapse timeLapse) {
            }
        });

        simulator.start();
        return simulator;
    }

    static ImmutableList<ImmutableList<Point>> createPoints(Iterable<String> words) {
        final ImmutableList.Builder<ImmutableList<Point>> pointBuilder = ImmutableList.builder();
        for (final String word : words) {
            pointBuilder.add(SwarmDemo.measureString(word, FONT_SIZE, SPACING, 2));
        }
        return pointBuilder.build();
    }

    static Graph<?> createGraph(ImmutableList<ImmutableList<Point>> points) {
        int max = 0;
        double xMax = 0;
        double yMax = 0;
        for (final List<Point> ps : points) {
            max = Math.max(max, ps.size());
            for (final Point p : ps) {
                xMax = Math.max(p.x, xMax);
                yMax = Math.max(p.y, yMax);
            }
        }

        int width = DoubleMath.roundToInt(xMax / SPACING, RoundingMode.CEILING);
        width += VERTICAL_LINE_SPACING - width % VERTICAL_LINE_SPACING;
        width += width / VERTICAL_LINE_SPACING % 2 == 0 ? VERTICAL_LINE_SPACING : 0;

        int height = DoubleMath.roundToInt(yMax / SPACING, RoundingMode.CEILING) + 2;
        height += height % 2;
        return createGrid(width, height, 1, VERTICAL_LINE_SPACING, SPACING);
    }

    static void addPath(Graph<?> graph, Point... points) {
        final List<Point> newPoints = newArrayList();
        for (int i = 0; i < points.length - 1; i++) {
            final double dist = Point.distance(points[i], points[i + 1]);
            final Point unit = Point.divide(Point.diff(points[i + 1], points[i]), dist);
            final int numPoints = DoubleMath.roundToInt(dist / POINT_DISTANCE, RoundingMode.FLOOR);
            for (int j = 0; j < numPoints; j++) {
                final double factor = j * POINT_DISTANCE;
                newPoints.add(new Point(points[i].x + factor * unit.x, points[i].y + factor * unit.y));
            }
        }
        newPoints.add(points[points.length - 1]);
        Graphs.addPath(graph, newPoints.toArray(new Point[newPoints.size()]));
    }

    static ImmutableList<Point> getBorderNodes(Graph<?> g) {
        final Set<Point> points = g.getNodes();
        double xMin = Double.MAX_VALUE;
        double yMin = Double.MAX_VALUE;
        double xMax = Double.MIN_VALUE;
        double yMax = Double.MIN_VALUE;

        for (final Point p : points) {
            xMin = Math.min(xMin, p.x);
            yMin = Math.min(yMin, p.y);
            xMax = Math.max(xMax, p.x);
            yMax = Math.max(yMax, p.y);
        }
        final ImmutableList.Builder<Point> builder = ImmutableList.builder();
        for (final Point p : points) {
            if (p.x == xMin || p.x == xMax || p.y == yMin || p.y == yMax) {
                builder.add(p);
            }
        }
        return builder.build();
    }

    static Graph<LengthData> createGrid(int width, int height, int hLines, int vLines, double distance) {
        final Graph<LengthData> graph = new MultimapGraph<LengthData>();

        int v = 0;
        // draw vertical lines
        for (int i = 0; i < width + 1; i++) {
            Point prev = new Point(i * distance, 0);
            if (i % vLines == 0) {
                for (int j = 1; j < height; j++) {
                    final Point cur = new Point(i * distance, j * distance);
                    if (v % 2 == 0) {
                        graph.addConnection(prev, cur);
                    } else {
                        graph.addConnection(cur, prev);
                    }
                    prev = cur;
                }
                v++;
            }
        }

        int y = 1;
        for (int i = 0; i < height; i++) {
            Point prev = new Point(0, i * distance);
            if (i % hLines == 0) {
                for (int j = 1; j < width + 1; j++) {
                    final Point cur = new Point(j * distance, i * distance);
                    if (y % 2 == 0) {
                        graph.addConnection(prev, cur);
                    } else {
                        graph.addConnection(cur, prev);
                    }
                    prev = cur;
                }
            }
            y++;
        }
        return graph;
    }
}