Reading delta values from R&H spectrum analysers - c++

I am currently working on a project where I need to read the difference between the minimum
and maximum markers of a Rhode and Schwarz FSC3 device. I am using NIVisa to connect to the
device over an ethernet connection and pass SCPI commands to it.
The operating system I am using is Ubuntu 20.04.
The code I am using is as shown below -
// Gloabl Visa ResouceManager reference
VisaResourceManager rm;
/**
* Custom type that defines a relation between the deviceIP string
* and a session_t within the Resource Manager
**/
typedef std::map<std::string, VisaResourceManager::session_t> deviceIpSessionMap_t;
deviceIpSessionMap_t devices;
bool device_exists(const std::string deviceIP)
{
deviceIpSessionMap_t::iterator iter = devices.find(deviceIP);
if (iter != devices.end())
{
return true;
}
else
{
return false;
}
}
// --------------------------------------------------------
// Struct defining the ReadConfiguration which is required
// to get readings from the device
// --------------------------------------------------------
struct ReadConfig
{
// The center frequency for the reading
std::string center;
// The span for the reading
std::string span;
// rbw value for reading
std::string rbw;
// vbw value for reading
std::string vbw;
// IP address of the X-pole device
std::string ip;
};
/**
* This function retrieves values from the
* spectrum analyser
*/
int getValueFromDevice(ReadConfig &conf)
{
try
{
//-----------------------------------------------------------
// Set SCPI commands strings
//-----------------------------------------------------------
std::string DeviceIP = "TCPIP::" + conf.ip;
std::string CenterFreq = "FREQ:CENT " + conf.center + "KHz";
std::string Span = "FREQ:SPAN " + conf.span + "KHz";
std::string Rbw = "BAND " + conf.rbw + "KHz";
std::string Vbw = "BAND:VID " + conf.vbw + "Hz";
// logConf(DeviceIP, CenterFreq, Span, Rbw, Vbw);
// Check if the session already exists and reuse it
// if available. If not create a new session and add it
// to the deviceIP to session map
VisaResourceManager::session_t session;
if (device_exists(conf.ip))
{
session = devices[conf.ip];
}
else
{
session = rm.connect(DeviceIP);
devices[conf.ip] = session;
}
session->write("*RST;*CLS\n"); // Reset and clear the device
//-----------------------------------------------------------
// ID the device:
//-----------------------------------------------------------
// session->write("*IDN?");
// std::cout << "status byte = " << session->readSTB() << std::endl;
// std::cout << "*IDN? = " << session->read() << std::endl;
// std::cout << "status byte = " << session->readSTB() << std::endl;
//-----------------------------------------------------------
// Basic Device Settings:
//-----------------------------------------------------------
session->write(CenterFreq); // Setting the center frequency
session->write(Span); // Setting the span
session->write(Rbw); // Setting the RBW
session->write(Vbw); // Setting the VBW
session->write("CALC:DELT1 OFF"); // Removes/resets MARK2 position
session->write("CALC:DELT2 OFF"); // Removes/resets MARK2 position
session->write("CALC:MARK1 OFF"); // Removes/resets MARK1 position
session->write("CALC:MARK2 OFF"); // Removes/resets MARK1 position
session->write("*OPC?"); // Using *OPC? waits until all the instrument settings are finished
//-----------------------------------------------------------
// Setting marker to min and reading the marker Y
//-----------------------------------------------------------
session->write("CALC:DELT1:MIN");
session->write("CALC:MARK1:MAX");
session->write("*OPC?");
session->write("CALC:DELT1:Y?\n");
std::string min = session->read();
int iMin = abs(std::stoi(min));
// std::cout << "iMin : " << iMin << '\n';
//-----------------------------------------------------------
// Disconnect from Device
//-----------------------------------------------------------
// rm.disconnect(session);
return iMin;
}
catch (VisaException ex)
{
std::cout << ex.what() << " -- " << VisaResourceManager::statusDescription(ex.getErrorCode()) << std::endl;
return 0;
}
catch (...){
std::cout << "Encountered an unknown error" << std::endl;
return 0;
}
}
This usually shows me the correct values, but when the analyzer has been on for a while it starts
malfunctioning/reporting absurd values that are too high.
What am I doing wrong ?

Related

Unable to find/read config file .conf - FileIOException

