Ros subscriber is processing an old message - c++

I am currently trying to pass some information between two ros node.
The publisher, being a ros node written in python publishes a string on to a topic, and the subscriber, being a ros node written in cpp, has a callback function which reacts on messages being sent to that topic.
My problem is with the callback function in the cpp part, which doesn't process the recently published message, but only the one sent just before the new one.The cpp subscriber is basically one message behind.
Echoing the topic shows that the message being published on to the topic is the correct one, so something is must be wrong on the cpp part.
The callback is currently only printing the incomming message, and nothing else.
The subscriber on the CPP part is initialized as such:
status(nodehandle.subscribe("/status",10000,&wrapper::callback, this))
void wrapper::callback(const std_msgs::String& command)
{
ROS_ERROR_STREAM("RECEIVED a callback");
std::cout <<"Received unconverted message: "<< command.data << std::endl;
}
I tried changing the queue_size with no effect.
I am sure that the python code is publishing the right message, by debugging it via echoing the topic.
And sending multiple messages, proves that the messages received on the cpp part is delayed by one message.
Why am I not able to read the newest message published on to the topic?
MWE:
ros::NodeHandle nodehandle;
ros::Publisher control_cpp_to_python;
ros::Publisher control_front_to_python;
ros::Subscriber status_manual;
ros::Subscriber status_auto;
ros::Rate loop_rate;
void callback_manual(const std_msgs::String& command)
{
ROS_ERROR_STREAM("RECEIVED a callback");
std::cout <<"Received unconverted message - manuak: "<< command.data << std::endl;
if(checked == true)
{
std::cout << "Message received from correct callback - Manual" << std::endl;
checked = false;
thread_running=false;
}
else
{
checked = true;
}
}
void callback_auto(const std_msgs::String& command)
{
ROS_ERROR_STREAM("RECEIVED a callback");
std::cout <<"Received unconverted message - auto: "<< command.data << std::endl;
if(checked == true)
{
std::cout << "Message received from correct callback - Manual" << std::endl;
checked = false;
thread_running=false;
}
else
{
checked = true;
}
}
while(thread_running)
{
loop_rate.sleep();
if(!thread_running) break;
if(mode == "manual")
{
std_msgs::Int8 msg;
std::bitset<4> msg_bit;
msg_bit.set(3,1);
msg_bit.set(2,1);
msg_bit.set(1,1);
msg_bit.set(0,0);
std::cout << "Sending message in manual mode!" << std::endl;
std::cout << "Message being: "<< msg_bit << std::endl;
msg.data = int(msg_bit.to_ulong());
control_front_to_python.publish(msg);
}
if(mode == "auto")
{
std::cout << "Publishing message in auto" << std::endl;
std_msgs::Int8 msg;
msg.data = 8;
control_cpp_to_python.publish(msg);
}
ros::spinOnce();
}
I guess this is as scraped as it can be. I guess the issue must be due to me setting the thread_running to false inside the callback. I've currently fixed it by the checked bool as a temporary fix.

Related

QuickFIX C++: How to multithread Market Data function with non-standard QuickFIX functions?

