package com.roboclub.robobuggy.nodes.sensors;
import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamResolution;
import com.google.gson.JsonObject;
import com.roboclub.robobuggy.main.RobobuggyLogicNotification;
import com.roboclub.robobuggy.main.RobobuggyMessageLevel;
import com.roboclub.robobuggy.messages.ImageMessage;
import com.roboclub.robobuggy.messages.NodeStatusMessage;
import com.roboclub.robobuggy.nodes.baseNodes.BuggyBaseNode;
import com.roboclub.robobuggy.nodes.baseNodes.PeriodicNode;
import com.roboclub.robobuggy.ros.Message;
import com.roboclub.robobuggy.ros.MessageListener;
import com.roboclub.robobuggy.ros.NodeChannel;
import com.roboclub.robobuggy.ros.Publisher;
import com.roboclub.robobuggy.ros.Subscriber;
import org.jcodec.api.awt.SequenceEncoder;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* @author Trevor Decker
* <p>
* A software driver for listening to a camera and publishing images from
* it to a message channel
*/
public class CameraNode extends PeriodicNode {
private Webcam webcam;
private Publisher imagePublisher;
private int count = 0;
private SequenceEncoder videoEncoder;
static {
Webcam.setHandleTermSignal(true);
}
/**
* @param channel The channel to publish messages on
* @param period How often new images should be pulled
*/
public CameraNode(NodeChannel channel, int period) {
super(new BuggyBaseNode(channel), period, "Camera_Node");
//setup the webcam
List<Webcam> webcams = Webcam.getWebcams();
//TODO figure out a better way to select
for (Webcam webcam : webcams) {
if (webcam.getName().contains("Logitech")) {
this.webcam = webcam;
this.webcam.setViewSize(WebcamResolution.QVGA.getSize());
this.webcam.open();
break;
}
}
if (this.webcam == null) {
new RobobuggyLogicNotification("Couldn't find Logitech webcam!", RobobuggyMessageLevel.EXCEPTION);
this.webcam = Webcam.getDefault();
// your camera have to support HD720p to run this code
Webcam webcam = Webcam.getDefault();
webcam.setCustomViewSizes(new Dimension[] { WebcamResolution.QVGA.getSize(), WebcamResolution.HD720.getSize() });
webcam.setViewSize(WebcamResolution.QVGA.getSize());
}
//setup image publisher
imagePublisher = new Publisher(channel.getMsgPath());
setupLoggingTrigger();
resume();
}
private void setupLoggingTrigger() {
new Subscriber("cam", NodeChannel.NODE_STATUS.getMsgPath(), new MessageListener() {
@Override
public void actionPerformed(String topicName, Message m) {
try {
NodeStatusMessage message = (NodeStatusMessage) m;
INodeStatus status = message.getMessage();
if (status.equals(LoggingNode.LoggingNodeStatus.STARTED_LOGGING)) {
JsonObject params = message.getParams();
String outputDir = params.get("outputDir").getAsString();
if (!webcam.isOpen()) {
webcam.open();
}
videoEncoder = new SequenceEncoder(new File(outputDir + "/webcam.mp4"));
new RobobuggyLogicNotification("Camera ready", RobobuggyMessageLevel.NOTE);
} else if (status.equals(LoggingNode.LoggingNodeStatus.STOPPED_LOGGING)) {
if (webcam.isOpen()) {
videoEncoder.finish();
webcam.close();
}
} else {
new RobobuggyLogicNotification("Status not recognized by CameraNode", RobobuggyMessageLevel.WARNING);
}
} catch (IOException e) {
new RobobuggyLogicNotification("Log directory doesn't exist!", RobobuggyMessageLevel.EXCEPTION);
}
}
});
}
@Override
protected boolean startDecoratorNode() {
// TODO Auto-generated method stub
return false;
}
@Override
protected boolean shutdownDecoratorNode() {
return true;
}
@Override
protected void update() {
try {
if (webcam != null && imagePublisher != null) {
if (webcam.isOpen()) {
BufferedImage mostRecentImage = webcam.getImage();
imagePublisher.publish(new ImageMessage(mostRecentImage, count));
count = count + 1;
if (videoEncoder != null) {
videoEncoder.encodeImage(mostRecentImage);
}
}
}
} catch (IOException e) {
new RobobuggyLogicNotification("Something went wrong trying to get image!", RobobuggyMessageLevel.EXCEPTION);
}
}
}