I'm trying to open and read a .conf file in my program using libconfig::readFile(), but it gives me always a FileIOException. I think that the program is unable to locate the file but I don't know where the problem is.
This is the .conf file code:
controlLoopPeriod = 100.0; # ms
saturationMax = [10.0];
saturationMin = [-10.0];
task = { Linear_Velocity = {
type = 0; # 0 equality, 1 inequality
gain = 1.0;
enable = true;
saturation = 10.0;
};
};
priorityLevels = ( { name = "PL_JPosition";
tasks = ["Joint_Position"];
lambda = 0.0001;
threshold = 0.01;
}
);
actions = ( { name = "jPosition";
levels = ["PL_JPosition"];
}
);
states = { State_move = {
minHeadingError = 0.05;
maxHeadingError = 0.2;
};
};
This is where I'm trying to open the file and read it:
bool RobotPositionController::LoadConfiguration() {
libconfig::Config confObj;
// Inizialization
std::string confPath = "home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot";
confPath.append("/conf/");
confPath.append(fileName_);
std::cout << "PATH TO CONF FILE : " << confPath << std::endl;
// Read the file. If there is an error, report it and exit.
try {
confObj.readFile(confPath.c_str());
} catch (const libconfig::FileIOException& fioex) {
std::cerr << "I/O error while reading file: " << fioex.what() << std::endl;
return -1;
} catch (const libconfig::ParseException& pex) {
std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine() << " - " << pex.getError() << std::endl;
return -1;
}
conf_->ConfigureFromFile(confObj);
ConfigureTaskFromFile(tasksMap_, confObj);
ConfigurePriorityLevelsFromFile(actionManager_, tasksMap_, confObj);
// Set Saturation values for the iCAT (read from conf file)
iCat_->SetSaturation(conf_->saturationMin, conf_->saturationMax);
ConfigureActionsFromFile(actionManager_, confObj);
//insert states in the map
statesMap_.insert({ states::ID::jPos, stateJPosition_ });
ConfigureSatesFromFile(statesMap_, confObj);
//insert command in the map
commandsMap_.insert({ commands::ID::jPos, commandJPosition_ });
return true;
}
Thanks in advance for any type of help.
It looks to me you are missing a / at the beginning of your home path.
I.e., change:
std::string confPath = "home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot";
For:
std::string confPath = "/home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot";
I take it you have checked the .conf file exists at:
/home/nimblbot/tpik_ctr_algo/ctrl_rob_nimblbot/conf

SFML UDP lag on localhost

