We are working with ros and try to run a node via SSH in a shell script.
We have an controlling (master) computer on which we execute the script with the following line:
ssh user#xxx.xxx.x.x -x "/bin/bash -c 'source /etc/profile; rosrun stargazer_alter stargazer_node'"
The node is getting started (it occurs in "rosnode list" and the node is also listed as a publisher in "rostopic info") but the main method seems not to be executed (neither any print lines show up nor any messages were published).
#include "Stargazer_listener.h"
enum STATES {config, readData};
int main(int argc, char** argv) {
ROS_INFO("Test!!!! Stargazer starts!");
ros::init(argc, argv, "stargazer_node");
Stargazer_listener starG;
int iFd = 0;
char *rec_msg = (char*)malloc(BUFFSIZE * sizeof(char));
iFd = starG.portSetup();
STATES STATE = config;
while(ros::ok()) {
switch(STATE) {
case config:
starG.cmd(iFd, rec_msg, "~#CalcStop`");
printf("CalcStop\n");
starG.cmd(iFd, rec_msg, "~#CalcStart`");
printf("CalcStart\n");
STATE = readData;
break;
case readData:
starG.publish_data(iFd, rec_msg);
break;
}
}
free(rec_msg);
return 0;
}
The line "starG.portSetup()" opens the ttyUSB0 port which is not used by other processes.
The stargazer_node is getting compiled via catkin_make. According to the code, the first thing to happen should be the following print line: "ROS_INFO("Test!!!! Stargazer starts!");".
Which doesnt happen!
The same shell script command did work fine with other nodes. If we add the node to a ros ".launch" file, the same thing happens.
If I connect via ssh in a terminal (ssh user#xxx.xxx.x.x) and then run the same line (rosrun stargazer_alter stargazer_node) everything works fine!
Related
I have found this code as a bash autocomplete. But, it looks strange to me. What if I do not like to run the code at all. If I would like to type ./a.out then space (without entering) and then by pressing tab, I would like to see only two options apple and cherry and if I type a and press tab, then it autocomplete the option apple and similarly for c. Let's say only one of the two options are acceptable:
./a.out apple
./a.out cherry
where apple and cherry are options and not the name of the files in the directory. In the first case, I would like the program types that your option is apple and in the second case your option is cherry. In any other case, the program should print an error that the option is not valid.
All examples that I find on the internet such as what follows look like that you should run the program first, then it reacts. The while loop inside the main function collides with the normal functionality of the program. Have I misunderstood the readline library? Is the above-described application possible to implement by editing the following code?
// sudo apt-get install libreadline-dev
// g++ -std=c++11 main.cpp -lreadline
#include <iostream>
#include "readline/readline.h"
#include "readline/history.h"
using namespace std;
int main(int argc, char** argv)
{
const char *line;
while ((line = readline("? ")) != nullptr) {
cout << "[" << line << "]" << endl;
if (*line) add_history(line);
free(line);
}
// if(argc!=2)
// {
// cout<<"<exe> one_parameter"<<endl;
// return 1;
// }
// string option=argv[1];
// if(option=="apple" || option=="cherry")
// cout<<"Your option is "<<option<<endl;
// else
// {
// cout<<"Error: invalid option "<<option<<endl;
// return 1;
// }
return 0;
}
// partial answer - why you may want to invoke the app while doing the autocompletion
One way of implementing the autocomplete for an application is to have the application binary configure it (by having a flag that prints the instructions for autocomplete configuration or by just parsing the --help output of the application).
Schemataically:
complete -F $(./a.out --generate-autocomplete-config) ./a.out
This is why you might see the binary actually invoked as a part of autocomplete implementation.
This has nothing to do with your executable. You need to put this in a file and source (source autocomplete_file or . autocomplete_file) it in the bash.
_a_complete_()
{
local word=${COMP_WORDS[COMP_CWORD]}
local files='apple cherry'
COMPREPLY=( $( compgen -W "${files}" -- ${word} ) )
}
complete -F _a_complete_ ./a.out
Here a nice documentation can be found.
I have the following small program:
#include <unistd.h>
#include <pwd.h>
#include <QCoreApplication>
#include <QDir>
const char * homeDir()
{
return getpwuid(geteuid())->pw_dir;
}
int main(int argc, char *argv[])
{
printf("Qt homedir: %s\n", qPrintable(QDir::homePath()));
printf("Native homedir: %s\n", homeDir());
QCoreApplication a(argc, argv);
return a.exec();
}
Now:
when run directly by a "normal" user, ./program, the output is:
Qt homedir: /home/user
Native homedir: /home/usr
which is ok
when run directly by root, ./program, the output is:
Qt homedir: /root
Native homedir: /root
which is ok
when run by root as a different user by the means of sudo, e.g. sudo -u user ./program, the output is:
Qt homedir: /home/user
Native homedir: /home/user
which is ok
when run by root as a different user by the means of startproc, e.g. startproc -u user /full/path/to/program, the output is:
Qt homedir: /root
Native homedir: /home/user
which is NOT ok, or not expected (at least for me)
And my question is: why does the last run give a different result than the others? Is it a bug in Qt (doesn't take into account the fact, that the effective user is different than the real user, or something different), or am I missing some background info (e.g. the mechanism of how startproc works)?
The version of Qt in question is 5.6.1.
Qt's QFileSystemEngine uses the contents of the HOME environment variable on Unix - see its implementation. Yet startproc -u does not set HOME: that's why it fails.
The getpwuid call can be potentially very expensive and can block, i.e. by getting information from an LDAP or AD server, etc., and it's best if you take care of it yourself. Furthermore, it's not thread-safe, and you should use getpwuid_r instead.
An implementation might look as follows:
static QString getHomeDir() {
auto const N = sysconf(_SC_GETPW_R_SIZE_MAX);
auto *buffer = std::make_unique<char[]>(N);
passwd pwd;
passwd *result;
getpwuid_r(geteuid(), &pwd, buffer.get(), N, &result);
if (result) {
auto *dir = result->pw_dir;
auto const decoded = QFile::decodeName(dir);
return QDir::cleanPath(decoded);
}
return {};
}
enum class HomeDir { Default, Init };
QString homeDir(HomeDir option = HomeDir::Default) {
// needs a C++11 compiler for thread-safe initialization
static QFuture<QString> home = QtConcurrent::run(getHomeDir);
return (option == HomeDir::Init) ? QString() : home;
};
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
homeDir(HomeDir::Init);
// do other time-consuming initializations here
QString () << homeDir();
}
For some reason, I am unable to start a process using QProcess on Ubuntu, and I do not understand why...
int main(int argc, char *argv[])
{
//Run the process:
QString procName = "./path/to/executable/Individual";
QProcess *proc = new QProcess();
proc->start(procName);
if(!proc->waitForStarted())
{
std::cout<<"Fail!"<<std::endl;
getchar();
return 0;
}
int exitCode = proc->exitCode();
std::cout<<"Exit code: "<<exitCode<<std::endl;
getchar();
return 0;
}
This always prints 'Fail' to the terminal.
If I type ./path/to/executable/Individual into the terminal, it works just fine, so the path seems to be correct.
Can anyone tell me why the program will not start?
I am using Qt version 5.9.1 on Ubuntu.
Since you're using Linux, you can
sudo ln -s /path/to/executable/Individual /usr/local/bin/individual
then try:
proc->start("individual");
You can try with:
proc->start("cd /usr/local/bin/ && individual");
I have some code that is executed from the command line. It takes 3 parameters:
"example.txt" 3 s
I want to be able to run this program from inside of my Eclipse IDE instead of running it from the command line but I do not know how to assign the parameters without creating bugs int the program.
Here is the main method below:
int main(int argc, char **argv) {
if (argc != 4) {
fprintf(stderr, "Usage: %s <input file> <num clusters> "
"<linkage type>\n", argv[0]);
exit(1);
} else {
item_t *items = NULL;
int num_items = process_input(&items, argv[1]);
set_linkage(argv[3][0]);
if (num_items) {
cluster_t *cluster = agglomerate(num_items, items);
free(items);
if (cluster) {
fprintf(stdout, "CLUSTER HIERARCHY\n"
"--------------------\n");
print_cluster(cluster);
int k = atoi(argv[2]);
fprintf(stdout, "\n\n%d CLUSTERS\n"
"--------------------\n", k);
get_k_clusters(cluster, k);
free_cluster(cluster);
}
}
}
return 0;
}
I am using c++ and eclipse IDE.
You basically need to create a debug/run configuration for said project. Go to Run->Debug Configurations, select C/C++ Application, then create a new configuration. After that, you have to specify some information, like the application, the eclipse project, and your program`s arguments, on the Arguments Tab.
Screenshots from here are a bit old, but should give you the idea.
After that, hit Debug or Run, and Eclipse shoud start your program with the given parameters.
I have a simple text editor in which I would like to open a file when it's double-clicked from the system file manager.
I managed to do that without any problems under Ubuntu Linux (13.04), but in Mac OS X my code did not work.
After researching a bit, I found out that you need to add the --args argument in terminal in order to parse the arguments to main().
I fixed my code and now my application bundle can open files from the terminal, but when I double click a file in Finder (and select my app), my application launches as if did not receive any terminal arguments (creates a new file).
Here is the code of the main() function:
int main(int argc, char *argv[])
{
QApplication MyApp(argc, argv);
Textpad.setApplicationName("MyApp");
Textpad.setApplicationVersion("0.7.2");
Textpad.setWindowIcon(QIcon(":/app-icon/48x48/icon.png"));
MainWindow *Window = new MainWindow();
QString Arguments;
QString FileLocation;
if (argc != 1) {
int i;
for (i = 0; i < argc; i++)
Arguments = argv[i];
// Check if the OS is Mac OS X (Mac OS X is 3)
if (Window->CheckOS() == 3)
// Remove the "--args" so that we don't confuse it with the file location
Arguments.replace("--args", "");
if (Arguments == "--help") {
// Show help
}
// Create a new file when Textpad is launched normally (under Linux)
if (Arguments == "%U") {
FileLocation.clear();
// Load settings and create UI
Window->Initialize();
// Open the requested file
Window->LoadFile(FileLocation);
}
else {
FileLocation = Arguments;
// Load settings and create UI
Window->Initialize();
// Open the requested file
Window->LoadFile(FileLocation);
}
}
else {
// Create new file
FileLocation.clear();
// Load settings and create UI
Window->Initialize();
// Open the requested file
Window->LoadFile(FileLocation);
}
return MyApp.exec();
}
As I said before my application opens files without probles from the terminal when I write the following:
open MyApp.app --args <location of my file>
But fails when I try to open a file from Finder.
What I am missing?
Thank you in advance.
First of all, you will have to link against the OX-X Framework. OSX works with Events similar to signal slots. The filename will also be given by an apple event. I`ve had this quite some time ago with another language, but i still found a reference:
Edit doc now in Qt archive:
https://doc.qt.io/archives/qq/qq12-mac-events.html