Goal:
To use multi-threading to enable the MarketDataSnapshotFullRefresh to continually run whilst other functions are also running.
Details:
I am aware that QuickFIX C++ uses multithreading to enable multiple sessions to run at the same time when instructed from the configuration file. However, I am unsure of how to achieve the simultaneous running of multiple functions in the same session.
I have a function that consists of a while loop that listens out for information from an alternative data source. Whilst this is running, the MarketDataSnapshotFullRefresh is supposed to be listening out for new market data messages to update a limit order price, and subsequently print these messages to the terminal.
Problem:
The function called request() that is listening out for information is blocking the MarketDataSnapshotFullRefresh function from printing out messages coming from the server, after a successful MarketDataRequest message has been sent.
Please note: A similar question has been asked here regarding this problem, but only solutions for general C++ multithreading was provided (rather than in the context of QuickFIX multithreading).
Questions:
Q1. In the context of QuickFIX C++, can anyone please show a way (or point me to some code examples) for me to achieve a multithreaded solution whereby the function request() can run whilst MarketDataSnapshotFullRefresh messages can be printed to the terminal?
Simplified Program:
#include "Application.h"
#include "quickfix/Session.h"
#include <iostream>
static bool listeningToMarketData = false;
static bool requestMadeAlready = false;
// Output when logged on
void Application::onLogon( const FIX::SessionID& sessionID ) {
std::cout << std::endl << "Logon - " << sessionID << std::endl;
}
// Output when logged out
void Application::onLogout( const FIX::SessionID& sessionID ) {
std::cout << std::endl << "Logout - " << sessionID << std::endl;
}
// Admin output sending from client
void Application::toAdmin( FIX::Message& message, const FIX::SessionID& sessionID) {
// Set logon msg Username/Password
if (FIX::MsgType_Logon == message.getHeader().getField(FIX::FIELD::MsgType))
{
message.getHeader().setField(FIX::Username("XXXXX"));
message.getHeader().setField(FIX::Password("XXXXX"));
}
}
// Output coming from server
void Application::fromApp( const FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::FieldNotFound, FIX::IncorrectDataFormat, FIX::IncorrectTagValue, FIX::UnsupportedMessageType ) {
crack( message, sessionID );
std::cout << std::endl << "INCOMING: " << message << std::endl;
}
// Output sending from this client
void Application::toApp( FIX::Message& message, const FIX::SessionID& sessionID )
throw( FIX::DoNotSend ) {
try {
FIX::PossDupFlag possDupFlag;
message.getHeader().getField( possDupFlag );
if ( possDupFlag ) throw FIX::DoNotSend();
}
catch ( FIX::FieldNotFound& ) {}
std::cout << std::endl << "OUTGOING: " << message << std::endl;
}
// Function handling market data
void Application::onMessage(const FIX44::MarketDataSnapshotFullRefresh& mdMessage, const FIX::SessionID& session) {
static bool isFirstMdMessage = true;
listeningToMarketData = true;
// Print logic redacted for clarity
}
void listenToMarketData() {
FIX44::MarketDataRequest marketDataRequest(
FIX::MDReqID("ABC1"),
FIX::SubscriptionRequestType('1'),
FIX::MarketDepth(1));
marketDataRequest.set( FIX::MDUpdateType(0) );
marketDataRequest.set( FIX::NoMDEntryTypes(2) );
marketDataRequest.set( FIX::NoRelatedSym(1) );
FIX44::MarketDataRequest::NoRelatedSym noRelatedSym;
FIX44::MarketDataRequest::NoMDEntryTypes noMDEntryTypes1;
FIX44::MarketDataRequest::NoMDEntryTypes noMDEntryTypes2;
noRelatedSym.set(FIX::SecurityIDSource("8"));
noRelatedSym.set(FIX::SecurityID("100800"));
noMDEntryTypes1.set( FIX::MDEntryType('0') ); // Bid
noMDEntryTypes2.set( FIX::MDEntryType('1') ); // Offer
marketDataRequest.addGroup( noRelatedSym );
marketDataRequest.addGroup( noMDEntryTypes1 );
marketDataRequest.addGroup( noMDEntryTypes2 );
FIX::Header& mdHeader = marketDataRequest.getHeader();
mdHeader.setField(FIX::TargetCompID("TARGET"));
mdHeader.setField(FIX::SenderCompID("SENDER"));
FIX::Session::sendToTarget(marketDataRequest);
}
void request() {
requestMadeAlready = true;
while (true) {
std::cout << "listening" << std::endl;
usleep(1000000);
}
}
// Run the client application
void Application::run() {
initialiseSystem();
}
// Function initilises market data & web scraper
void Application::initialiseSystem() {
while (true) {
try {
if (!listeningToMarketData) {
listenToMarketData();
}
usleep(5000000);
if (!requestMadeAlready) {
request();
}
}
catch ( std::exception & e )
{
std::cout << "Message Not Sent: " << e.what() << std::endl;
}
}
}

Trying to generate a timed connection for serial device ttys0 on unix-system