I am currently using SFML to create a game which will allow a client to connect and watch the player gameplay. This is currently being done on localhost, 127.0.0.1 on same port since its UDP.
I am launching two executables - one will be client and the other will be the main player[udpserver].
I am noticing that on the client, there is jittering when spaceship moves, and also bullet is drawn two or three times in instantiating position before going upward. (when bullet spawns, it is rendered to go upward, code executes for both client and server). This is what I have -
void createUdpServer(unsigned short port) { // send data to client
// Create a socket to receive a message from anyone
sf::UdpSocket socket;
sf::IpAddress local = sf::IpAddress::getLocalAddress(); // Currently 127.0.0.1 localhost
sf::IpAddress receiver = sf::IpAddress::getLocalAddress();
socket.setBlocking(false);
// I was figuring out and arranging according to example.. set socket non blocking
// Listen to messages on the specified port
if (socket.bind(port) != sf::Socket::Done && !portBound) // You bind once
return; // error
else {
portBound = true;
}
std::cout << "Server is listening to port " << port << ", waiting for a connection... " << std::endl;
// Wait for a message
char in[128];
std::size_t received;
sf::IpAddress sender;
//unsigned short senderPort; we will be receiving and sending data on sa,e port
sf::SocketSelector selector;
selector.add(socket);
if (selector.wait(sf::milliseconds(10.f))) { // times out after 10ms
if (selector.isReady(socket)) {
if (socket.receive(in, sizeof(in), received, sender, port) != sf::Socket::Done) // blocking
return;
std::cout << "Message received from client " << sender << ": \"" << in << "\"" << std::endl;
}
}
// Sends connection established to client
/*
const char out[] = "Connection with server established!";
if (socket.send(out, sizeof(out), sender, port) != sf::Socket::Done)
return;
*/
// acknowledgement of packets
float playerXPosition = player->getPosition().x;
float playerYPosition = player->getPosition().y;
sf::Packet playerData;
sf::Packet bulletData;
playerData << playerXPosition << playerYPosition << bulletPtr->isAlive() << bulletPtr->getLocation().x << bulletPtr->getLocation().y;
//bulletData << bulletPtr->isAlive() << bulletPtr->getLocation().x << bulletPtr->getLocation().y;
socket.send(playerData, sender, port);
//socket.send(bulletData, sender, port);
//const char out[] = "";
//if (socket.send(out, sizeof(out), sender, port) != sf::Socket::Done)
// return;
}
void runUdpClient(unsigned short port) { // receive data from server
// Ask for the server address
server = "127.0.0.1";
/*
if (server == sf::IpAddress::None)
do
{
std::cout << "Type the address or name of the server to connect to: ";
std::cin >> server;
} while (server != sf::IpAddress::None);
*/
// Create a socket for communicating with the server
sf::UdpSocket socket;
sf::IpAddress recipient = sf::IpAddress::getLocalAddress();
char data[100] = "Connection with client established!";
if (socket.send(data, 100, server, port) != sf::Socket::Done && !sendInitialToServer) // if send once dont't send again
{
// added up top send this only once
// error...
}
else{
sendInitialToServer = true;
}
// Think about putting this globally
sf::SocketSelector selector;
selector.add(socket);
if (selector.wait(sf::milliseconds(10.f))) { // not enough time for server to be created with 0.1f
// received something
if (selector.isReady(socket)) {
// Wait for a message
char in[128];
std::size_t received; // am I using this?
sf::IpAddress sender;
sf::Packet playerData;
sf::Packet bulletData;
float playerXPosition;
float playerYPosition;
float clientXPosition;
float clientYPosition;
float clientBulletX;
float clientBulletY;
bool bulletShot;
socket.receive(playerData, sender, port);
//socket.receive(bulletData, sender, port);
if (playerData >> playerXPosition >> playerYPosition >> bulletShot >> clientBulletX >> clientBulletY) { // if you are able to read
clientXPosition = playerXPosition;
clientYPosition = playerYPosition;
player->setPosition(clientXPosition, clientYPosition);
if (bulletShot) {
// - might not need this
bulletPtr->spawn(true); // once bullet spawned, should be taken care of both sides
if (bulletPtr->isAlive())
bulletPtr->setLocation(clientXPosition - 13.f, clientYPosition - 24.f);
//else
// clientbulletx and clientbullety
//bulletPtr->draw(window); // client window handled from both client and server what to do if bullet is alive
}
}
/*
if (bulletData >> bulletShot >> clientBulletX >> clientBulletY) {
if (bulletShot) {
bulletPtr->spawn(true); // once bullet spawned, should be taken care of both sides
bulletPtr->setLocation(player->getPosition().x - 13.f, player->getPosition().y - 24.f);
//bulletPtr->draw(window); // client window handled from both client and server what to do if bullet is alive
}
}*/
else {
// Handle error / packet loss // else simulate?
std::cout << "Error - failed to read from player data packet!" << std::endl; // this is normal when packet is lost
// I think I am getting several packet drops as I am receiving and sending from the same PC same port, localhost
}
//unsigned short senderPort;
//if (socket.receive(in, sizeof(in), received, sender, port) != sf::Socket::Done)
// return;
//std::cout << "Message received from server " << sender << ": \"" << in << "\"" << std::endl;
}
// this shouldn't be here, receive stuff should go on client, server just sends
}
else {
// timeout reached, nothing was received
}
// prediction
// bullet
}
Let me know if I can provide additional information. This is the order of execution from main -
while (window.isOpen())
{
if (userChoice == NULL){
do {
std::cout << "User Choice - " << userChoice << std::endl;
std::cout << "Server or client? (s/c)" << std::endl;
std::cin >> userChoice;
} while (userChoice != 's' && userChoice != 'c');
// The game clock will keep on restarting until the user makes a decision
clock.restart(); // This solved issue to start movements and updates at same time once user chooses an option
}
if (userChoice == 's' || userChoice == 'c') { // start of main if // else start the whole program
// game time over here once game starts // frame independent
// Binding of ports for both client or server
/*
// bind the socket to a port
if (socket.bind(54000) != sf::Socket::Done)
{
// Using UDP starts listening on this port
// whatever happens, bind for both -> will work with two executables running on same network with two different local IPs
}
*/
// Puts the time counter back to zero and also returns the time elapsed since the clock was started
sf::Time deltaTime = clock.restart();
timeSinceLastUpdate += deltaTime;
while (timeSinceLastUpdate > TimePerFrame) // fixed time steps // userchoice != NULL otherwise it will start immeadiately
{
timeSinceLastUpdate -= TimePerFrame; // solves problem with variable delta time, each frame is unique
processEvents(window);
//update(TimePerFrame);
// Start of if server
if (userChoice == 's'){
//if(!serverCreated){ // if problems of continous connection, this needs to place outside of bind
// create connection
createUdpServer(SERVER_PORT); // over here its happening every frame
//serverCreated = true; // is server actually created though?
//}
// Player 1 movement
sf::Vector2f movement(0.f, 0.f);
if (mIsMovingUp)
movement.y -= playerSpeed;
if (mIsMovingDown)
movement.y += playerSpeed;
if (mIsMovingLeft)
movement.x -= playerSpeed;
if (mIsMovingRight)
movement.x += playerSpeed;
// shooting logic
if (mIsShooting) {
if (!bullet.isAlive()) // && !gameOver
{
bullet.spawn(true);
bullet.setLocation(mPlayer.getPosition().x - 13.f, mPlayer.getPosition().y - 24.f); // mPlayer.getPosition().x + 24 (offset) if origin is not set to center
}
}
// ** These two parts need to be put in an if statement, if server, direct movement, if client, move needs to happen with data received
// from server (Server - main player streamer; Client - viewer)
// Possibly this will be the data that needs to be sent to server
mPlayer.move(movement * TimePerFrame.asSeconds()); // Time.deltaTime frame independent movement
// for each player eventually
screenBound(mPlayer);
// screenbound enemies or else check that they do not go off bounds and change direction
// **
} // end of if server
else {
// Handle control through incoming network data
// vector x = datacoming in
// Hypothetically mPlayer.move(data coming in);
// bullet spawn
// setlocation from data packet
runUdpClient(SERVER_PORT);
}
// Enemy Behaviour // Ideally move to separate method
sf::Vector2f enemyMovement(1.f, 0.f);
float yOffset = 30.f;
float xOffset = 60.f;
// Be careful with iterators as when deleting it will automatically jump to the next item in vector
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) // CAUTION & solved everything again - lesson in C++, if we don't get address, we always create a copy and modify it, which is not what we want
{
//std::cout << "Direction before working move " << direction << std::endl;
i->getSprite().move(enemyMovement * direction); // Issue detected direction only changing sign if greater or less than screen bounds once
if (i->getSprite().getPosition().x + i->getSprite().getLocalBounds().width / 2 > game->getWindowWidth() ||
i->getSprite().getPosition().x - i->getSprite().getLocalBounds().width / 2 < game->getWindowWidth() - game->getWindowWidth()) { // this will be 0
direction = -(direction);
// Time stamp over here for network calculations
//std::cout << "Direction inside if statement " << direction << std::endl;
// another for loop move all down by yOffset
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
i->getSprite().setPosition(i->getSprite().getPosition().x, i->getSprite().getPosition().y + yOffset);
//enemy.move(0.f, enemy.getPosition().y + yOffset);
}
//enemy.setPosition(enemy.getPosition().x, enemy.getPosition().y + yOffset); // y axis is inverted in SFML
//return 0; // move to separate method
}
// This takes care of everything on both sides
if ((i->getSprite().getPosition().y > game->getWindowHeight() - mPlayer.getLocalBounds().height)) {
//removeEnemy(enemy);
// ALIVE is false, then draw based on whether alien is alive or not
std::cout << "Everyone should be dead game over!" << std::endl;
return 0; // change state to paused
}
}
}
updateStatistics(deltaTime, mStatisticsText);
// ** Start of if server
if (userChoice == 's'){
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
// Test player and alien collision
if (CollisionManager::collidesWith(mPlayer, *i) && i->isAlive()) { // *i it points to the enemy, and will give me an enemy
std::cout << "You're dead!" << std::endl;
mPlayerIsAlive = false;
return 0; //-> I'm dead gameOver = true;
}
// Test collision between bullets and aliens
if (CollisionManager::collidesWith(bullet, *i) && i->isAlive())
{
i->kill();
//enemyList->erase(i); // issue here, we are trying to do this in order to get rid of rendering problems .. shit just move it out of way
//i->setLocation(700.f, 10.f);
bullet.kill();
bullet.setLocation(700.f, 0.f); // temporary solution for dealing with not actually killing but stop drawing bullet
// without above line, the bullet will not be drawn but still exist on screen
}
/*
v.erase(std::remove_if(v.begin(), v.end(), //erase returns it, so it = erase
[](int i) { return i < 10; }), v.end());
*/
}
}
// ** end of if server
int deadEnemies = 0;
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
if (!(i->isAlive())) {
deadEnemies++;
}
if (deadEnemies >= NUMBER_OF_ALIENS) {
std::cout << "You win!" << std::endl;
return 0; // Set state win
}
}
//std::cout << "Total Dead Enemies - " << deadEnemies << std::endl;
//for (Enemy& enemy : enemyList) {
// if (enemy.isAlive()) {
// enemy.draw(window);
// }
//}
//enemy.render(alienArray, mWindow);
/*
for (int i = 0; i < mEnemies.size(); i++)
{
sf::Sprite temp = mEnemies.at(i);
mWindow.draw(temp);
}
*/
// Render All
// Remember draw order is important
window.clear();
window.draw(mBackground);
window.draw(mPlayer);
window.draw(mStatisticsText);
for (std::vector<Enemy>::iterator i = enemyList->begin(); i != enemyList->end(); ++i) {
if (i->isAlive()) {
i->draw(window);
//std::cout << "Enemy " << i->getID() << " position - " << i->getLocation().x << " " << i->getLocation().y << std::endl;
}
}
if (bullet.isAlive()) // && !gameOver // for game state and win / lose screen representation
{
//draw bullet
bullet.draw(window);
//move bullet
bullet.getSprite().move(0.f, -20);
}
//test collision with bullet and boundary
if (bullet.getSprite().getPosition().y < 0)
bullet.kill();
window.display();
} // end of main second if
}
return 0;
}

