org.robokind.api.motion.messaging.RemoteRobotHost Maven / Gradle / Ivy
/*
* Copyright 2011 Hanson Robokind LLC.
*
* 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 org.robokind.api.motion.messaging;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.robokind.api.motion.protocol.RobotRequest;
import org.jflux.api.core.Listener;
import org.jflux.api.messaging.rk.MessageAsyncReceiver;
import org.jflux.api.messaging.rk.MessageSender;
import org.robokind.api.motion.Joint;
import org.robokind.api.motion.Robot;
import org.robokind.api.motion.Robot.JointId;
import org.robokind.api.motion.Robot.RobotPositionMap;
import org.robokind.api.motion.protocol.RobotResponse;
import org.robokind.api.motion.protocol.RobotResponse.RobotResponseHeader;
import org.robokind.api.motion.protocol.MotionFrameEvent;
import org.robokind.api.motion.protocol.RobotDefinitionResponse;
/**
* Hosts a Robot to be controlled by a RemoteRobotClient through some Messaging
* channel. Receives RobotRequest Messages and replies with RobotResponse
* Messages.
*
* @author Matthew Stevenson
*/
public class RemoteRobotHost {
private final static Logger theLogger =
Logger.getLogger(RemoteRobotHost.class.getName());
private Robot myRobot;
private String mySourceId;
private String myDestinationId;
private MessageSender myResponseSender;
private MessageAsyncReceiver myRequestReceiver;
private RequestListener myRequestListener;
private RobotResponseFactory myResponseFactory;
private MessageAsyncReceiver myMotionFrameReceiver;
private Listener myMoveHandler;
/**
* Creates a new RemoteRobotHost to host the given Robot.
* @param robot Robot to host
* @param sourceId arbitrary String identifying this host
* @param destinationId arbitrary String identifying a client
* @param sender MessageSender to send RobotResponses
* @param receiver MessageReceiver to receive RobotRequests from a client
* @param factory factory for creating new RobotResponse Messages
* @param motionFrameReceiver MessageReceiver to receive MotionFrameEvents
* @param moveHandler Listener to handle MotionFrameEvents from clients
*/
public RemoteRobotHost(Robot robot,
String sourceId, String destinationId,
MessageSender sender,
MessageAsyncReceiver receiver,
RobotResponseFactory factory,
MessageAsyncReceiver motionFrameReceiver,
Listener moveHandler){
this(sourceId, destinationId);
initialize(robot, sender, receiver,
factory, motionFrameReceiver, moveHandler);
}
/**
* Creates an empty RemoteRobotHost.
* @param sourceId arbitrary String identifying this host
* @param destinationId arbitrary String identifying a client
*/
protected RemoteRobotHost(String sourceId, String destinationId){
if(sourceId == null || destinationId == null){
throw new NullPointerException();
}
mySourceId = sourceId;
myDestinationId = destinationId;
myRequestListener = new RequestListener();
theLogger.log(Level.INFO,
"Creating Remote Robot. sourceId={0}, destId={1}",
new Object[]{mySourceId, myDestinationId});
}
private void initialize(
Robot robot,
MessageSender sender,
MessageAsyncReceiver receiver,
RobotResponseFactory factory,
MessageAsyncReceiver motionFrameReceiver,
Listener moveHandler){
if(myRequestReceiver != null && myRequestListener != null){
myRequestReceiver.removeListener(myRequestListener);
}if(myMotionFrameReceiver != null && myMoveHandler != null){
myMotionFrameReceiver.removeListener(myMoveHandler);
}
myRobot = robot;
myResponseSender = sender;
myRequestReceiver = receiver;
myResponseFactory = factory;
myMotionFrameReceiver = motionFrameReceiver;
myMoveHandler = moveHandler;
if(myRequestReceiver != null){
myRequestReceiver.addListener(myRequestListener);
}
if(myMotionFrameReceiver != null){
myMotionFrameReceiver.addListener(myMoveHandler);
}
theLogger.log(Level.INFO,
"Initializing Remote Robot. sourceId={0}, destId={1}, robotId={2}",
new Object[]{mySourceId, myDestinationId, myRobot.getRobotId()});
}
/**
* Sets the Robot to host.
* @param robot Robot to host
*/
public void setRobot(Robot robot){
myRobot = robot;
}
/**
* Sets the MessageSender to send RobotResponses.
* @param sender MEssageSender to use
*/
public void setResponseSender(MessageSender sender){
myResponseSender = sender;
}
public MessageSender getResponseSender(){
return myResponseSender;
}
/**
* Sets the MessageReceiver to receive RobotRequests.
* @param receiver MessageReceiver to use
*/
public void setRequestReceiver(
MessageAsyncReceiver receiver){
if(myRequestReceiver != null && myRequestListener != null){
myRequestReceiver.removeListener(myRequestListener);
}
myRequestReceiver = receiver;
if(myRequestReceiver != null && myRequestListener != null){
myRequestReceiver.addListener(myRequestListener);
}
}
/**
* Sets the factory to use for creating new RobotResponse Messages.
* @param factory factory to use for creating new RobotResponse Messages
*/
public void setResponseFactory(RobotResponseFactory factory){
myResponseFactory = factory;
}
/**
* Sets the MessageReceiver to receive MotionFrames
* @param receiver MessageReceiver to use
*/
public void setMotionFrameReceiver(
MessageAsyncReceiver receiver){
if(myMotionFrameReceiver != null && myMoveHandler != null){
myMotionFrameReceiver.removeListener(myMoveHandler);
}
myMotionFrameReceiver = receiver;
if(myMotionFrameReceiver != null && myMoveHandler != null){
myMotionFrameReceiver.addListener(myMoveHandler);
}
}
/**
* Sets the Listener to handle MotionFrames from clients.
* @param moveHandler Listener to handle MotionFrames from clients
*/
public void setMoveHandler(Listener moveHandler){
if(myMotionFrameReceiver != null && myMoveHandler != null){
myMotionFrameReceiver.removeListener(myMoveHandler);
}
myMoveHandler = moveHandler;
if(myMotionFrameReceiver != null && myMoveHandler != null){
myMotionFrameReceiver.addListener(myMoveHandler);
}
}
/**
* Returns the hosted Robot's id.
* @return hosted Robot's id
*/
public Robot.Id getRobotId(){
if(myRobot == null){
return null;
}
return myRobot.getRobotId();
}
/**
* Returns a String identifying this host. Currently unused.
* @return String identifying this host
*/
public String getSourceId(){
return mySourceId;
}
/**
* Returns a String identifying a client. Currently unused.
* @return String identifying a client
*/
public String getDestinationId(){
return myDestinationId;
}
public Robot getRobot(){
return myRobot;
}
/**
* Creates and sends a RobotDefinitionResponse.
* @param req RobotRequest the host is responding to
*/
protected void handleDefinitionRequest(RobotRequest req){
sendDefinitionResponse(req);
}
/**
* Calls connect()
on the hosted Robot. The return value from
* that call is returned in a RobotStatusResponse.
* @param req RobotRequest the host is responding to
*/
protected void handleConnectRequest(RobotRequest req){
sendStatusResponse(req, getRobot().connect());
}
/**
* Calls disconnect()
on the hosted Robot. The return value
* from that call is returned in a RobotStatusResponse.
* @param req RobotRequest the host is responding to
*/
protected void handleDisconnectRequest(RobotRequest req){
getRobot().disconnect();
sendStatusResponse(req, true);
}
/**
* Creates and sends a RobotStatusResponse with the Robot's connection
* status
* @param req RobotRequest the host is responding to
*/
protected void handleConnectionStatusRequest(RobotRequest req){
sendStatusResponse(req, getRobot().isConnected());
}
/**
* Calls setEnabled(true)
on the hosted Robot. Sends a
* successful RobotStatusResponse.
* @param req RobotRequest the host is responding to
*/
protected void handleEnableRequest(RobotRequest req){
getRobot().setEnabled(true);
sendStatusResponse(req, true);
}
/**
* Calls setEnabled(false)
on the hosted Robot. Sends a
* successful RobotStatusResponse.
* @param req RobotRequest the host is responding to
*/
protected void handleDisableRequest(RobotRequest req){
getRobot().setEnabled(false);
sendStatusResponse(req, true);
}
/**
* Creates and sends a RobotStatusResponse with the Robot's enabled status
* @param req RobotRequest the host is responding to
*/
protected void handleEnabledStatusRequest(RobotRequest req){
sendStatusResponse(req, getRobot().isEnabled());
}
/**
* Calls setEnabled(true)
on the hosted Robot's Joint. Sends a
* successful RobotStatusResponse.
* @param req RobotRequest the host is responding to
*/
protected void handleEnableRequestForJoint(RobotRequest req){
getRequestedJoint(req).setEnabled(true);
sendStatusResponse(req, true);
}
/**
* Calls setEnabled(true)
on the hosted Robot's Joint. Sends a
* successful RobotStatusResponse.
* @param req RobotRequest the host is responding to
*/
protected void handleDisableRequestForJoint(RobotRequest req){
getRequestedJoint(req).setEnabled(false);
sendStatusResponse(req, true);
}
/**
* Creates and sends a RobotStatusResponse with the Joint's connection
* status
* @param req RobotRequest the host is responding to
*/
protected void handleEnabledStatusRequestForJoint(RobotRequest req){
sendStatusResponse(req, getRequestedJoint(req).getEnabled());
}
/**
* Retrieves the Joint specified in the RobotRequest.
* @param req RobotRequest specifying a Joint
* @return Joint specified in the RobotRequest
*/
protected Joint getRequestedJoint(RobotRequest req){
Integer jIdInt = req.getRequestIndex();
if(jIdInt == null){
throw new NullPointerException();
}
Joint.Id jId = new Joint.Id(jIdInt);
Robot.Id rId = req.getRobotId();
JointId jointId = new Robot.JointId(rId, jId);
Joint j = getRobot().getJoint(jointId);
if(j == null){
throw new NullPointerException();
}
return j;
}
/**
* Sends a RobotPositionResponse with the Robot's default positions.
* @param req RobotRequest the host is responding to
*/
protected void handleDefaultPositionRequest(RobotRequest req){
sendPositionResponse(req, getRobot().getDefaultPositions());
}
/**
* Sends a RobotPositionResponse with the Robot's goal positions.
* @param req RobotRequest the host is responding to
*/
protected void handleGoalPositionRequest(RobotRequest req){
sendPositionResponse(req, getRobot().getGoalPositions());
}
/**
* Sends a RobotPositionResponse with the Robot's current positions.
* @param req RobotRequest the host is responding to
*/
protected void handleCurrentPositionRequest(RobotRequest req){
sendPositionResponse(req, getRobot().getCurrentPositions());
}
private void sendDefinitionResponse(RobotRequest req){
theLogger.log(Level.INFO,
"Sending Definition Response."
+ " Request Timestamp: {0}, Type: {1}, Source: {2}, Dest: {3}, Robot: {4}.",
new Object[]{req.getTimestampMillisecUTC(), req.getRequestType(),
req.getSourceId(), req.getDestinationId(), req.getRobotId()});
if(myResponseSender == null){
theLogger.log(Level.INFO,
"Unable to send Definition Response, missing ResponseSender."
+ " Request Timestamp: {0}, Type: {1}, Source: {2}, Dest: {3}, Robot: {4}.",
new Object[]{req.getTimestampMillisecUTC(), req.getRequestType(),
req.getSourceId(), req.getDestinationId(), req.getRobotId()});
return;
}
RobotResponseHeader header = getHeader(req);
Robot robot = getRobot();
theLogger.log(Level.INFO,
"Creating Definition Response."
+ " Request Timestamp: {0}, Type: {1}, Source: {2}, Dest: {3}, Robot: {4}."
+ " Using Header: {5}, Robot: {6}",
new Object[]{req.getTimestampMillisecUTC(), req.getRequestType(),
req.getSourceId(), req.getDestinationId(), req.getRobotId(),
header, robot});
RobotDefinitionResponse def =
myResponseFactory.createDefinitionResponse(header, robot);
myResponseSender.notifyListeners(def);
theLogger.log(Level.INFO,
"Definition Response Sent."
+ " Request Timestamp: {0}, Type: {1}, Source: {2}, Dest: {3}, Robot: {4}.",
new Object[]{req.getTimestampMillisecUTC(), req.getRequestType(),
req.getSourceId(), req.getDestinationId(), req.getRobotId()});
}
private void sendStatusResponse(RobotRequest req, boolean value){
if(myResponseSender == null){
return;
}
myResponseSender.notifyListeners(
myResponseFactory.createStatusResponse(
getHeader(req),
value));
}
private void sendPositionResponse(
RobotRequest req, RobotPositionMap positions){
if(myResponseSender == null){
return;
}
myResponseSender.notifyListeners(
myResponseFactory.createPositionResponse(
getHeader(req),
positions));
}
private RobotResponseHeader getHeader(RobotRequest req){
return myResponseFactory.createHeader(
getRobotId(), mySourceId, myDestinationId,
req.getRequestType(), req.getTimestampMillisecUTC());
}
class RequestListener implements Listener{
@Override
public void handleEvent(RobotRequest event) {
String reqType = event.getRequestType();
if(reqType == null){
theLogger.info("Received RobotRequest with null RequestType.");
}else{
theLogger.log(Level.INFO,
"Received RobotRequest with RequestType: {0}.", reqType);
}
if(reqType.equals(RobotRequest.CMD_GET_ROBOT_DEFINITION)){
handleDefinitionRequest(event);
}else if(reqType.equals(RobotRequest.CMD_CONNECT_ROBOT)){
handleConnectRequest(event);
}else if(reqType.equals(RobotRequest.CMD_DISCONNECT_ROBOT)){
handleDisconnectRequest(event);
}else if(reqType.equals(RobotRequest.CMD_GET_CONNECTION_STATUS)){
handleConnectionStatusRequest(event);
}else if(reqType.equals(RobotRequest.CMD_ENABLE_ROBOT)){
handleEnableRequest(event);
}else if(reqType.equals(RobotRequest.CMD_DISABLE_ROBOT)){
handleDisableRequest(event);
}else if(reqType.equals(RobotRequest.CMD_GET_ENABLED_STATUS)){
handleEnabledStatusRequest(event);
}else if(reqType.equals(RobotRequest.CMD_GET_DEFAULT_POSITIONS)){
handleDefaultPositionRequest(event);
}else if(reqType.equals(RobotRequest.CMD_GET_GOAL_POSITIONS)){
handleGoalPositionRequest(event);
}else if(reqType.equals(RobotRequest.CMD_GET_CURRENT_POSITIONS)){
handleGoalPositionRequest(event);
}else if(reqType.equals(RobotRequest.CMD_ENABLE_JOINT)){
handleEnableRequestForJoint(event);
}else if(reqType.equals(RobotRequest.CMD_DISABLE_JOINT)){
handleDisableRequestForJoint(event);
}else if(reqType.equals(RobotRequest.CMD_GET_JOINT_ENABLED_STATUS)){
handleEnabledStatusRequestForJoint(event);
}else{
theLogger.log(Level.WARNING,
"Received unknown request type: {0}", reqType);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy