Gnuradio,OOT: correcting send() for tagged stream block? - c++

I need help making a gnuradio OOT module. I am actually trying to extending one code.
I am trying to make 2 TX 1Rx tagged stream block (OOT). For 1Tx 1Rx, it
is working fine. I am trying to extend it. Now the problem is, I am not
being able to configure the send() function. With this code, one transmitter transmits, but other does not work. The subdev specification and frequency and other parameters are allocated correctly. I checked.
If I try make test, it does not show any problem. I checked the every
port of my USRP X310, it is working fine.
Here's the code. I putting a short part which deals with the send and receive buffer.
void
usrp_echotimer_cc_impl::send()
{
// Data to USRP
num_tx_samps = d_tx_stream->send(d_in_send1, total_num_samps,
d_metadata_tx, total_num_samps/(float)d_samp_rate+d_timeout_tx);
num_tx_samps = d_tx_stream->send(d_in_send0, total_num_samps,
d_metadata_tx, total_num_samps/(float)d_samp_rate+d_timeout_tx);
}
int
usrp_echotimer_cc_impl::work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
gr_complex *in0 = (gr_complex *) input_items[0];
gr_complex *in1 = (gr_complex *) input_items[1];
gr_complex *out = (gr_complex *) output_items[0];
// Set output items on packet length
noutput_items = ninput_items[0]=ninput_items[1];
// Resize output buffer
if(d_out_buffer.size()!=noutput_items)
d_out_buffer.resize(noutput_items);
// Send thread
d_in_send0 = in0;
d_in_send1 = in1;
d_noutput_items_send = noutput_items;
d_thread_send =
gr::thread::thread(boost::bind(&usrp_echotimer_cc_impl::send, this));
// Receive thread
d_out_recv = &d_out_buffer[0];
d_noutput_items_recv = noutput_items;
d_thread_recv =
gr::thread::thread(boost::bind(&usrp_echotimer_cc_impl::receive, this));
My system config is X310, daughterboard SBX-120 and I am using UHD-3.9. I checked the subdev specification, gain and frequency assignment. Those
are fine.

For completeness:
This has been asked yesterday on the GNU Radio mailing list; Sanjoy has already gotten two responses:
Martin Braun wrote:
Sorry, Sanjoy,
we'll need some more information before we can give you better
feedback. It's not clear exactly what you're trying to achieve, and
what exactly is failing.
Perhaps this helps getting started:
http://gnuradio.org/redmine/projects/gnuradio/wiki/ReportingErrors
Cheers, Martin
And my answer is a bit longish, but it's available here. In excerpts:
Hi Sanjoy,
I am trying to make 2 TX 1Rx tagged stream block(OOT). For 1Tx 1Rx, it was working fine. I am trying to extend it. Now the problem is, I
am not being able to configure the send() function.
Is there a
particular reason you're creating your own block? Is there a feature
missing on the USRP sink and source that come with gr-uhd?
...
your send() function looks a bit strange; what you're doing is
transmitting two things on a single channel after each other. Also,
what you should be doing (from a programming style point of view) is
pass the buffers you want to send as references or something, but not
save them to class properties and then call send(). To send two
buffers to two different channels, you will need to use a vector
containing the two buffers -- have a look at rx_multi_samples; that of
course recv()s rather than sends(), but the semantics are the same.
...
noutput_items is given to you to let your work now how much it may produce, that's why it's a parameter.
...
There's no reason GNU Radio couldn't already call your work function again while usrp_echotimer_cc_impl::send() hasn't even started to transmit samples. Then, your d_send variables will be overwritten.
...
Since a single X310 is inherently coherent and has the same time, you can simply use a USRP sink and a source, use set_start_time(...) on both with the same time spec, and have your flow graph consume and produce samples in different threads, coherently.

Related

Hard Realtime C++ for Robot Control

