Here, Sender RTC which has OutPort(s), and Receiver RTC which has InPort(s) are shown.
Setting of RTC Builder
If you use original data type, you must write IDL file and configure your RTC Builder.
Select menu -> window -> setting, and in the dialog, select “RTC Builder” -> “Data Type”, and select the folder your IDL file is placed in.
The default data type IDL is in C:¥Program Files (x86)¥OpenRTM-aist¥1.0¥rtm¥idl
I recommend you to reboot your eclipse.
ConsoleIn (RTC with OutPort)
ConsoleIn RTC receives your key inputs
RTC Builder
Tab | Parameter | Setting |
Basic | Module name | ConsoleIn |
Module description | Console In Component | |
Module version | 1.0.0 | |
Module vender | Your Name | |
Module category | TEST | |
Component type | STATIC | |
Component Kind | Data Flow | |
Component’s activity type | PERIODIC | |
Number of maximum instance | 1 | |
Execution Type | Periodic Execution Context | |
Execution Rate | 1.0 | |
Abstract | Not Important | |
RTC Type | Not Important | |
Output Project | ConsoleIn | |
Activity | on_execute | Check |
Data Port (OutPort Profile) |
PortName | out (Port name) |
DataType | TimedLong (Data type) | |
VarName | out (variable which has data of the port) | |
Disp. Position | RIGHT (Display position in RTSE) | |
Language & environment | Language | C++, Java, Python |
Coding
m_out is data buffer of OutPort, and m_outOut is OutPort itself. In the auto generated initialization code, both variables are connected so the data can automatically transported between two variables.
The writing sequence of OutPort is …
1. Write data to m_out (buffer).
2. Call m_outOut.write function.
RTC::ReturnCode_t ConsoleIn::onExecute(RTC::UniqueId ec_id) { std::cout << "Input number:" << std::endl; std::cin >> m_out.data; m_outOut.write(); return RTC::RTC_OK; } |
If out is sequence type (variable length array), you need to change the buffer length by calling “length” function.
RTC::ReturnCode_t ConsoleSeqIn::onExecute(RTC::UniqueId ec_id) { m_out.data.length(3); for(int i = 0;i < 3;i++) { long value; std::cout << "Input number:" << std::ends; std::cin >> value; std::cout << "Data is " << value << std::endl; m_out.data[i] = value; } m_outOut.write(); return RTC::RTC_OK; } |
- m_out_val : TimedLong
- m_out : DataRef
- m_outOut : DataPort
You must watch two of them, m_out (DataRef type) and m_outOut (DataPort type).
@Override protected ReturnCode_t onExecute(int ec_id) { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String line; try { System.out.println("Input Number"); line = reader.readLine(); System.out.println("Number is " + line); } catch (IOException ioex) { System.out.println("Excepiton occured in onExecute."); return RTC.ReturnCode_t.RTC_ERROR; } m_out.v.data = Integer.parseInt(line); m_out.v.tm = new RTC.Time(0, 0); m_outOut.write(); return super.onExecute(ec_id); } |
You must write your data to m_out.v parameter. If you use Sequence type, data is array (collection type).
Difference to C++ is Timestamp. The timestamp is not automatically generated, so you must manually set the timestamp at least once.
If you use sequence type (variable length array), “m_out.v.data” is array.
First, allocate enough size of array for the “m_out.v.data”. (I recommend you to set the memory in onInitialized function, because “new” operator is heavy.)
@Override protected ReturnCode_t onExecute(int ec_id) { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String lineBuffer; m_out.v.tm = new RTC.Time(0, 0); m_out.v.data = new int[3]; for(int i = 0;i < 3;i++) { System.out.print("Input Number:"); try { lineBuffer = reader.readLine(); } catch (IOException ioe) { System.out.println(ioe); return RTC.ReturnCode_t.RTC_ERROR; } int value = Integer.parseInt(lineBuffer); System.out.println("Value = " + value); m_out.v.data[i] = value; } m_outOut.write(); return super.onExecute(ec_id); } |
Set data to “_d_out”, and call “_outOut.write” function.
def onExecute(self, ec_id): print "Input number: " self._d_out.data = long(sys.stdin.readline()) OpenRTM_aist.setTimestamp(self._d_out) print "Data is %d" % (self._d_out.data) self._outOut.write() return RTC.RTC_OK |
In Python, if you use sequence, prepare an empty list, and use append function to add elements, then, set the list to “_d_out.data” variable.
def onExecute(self, ec_id): OpenRTM_aist.setTimestamp(self._d_out) dataBuffer = []; print "Input 3 numbers" for v in range(3): print "Input number: " value = long(sys.stdin.readline()) print "Data is %d" % (value) dataBuffer.append(value) self._d_out.data = dataBuffer; self._outOut.write() return RTC.RTC_OK |
RTC with InPort
RTC Builder
Tab | Parameter | Setting |
Basic | Module name | ConsoleOut |
Module description | Console Out Component | |
Module version | 1.0.0 | |
Module vender | Your name | |
Module category | TEST | |
Component type | STATIC | |
Component Kind | Data Flow | |
Component’s activity type | PERIODIC | |
Number of maximum instance | 1 | |
Execution Type | Periodic Execution Context | |
Execution Rate | 1.0 | |
Abstract | Not important | |
RTC Type | Not important | |
Output Project | ConsoleOut | |
Activity | on_execute | Checked |
DataPort (InPort) | PortName | in (name of port) |
DataType | TimedLong (type of port) | |
VarName | in (variable of buffer) | |
Disp. Position | LEFT (direction of display) | |
Language and Environment | Language | C++, Java, Python |
Coding
Edit onExecute function.
“m_inIn” is InPort class object. You can use InPort#isNew function to check if the InPort received data (or not). If isNew returns true, you can receive data with InPort#read function.
When read function succeeded, the received data is copied to “m_in”, and you can get the data from m_in.data member.
RTC::ReturnCode_t ConsoleOut::onExecute(RTC::UniqueId ec_id) { if (m_inIn.isNew()) { m_inIn.read(); std::cout << "Data is " << m_in.data << std::endl; } return RTC::RTC_OK; } |
If you use sequence, m_in.data is array. The length function (without any argument) returns the length of array received.
RTC::ReturnCode_t ConsoleSeqOut::onExecute(RTC::UniqueId ec_id) { if(m_inIn.isNew()) { m_inIn.read(); std::cout << m_in.data.length() << " datas received." << std::endl; for(int i = 0;i < m_in.data.length();i++) { std::cout << "Data is " << m_in.data[i] << std::endl; } } return RTC::RTC_OK; } |
You only have to know m_in (DataRef type), and m_inIn (InPort).
@Override protected ReturnCode_t onExecute(int ec_id) { if(m_inIn.isNew()) { m_inIn.read(); System.out.println("Data is " + m_in.v.data); } return super.onExecute(ec_id); } |
First, use isNew function to test if the data is received or not.
If read function is succeeded, m_in variable has the data.
If sequence, m_in.v.data is array.
@Override protected ReturnCode_t onExecute(int ec_id) { if(m_inIn.isNew()) { m_inIn.read(); System.out.println(m_in.v.data.length + " data received."); for(int i = 0;i < m_in.v.data.length;i++) { System.out.println("Data is " + m_in.v.data[i]); } } return super.onExecute(ec_id); } |
You can use _inIn.read function, and the return value is received value.
def onExecute(self, ec_id): if self._inIn.isNew(): data = self._inIn.read() print "Received: ", data.data return RTC.RTC_OK |
If sequence, its quite natural for Python programmer.
def onExecute(self, ec_id): if self._inIn.isNew(): dataBuffer = self._inIn.read() print "Receive %d datas" % len(dataBuffer.data) for v in dataBuffer.data: print "Data is %d" % (v) return RTC.RTC_OK |
Execution
Edit rtc.conf file.
corba.nameservers: localhost:2809
Then, launch name service and execute ConsoleIn / ConsoleOut.
Connection using RT System Editor
Next, let’s connect RTCs.
Select File -> “Open New System Editor”, then, drag / drop both RTCs from “Name Service View” to the editor
Next, connect both connectors by drag/drop. An dialog will be shown, immediately after you connect.
Then select “push” in Dtataflow type.
Okay, you are ready to communicate.
When you activate both RTCs, you can find “Input number” in console of ConsoleIn.
Input number as you like, and then, press enter.
You can find the number you put in the console of ConsoleOut.
Sammary
What do you think of it?
You can realize the communication among RTCs.
C++: ConsoleOut
C++: ConsoleIn
Java: ConsoleInOutJ
Python: ConsoleInOutPy
Example of Sequence
C++: ConsoleSeqInOut
Java: ConsoleSeqInOutJ
Python: ConsoleSeqInOutPy
Column
subscription_type
Subscription type is very important, and you need to know if you manage the whole RT system.
You can select three types of subscription_type parameter.
flush
Immediately after you call OutPort#write, data is sent to InPort’s buffer. The write function blocks when the data is successfully transported.
new
The data is sent by another process, so write method does not block. This setting can select “push policy”.
ALL: all available datas in OutPort side buffer will be sent to InPort side.
FIFO: one data will be sent.
SKIP: a certain number of datas are sent.
NEW: the newest one is sent.
periodic
The data is sent periodically. You can not synchronize Sender and Receiver. If you set “push rate”, frequency of data transport can be changed, but tuning is difficult.