How to do: when we press and hold, program just do once?

I am making a game console with C++, I have a problem. When I press SPACE, my car in my game will jump. When I press and hold keyboard, my car will jump many times. I want: when I hold SPACE keyboard my car just jump once.
How to do this ?
I have read many topics about GetAsyncKeyState() but I don't know how to use it for my game.
if ( _kbhit() )
{
char key = _getch();
if ((key == 75) && (car.position.x > 2))
{
car.position.x -= 3;
}
else if ((key == 77) && (car.position.x < 24))
{
car.position.x += 3;
}
else if ((key == 32) && (car.position.y > 2))
{
car.position.y -= 5;
}
}
Below I have an example software of one possible way to 'filter' duplicate space chars out of an input stream.
The idea relies on the use of two threads.
Thrd1 reads from a stringstream called ssIn. (Replaced with cin in your code.)
Thrd1 (a filter) detects and discards back-to-back space chars, and only sends the first (of multiple space chars) to thrd2.
Thrd2 - reads from the single char buffer filled by thrd1 which will never see back-to-back space characters.
The 2 thrds are synchronized by a pair of semaphores (not mutex).
In my example, for my convenience, I used my version of a Posix semaphore. I do not know if you have Posix, but I am confident you will easily find many example C++ semaphores available on the web, even within SO, and most using only C++ features.
Note that this is only 1 test ... the alphabet with 1,000,000 spaces injected after 'j'. This is not a thourough test. There probably will be other issues to deal with. I have installed a harsh handling of input mis-behaviour. The assert will help you identify the issues.
"thrd2" represents your toe-hold into this example. Thrd2 receives the filtered stream.
#include "../../bag/src/dtb_chrono.hh"
using namespace std::chrono_literals; // support suffixes like 100ms, 2s, 30us
using std::chrono::duration_cast;
#include <iostream>
using std::cout, std::flush, std::endl;
//using std::cin;
#include <thread>
using std::thread, std::this_thread::sleep_for;
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
// Posix Process Semaphore, local mode, unnamed, unlocked
#ifndef DTB_PPLSEM_HH
#include "../../bag/src/dtb_pplsem.hh"
using DTB::PPLSem_t;
#endif
// string ops
#ifndef DTB_SOPS_HH
#include "../../bag/src/dtb_sops.hh"
using DTB::SOps_t;
#endif
#include <cassert>
namespace DTB
{
class T946_t
{
public:
int operator()(int argc, char* argv[]) // functor entry
{ return exec(argc, argv); }
private:
// uses compiler provided default ctor and dtor
// Posix Process Semaphore, local mode (unnamed, unshared)
// initial value unlocked
PPLSem_t th1Sem;
PPLSem_t th2Sem;
char kar = '\n';
bool done = false;
size_t m_rdy;
thread* th1;
string th1Log;
thread* th2;
string th2Log;
stringstream ssIn; // debug - replaces cin
stringstream ss1DR; // th1 delay'd report
stringstream ss2DR; // th2 delay'd report
// utilities
SOps_t sops; // string ops - digiComma
int exec(int , char** )
{
// test init: insert a possible user input into ssIn
init_ssIn();
int retVal = 0;
Time_t start_ns = HRClk_t::now();
th1Sem.lock(); // block until threads are ready
th2Sem.lock(); // block
// start ---------vvvvvvvvvvvvvvvvvvv
th1 = new thread(&T946_t::thrd1, this);
assert(nullptr != th1);
while (0 == (m_rdy & 0x01))
std::this_thread::sleep_for(10ms);
// start ---------vvvvvvvvvvvvvvvvvv
th2 = new thread(&T946_t::thrd2, this);
assert(nullptr != th2);
while (0 == (m_rdy & 0x02))
std::this_thread::sleep_for(10ms);
th1Sem.unlock();
// spin wait for threads to complete
while (!done)
{
std::this_thread::sleep_for(100ms);
}
th1->join();
th2->join();
cout << "\n join()'s complete";
auto duration_ns = duration_cast<NS_t>(HRClk_t::now() - start_ns).count();
cout << "\n T901_t::exec() duration "
<< sops.digiComma(duration_ns) << " ns" << endl;
// output the delay'd reports
cout << ss1DR.str() << ss2DR.str() << endl;
return retVal;
}
void init_ssIn()
{
ssIn << "abcdefghij";
for (int i=0; i<1000001; ++i) ssIn << ' ';
std::string::size_type k = ssIn.str().size();
ssIn << "klmnopqrstuvwxyz";
// a..j
cout << "\n ssIn: '" << ssIn.str().substr(0, 10)
<< " ...spaces... " << ssIn.str().substr(k, 16) << "'"
<< "\n ssIn.str().size(): "
<< sops.digiComma(ssIn.str().size()) << endl;
}
void thrd1()
{
uint64_t th1Count = 0;
uint64_t th1Skips = 0;
char lkar = '\0';
m_rdy |= 0x01; // sync msg to main
do {
getNextKar(lkar); // read from input (ssIn or cin)
th1Sem.lock(); // wait for thrd2 to give permission
{
if(' ' == lkar) // current input kar
{
if(' ' == kar) // previous kar
{
// filter out back-to-back space chars
th1Skips += 1;
th1Sem.unlock(); // skip the handshake, no char to send,
// give self permission-to-proceed
continue;
}
}
// else, not a duplicate space
th1Count += 1;
kar = lkar; // write to input of thrd2
th1Log += lkar; // log
lkar = ' ';
}
th2Sem.unlock(); // give thrd2 permission-to-proceed
if (ssIn.eof())
{
done = true;
break;
}
}while(!done);
ss1DR
<< "\n th1Count " << sops.digiComma(th1Count)
<< "\n th1Skips " << sops.digiComma(th1Skips)
<< "\n th1Log " << th1Log
<< "\n thrd1 exit " << endl;
}
// read from ssIn for development
// read from cin for app
void getNextKar(char& lkar)
{
// ssIn >> lkar; // reads 1 char, but skips multiple blank chars
// lkar = ssIn.get(); returns an integer (not a char)
(void)ssIn.get (lkar);
if(ssIn.fail())
{
if(ssIn.eof()) return; // not a fail
assert(0); // harsh exit, might want something gentler
}
}
void thrd2()
{
uint64_t th2Count = 0;
m_rdy |= 0x02; // sync msg to main
do {
th2Sem.lock(); // wait for thrd1 to give permission
char t = kar;
th1Sem.unlock(); // give permission-to-proceed to thrd1
// simulate application - no duplicate spaces from input
th2Log += t;
th2Count += 1;
// end of sim
}while(!done);
ss2DR
<< "\n th2Count " << sops.digiComma(th2Count)
<< "\n th2Log " << th2Log
<< "\n thrd2 exit " << endl;
}
}; // class T946_t
} // namespace DTB
int main(int argc, char* argv[]) { return DTB::T946_t()(argc, argv); }
The output looks like:
ssIn: 'abcdefghij ...spaces... klmnopqrstuvwxyz'
ssIn.str().size(): 1,000,027
join()'s complete
T901_t::exec() duration 120,421,582 ns
th1Count 28
th1Skips 1,000,000
th1Log abcdefghij klmnopqrstuvwxyz
thrd1 exit
th2Count 28
th2Log abcdefghij klmnopqrstuvwxyz
thrd2 exit
The duration is 120 ms for 1 Million chars input.
As #Remy Lebeau pointed out you can get the repeat count by install WH_KEYBOARD hook and filter the key held pressed in KeyboardProc.
Of course, for simple, no need install a hook you can filter repeat WM_KEYDOWN messages in window procedure when you press the space key and hold. The following is an example you can refer to:
case WM_KEYDOWN:
if (wParam == VK_SPACE)
{
if (!((HIWORD(lParam) & 0x4000) || (HIWORD(lParam) & 0x8000)))
{
isKeyHold = TRUE; // First time pressed
OutputDebugString(TEXT("pressed !\n"));
}
else if (isKeyHold && (HIWORD(lParam) & 0x4000))
{
OutputDebugString(TEXT("hold !\n"));
return 1; // Don't handle the message when the key is pressed and held.
}
}
break;
case WM_KEYUP:
if (wParam == VK_SPACE && isKeyHold)
{
isKeyHold = FALSE; // Clear the isKeyHold flag when release the key.
OutputDebugString(TEXT("release !\n"));
}
break;