I am trying to control a robot using a template-based controller class written in c++. Essentially I have a UDP connection setup with the robot to receive the state of the robot and send new torque commands to the robot. I receive new observations at a higher frequency (say 2000Hz) and my controller takes about 1ms (1000Hz) to calculate new torque commands to send to the robot. The problem I am facing is that I don't want my main code to wait to send the old torque commands while my controller is still calculating new commands to send. From what I understand I can use Ubuntu with RT-Linux kernel, multi-thread the code so that my getTorques() method runs in a different thread, set priorities for the process, and use mutexes and locks to avoid data race between the 2 threads, but I was hoping to learn what the best strategies to write hard-realtime code for such a problem are.
// main.cpp
#include "CONTROLLER.h"
#include "llapi.h"
void main{
...
CONTROLLERclass obj;
...
double new_observation;
double u;
...
while(communicating){
get_newObs(new_observation); // Get new state of the robot (2000Hz)
obj.getTorques(new_observation, u); // Takes about 1ms to calculate new torques
send_newCommands(u); // Send the new torque commands to the robot
}
...
}
Thanks in advance!
Okay, so first of all, it sounds to me like you need to deal with the fact that you receive input at 2 KHz, but can only compute results at about 1 KHz.
Based on that, you're apparently going to have to discard roughly half the inputs, or else somehow (in a way that makes sense for your application) quickly combine the inputs that have arrived since the last time you processed the inputs.
But as the code is structured right now, you're going to fetch and process older and older inputs, so even though you're producing outputs at ~1 KHz, those outputs are constantly being based on older and older data.
For the moment, let's assume you want to receive inputs as fast as you can, and when you're ready to do so, you process the most recent input you've received, produce an output based on that input, and repeat.
In that case, you'd probably end up with something on this general order (using C++ threads and atomics for the moment):
std::atomic<double> new_observation;
std::thread receiver = [&] {
double d;
get_newObs(d);
new_observation = d;
};
std::thread sender = [&] {
auto input = new_observation;
auto u = get_torques(input);
send_newCommands(u);
};
I've assumed that you'll always receive input faster than you can consume it, so the processing thread can always process whatever input is waiting, without receiving anything to indicate that the input has been updated since it was last processed. If that's wrong, things get a little more complex, but I'm not going to try to deal with that right now, since it sounds like it's unnecessary.
As far as the code itself goes, the only thing that may not be obvious is that instead of passing a reference to new_input to either of the existing functions, I've read new_input into variable local to the thread, then passed a reference to that.

Why is my Arduino MKR NB 1500 stuck after sending or receiving a couple of MQTT messages?