i am trying to generate a class for reading from a specific serial device.
For the start process it is necessary to send a char '1', then i have to wait for a response (254 and 255).
Within a period of 10 milliseconds i must sent the next command to the device, but this time the command length is 5 char.
When the communication hasn´t been send in the correct time, the device will run into a timeout and is sending me 255,255,255,2,4.
So i need different sizes of reading and the most importing thing for me is a timeout for the communication, cause otherwise the system will stop working by missing some values.
Therefore i have tried to generate a class using boost::asio::async_read.
It is working in the correct way, i can define the timeout,also the size of bytes to be read. When the device isn´t sending the correct size, the routine is going to be left.
But only the first time, when i try it a second time, the device isn´t sending me something. I have tried to use .open again, but it isn´t solving the issue. Also deactivating the close-function isn´t solving the issue, then the routine is running into an error.
Can someone give me a small tip for my issue. Maybe i am to blind to see my problem.... Bernd
ConnectionWithTimeout::ConnectionWithTimeout(int timeout_)
: timer_(io_service_, boost::posix_time::milliseconds(timeout_))
, serial_port_(io_service_) {
}
void ConnectionWithTimeout::ReadNumberOfChars(int numberOfCharactersToRead_)
{
buffer_.resize(numberOfCharactersToRead_);
for (int i = 0; i < numberOfCharactersToRead_; ++i) {
std::cout << "Clear Buffer[" << i << "]" << std::endl;
buffer_[i] = 0;
}
timer_.async_wait(boost::bind(&::ConnectionWithTimeout::Stop, this));
//async read from serial port
boost::asio::async_read(serial_port_, boost::asio::buffer(buffer_),
boost::bind(&ConnectionWithTimeout::ReadHandle, this,
boost::asio::placeholders::error));
io_service_.run();
}
void ConnectionWithTimeout::Stop() {
std::cout << "Connection is being closed." << std::endl;
serial_port_.close();
std::cout << "Connection has been closed." << std::endl;
}
void ConnectionWithTimeout::ReadHandle(const boost::system::error_code& ec) {
if (ec) {
std::cout << "The amount of data is to low: " << ec << std::endl;
for (std::vector<char>::iterator it = buffer_.begin();
it != buffer_.end(); ++it)
{
std::cout << int(*it) << std::endl;
}
}
else {
std::cout << "The amount of data is correct: " << ec << std::endl;
for (std::vector<char>::iterator it = buffer_.begin(); it !=
buffer_.end(); ++it)
{
std::cout << int(*it) << std::endl;
}
}
}

zeromq / zmqpp : Forward metadata with message

