I have a simple data acquisition system to read analog dc voltage from the NI USB 6009. I have also created a qt console application to use the NIDAQmxbase functionality.
The .pro file is as follows
QT += core
QT -= gui
TARGET = untitled4
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
LIBS += "C:\Users\nikhilmurthy161229\Documents\untitled3\nidaqmxbase.lib"
HEADERS += "C:\Users\nikhilmurthy161229\Documents\untitled3\NIDAQmxBase.h"
I have included the .lib file and the .h file in the project folder.
MY main.cpp file looks as follows
#include <QCoreApplication>
#include <stdio.h>
#include <NIDAQmxBase.h>
#define DAQmxErrChk(functionCall) { if( DAQmxFailed(error=(functionCall)) ) { goto Error; } }
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// Task parameters
int32 error = 0;
TaskHandle taskHandle = 0;
char errBuff[2048]={'\0'};
// Channel parameters
char chan[] = "nikhil\ai0";
float64 min = 0;
float64 max = 5;
// Timing parameters
uInt64 samplesPerChan = 1;
// Data read parameters
float64 data;
int32 pointsToRead = 1;
int32 pointsRead;
float64 timeout = 5;
DAQmxErrChk (DAQmxBaseCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxBaseCreateAIVoltageChan(taskHandle,chan,"",DAQmx_Val_Cfg_Default,min,max,DAQmx_Val_Volts,NULL));
DAQmxErrChk (DAQmxBaseStartTask(taskHandle));
DAQmxErrChk (DAQmxBaseReadAnalogF64(taskHandle,pointsToRead,timeout,DAQmx_Val_GroupByChannel,&data,samplesPerChan,&pointsRead,NULL));
DAQmxErrChk (DAQmxBaseStopTask(taskHandle));
DAQmxErrChk (DAQmxBaseClearTask(taskHandle));
printf ("Acquired reading: %f\n", data);
Error:
if( DAQmxFailed(error) )
DAQmxBaseGetExtendedErrorInfo(errBuff,2048);
if( taskHandle!=0 ) {
DAQmxBaseStopTask(taskHandle);
DAQmxBaseClearTask(taskHandle);
}
if( DAQmxFailed(error) )
printf ("DAQmxBase Error %ld: %s\n", error, errBuff);
return a.exec();
}
However when i run the program I am getting the following error
"DAQmxBase Error -200428: Value passed to the Task/channels In contril is invalid"
I have verified that the device name is same as in NI MAX but the problem still persists.
PLEASE HELP
As a quick guess I would make your chan variable
char chan[] = "nikhil\\ai0";
The char array is probably interpreting the backslash
The DAQ device name is incorrect.
Even though you used MAX to rename the device to nikhil, DAQmx Base enumerates devices differently. Use the lsdaq utility to find your device name (likely Dev1) and change your chan variable to use the discovered name.
Related
I am try to get list of SSID in Fedora 31 Linux, by D-Bus message, using Qt5.
I am checking many tutorials, but still cant communicate by D-Bus, and I still do not understand differences between interface, path and service. With documentation help (https://developer.gnome.org/NetworkManager/stable/spec.html) and Internet I wrote:
QDBusInterface nm("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager.Device.Wireless", QDBusConnection::systemBus());
if(nm.isValid()) {
QDBusMessage msg = nm.call("GetAllAccessPoints");
}
But variable "msg" receiving one argument:
"No interface „org.freedesktop.NetworkManager.Device.Wireless” in object at path /org/freedesktop/NetworkManager"
How can I connect to D-Bus ?
Your confusion is justified, as the process is not really intuitive. Basically what you need to do is to first create a QDBusInterface representing NetworkManager itself. Via that object you need to get the list of the network interfaces, iterate through them, filter out the WiFi interface(s), creating a corresponding QDBusInterface, instruct the interface to scan the available networks, and then request the list of visible access points. Then you get the SSID property of each Access Point object. Here is a simple example which demonstrates the process with plain Qt:
list_ssid.pro:
QT -= gui
QT += dbus
SOURCES += list_ssid.cpp
list_ssid.cpp:
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtDBus/QtDBus>
#include <QDebug>
#include <QThread>
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
// get the interface to nm
QDBusInterface nm("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager",
"org.freedesktop.NetworkManager", QDBusConnection::systemBus());
if(!nm.isValid())
{
qFatal("Failed to connect to the system bus");
}
// get all devices
QDBusMessage msg = nm.call("GetDevices");
qDebug() << "GetDevices reply: " << msg << endl;
QDBusArgument arg = msg.arguments().at(0).value<QDBusArgument>();
if(arg.currentType() != QDBusArgument::ArrayType)
{
qFatal("Something went wrong with getting the device list");
}
QList<QDBusObjectPath> pathsLst = qdbus_cast<QList<QDBusObjectPath> >(arg);
foreach(QDBusObjectPath p, pathsLst)
{
qDebug() << "DEV PATH: " << p.path();
// creating an interface used to gather this devices properties
QDBusInterface device("org.freedesktop.NetworkManager", p.path(),
"org.freedesktop.NetworkManager.Device", QDBusConnection::systemBus());
// 2 is WiFi dev, see https://people.freedesktop.org/~lkundrak/nm-docs/nm-dbus-types.html#NMDeviceType
if (device.property("DeviceType").toInt() != 2)
{
continue;
}
// we got a wifi device, let's get an according dbus interface
QDBusInterface wifi_device("org.freedesktop.NetworkManager", p.path(),
"org.freedesktop.NetworkManager.Device.Wireless", QDBusConnection::systemBus());
// we need to call scan on the inteface prior to request the list of interfaces
QMap<QString, QVariant> argList;
QDBusMessage msg = wifi_device.call("RequestScan", argList);
QThread::sleep(2); // not the best solution, but here we just wait for the scan
// doing the actual call
msg = wifi_device.call("GetAllAccessPoints");
qDebug()<< "Answer for GetAllAccessPoints: " << msg << endl << endl;
// dig out the paths of the Access Point objects:
QDBusArgument ap_list_arg = msg.arguments().at(0).value<QDBusArgument>();
QList<QDBusObjectPath> ap_path_list = qdbus_cast<QList<QDBusObjectPath> >(ap_list_arg);
// and iterate through the list
foreach(QDBusObjectPath p ,ap_path_list)
{
// for each Access Point we create an interface
QDBusInterface ap_interface("org.freedesktop.NetworkManager", p.path(),
"org.freedesktop.NetworkManager.AccessPoint", QDBusConnection::systemBus());
// and getting the name of the SSID
qDebug() << "SSID: " << ap_interface.property("Ssid").toString();
}
}
return 0;
}
The same using networkmanager-qt, for the sake of comparison:
CMakeLists.txt:
project(ssid_list LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 REQUIRED COMPONENTS
Core
Gui
Network
DBus
)
find_package(KF5NetworkManagerQt REQUIRED)
add_executable(ssid_list
ssid_list.cpp
)
target_link_libraries(ssid_list Qt5::Core Qt5::DBus Qt5::Network KF5::NetworkManagerQt)
ssid_list.cpp
#include <arpa/inet.h>
#include <QThread>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/Device>
#include <NetworkManagerQt/WirelessDevice>
#include <NetworkManagerQt/AccessPoint>
int main()
{
// getting all of the devices, and iterate through them
NetworkManager::Device::List list = NetworkManager::networkInterfaces();
Q_FOREACH (NetworkManager::Device::Ptr dev, list)
{
if(dev->type() != NM_DEVICE_TYPE_WIFI)
{
//skipping non-wifi interfaces
continue;
}
// creating a Wifi device with this object path
NetworkManager::WirelessDevice wifi_dev(dev->uni());
wifi_dev.requestScan();
QThread::sleep(2); // still not the best solution:w
//get the Object Path of all the visible access points
// and iterate through
foreach(QString ap_path, wifi_dev.accessPoints())
{
// creating an AccessPoint object with this path
NetworkManager::AccessPoint ap(ap_path);
// and finally get the SSID
qDebug() << "SSID:" << ap.ssid();
}
}
}
I am trying to add a custom sqlite3 regexp function into my Qt application (as recommended by this answer). But as soon as I call the sqlite3_create_function function, I get the message The program has unexpectedly finished. When I debug, it terminates in a segmentation fault in sqlite3_mutex_enter. There is a MWE below, with apologies for the absolute file paths.
The regexp implementation in my code is from this site; it also fails with the msign function here. The various checks of driver()->handle() are straight from the Qt docs.
Incidentally, I used select sqlite_version(); to determine that Qt 5.5 uses sqlite version 3.8.8.2. I found that version by looking through old commits in the Qt GitHub repository.
MWE.pro
QT += core gui
TARGET = MWE
TEMPLATE = app
QT += sql
SOURCES += main.cpp \
D:\Qt\Qt5.5.0\5.5\Src\3rdparty\sqlite\sqlite3.c
HEADERS += D:\Qt\Qt5.5.0\5.5\Src\3rdparty\sqlite\sqlite3.h
main.cpp
#include <QtSql>
#include "D:/Qt/Qt5.5.0/5.5/Src/3rdparty/sqlite/sqlite3.h"
void qtregexp(sqlite3_context* ctx, int argc, sqlite3_value** argv)
{
QRegExp regex;
QString str1((const char*)sqlite3_value_text(argv[0]));
QString str2((const char*)sqlite3_value_text(argv[1]));
regex.setPattern(str1);
regex.setCaseSensitivity(Qt::CaseInsensitive);
bool b = str2.contains(regex);
if (b)
{
sqlite3_result_int(ctx, 1);
}
else
{
sqlite3_result_int(ctx, 0);
}
}
int main(int argc, char *argv[])
{
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("my.db");
db.open();
QVariant v = db.driver()->handle();
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*")==0) {
sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());
if (db_handle != 0) { // check that it is not NULL
// This shows that the database handle is generally valid:
qDebug() << sqlite3_db_filename(db_handle, "main");
sqlite3_create_function(db_handle, "regexp", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, NULL, &qtregexp, NULL, NULL);
qDebug() << "This won't be reached."
QSqlQuery query;
query.prepare("select regexp('p$','tap');");
query.exec();
query.next();
qDebug() << query.value(0).toString();
}
}
db.close();
}
You need to call sqlite3_initialize() after you get the database handle from Qt, according to this forum post.
...
sqlite3 *db_handle = *static_cast<sqlite3 **>(v.data());
if (db_handle != 0) { // check that it is not NULL
sqlite3_initialize();
...
This solves the issue.
in pcd_register.cpp
I have code,
#include <ros/ros.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <terminal_tools/print.h>
#include <terminal_tools/parse.h>
#include <terminal_tools/time.h>
#include <pcl/registration/icp.h>
#include <pcl/registration/icp_nl.h>
#include <pcl/registration/gicp.h>
#include <pcl/registration/transforms.h>
#include <pcl/filters/voxel_grid.h> // TEMP: currently used instead of octomap
#include "pcl/registration/types.h"
using namespace pcl::registration;
int main (int argc, char** argv) {
ros::init (argc, argv, "pcd_register");
ros::Time::init();
terminal_tools::TicToc tictoc;
// Downsampling
bool downsampling_enabled = true;
double downsampling_leaf_size = 0.001;
terminal_tools::parse_argument(argc, argv, "-d", downsampling_enabled);
terminal_tools::parse_argument(argc, argv, "-D", downsampling_leaf_size);
// read point clouds
vector<PointCloud> data;
std::string extension (".pcd");
for (int i = 1; i < argc; i++)
{
string fname = string (argv[i]);
if (fname.size () <= extension.size ())
continue;
transform (fname.begin (), fname.end (), fname.begin (), (int(*)(int))tolower);
if (fname.compare (fname.size () - extension.size (), extension.size (), extension) == 0)
{
PointCloud cloud;
pcl::io::loadPCDFile (argv[i], cloud);
if (cloud.points.size() == 0) continue;
data.push_back(cloud);
terminal_tools::print_highlight("Read point cloud from "); terminal_tools::print_value("%s", argv[i]); terminal_tools::print_info(" containing "); terminal_tools::print_value("%d", cloud.points.size()); terminal_tools::print_info(" points.\n");
}
}
if (data.empty ())
{
ROS_ERROR ("Syntax is: %s <source.pcd> <target.pcd> [*]", argv[0]);
ROS_ERROR ("[*] - multiple files can be added. The registration results of (i, i+1) will be registered against (i+2), etc");
ROS_INFO ("Example: %s `rospack find pcl`/test/bun0.pcd `rospack find pcl`/test/bun4.pcd", argv[0]);
return (-1);
}
terminal_tools::print_highlight(" Loaded "); terminal_tools::print_value("%d ", (int)data.size ()); terminal_tools::print_info("datasets.\n");
pcl::GeneralizedIterativeClosestPoint<pcl::registration::Point, pcl::registration::Point> reg;
PointCloud cloud_input, cloud_output, cloud_model;
char filename[255];
unsigned int number_clouds_processed = 0;
for (unsigned int i = 0; i < data.size(); ++i) {
// some filtering or whatever here ...
if (downsampling_enabled) {
pcl::VoxelGrid<Point> sor;
sor.setInputCloud(boost::make_shared<PointCloud>(data[i]));
sor.setLeafSize(downsampling_leaf_size, downsampling_leaf_size, downsampling_leaf_size);
sor.filter(cloud_input);
}
else
cloud_input = data[i];
// write input files
sprintf(filename, "registration_input_%04d.pcd", number_clouds_processed);
pcl::io::savePCDFileBinary(filename, cloud_input);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (number_clouds_processed == 0) { // no registration needed
cloud_output = cloud_input;
cloud_model = cloud_input;
terminal_tools::print_highlight("Adding first scan to model.\n");
// TODO: simply use first point cloud to update/initialize world mode, get cloud_model for next registration from world model
}
else {
//terminal_tools::print_highlight("Registering scan %04d (%d points) against model (%d points)", number_clouds_processed, cloud_input.points.size(), cloud_model.size());
terminal_tools::print_highlight("Registering scan "); terminal_tools::print_value("%04d ", number_clouds_processed);
terminal_tools::print_info("("); terminal_tools::print_value("%d", cloud_input.points.size()); terminal_tools::print_info(" points) against model ("); terminal_tools::print_value("%d ", cloud_model.size()); terminal_tools::print_info("points)");
tictoc.tic();
reg.setInputCloud(boost::make_shared<const PointCloud>(cloud_input));
reg.setInputTarget(boost::make_shared<const PointCloud>(cloud_model));
reg.setMaximumIterations(2); // only one iteration, gicp implementation has inner iterations in optimization
reg.align(cloud_output); // cloud_output = registered point cloud
terminal_tools::print_info("[done, "); terminal_tools::print_value("%g", tictoc.toc()); terminal_tools::print_info("s]\n");
// setting up new model
//cloud_model_normals += cloud_output; // TEMP
double model_subsampling_leaf_size = downsampling_leaf_size; // TEMP
PointCloud cloud_temp; // TEMP
cloud_model += cloud_output; // TEMP
pcl::VoxelGrid<Point> grid; // TEMP
grid.setInputCloud(boost::make_shared<PointCloud>(cloud_model)); // TEMP
grid.setLeafSize(model_subsampling_leaf_size, model_subsampling_leaf_size, model_subsampling_leaf_size); // TEMP
grid.filter(cloud_temp); // TEMP
cloud_model = cloud_temp; // TEMP
// TODO: use cloud_output to udpate world model, get cloud_model from world model
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// write output files
sprintf(filename, "registration_output_%04d.pcd", number_clouds_processed);
pcl::io::savePCDFileBinary(filename, cloud_output);
++number_clouds_processed;
}
pcl::io::savePCDFileBinary("registration_final_model.pcd", cloud_model);
return 0;
}
but when i am compiling it does not know all the terminal_tools header files. but i have downloaded ROS.
Do I have to specify or something on CMakeLists.txt? this is my cmake
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(pcd_register)
find_package(PCL 1.2 REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
add_executable (pcd_register pcd_register.cpp)
target_link_libraries (pcd_register ${PCL_LIBRARIES})
I have a ROS running a similar node using the PCL library and your CMakeLists.txt looks good regarding PCL. If cmake is not finding the terminal tools headers, it is because you have not specified to add those include directories within cmake. In general, if you know how to compile with g++ myprogram.cpp -I${INCLUDE_DIRS} -L${LIB_DIRS} -l${LIBS}, then you need to add the following lines to your CMakeLists:
include_directories(${INCLUDE_DIRS})
link_directories(${LIB_DIRS})
target_link_libraries(pcd_register ${LIBS}).
In your case, you need to specify the include directories of terminal_tools with an include_directories line.
I have JBoss running on Sun Java 1.5.
From time to time, it unexpectedly shuts down (in orderly fashion).
I suspect some other process is sending it kill or CTRL+C signals.
Is there a way on Unix/Solaris to trace who sent the signal?
On Solaris, you can use a simple dtrace script to find who is killing your process (assuming its name is java, adjust it otherwise):
dtrace -qn '
proc:::signal-send
/ args[1]->pr_fname == "java" /
{
printf("Process %d (%s by UID %d) sending signal %d to java (pid=%d)\n",
pid,execname,uid,arg1,args[1]->pr_pid);
}'
You can use sigaction to determine the source of the signal. pid may be zero as the signal was send from the kernel or via some user interaction (pressing ctrl+c)
#include <signal.h>
#include <string.h>
#include <stdio.h>
static void signal_handler(int sig, siginfo_t *info, void *data) {
printf ("signal: [%d], pid: [%d], uid: [%d]\n", sig,
info->si_pid,
info->si_uid );
}
int main(int argc, char *argv[]) {
struct sigaction sa;
memset ( &sa, '\0', sizeof ( struct sigaction ) );
sa.sa_sigaction = &signal_handler;
sa.sa_flags |= SA_SIGINFO;
sigemptyset ( &sa.sa_mask );
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGQUIT, &sa, NULL);
while ( 1 ) {
sleep (1);
}
return 0;
}
We know that, shared memory in Windows is implemented via memory mapped files backed by system pagefile, and it is always managed in a reference counted way (http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537(v=vs.85).aspx).
I wonder whether Unix does it in a similar way. Someone (http://stackoverflow.com/q/4278391/939142) says that Unix also manages shm in a reference counted way. I tried the an experiment on Mac OS X, and found that it was not the case.
Using the code supplied in the end, compile two programs: host and client. Type
./host
which creates a shm, writes (int) 10 at its first address, and quits. Then type
./client <shmid>
to examine the shm segment, which attaches to the shm created, prints the first int, and quits.
Note that we used shmat and shmdt to connect to / disconnect from the shm, and shmget to create the shm.
To destroy the shm, we have to do it manually using shmctl.
Conclusion:
shm is not managed as reference counting in Unix, at least for Mac OS X
/************************** host.c ****************************/
#include <stdio.h>
#include <sys/shm.h>
#include <mach/vm_param.h>
#include <assert.h>
int
main(int argc, char** argv)
{
int value = 10;
int id;
void* ptr;
/* create a new shm */
id = shmget(IPC_PRIVATE, PAGE_SIZE, IPC_CREAT | 0666);
assert(id != -1);
/* attach to the new shm */
ptr = shmat(id, (const void*) NULL, 0);
assert((int*) ptr != -1);
/* print the id so that client can use */
printf("shm id = %ld\n", id);
printf("address of id = %ld, length = %ld\n", ptr, PAGE_SIZE);
((int*) ptr)[0] = value;
printf("value at address %ld = %ld\n", ptr, *(int*) ptr);
/* detach from the shm and exit */
shmdt((const void*) ptr);
return 0;
}
/************************** host.c ****************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include "assert.h"
#include <mach/vm_param.h>
int
main(int argc, char** argv)
{
void* ptr;
int id = atoi(argv[1]);
assert(id != -1);
/* attach to the shm */
ptr = shmat(id, NULL, 0);
assert(ptr != -1);
printf("value at ptr = %ld = %ld\n", ptr, *(int*) ptr);
shmdt((const void*) ptr);
return 0;
}
It not pure reference counting. According to shmctl(2):
IPC_RMID: Mark the segment to be destroyed. The segment will only
actually be destroyed after the last process detaches it
(i.e., when the shm_nattch member of the associated structure
shmid_ds is zero). The caller must be the owner or creator,
This means: IPC_RMID will not delete immediately but only after the reference count drops to zero the next time.
This allows you to achieve several goals with the same tool:
Either a server/client approach where the server creates, attaches and immediately sets RMID. Then clients can connect as long as the server is here. If the server goes down, the clients should disconect and the resource is cleaned up by the OS.
Or the "message" approach: Someone writes a message, pins it to a known location. After that someone else can come, look for a message and act accordingly. This is what you have done. This approach is more open to resource garbage of course. But there are usecases for this.