Good morning everyone, newcomer writing his first question here (and new to C++/OOP).
So, i'm currently working on a project in which i have to send 2 types of JSON payloads to a MQTT broker after regular intervals (which can be set by sending a message to the Arduino MKR NB 1500).
I'm currently using these libraries: ArduinoJson, StreamUtils to generate and serialize/deserialize the JSONs, PubSubClient to publish/receive, and MKRNB in my VS code workplace.
What I noticed is that my program runs fine for a couple of publishes/receives and then stays stuck in the serialization function: I tried to trace with the serial monitor to see exactly where, but eventually arrived at a point in which my knowledge in C++ is too weak to recognize where to even put the traces in the code...
Let me show a small piece of the code:
DynamicJsonDocument coffeeDoc(12288); //i need a big JSON document (it's generated right before
//the transmission and destroyed right after)
coffeeDoc["device"]["id"] = boardID
JsonObject transaction = coffeeDoc.createNestedObject("transaction");
transaction["id"] = j; //j was defined as int, it's the number of the message sent
JsonArray transaction_data = transaction.createNestedArray("data");
for(int i = 0; i < total; i++){ //this loop generates the objects in the JSON
transaction_data[i] = coffeeDoc.createNestedObject();
transaction_data[i]["id"] = i;
transaction_data[i]["ts"] = coffeeInfo[i].ts;
transaction_data[i]["pwr"] = String(coffeeInfo[i].pwr,1);
transaction_data[i]["t1"] = String(coffeeInfo[i].t1,1);
transaction_data[i]["t2"] = String(coffeeInfo[i].t2,1);
transaction_data[i]["extruder"] = coffeeInfo[i].extruder;
transaction_data[i]["time"] = coffeeInfo[i].time;
}
client.beginPublish("device/coffee", measureJson(coffeeDoc), false);
BufferingPrint bufferedClient{client, 32};
serializeJson(coffeeDoc, bufferedClient); //THE PROGRAM STOPS IN THIS AND NEVER COMES OUT
bufferedClient.flush();
client.endPublish();
j++;
coffeeDoc.clear(); //destroy the JSON document so it can be reused
The same code works as it should if i use an Arduino MKR WiFi 1010, I think i know too little about how the GSM works.
What am I doing wrong? (Again, it works about twice before getting stuck).
Thanks to everybody who will find the time to help, have a nice one!!
Well, here's a little update: turns out i ran out of memory, so 12288 bytes were too many for the poor microcontroller.
By doing some "stupid" tries, i figured 10235 bytes are good and close to the maximum available (the program won't use more than 85% of the RAM); yeah, that's pretty close to the maximum, but the requirements of the project give no other option.
Thanks even for having read this question, have a nice one!

I need help figuring out tcp sockets (clsocket)

I am having trouble figuring out sockets i am just asking the server for data at a position (glm::i64vec4) and expecting a response but the position gets way off when i get the response and the data for that position reflects that (aka my voxel game make a kinda cool looking but useless mess)
It's probably just me not understanding sockets whatsoever or maybe something weird with this library
one thought i had is it was maybe something to do with mismatching blocking and non blocking on the server and client
but when i switched the server to blocking (and put each client in a seperate thread from each other and the accepting process) it did nothing
if i'm doing something really stupid please tell me i know next to nothing about sockets
here is some code that probably looks horrible
Server Code
std::deque <CActiveSocket*> clients;
CPassiveSocket socket;
socket.Initialize();
socket.SetNonblocking();//I'm doing this so i don't need multiple threads for clients
socket.Listen("0.0.0.0",port);
while (1){
{
CActiveSocket* c;
if ((c = socket.Accept()) != NULL){
clients.emplace_back(c);
}
}
for (CActiveSocket*& c : clients){
c->Receive(sizeof(glm::i64vec4));
if (c->GetBytesReceived() == sizeof(glm::i64vec4)){
chkpkt chk;
chk.pos = *(glm::i64vec4*)c->GetData();
LOOP3D(chksize+2){
chk.data(i,j,k).val = chk.pos.y*chksize+j;
chk.data(i,j,k).id=0;
}
while (c->Send((uint8*)&chk,sizeof(chkpkt)) != sizeof(chkpkt)){}
}
}
}
Client Code
//v is a glm::i64vec4
//fsock is set to Blocking
if(fsock.Send((uint8*)&v,sizeof(glm::i64vec4)))
if (fsock.Receive(sizeof(chkpkt))){
tthread::lock_guard<tthread::fast_mutex> lock(wld->filemut);
wld->ichks[v]=(*(chkpkt*)fsock.GetData()).data;//i tried using the position i get back from the server to set this (instead of v) but that made it to where nothing loaded
//i checked it and the chunks position never lines up with what i sent
}
Without your complete application codes it's unrealistic to offer any suggestions of any particular lines of code correction.
But it seems like you are using this library. It doesn't matter if not, because most of time when doing network programming, socket's weird behavior make some problems somewhat universal. Thus there are a few suggestions for the portion of socket application in your project:
It suffices to have BLOCKING sockets.
Most of time socket's read have somewhat weird behavior, that is, it might not receive the requested size of bytes at a time. Due to this, you need to repeatedly call read until the receiving buffer is read thoroughly. For a complete and robust solution you can refer to Stevens's readn routine ([Ref.1], page122).
If you are using exactly the library mentioned above, you can see that your fsock.Receive eventually calls recv. And recv is just an variant of read[Ref.2], thus the solutions for both of them are just identical. And this pattern might help:
while(fsock.Receive(sizeof(chkpkt))>0)
{
// ...
}
Ref.1: https://mathcs.clarku.edu/~jbreecher/cs280/UNIX%20Network%20Programming(Volume1,3rd).pdf
Ref.2: https://man7.org/linux/man-pages/man2/recv.2.html#DESCRIPTION

c++ streaming udp data into a queue?

I am streaming data as a string over UDP, into a Socket class inside Unreal engine. This is threaded, and runs in the background.
My read function is:
float translate;
void FdataThread::ReceiveUDP()
{
uint32 Size;
TArray<uint8> ReceivedData;
if (ReceiverSocket->HasPendingData(Size))
{
int32 Read = 0;
ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
ReceiverSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), Read, *targetAddr);
}
FString str = FString(bytesRead, UTF8_TO_TCHAR((const UTF8CHAR *)ReceivedData));
translate = FCString::Atof(*str);
}
I then call the translate variable from another class, on a Tick, or timer.
My test case sends an incrementing number from another application.
If I print this number from inside the above Read function, it looks as expected, counting up incrementally.
When i print it from the other thread, it is missing some of the numbers.
I believe this is because I call it on the Tick, so it misses out some data due to processing time.
My question is:
Is there a way to queue the incoming data, so that when i pull the value, it is the next incremental value and not the current one? What is the best way to go about this?
Thank you, please let me know if I have not been clear.
Is this the complete code? ReceivedData isn't used after it's filled with data from the socket. Instead, an (in this code) undefined variable 'buffer' is being used.
Also, it seems that the while loop could run multiple times, overwriting old data in the ReceivedData buffer. Add some debugging messages to see whether RecvFrom actually reads all bytes from the socket. I believe it reads only one 'packet'.
Finally, especially when you're using UDP sockets over the network, note that the UDP protocol isn't guaranteed to actually deliver its packets. However, I doubt this is causing your problems if you're using it on a single computer or a local network.
Your read loop doesn't make sense. You are reading and throwing away all datagrams but the last in any given sequence that happen to be in the socket receive buffer at the same time. The translate call should be inside the loop, and the loop should be while(true), or while (running), or similar.