With zmq and zmqpp, I am looking for a way to forward meta-data along with the message it belong. The goal is to get the 'User-Id' in a worker behind a load balancer which own the secure socket.
Here is a simple example, you can see the metadata disappear after being forwarded. I am not sure: is this metadata 'vanishment' a bug or a feature? Is there any workaround?
#include "zmqpp/zmqpp.hpp"
#include "zmqpp/curve.hpp"
int main()
{
zmqpp::curve::keypair client_keypair = zmqpp::curve::generate_keypair();
zmqpp::curve::keypair server_keypair = zmqpp::curve::generate_keypair();
std::cout << "Client Public Key: " << client_keypair.public_key << std::endl;
std::cout << "Server Public Key: " << server_keypair.public_key << std::endl;
zmqpp::context context;
zmqpp::auth authenticator(context);
authenticator.set_verbose(false);
authenticator.configure_curve(client_keypair.public_key);
zmqpp::socket curve_rep(context, zmqpp::socket_type::rep);
curve_rep.set(zmqpp::socket_option::curve_server, true);
curve_rep.set(zmqpp::socket_option::curve_secret_key, server_keypair.secret_key);
curve_rep.bind("tcp://127.0.0.1:4242");
zmqpp::socket curve_req(context, zmqpp::socket_type::req);
curve_req.set(zmqpp::socket_option::curve_server_key, server_keypair.public_key);
curve_req.set(zmqpp::socket_option::curve_public_key, client_keypair.public_key);
curve_req.set(zmqpp::socket_option::curve_secret_key, client_keypair.secret_key);
curve_req.connect("tcp://127.0.0.1:4242");
zmqpp::socket internal_rep(context, zmqpp::socket_type::rep);
internal_rep.bind("inproc://clear");
zmqpp::socket internal_req(context, zmqpp::socket_type::req);
internal_req.connect("inproc://clear");
{
zmqpp::message msg;
msg << "Hello";
curve_req.send(msg);
}
{
zmqpp::message msg;
curve_rep.receive(msg);
// read User-Id
std::string user_id;
std::cout << "- Before forward: ";
if (msg.get_property("User-Id", user_id))
std::cout << user_id << std::endl;
else
std::cout << "No user id" << std::endl;
// Forward message
internal_req.send(msg);
}
{
zmqpp::message msg;
internal_rep.receive(msg);
// read User-Id
std::string user_id;
std::cout << "- After forward: ";
if (msg.get_property("User-Id", user_id))
std::cout << user_id << std::endl;
else
std::cout << "No user id" << std::endl;
std::string content;
msg >> content;
std::cout << "- Message: " << content << std::endl;
}
{
zmqpp::message msg;
msg << "world !";
internal_rep.send(msg);
}
{
zmqpp::message msg;
internal_req.receive(msg);
// Forward message
curve_rep.send(msg);
}
{
zmqpp::message msg;
curve_req.receive(msg);
std::cout << "- Message: " << msg.get<std::string>(0) << std::endl;
}
return 0;
}
Output:
Client Public Key: }-}3(fH/r!I/9*tJX0bN/TT]Y2Qd#{IqszYzBX.g
Server Public Key: !#kpBlDrmW#e3jW)q6FumkKGjv#7lU?y9mD(QWd8
auth: Starting ZAP Authentication Server
- Before forward: }-}3(fH/r!I/9*tJX0bN/TT]Y2Qd#{IqszYzBX.g
- After forward: No user id
- Message: Hello
- Message: world !
auth: Shutdown ZAP Authentication Server
This can be a confusing element of ZMQ. The meta-data to which you are referring is not a part of the ZMQ message itself, it's part of the connection over which you received that message. The fact that you can access it as a property of that message is an artifact of the ZMQ wireline protocol, how data is transferred from one socket to another with all of the information that the receiving socket needs to appropriately process that message. A ZMQ message has no "headers" per se, it just has "frames", and the ZMQ sockets know how to handle those frames when they include metadata.
So, the short answer is that the sockets, being given details to negotiate the Curve crypto, send crypto metadata along with the message and the receiving socket, being set up with crypto details, knows what to do with that meta data. When you send it over "normal" sockets with no crypto, that metadata is stripped. If the backend pair of sockets used crypto, it would no longer have the metadata that applied to the frontend, it would have a User-Id that applied to the broker backend socket.
If you want to add the metadata to the message so it gets sent back to the backend, you'll have to append it to the message data, either directly or in a new message frame (multi-part message) and handle it yourself, it won't be metadata anymore it'll be first-class data.

C++ Wait But Allow Events To Fire

