Using UDP transport data to Non-ROS computer over UDP - c++

I want to transport the data from a ROS computer to the Non-ROS computer over the UDP.
To specify my works now :
I have a LiDAR(Sick TiM561) and I can launch it by the ROS computer successfully, and I can use the "Subscriber" to get the data of the LiDAR now using roscpp which is the c++ code in the ROS. Now,I need to transport the LiDAR's data to the microbox which is a MATLAB-based computer (this PC that you can build your program in it by MATLAB). But I'm not familiar in the c++ code, could someone can suggest me or direct me how to modify the code as below and add it into my roscpp code? Thanks in advance!
For the structure, the Micro box is the client, ROS PC is server.
This is the code of my roscpp:
#include "ros/ros.h"
#include "std_msgs/String.h"
#include "sensor_msgs/LaserScan.h"
void laser_msg_Callback(const sensor_msgs::LaserScan::ConstPtr& scan)
{
for (int x=0;x< scan->ranges.size();x++)
{
ROS_INFO("I heard: [%f]", scan->ranges[x]);
}
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "sick_listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("scan", 811, laser_msg_Callback);
ros::spin();
return 0;
}
And this code maybe is what I need:
UdpClient client;
public IPAddress serverIP = IPAddress.Parse("140.124.35.1");
public Form1()
{
InitializeComponent();
client = new UdpClient();
}
public void SendData()
{
client.Connect(serverIP, 3000);
byte[] data = Encoding.ASCII.GetBytes("Hi, I'm new client.");
client.Send(data, data.Length);
DoListening();
}
public void DoListening()
{
IPEndPoint adress = new IPEndPoint(serverIP, 3000);
byte[] receivedbytes = client.Receive(ref adress);
string recieved = Encoding.ASCII.GetString(receivedbytes);
MessageBox.Show("Recieved: " + recieved);
}
private void button1_Click(object sender, EventArgs e)
{
SendData();
}

I'd think a possible way to go for you is to check out the rossereal implementations. I'm not familiar with development for microbox, probably none of the rosserial supported platforms works with it out of the box, but I thought it's what the rosserial for: to provide a ros-compliant protocol for communicating a ros server with non-ros devices. For that your ros-nodes' code don't even need to know if the client's publishers and/or subscribers are regular ros nodes running on a ros-running computer or they are mimicked by a rosserial client on a non-ros device.
When I used it, the efficiency of rosserial_windows was good for me. I was able to control a rather high resolution camera attached to a windows computer connected to a network with several ros running computers to transfer image messages from the camera with a satisfiable rate.
If none of the available rosserial implementations are compatible with microbox then you may want to check out the rosserial's "Adding Support for New Hardware" and the existing code for rosserial_embeddedlinux to implement the rosserial-like connection thru udp.

Related

How to set low latency in serial port open by QSerialPort