ZMQ messages not being received

Please forgive me if I'm missing something simple, this is my first time doing anything with messaging and I inherited this codebase from someone else.
I am trying to send a message from a windows machine with an IP of 10.10.10.200 to an Ubuntu machine with an IP of 10.10.10.15.
I got the following result when running TCPView from the Windows machine, which makes me suspect that the problem lies in the Ubuntu machine. If I'm reading that right, then my app on the windows machine has created a connection on port 5556 which is what it is supposed to do. In case I'm wrong, I'll include the windows code too.
my_app.exe 5436 TCP MY_COMPUTER 5556 MY_COMPUTER 0 LISTENING
Windows app code:
void
NetworkManager::initializePublisher()
{
globalContext = zmq_ctx_new();
globalPublisher = zmq_socket(globalContext, ZMQ_PUB);
string protocol = "tcp://*:";
string portNumber = PUBLISHING_PORT; //5556
string address = protocol + portNumber;
char *address_ptr = new char[address.size() + 1];
strncpy_s(address_ptr, address.size() + 1, address.c_str(), address.size());
int bind_res = zmq_bind(globalPublisher, address_ptr);
if (bind_res != 0)
{
cerr << "FATAL: couldn't bind to port[" << portNumber << "] and protocol [" << protocol << "]" << endl;
}
cout << " Connection: " << address << endl;
}
void
NetworkManager::publishMessage(MESSAGE msgToSend)
{
// Get the size of the message to be sent
int sizeOfMessageToSend = MSG_MAX_SIZE;//sizeof(msgToSend);
// Copy IDVS message to buffer
char buffToSend[MSG_MAX_SIZE] = "";
// Pack the message id
size_t indexOfId = MSG_ID_SIZE + 1;
size_t indexOfName = MSG_NAME_SIZE + 1;
size_t indexOfdata = MSG_DATABUFFER_SIZE + 1;
memcpy(buffToSend, msgToSend.get_msg_id(), indexOfId - 1);
// Pack the message name
memcpy(buffToSend + indexOfId, msgToSend.get_msg_name(), indexOfName - 1);
// Pack the data buffer
memcpy(buffToSend + indexOfId + indexOfName, msgToSend.get_msg_data(), indexOfdata - 1);
// Send message
int sizeOfSentMessage = zmq_send(globalPublisher, buffToSend, MSG_MAX_SIZE, ZMQ_DONTWAIT);
getSubscriptionConnectionError();
// If message size doesn't match, we have an issue, otherwise, we are good
if (sizeOfSentMessage != sizeOfMessageToSend)
{
int errorCode = zmq_errno();
cerr << "FATAL: couldn't not send message." << endl;
cerr << "ERROR: " << errorCode << endl;
}
}
I can include more of this side's code if you think it's needed, but the error is popping up on the Ubuntu side, so I'm going to focus there.
The problem is when I call zmq_recv it returns -1 and when I check zmq_errno I get EAGAIN (Non-blocking mode was requested and no messages are available at the moment.) I also checked with netstat and I didn't see anything on port 5556
First is the function to connect to the publisher, then the function to get data, followed by main.
Ubuntu side code:
void
*connectoToPublisher()
{
void *context = zmq_ctx_new();
void *subscriber = zmq_socket(context, ZMQ_SUB);
string protocol = "tcp://";
string ipAddress = PUB_IP; //10.10.10.15
string portNumber = PUB_PORT; // 5556
string address = protocol + ipAddress + ":" + portNumber;
cout << "Address: " << address << endl;
char *address_ptr = new char[address.size() + 1];
strcpy(address_ptr, address.c_str());
// ------ Connect to Publisher ------
bool isConnectionEstablished = false;
int connectionStatus;
while (isConnectionEstablished == false)
{
connectionStatus = zmq_connect(subscriber, address_ptr);
switch (connectionStatus)
{
case 0: //we are good.
cout << "Connection Established!" << endl;
isConnectionEstablished = true;
break;
case -1:
isConnectionEstablished = false;
cout << "Connection Failed!" << endl;
getSubscriptionConnectionError();
cout << "Trying again in 5 seconds..." << endl;
break;
default:
cout << "Hit default connecting to publisher!" << endl;
break;
}
if (isConnectionEstablished == true)
{
break;
}
sleep(5); // Try again
}
// by the time we get here we should have connected to the pub
return subscriber;
}
static void *
getData(void *subscriber)
{
const char *filter = ""; // Get all messages
int subFilterResult = zmq_setsockopt(subscriber, ZMQ_SUBSCRIBE, filter, strlen(filter));
// ------ Get in main loop ------
while (1)
{
//get messages from publisher
char bufferReceived[MSG_MAX_SIZE] = "";
size_t expected_messageSize = sizeof(bufferReceived);
int actual_messageSize = zmq_recv(subscriber, bufferReceived, MSG_MAX_SIZE, ZMQ_DONTWAIT);
if (expected_messageSize == actual_messageSize)
{
MESSAGE msg = getMessage(bufferReceived); //Uses memcpy to copy id, name, and data strutct data from buffer into struct of MESSAGE
if (strcmp(msg.get_msg_id(), "IDXY_00000") == 0)
{
DATA = getData(msg); //Uses memcpy to copy data from buffer into struct of DATA
}
} else
{
// Something went wrong
getReceivedError(); //This just calls zmq_errno and cout the error
}
usleep(1);
}
}
int main (int argc, char*argv[])
{
//Doing some stuff...
void *subscriber_socket = connectoToHeadTrackerPublisher();
// Initialize Mux Lock
pthread_mutex_init(&receiverMutex, NULL);
// Initializing some variables...
// Launch Thread to get updates from windows machine
pthread_t publisherThread;
pthread_create(&publisherThread,
NULL, getData, subscriber_socket);
// UI stuff
zmq_close(subscriber_socket);
return 0;
}
If you cannot provide a solution, then I will accept identifying the problem as a solution. My main issue is that I don't have the knowledge or experience with messaging or networking to correctly identify the issue. Typically if I know what is wrong, I can fix it.
Ok, this has nothing to do with signalling / messaging framework
Your Ubuntu code instructs the ZeroMQ Context()-instance engine to create a new SUB-socket instance and next the code insist this socket to try to _connect() ( to setup a tcp:// transport-class connection towards the peering counterparty ) to "opposite" access-point, sitting on an address of the Ubuntu localhost:port# that was setup as 10.10.10.15:5556, while the intended PUB-side archetype access-point actually lives not on this Ubuntu machine, but on another, Windows host, IP:port# of which is 10.10.10.200:5556
This seems to be the root-cause of the problem, so change it accordingly to match the physical layout and you may get the toys work.

PCL OpenNI2Grabber get Point Cloud without viewer

I have an Asus XTION camera. On my PC there is Windows 7 with Visual Studio 2013 installed. I also got PCL, openCV compiled for VS2013 and the openNi Driver is intalled. Now I want to get a Point Cloud from the Camera. With the sample I can view the actual frames and save one:
// Original code by Geoffrey Biggs, taken from the PCL tutorial in
// http://pointclouds.org/documentation/tutorials/pcl_visualizer.php
// Simple OpenNI viewer that also allows to write the current scene to a .pcd
// when pressing SPACE.
#define _CRT_SERCURE_NO_WARNINGS
#include <pcl/io/openni2_grabber.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/console/parse.h>
#include <pcl/filters/passthrough.h>
#include <iostream>
using namespace std;
using namespace pcl;
PointCloud<PointXYZRGBA>::Ptr cloudptr(new PointCloud<PointXYZRGBA>); // A cloud that will store color info.
PointCloud<PointXYZ>::Ptr fallbackCloud(new PointCloud<PointXYZ>); // A fallback cloud with just depth data.
PointCloud<PointXYZRGBA>::Ptr filteredCloud(new PointCloud<PointXYZRGBA>);
boost::shared_ptr<visualization::CloudViewer> viewer; // Point cloud viewer object.
Grabber* openniGrabber; // OpenNI grabber that takes data from the device.
unsigned int filesSaved = 0; // For the numbering of the clouds saved to disk.
bool saveCloud(false), noColor(false); // Program control.
void
printUsage(const char* programName)
{
cout << "Usage: " << programName << " [options]"
<< endl
<< endl
<< "Options:\n"
<< endl
<< "\t<none> start capturing from an OpenNI device.\n"
<< "\t-v FILE visualize the given .pcd file.\n"
<< "\t-h shows this help.\n";
}
// This function is called every time the device has new data.
void
grabberCallback(const PointCloud<PointXYZRGBA>::ConstPtr& cloud)
{
if (!viewer->wasStopped())
viewer->showCloud(cloud);
if (saveCloud)
{
stringstream stream;
stream << "inputCloud" << filesSaved << ".pcd";
string filename = stream.str();
// Filter object.
PassThrough<pcl::PointXYZRGBA> filter;
filter.setInputCloud(cloud);
// Filter out all points with Z values not in the [0-2] range.
filter.setFilterFieldName("z");
filter.setFilterLimits(0.0, 1.5);
filter.filter(*filteredCloud);
if (io::savePCDFile(filename, *filteredCloud, true) == 0)
{
filesSaved++;
cout << "Saved " << filename << "." << endl;
}
else PCL_ERROR("Problem saving %s.\n", filename.c_str());
saveCloud = false;
}
}
// For detecting when SPACE is pressed.
void
keyboardEventOccurred(const visualization::KeyboardEvent& event,
void* nothing)
{
if (event.getKeySym() == "space" && event.keyDown())
saveCloud = true;
}
// Creates, initializes and returns a new viewer.
boost::shared_ptr<visualization::CloudViewer>
createViewer()
{
boost::shared_ptr<visualization::CloudViewer> v
(new visualization::CloudViewer("OpenNI viewer"));
v->registerKeyboardCallback(keyboardEventOccurred);
return (v);
}
int
main(int argc, char** argv)
{
if (console::find_argument(argc, argv, "-h") >= 0)
{
printUsage(argv[0]);
return -1;
}
bool justVisualize(false);
string filename;
if (console::find_argument(argc, argv, "-v") >= 0)
{
if (argc != 3)
{
printUsage(argv[0]);
return -1;
}
filename = argv[2];
justVisualize = true;
}
else if (argc != 1)
{
printUsage(argv[0]);
return -1;
}
// First mode, open and show a cloud from disk.
if (justVisualize)
{
// Try with color information...
try
{
io::loadPCDFile<PointXYZRGBA>(filename.c_str(), *cloudptr);
}
catch (PCLException e1)
{
try
{
// ...and if it fails, fall back to just depth.
io::loadPCDFile<PointXYZ>(filename.c_str(), *fallbackCloud);
}
catch (PCLException e2)
{
return -1;
}
noColor = true;
}
cout << "Loaded " << filename << "." << endl;
if (noColor)
cout << "This cloud has no RGBA color information present." << endl;
else cout << "This cloud has RGBA color information present." << endl;
}
// Second mode, start fetching and displaying frames from the device.
else
{
openniGrabber = new pcl::io::OpenNI2Grabber();
if (openniGrabber == 0)
return -1;
boost::function<void(const PointCloud<PointXYZRGBA>::ConstPtr&)> f =
boost::bind(&grabberCallback, _1);
openniGrabber->registerCallback(f);
}
viewer = createViewer();
if (justVisualize)
{
if (noColor)
viewer->showCloud(fallbackCloud);
else viewer->showCloud(cloudptr);
}
else openniGrabber->start();
// Main loop.
while (!viewer->wasStopped())
boost::this_thread::sleep(boost::posix_time::seconds(1));
if (!justVisualize)
openniGrabber->stop();
}
But with this code I need the viewer. How can I get the Point Cloud without the viewer? It should work without kinect SDK, only with PCL, openni.
I solved the problem like this:
#include <pcl/io/openni2_grabber.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/parse.h>
#include <iostream>
using namespace std;
using namespace pcl;
int main(int argc, char** argv)
{
PointCloud<PointXYZRGBA>::Ptr sourceCloud(new PointCloud<PointXYZRGBA>);
boost::function<void(const PointCloud<PointXYZRGBA>::ConstPtr&)> function = [&sourceCloud](const PointCloud<PointXYZRGBA>::ConstPtr &cloud)
{
copyPointCloud(*cloud, *sourceCloud);
};
// Create Kinect2Grabber
Grabber* grabber = new io::OpenNI2Grabber();
// Regist Callback Function
grabber->registerCallback(function);
// Start Retrieve Data
grabber->start();
boost::this_thread::sleep(boost::posix_time::seconds(1));
// Stop Retrieve Data
grabber->stop();
cout << "The Cloud size: " << sourceCloud->size() << " points ..." << endl;
}