/******************************************************************************** * * JOrocos Library * * Copyright (c) 2011 * All rights reserved. * * Luca Gherardi * University of Bergamo * Dept. of Information Technology and Mathematics * * ------------------------------------------------------------------------------- * * File: CorbaOrocosConnection.java * Created: Jul 27, 2011 * * Author: <A HREF="mailto:luca.gherardi@unibg.it">Luca Gherardi</A> * * Supervised by: <A HREF="mailto:brugali@unibg.it">Davide Brugali</A> * * In cooperation with: <A HREF="mailto:herman.bruyninckx@mech.kuleuven.be">Herman Bruyninckx</A> * * ------------------------------------------------------------------------------- * * This software is published under a dual-license: GNU Lesser General Public * License LGPL 2.1 and BSD license. The dual-license implies that users of this * code may choose which terms they prefer. * * ------------------------------------------------------------------------------- * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - Neither the name of the University of Bergamo nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License LGPL as * published by the Free Software Foundation, either version 2.1 of the * License, or (at your option) any later version or the BSD license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License LGPL and the BSD license for more details. * * You should have received a copy of the GNU Lesser General Public * License LGPL and BSD license along with this program. * *******************************************************************************/ package it.unibg.robotics.jorocos.corba; import it.unibg.robotics.jorocos.core.AbstractOrocosConnection; import it.unibg.robotics.jorocos.core.OrocosDataPort; import it.unibg.robotics.jorocos.core.OrocosDataPort.OutputPortStatus; import it.unibg.robotics.jorocos.core.OrocosDataPort.PortType; import it.unibg.robotics.jorocos.core.PortReadingResult; import it.unibg.robotics.jorocos.exceptions.WrongUseOfConnectionException; import org.apache.log4j.Logger; import org.omg.CORBA.AnyHolder; import RTT.corba.CConnPolicy; import RTT.corba.CConnPolicyHolder; import RTT.corba.CConnectionModel; import RTT.corba.CFlowStatus; import RTT.corba.CNoCorbaTransport; import RTT.corba.CNoSuchPortException; /** * The Class CorbaOrocosConnection is a specialization of AbstractOrocosConnection * defined for the CORBA transport. * * @author <A HREF="mailto:luca.gherardi@unibg.it">Luca Gherardi</A> * @version 1.0 * @since August 2011 */ public class CorbaOrocosConnection extends AbstractOrocosConnection { /** The logger. */ private Logger logger; /** * Instantiates a new Orocos connection impl. * * @param port the port * @param connectionType the connection type. {@link #connectionType} * @param init the init option. If true, one should initialize the connection's value with the last * value written on the writer port. This is only possible if the writer * port has the keepsLastWrittenValue() flag set (i.e. if it remembers what was the last written value). * @param lockPolicy the lock policy. {@link #lockPolicy} * @param pull the pull option. If true, then the sink will have to pull data. Otherwise, it is pushed * from the source. In both cases, the reader side is notified * that new data is available by base::ChannelElementBase::signal() * @param bufferSize the buffer size * @param transport the transport option. Can be used to force a certain kind of transports. The number is a RTT * transport id. When the transport type is zero, local in-process communication * is used, unless one of the ports is remote. If the transport type deviates * from the default remote transport of one of the ports, an out-of-band transport * is setup using that type * @param dataSize the data size. Some protocols require a hint on big the data will be, especially if the data is dynamically * sized (like std::vector<double>). If you leave this empty (recommended), the protocol * will try to guess it. The unit of data size is protocol dependent. * @param connectionName the connection name. The connection name. * Can be used to coordinate out of band transport such that they can find each other by * name. In practice, the name contains a port number or file descriptor to be opened. * You only need to provide a name_id if you're using out-of-band transports without * supervisor, for example, when using MQueues without Corba. * @throws CNoCorbaTransport the c no corba transport * @throws CNoSuchPortException the c no such port exception */ private CorbaOrocosConnection(OrocosDataPort port, ConnectionType connectionType, boolean init, LockPolicy lockPolicy, boolean pull, int bufferSize, int transport, int dataSize, String connectionName) throws CNoCorbaTransport, CNoSuchPortException { logger = Logger.getLogger(CorbaOrocosConnection.class); this.port = port; this.connectionType = connectionType; CConnectionModel type; if(connectionType == ConnectionType.DATA){ type = RTT.corba.CConnectionModel.CData; }else{ type = RTT.corba.CConnectionModel.CBuffer; } RTT.corba.CLockPolicy policy; if(lockPolicy == LockPolicy.USYNC){ policy = RTT.corba.CLockPolicy.CUnsync; }else if(lockPolicy == LockPolicy.LOCK_FREE){ policy = RTT.corba.CLockPolicy.CLockFree; }else{ policy = RTT.corba.CLockPolicy.CLocked; } connectionPolicy = new CConnPolicy(type, init, policy, pull, bufferSize, transport, dataSize, connectionName); CConnPolicyHolder policyHolder = new CConnPolicyHolder(connectionPolicy); if(port.getPortType() == PortType.INPUT_PORT){ channelElement = port.getComponent().getCDataFlowInterface().buildChannelOutput(port.getName(), policyHolder); if(port.getComponent().getCDataFlowInterface().channelReady(port.getName(), channelElement)){ logger.info("Createad a connection to the port " + port.getName()); }else{ logger.warn("Connection to the port " + port.getName() + " failed"); } }else{ channelElement = port.getComponent().getCDataFlowInterface().buildChannelInput(port.getName(), policyHolder); logger.info("Createad a connection to the port " + port.getName()); } } /** * Creates a data connection to the specified data port. * * @param port the port * @param lockPolicy the lock policy * @return the created connection * @throws CNoCorbaTransport the c no corba transport * @throws CNoSuchPortException the c no such port exception */ public static AbstractOrocosConnection createDataConnection(OrocosDataPort port, LockPolicy lockPolicy) throws CNoCorbaTransport, CNoSuchPortException{ return new CorbaOrocosConnection(port, ConnectionType.DATA, false, lockPolicy, false, 0, 0, 0, ""); } /** * Creates a buffer connection to the specified data port. * * @param port the port * @param lockPolicy the lock policy * @param bufferSize the buffer size * @return the created connection * @throws CNoCorbaTransport the c no corba transport * @throws CNoSuchPortException the c no such port exception */ public static AbstractOrocosConnection createBufferConnection(OrocosDataPort port, LockPolicy lockPolicy, int bufferSize ) throws CNoCorbaTransport, CNoSuchPortException{ return new CorbaOrocosConnection(port, ConnectionType.BUFFER, false, lockPolicy, false, bufferSize, 0, 0, ""); } /** * @see AbstractOrocosConnection#readData() */ @Override public PortReadingResult readData() throws WrongUseOfConnectionException{ if(port.getPortType() == PortType.INPUT_PORT){ logger.error("You are trying to read from an Orocos input port "); throw new WrongUseOfConnectionException(port.getPortType()); } AnyHolder holder = new AnyHolder(); CFlowStatus flowStatus = channelElement.read(holder, false); if(flowStatus == CFlowStatus.CNewData){ return new PortReadingResult(OutputPortStatus.NEW_DATA, AnyObjectCast.anyToObject(holder.value)); //return new ReadOperationResult(OutputPortStatus.NEW_DATA, holder.value); }else if(flowStatus == CFlowStatus.COldData){ return new PortReadingResult(OutputPortStatus.OLD_DATA, AnyObjectCast.anyToObject(holder.value)); //return new ReadOperationResult(OutputPortStatus.OLD_DATA, holder.value); }else{ return new PortReadingResult(OutputPortStatus.NO_DATA, null); } } /** * @see AbstractOrocosConnection#writeData(Object) */ @Override public boolean writeData(Object value) throws WrongUseOfConnectionException { if(port.getPortType() == PortType.OUTPUT_PORT){ logger.error("You are trying to write on an Orocos output port "); throw new WrongUseOfConnectionException(port.getPortType()); } String portDataType = port.getDataType().toLowerCase(); String valueDataType = value.getClass().getSimpleName(); boolean generalTypesCondition = portDataType.equals(value.getClass().getSimpleName().toLowerCase()) || portDataType.endsWith(value.getClass().getSimpleName().toLowerCase()); // for complex data type (e.g. /std/string) boolean booleanCondition = portDataType.equals("bool") && value.getClass().isAssignableFrom(Boolean.class); boolean charCondition = portDataType.equals("char") && value.getClass().isAssignableFrom(Character.class); boolean intCondition = (portDataType.equals("int") || portDataType.equals("uint")) && value.getClass().isAssignableFrom(Integer.class); boolean arrayCondition = portDataType.equals("array") && (valueDataType.equals("boolean[]") || valueDataType.equals("char[]") || valueDataType.equals("double[]") || valueDataType.equals("float[]") || valueDataType.equals("int[]") || valueDataType.equals("java.lang.String[]")); if(! ( generalTypesCondition || booleanCondition || charCondition || intCondition || arrayCondition)){ //System.out.println(value.getClass().getSimpleName().toLowerCase()); //System.out.println(port.getDataType().toLowerCase()); logger.error("You are trying to write a wrong data type (port type: " + port.getDataType() + " - object type: " + value.getClass().getSimpleName() + ")"); return false; } return channelElement.write(AnyObjectCast.objectToAny(value,port.getDataType().toLowerCase())); } }