edu.umich.robot.util.SimBattery.java Source code

Java tutorial

Introduction

Here is the source code for edu.umich.robot.util.SimBattery.java

Source

/*
 * Copyright (c) 2011, Regents of the University of Michigan
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package edu.umich.robot.util;

import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.common.collect.Maps;
import com.google.common.util.concurrent.MoreExecutors;

/**
 * Super simple battery model for splinter system. Not intended model reality.
 * 
 * Thread-safe.
 * 
 * @author voigtjr
 *
 */
public class SimBattery {
    private static final Log logger = LogFactory.getLog(SimBattery.class);

    private final double mAh_max;
    private final AtomicReference<Double> mAh;
    private final double mAh_min;
    private final ScheduledExecutorService schexec = MoreExecutors
            .getExitingScheduledExecutorService(new ScheduledThreadPoolExecutor(1));
    private final int UPDATE_DT = 5; // seconds
    private final Map<String, Double> current = Maps.newConcurrentMap();
    private final AtomicReference<ScheduledFuture<?>> updateTask = new AtomicReference<ScheduledFuture<?>>();

    /**
     * @param mAh_max
     * @param doc depth of charge
     */
    public SimBattery(double mAh_max, double doc) {
        if (doc > 1.0 || doc < 0.1)
            doc = 1.0;
        if (mAh_max < 0)
            mAh_max = 10000;

        this.mAh_max = mAh_max;
        this.mAh = new AtomicReference<Double>(Double.valueOf(mAh_max));
        this.mAh_min = mAh_max * (1 - doc);

        logger.trace("Battery created with max " + mAh_max + " min " + mAh_min);

        start();
    }

    private final Runnable update = new Runnable() {
        public void run() {
            double total = 0;
            for (Double c : current.values())
                total += c;
            total *= (double) UPDATE_DT / TimeUnit.SECONDS.convert(1, TimeUnit.HOURS);

            double ah = mAh.get();
            ah -= total;

            if (ah < mAh_min)
                ah = mAh_min;

            mAh.set(ah);

            if (logger.isTraceEnabled())
                logger.trace(
                        String.format("Battery life: %3.3f%%, mAh: %2.5f", getRemainingLife() * 100, mAh.get()));
        }
    };

    public void stop() {
        ScheduledFuture<?> t = updateTask.getAndSet(null);
        if (t != null)
            t.cancel(false);
    }

    public void start() {
        updateTask.compareAndSet(null, schexec.scheduleAtFixedRate(update, UPDATE_DT, UPDATE_DT, TimeUnit.SECONDS));
    }

    public void resetCharge() {
        mAh.set(Double.valueOf(this.mAh_max));
    }

    public void setMilliAmpCurrent(String name, double mAh) {
        current.put(name, Double.valueOf(mAh));
    }

    public void removeMilliAmpCurrent(String name) {
        current.remove(name);
    }

    public double getRemainingLife() {
        return (mAh.get() - mAh_min) / (mAh_max - mAh_min);
    }

    public void shutdown() {
        schexec.shutdown();
    }
}