Correct use of memcpy

I have some problems with a project I'm doing. Basically I'm just using memcpy the wrong way. I know the theroy of pointer/arrays/references and should know how to do that, nevertheless I've spend two days now without any progress. I'll try to give a short code overview and maybe someone sees a fault! I would be very thankful.
The Setup: I'm using an ATSAM3x Microcontroller together with a uC for signal aquisition. I receive the data over SPI.
I have an Interrupt receiving the data whenever the uC has data available. The data is then stored in a buffer (int32_t buffer[1024 or 2048]). There is a counter that counts from 0 to the buffer size-1 and determines the place where the data point is stored. Currently I receive a test signal that is internally generated by the uC
//ch1: receive 24 bit data in 8 bit chunks -> store in an int32_t
ch1=ch1|(SPI.transfer(PIN_CS, 0x00, SPI_CONTINUE)<<24)>>8;
ch1=ch1|(SPI.transfer(PIN_CS, 0x00, SPI_CONTINUE)<<16)>>8;
ch1=ch1|(SPI.transfer(PIN_CS, 0x00, SPI_CONTINUE)<<8)>>8;
if(Not Important){
_ch1Buffer[_ch1SampleCount] = ch1;
_ch1SampleCount++;
if(_ch1SampleCount>SAMPLE_BUFFER_SIZE-1) _ch1SampleCount=0;
}
This ISR is active all the time. Since I need raw data for signal processing and the buffer is changed by the ISR whenever a new data point is available, i want to copy parts of the buffer into a temporary "storage".
To do so, I have another, global counter wich is incremented within the ISR. In the mainloop, whenever the counter reaches a certain size, i call a method get some of the buffer data (about 30 samples).
The method aquires the current position in the buffer:
'int ch1Pos = _ch1SampleCount;'
and then, depending on that position I try to use memcpy to get my samples. Depending on the position in the buffer, there has to be a "wrap-around" to get the full set of samples:
if(ch1Pos>=(RAW_BLOCK_SIZE-1)){
memcpy(&ch1[0],&_ch1Buffer[ch1Pos-(RAW_BLOCK_SIZE-1)] , RAW_BLOCK_SIZE*sizeof(int32_t));
}else{
memcpy(&ch1[RAW_BLOCK_SIZE-1 - ch1Pos],&_ch1Buffer[0],(ch1Pos)*sizeof(int32_t));
memcpy(&ch1[0],&_ch1Buffer[SAMPLE_BUFFER_SIZE-1-(RAW_BLOCK_SIZE- ch1Pos)],(RAW_BLOCK_SIZE-ch1Pos)*sizeof(int32_t));
}
_ch1Buffer is the buffer containing the raw data
SAMPLE_BUFFER_SIZE is the size of that buffer
ch1 is the array wich is supposed to hold the set of samples
RAW_BLOCK_SIZE is the size of that array
ch1Pos is the position of the last data point written to the buffer from the ISR at the time where this method is called
Technically I'm aware of the requirements, but apparently thats not enough ;-).
I know, that the data received by the SPI interface is "correct". The problem is, that this is not the case for the extracted samples. There are a lot of spikes in the data that indicate that I've been reading something I wasn't supposed to read. I've changed the memcpy commands that often, that I completly lost the overview. The code sample above is one version of many's, and while you're reading this I'm sure I've changed everything again.
I would appreciate every hint!
Thanks & Greetings!
EDIT
I've written down everything (again) on a sheet of paper and tested some constellations. This is the updated Code for the memcpy part:
if(ch1Pos>=(RAW_BLOCK_SIZE-1)){
memcpy(&ch1[0],&_ch1Buffer[ch1Pos-(RAW_BLOCK_SIZE-1)] , RAW_BLOCK_SIZE*sizeof(int32_t));
}else{
memcpy(&ch1[RAW_BLOCK_SIZE-1-ch1Pos],&_ch1Buffer[0],(ch1Pos+1)*sizeof(int32_t));
memcpy(&ch1[0],&_ch1Buffer[SAMPLE_BUFFER_SIZE-(RAW_BLOCK_SIZE-1-ch1Pos)],(RAW_BLOCK_SIZE-1-ch1Pos)*sizeof(int32_t));
}
}
This already made it a lot better. From all the changes, everything kinda got messed up. Now there is just one Error there. There is a periodical spike. I'll try to get more information, but I think it is a wrong access while wrapping around.
I've changed the if(_ch1SampleCount>SAMPLE_BUFFER_SIZE-1) _ch1SampleCount=0; to if(_ch1SampleCount>=SAMPLE_BUFFER_SIZE) _ch1SampleCount=0;.
EDIT II
To answer the Questions of #David Schwartz :
SPI.transfer returns a single byte
The buffer is initialised once at startup: memset(_ch1Buffer,0,sizeof(int32_t)*SAMPLE_BUFFER_SIZE);
EDIT III
Sorry for the frequent updates, the comment section is getting too big.
I managed to get rid of a bunch of zero values at the beginning of the stream by decreasing ch1Pos: 'int ch1Pos = _ch1SampleCount;' Now there is just one periodic "spike" (wrong value). It must be something with the splitted memcpy command. I'll continue looking. If anyone has an idea ... :-)