Building a SignalR C++ client using Visual Studio 2013, I am starting with the working sample code from NuGet Package Microsoft.AspNet.SignalR.Client.Cpp.v120.WinDesktop, source here
Reviewing the library source it seems to me the event handling processes are based on the Concurrency Runtime (pplx::task) which relies on C++11 features
void chat(const utility::string_t& name)
{
signalr::hub_connection connection{ U("https://testsite") };
auto proxy = connection.create_hub_proxy(U("ChatHub"));
proxy.on(U("broadcastMessage"), [](const web::json::value& m)
{
ucout << std::endl << m.at(0).as_string() << U(" wrote:") << m.at(1).as_string() << std::endl << U("Enter your message: ");
});
connection.start()
.then([proxy, name]()
{
for (;;)
{
utility::string_t message;
std::getline(ucin, message);
if (message == U(":q"))
{
break;
}
send_message(proxy, name, message);
}
})
.then([&connection]() // fine to capture by reference - we are blocking so it is guaranteed to be valid
{
return connection.stop();
})
.then([](pplx::task<void> stop_task)
{
try
{
stop_task.get();
ucout << U("connection stopped successfully") << std::endl;
}
catch (const std::exception &e)
{
ucout << U("exception when starting or stopping connection: ") << e.what() << std::endl;
}
}).get();
}
I want to eliminate the "user input" component; and instead quit loop when a particular "broadcastMessage" has been received.
If I replace the for loop with a sleep statement, the broadcastMessage event stops firing.
If I use the for loop without the getline, set bComplete to true when done, it works the way I want but causes high CPU usage (obviously)
for (;;)
{
if (bComplete) break;
}
Ideally I want connection to start, and then just wait until the broadcastMessage events signals to close the connection.
In addition the "chat" function shouldn't return until connection has closed.
I can see in your answer that you've already discovered Windows event objects; however, if you were looking for a C++11 platform-independent solution, consider std::condition_variable!
unsigned int accountAmount;
std::mutex mx;
std::condition_variable cv;
void depositMoney()
{
// go to the bank etc...
// wait in line...
{
std::unique_lock<std::mutex> lock(mx);
std::cout << "Depositing money" << std::endl;
accountAmount += 5000;
}
// Notify others we're finished
cv.notify_all();
}
void withdrawMoney()
{
std::unique_lock<std::mutex> lock(mx);
// Wait until we know the money is there
cv.wait(lock);
std::cout << "Withdrawing money" << std::endl;
accountAmount -= 2000;
}
int main()
{
accountAmount = 0;
std::thread deposit(&depositMoney);
std::thread withdraw(&withdrawMoney);
deposit.join();
withdraw.join();
std::cout << "All transactions processed. Final amount: " << accountAmount << std::endl;
return 0;
}
In this example we make two threads: one to deposit money into the account and one to withdraw money. Because it's possible for the thread to withdraw the money to run first, especially because there's more processing involved with depositMoney(), we need to wait until we know the money is there. We lock our thread before accessing the money, and then tell the condition_variable what we are waiting for. The condition_variable will unlock the thread, and once the money has been deposited and notify_all() is called we'll be re-awoken to finish processing our logic.
Note that it's possible to do the exact same using the Windows event objects. Instead of std::condition_variable::wait() and std::condition_variable::notify_all() you'd use SetEvent() and WaitForSingleObject(). This is platform-independent though.
I got this working using WinAPI WaitForSingleObject:
HANDLE hEvent;
void chat(const utility::string_t& name)
{
signalr::hub_connection connection{ U("https://testsite") };
auto proxy = connection.create_hub_proxy(U("ChatHub"));
proxy.on(U("broadcastMessage"), [](const web::json::value& m)
{
ucout << std::endl << m.at(0).as_string() << U(" wrote:") << m.at(1).as_string() << std::endl;
if (m.at(1).as_string() == L"quit")
{
SetEvent(hEvent);
}
});
hEvent = CreateEvent(0, TRUE, FALSE, 0);
connection.start()
.then([proxy, name]()
{
WaitForSingleObject(hEvent, INFINITE);
})
.then([&connection]() // fine to capture by reference - we are blocking so it is guaranteed to be valid
{
return connection.stop();
})
.then([](pplx::task<void> stop_task)
{
try
{
stop_task.get();
ucout << U("connection stopped successfully") << std::endl;
}
catch (const std::exception &e)
{
ucout << U("exception when starting or stopping connection: ") << e.what() << std::endl;
}`enter code here`
}).get();
}

CORBA AMI call not producing callback?