I have already developed an application and it performs serial communication with sensors.
For an unknown reason, my received data is slow with QT C++ Framework.
I have tested the sample code (https://www.pjrc.com/tmp/host_software/receive_test.c). I received data in the appropriate time with this sample code.
Here i found that low latency mode is set ASYNC_LOW_LATENCY.
I have read (https://doc.qt.io/qt-5/qserialport.html) but didn't get any idea about how to set low latency with QSerialPort
Q1: Please give a sample code in qt c++ with QSerialPort on how to set low latency.
Please don't suggest writing c code inside qt c++ this is not the right approach to solve this probleam.
QSerialPort *pUsbSerialPort;
pUsbSerialPort = new QSerialPort();
if(IS_VALID_OBJ(pUsbSerialPort))
{
pUsbSerialPort->setPortName(sSerialPort);
pUsbSerialPort->setBaudRate(BaudRate);
pUsbSerialPort->setDataBits(QSerialPort::Data8);
pUsbSerialPort->setParity(QSerialPort::NoParity);
pUsbSerialPort->setStopBits(QSerialPort::OneStop);
pUsbSerialPort->setFlowControl(QSerialPort::NoFlowControl);
if(pUsbSerialPort->open(QIODevice::ReadWrite))
{
connect(pUsbSerialPort, &QSerialPort::readyRead,this , &Laser::LaserReadyRead);
PRINT_INFO("Serial port successfully initialized" + sSerialPort);
bIsServeropen = true;
}
else
{
PRINT_INFO("Serial port initialization failed" + sSerialPort);
return;
}
}
else
{
PRINT_INFO(" Failed to assign memory to pUsbSerialPort" + sSerialPort);
return;
}
The descriptor is the Handle of the QSerialPort:
#include <sys/ioctl.h>
#include <linux/serial.h>
// ...
pUsbSerialPort->open(QIODevice::ReadOnly);
int fd = pUsbSerialPort->handle();
struct serial_struct kernel_serial_settings;
::ioctl(fd, TIOCGSERIAL, &kernel_serial_settings);
kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
::ioctl(fd, TIOCSSERIAL, &kernel_serial_settings);

Micro:Bit read bluetooth message

I want to send messages from my Micro:Bit to a linked device over bluetooth. I have the following code for Micro:Bit:
#include "MicroBit.h"
#include "MicroBitUARTService.h"
MicroBitUARTService *uart;
MicroBit uBit;
uint8_t connected = 0;
void onConnect(MicroBitEvent)
{
connected = 1;
uBit.display.print("C");
}
void onDisconnect(MicroBitEvent)
{
connected = 0;
uBit.display.print("D");
}
void onButtonA(MicroBitEvent e)
{
if (connected == 0) {
uBit.display.print("X");
return;
}
uart->send("Button A");
uBit.display.print("A");
}
void onButtonB(MicroBitEvent e)
{
if (connected == 0) {
uBit.display.print("X");
return;
}
uart->send("Button B");
uBit.display.print("B");
}
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, onConnect);
uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, onDisconnect);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, onButtonA);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonB);
uart = new MicroBitUARTService(*uBit.ble, 32, 32);
uBit.display.print("S");
release_fiber();
}
I'm able to pair it with my macbook using the following tool:
Once paired, I don't know how to read the messages sent over uart bluetooth.
Don't let the term UART in the characteristic name confuse you, it's just a standard characteristic and has nothing to do with actual UART.
according to the documentation, indications are used with the UART TX characteristic so look at how to use Indications from your API .
https://lancaster-university.github.io/microbit-docs/resources/bluetooth/bluetooth_profile.html
And
https://lancaster-university.github.io/microbit-docs/ble/uart-service/#example-microbit-application-animal-vegetable-mineral-game for an Android example.
Martin
More....
Per the profile documentation for which I gave the link above, you can write to the RX characteristic but must subscribe to Indications to the TX characteristic. You cannot read it directly.
On a Raspberry Pi I would use the Noble node.hs module:
https://github.com/sandeepmistry/noble
For indications use
characteristic.subscribe([callback(error)]);
and
characteristic.on('data', callback(data, isNotification));
For writing use
characteristic.write(data, withoutResponse[, callback(error)]); // data is a buffer, withoutResponse is true|false
I know you are not interested in phones but the principle is exactly the same, whichever platform you are coding for and whichever API you use. You just need to know what operations each characteristic supports and then use your API accordingly.

open : Resource busy when trying to communicate to arduino