I'm modifying the stock quoter example from the wustl CORBA release. The assignment is to implement a reply handler for the StockFactory class that handles calls to get_stock()
Here's my FactoryHandler implementation:
FactoryHandler_i.h:
#ifndef TAO_TUTORIALS_QUOTER_AMI_CLIENT_FACTORYHANDLER_I_H
#define TAO_TUTORIALS_QUOTER_AMI_CLIENT_FACTORYHANDLER_I_H
#include "QuoterS.h"
class Stock_Factory_Handler_i : public POA_Quoter::AMI_Stock_FactoryHandler
{
public:
Stock_Factory_Handler_i (int *response_count, ::Quoter::Stock_var& result);
void get_stock (::Quoter::Stock_ptr ami_return_val);
void get_stock_excep (::Messaging::ExceptionHolder * excep_holder);
private:
int *response_count_;
::Quoter::Stock_var& result_;
};
#endif /* TAO_TUTORIALS_QUOTER_AMI_CLIENT_HANDLER_I_H */
FactoryHandler_i.cpp:
#include "FactoryHandler_i.h"
#include "ace/streams.h"
Stock_Factory_Handler_i::
Stock_Factory_Handler_i (int *response_count, ::Quoter::Stock_var& result)
: response_count_ (response_count), result_ (result)
{
}
void
Stock_Factory_Handler_i::get_stock (::Quoter::Stock_ptr ami_return_val)
{
cout << "storing result" << endl;
result_ = ami_return_val;
(*this->response_count_)++;
}
void
Stock_Factory_Handler_i::get_stock_excep (::Messaging::ExceptionHolder * excep_holder)
{
// We ignore the exception, but this counts as a response, otherwise
// the application would not finish.
cerr << "Exception raised while getting stock"
<< endl;
(*this->response_count_)++;
}
And the client.cpp, from just before the part where changes have been made:
// ...
// Create and activate the handler...
int response_count = 0;
Single_Query_Stock_Handler_i handler_i (&response_count);
Quoter::AMI_Single_Query_StockHandler_var handler =
handler_i._this ();
// Create and activate the factory handler...
Quoter::Stock_var result;
Stock_Factory_Handler_i factory_handler_i (&response_count, result);
Quoter::AMI_Stock_FactoryHandler_var factory_handler =
factory_handler_i._this();
// Send all the requests, careful with error handling
int request_count = 0;
for (int i = 2; i != argc+1; ++i) {
try {
// Get the stock object
cout << "looking up stock symbol " << argv[i] << endl;
factory->sendc_get_stock (factory_handler.in (), argv[i]);
sleep(3); // wait for a response
cout << "converting result" << endl;
Quoter::Single_Query_Stock_var stock =
Quoter::Single_Query_Stock::_narrow (result.in ());
cout << "checking result" << endl;
CORBA::Any any;
any <<= stock;
CORBA::TypeCode_var tc = any.type();
cout << tc->kind() << endl;
if (CORBA::is_nil (stock.in ())) {
cerr << "Cannot get single query interface for <"
<< argv[i] << ">" << endl;
continue;
}
cout << "reading result" << endl;
stock->sendc_get_price_and_names (handler.in ());
request_count++;
}
catch (Quoter::Invalid_Stock_Symbol &) {
cerr << "Invalid stock symbol <"
<< argv[i] << ">" << endl;
}
}
while (response_count < 2 * request_count // multiply by 2 because both handlers increment response_count
&& orb->work_pending ()) {
orb->perform_work ();
}
// ...
When running the client, the output is:
looking up stock symbol MSFT
converting result
checking result
14
Cannot get single query interface for <MSFT>
(The 14 is the typecode for Stock, that's only for debugging)
Notably missing from the above is the "storing result" message that's supposed to be printed in the FactoryHandler's get_stock() callback method. I'm at a loss as to why, since the sendc_get_stock() method doesn't produce any (immediate) errors and is basically just a copy of the StockHandler's code, and from there it's the responsibility of the AMI/ORB interface to make the callback. But the original example (with a StockHandler only) works fine.
What am I doing wrong (and how do I fix it)?
EDIT: another bit of information: on the server side, StockFactory's get_stock() method does get called.
Sorry, I've no aswer for you. But a hint, ask your question at TOA's maling list at http://www.cs.wustl.edu/~schmidt/ACE-mail.html
HTH
I think that your problem is that work_pending returns true only if the ORB has immediate work to do, so it returns false in the time after your client sent his request and before the server sends his reply.
To validate that, simply remove the && orb->work_pending() condition from the loop, and use the version of perform_work that takes a timeout argument.