I have a very simple question but for some reason I can't find any answer. I'm a total beginner with arduino and c++. I just want to be able to send an angle from xcode to a servo motor. I'm on macos 10.9.5.
So my arduino is connected to the serial port "/dev/cu.usbmodem1411". My c++ code connects to this port and send a number. Then my arduino should receive it and control the servo. It's pretty simple but apparently my c++ code can't access the serial port when my arduino is connected. How am I supposed to make them communicate ?
If I run my c++ code first, I get a timeout error on arduino.
Here is my arduino code :
#include <AFMotor.h>
#include <Servo.h>
Servo servo1;
void setup() {
Serial.begin(9600);
servo1.attach(9);
}
void loop() {
if (Serial.available()>0){
int x;
x = Serial.read()
servo1.write(x);
}
And my c++ code :
using namespace std;
int main()
{
unsigned int angle;
fstream arduino;
arduino.open("/dev/cu.usbmodem1411");
if(arduino.is_open())
{
do
{
cout<<"\n\nangle ?";
cin>>angle;
arduino<<angle;
}while(angle <= 360);
arduino.close();
}
else
{
cout<<"error";
}
}
I tried another c++ code using the boost library and received the error "open: Resource busy". I have no problem if I try to connect to another port like "/dev/tty.usbmodem1411" but it's not proposed in the arduino tool menu.
My problem is very similar to this one that didn't have a convincing solution.

edited: accessing a method in a running c++ program

I need to make a statistical printout of a socket program.
I am using method Listen(uint32_t port) in c++ thread to listen to clients on the specified port (more than one) and send/receive client's transactions to/from a server.
Now i need to write a log file of how many packet received/sent by this method.
my implementation is shown in the skeleton below:
hub.cpp
//set up necessary header
#include <iostream>
....
#include <vector>
//global variables
std::map<uint32_t,long> * received_pk;
std::map<uint32_t,long> * sent_pk;
void Listen(uint32_t port ); // method
int main (int argc, char **argv){
//set up client ports
vector<uint32_t> client_ports;
client_ports.push_back(50002);
client_ports.push_back(50003);
//initialize variables
received_pk = new std::map<uint32_t,uint32_t>();
sent_pk = new std::map<uint32_t,uint32_t>();
for(uint32_t i=0;i<client_ports.size();i++){
received_pk->insert(std::pair<uint32_t,uint32_t>(client_ports.at(i),0) );
sent_pk->insert(std::pair<uint32_t,uint32_t>(client_ports.at(i),0) );
}
//set up thread
vector<thread*> threads;
for(uint32_t i=0;i<client_ports.size();i++){
cout << "Create Listener in port " << client_ports.at(i) << endl;
threads.push_back(new thread(Listen,client_ports.at(i)));
}
//Wait for the threads to finish
for(uint32_t i=0;i<client_ports.size();i++){
threads.at(i)->join();
}
}
void Listen(uint32_t port){
...
set up struct sockaddr_in client, host;
listen on port: port
...
while(1){
receive packet from client;
received_pk->at(port)++;
check packet type
if(packet==status packet){
update the packet id number
}
if (packet==transaction){
send packet to Server
receive reply
send reply back to client
sent_pk->at(port)++;
}
}
}
Now i need to access received_pk and sent_pk while hub.cpp is still running (probably in the while loop)
I thought of two options:
Access received_pk and sent_pk from an external program: like define a method that can get the packet information while the thread is till running
problem: I don't know if i can access a variable/method while program is executing .
or print received_pk and sent_pk to a log file every 5 seconds.
problem: I don't know if it makes sense to have a timer in the multiple thread.
Please any advice will be appreciated.
Kehinde
Quite possibly, the easiest solution is to put the data in shared memory. The map x is a bit suspect - did you mean std::map<Key, Value>? That doesn't fit well in shared memory. Instead, use simple arrays. There are just 64K ports, and sizeof(long long[65536]) isn't excessive.

C++/IOS Websockets using the Poco Library

I've recently started using the Poco library (which I think is great) and I'm trying to create an Server to connect too using an ios application using socket.io - websocket's. I've managed to use an node js implementation to connect but require a C++ implementation. I've stated by instantiating the websocket within the handleRequest method but unsure to what the next steps are...
Any help would be very much appreciated..
virtual void handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)
{
char buffer[16384];
WebSocket* ws = new WebSocket(req, resp);
//ws->setKeepAlive(false);
int flags;
if (!ws->poll(500,Poco::Net::Socket::SELECT_READ || Poco::Net::Socket::SELECT_ERROR))
{
cout << ".";
}
else
{
int n = ws->receiveFrame(buffer, sizeof(buffer), flags);
if (n > 0)
{
if ((flags & WebSocket::FRAME_OP_BITMASK) == WebSocket::FRAME_OP_BINARY)
{
// process and send out to all other clients
}
}
}
}
Next steps depend on what you are trying to do. Once connected, you have an open channel that you can use for two-way data exchange between browser and server.
For details, see the WebSocketServer example.