I'm writing a minimalistic library for window creation in xcb.
I want to be able to create a non-resizeable window. I found out, that it is possible to give hints to the window manager with:
xcb_void_cookie_t xcb_change_property (xcb_connection_t *c, /* Connection to the X server */
uint8_t mode, /* Property mode */
xcb_window_t window, /* Window */
xcb_atom_t property, /* Property to change */
xcb_atom_t type, /* Type of the property */
uint8_t format, /* Format of the property (8, 16, 32) */
uint32_t data_len, /* Length of the data parameter */
const void *data); /* Data */
I tried to change the WM_NORMAL_HINTS and WM_SIZE_HINTS with this function, but how do I know what data I have to put in the *data parameter? Is the type XCB_ATOM_INTEGER or something else?
If you want to do this without depending on xcb_icccm you can directly change the property.
struct WMSizeHints
{
uint32_t flags;
int32_t x, y;
int32_t width, height;
int32_t min_width, min_height;
int32_t max_width, max_height;
int32_t width_inc, height_inc;
int32_t min_aspect_num, min_aspect_den;
int32_t max_aspect_num, max_aspect_den;
int32_t base_width, base_height;
uint32_t win_gravity;
};
enum WMSizeHintsFlag
{
WM_SIZE_HINT_US_POSITION = 1U << 0,
WM_SIZE_HINT_US_SIZE = 1U << 1,
WM_SIZE_HINT_P_POSITION = 1U << 2,
WM_SIZE_HINT_P_SIZE = 1U << 3,
WM_SIZE_HINT_P_MIN_SIZE = 1U << 4,
WM_SIZE_HINT_P_MAX_SIZE = 1U << 5,
WM_SIZE_HINT_P_RESIZE_INC = 1U << 6,
WM_SIZE_HINT_P_ASPECT = 1U << 7,
WM_SIZE_HINT_BASE_SIZE = 1U << 8,
WM_SIZE_HINT_P_WIN_GRAVITY = 1U << 9
};
struct WMSizeHints hints =
{
.flags = WM_SIZE_HINT_P_WIN_GRAVITY,
.win_gravity = XCB_GRAVITY_STATIC
};
if (centerWindow)
hints.win_gravity = XCB_GRAVITY_CENTER;
else
{
hints.flags |= WM_SIZE_HINT_P_SIZE;
hints.x = x;
hints.y = y;
}
xcb_change_property(xcb, XCB_PROP_MODE_REPLACE, window,
XCB_ATOM_WM_NORMAL_HINTS, XCB_ATOM_WM_SIZE_HINTS,
32, sizeof(struct WMSizeHints) >> 2, &hints);
Here is the solution:
#include <xcb/xcb.h>
#include <xcb/xcb_icccm.h>
#define WIDTH 900
#define HEIGHT 600
int main(){
//...
//Connect to X Server and
//Create a window
//...
xcb_size_hints_t hints;
xcb_icccm_size_hints_set_min_size(&hints, WIDTH, HEIGHT);
xcb_icccm_size_hints_set_max_size(&hints, WIDTH, HEIGHT);
xcb_icccm_set_wm_size_hints(connection, window, XCB_ATOM_WM_NORMAL_HINTS, &hints);
return 0;
}
Related
I encountered the following error
gr::log :WARN: tpb_thread_body - asynchronous message buffer overflowing, dropping message
Out of serendipity, I ran into this GNU Radio presentation on
Youtube.
The presenter mentioned an OOT block he called "buffer" that is capable of eliminating the "buffer overflowing" error. Apparently, this block plays with different sample rates and the so-called "circular buffers". I haven't worked with circular buffers myself. Any ideas on circular buffers or any hints on how to build this buffer block are welcome.
EDIT
Below is the flowgraph that generates the error. As it was suggested in the comments, the culprits could be the message processing blocks (red-circled) namely generateCADU (for generating standard CCSDS frames) and processCADU (for extracting CADUs from a data stream).
The implementation file of the generateCADU block is given below
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "generateCADU_impl.h"
#include "fec/ReedSolomon/ReedSolomon.h"
#include "fec/Scrambler/Scrambler.h"
namespace gr {
namespace ccsds {
generateCADU::sptr
generateCADU::make(int frameLength,std::string sync, int scramble, int rs, int intDepth)
{
return gnuradio::get_initial_sptr
(new generateCADU_impl(frameLength, sync, scramble, rs, intDepth));
}
/*
* The private constructor
*/
generateCADU_impl::generateCADU_impl(int frameLength,std::string sync, int scramble, int rs, int intDepth)
: gr::sync_block("generateCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(0, 0, 0)),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
set_output_multiple(d_frameLength);
//Registering output port
message_port_register_out(pmt::mp("out"));
d_sync = parse_string(sync);
}
/*
* Our virtual destructor.
*/
generateCADU_impl::~generateCADU_impl()
{
}
unsigned char
generateCADU_impl::parse_hex(char c)
{
if ('0' <= c && c <= '9') return c - '0';
if ('A' <= c && c <= 'F') return c - 'A' + 10;
if ('a' <= c && c <= 'f') return c - 'a' + 10;
std::abort();
}
std::vector<unsigned char>
generateCADU_impl::parse_string(const std::string & s)
{
if (s.size() % 2 != 0) std::abort();
std::vector<unsigned char> result(s.size() / 2);
for (std::size_t i = 0; i != s.size() / 2; ++i)
result[i] = 16 * parse_hex(s[2 * i]) + parse_hex(s[2 * i + 1]);
return result;
}
int
generateCADU_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
//Reed-Solomon and Scrambler objects
ReedSolomon RS(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
Scrambler S;
//Buffers
unsigned char *frameBuffer1 = (unsigned char*)malloc(d_frameLength*sizeof(unsigned char));
std::vector<unsigned char> frameBuffer2;
//The work function engine
for(int i = 0; (i + d_frameLength) < noutput_items; i += d_frameLength)
{
//Copying data from input stream
memcpy(frameBuffer1,in + i + d_frameLength,d_frameLength);
//Copying frame into std::vector buffer
frameBuffer2.insert(frameBuffer2.begin(),frameBuffer1, frameBuffer1 + d_frameLength);
//Optional scrambling and Reed-Solomon
if (d_rs) RS.Encode_RS(frameBuffer2);
if (d_scramble) S.Scramble(frameBuffer2);
//Insert sync word
frameBuffer2.insert(frameBuffer2.begin(), d_sync.begin(), d_sync.end());
//Transmitting PDU
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer2.data(),frameBuffer2.size())));
message_port_pub(pmt::mp("out"), pdu);
//Clear buffer
frameBuffer2.clear();
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace ccsds */
} /* namespace gr */
And here is the processCADU block. This block uses tags generated by the synchronizeCADU (which is simply a wrapper for the correlate_access_tag block) to extract CADUs
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "processCADU_impl.h"
#include "fec/ReedSolomon/ReedSolomon.h"
#include "fec/Scrambler/Scrambler.h"
namespace gr {
namespace ccsds {
processCADU::sptr
processCADU::make(int frameLength, int scramble, int rs, int intDepth, std::string tagName)
{
return gnuradio::get_initial_sptr
(new processCADU_impl(frameLength, scramble, rs, intDepth, tagName));
}
/*
* The private constructor
*/
processCADU_impl::processCADU_impl(int frameLength, int scramble, int rs, int intDepth, std::string tagName)
: gr::sync_block("processCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(0, 0, 0)),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
//Multiple input
set_output_multiple(d_frameLength * 8);
//Registering output port
message_port_register_out(pmt::mp("out"));
if (d_rs) d_frameLength += 32 * d_intDepth;
//SEtting tag name
key = pmt::mp(tagName);
}
/*
* Our virtual destructor.
*/
processCADU_impl::~processCADU_impl()
{
delete d_pack;
}
int
processCADU_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];
void *msg_data = NULL;
unsigned char frame_data[d_frameLength];
unsigned char frame_len = 0;
std::vector<unsigned char> frameBuffer;
//Reed-Solomon and Scrambler objects
ReedSolomon RS(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
std::vector<int> errors;//errors.push_back(0);
Scrambler S;
d_tags.clear();
d_pack = new blocks::kernel::pack_k_bits(8);
this->get_tags_in_window(d_tags, 0, 0, noutput_items,key);
for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++) {
// Check that we have enough data for a full frame
if ((d_tags_itr->offset - this->nitems_read(0)) > (noutput_items - (d_frameLength) * 8))
{
return (d_tags_itr->offset - this->nitems_read(0) - 1);
}
//Pack bits into bytes
d_pack->pack(frame_data, &in[d_tags_itr->offset - this->nitems_read(0)], d_frameLength);
//Copying frame into std::vector buffer
frameBuffer.insert(frameBuffer.begin(),frame_data, frame_data + d_frameLength);
//Optional scrambling and Reed-Solomon
if (d_scramble) S.Scramble(frameBuffer);
//if (d_rs) RS.Decode_RS(frameBuffer,errors);
//If there is Reed-Solomon decoding
if(d_rs)
{
RS.Decode_RS(frameBuffer,errors);
if (RS.Success(errors)) // Success
{
//std::cout << "Success" << std::endl;
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer.data(),frameBuffer.size())));
message_port_pub(pmt::mp("out"), pdu);
/*for(int i=0; i < errors.size(); i++)
{
//std::cout << "Number of Errors : " << errors.at(i) << std::endl << std::endl;
}*/
}
else // Failure
{
std::cout << "RS failure" << std::endl;
}
}
else{
pmt::pmt_t pdu(pmt::cons(pmt::PMT_NIL,pmt::make_blob(frameBuffer.data(),frameBuffer.size())));
message_port_pub(pmt::mp("out"), pdu);
}
//Clear buffers
frameBuffer.clear();
errors.clear();
}
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace ccsds */
} /* namespace gr */
Regards,
M
Thanks to #MarcusMüller suggestion, using the tagged_stream paradigma as opposed to PDUs solved the problem. I was able to transmit 47 terabytes of data without any problems. Below is the code for the newly implemented block.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "genCADU_impl.h"
namespace gr {
namespace ccsds {
genCADU::sptr
genCADU::make(int frameLength,std::string sync, int scramble, int rs, int intDepth, std::string len_tag_key)
{
return gnuradio::get_initial_sptr
(new genCADU_impl(frameLength, sync, scramble, rs, intDepth, len_tag_key));
}
/*
* The private constructor
*/
genCADU_impl::genCADU_impl(int frameLength,std::string sync, int scramble, int rs, int intDepth, std::string len_tag_key)
: gr::tagged_stream_block("genCADU",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(1, 1, sizeof(unsigned char)),len_tag_key),
d_frameLength(frameLength),d_scramble(scramble == 1),d_rs(rs >= 1), d_basis(rs >= 2), d_intDepth(intDepth)
{
//Synchronization pattern
d_sync = parse_string(sync);
//Reed-Solomon and Scrambler objects
RS = new ReedSolomon(16,d_intDepth,d_basis);// False = conventional, True = dual-basis
S = new Scrambler();
}
/*
* Our virtual destructor.
*/
genCADU_impl::~genCADU_impl()
{
delete RS;
delete S;
}
int
genCADU_impl::calculate_output_stream_length(const gr_vector_int &ninput_items)
{
int noutput_items = (d_rs) ? d_frameLength + 32*d_intDepth + d_sync.size() : d_frameLength + d_sync.size();
return noutput_items ;
}
unsigned char
genCADU_impl::parse_hex(char c)
{
if ('0' <= c && c <= '9') return c - '0';
if ('A' <= c && c <= 'F') return c - 'A' + 10;
if ('a' <= c && c <= 'f') return c - 'a' + 10;
std::abort();
}
std::vector<unsigned char>
genCADU_impl::parse_string(const std::string & s)
{
if (s.size() % 2 != 0) std::abort();
std::vector<unsigned char> result(s.size() / 2);
for (std::size_t i = 0; i != s.size() / 2; ++i)
result[i] = 16 * parse_hex(s[2 * i]) + parse_hex(s[2 * i + 1]);
return result;
}
int
genCADU_impl::work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];
int total_len;
//Copy pdu from circular buffer to local buffer
buffer.insert(buffer.end(), in, in + d_frameLength);
//Optional scrambling and Reed-Solomon. TO DO: Turbo and LDPC
if (d_rs) RS->Encode_RS(buffer);
if (d_scramble) S->Scramble(buffer);
//Insert sync word
buffer.insert(buffer.begin(), d_sync.begin(), d_sync.end());
//Copy from local buffer to circular buffer
std::copy(buffer.begin(),buffer.end(),out);
//Clear the local buffer
total_len = buffer.size();
buffer.clear();
// Tell runtime system how many output items we produced.
return total_len;
}
} /* namespace ccsds */
} /* namespace gr */
Regards,
M.
I have tried to do offscreen rendering in my linux server(a virtual machine with no graphics card and no window system) by OSMesa, refer to the osmesa demo osdemos. Every thing works fine.
For antialiasing, i tried to create a multisamping render buffer to bind to FBO, but result with GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, the single sampled render buffer works fine.
here is the code to create the FBO, change the sample_number for 1, works fine, for 4 with GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT error. Any suggestions are appricate.
#define GL_GLEXT_PROTOTYPES
#include <GL/glu.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iostream>
#include "GL/osmesa.h"
#include <GL/glut.h>
const int Width = 1920;
const int Height = 1080;
int main(int argc, char *argv[])
{
OSMesaContext ctx;
void *buffer;
#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
ctx = OSMesaCreateContextExt( OSMESA_RGBA, 32, 0, 0, NULL );
#else
ctx = OSMesaCreateContext( OSMESA_RGBA, NULL );
#endif
if (!ctx) {
printf("OSMesaCreateContext failed!\n");
return 0;
}
buffer = malloc( Width * Height * 4 * sizeof(GLubyte) );
if (!buffer) {
printf("Alloc image buffer failed!\n");
return 0;
}
if (!OSMesaMakeCurrent( ctx, buffer, GL_UNSIGNED_BYTE, Width, Height )) {
printf("OSMesaMakeCurrent failed!\n");
return 0;
}
int render_width = 200, render_height = 200;
enum { Color, Depth, NumRenderbuffers };
// multi-sampled frame buffer object as the draw target
GLuint framebuffer_ms, renderbuffer_ms[NumRenderbuffers];
// generate color and depth render buffers and allocate storage for the multi-sampled FBO
glGenRenderbuffers(NumRenderbuffers, renderbuffer_ms);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_ms[Color]);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, // here set 1 works fine
GL_RGBA8, render_width, render_height);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_ms[Depth]);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, // here set 1 works fine
GL_DEPTH_COMPONENT24, render_width, render_height);
// generate frame buffer object for the multi-sampled FBO
glGenFramebuffers(1, &framebuffer_ms);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer_ms);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, renderbuffer_ms[Color]);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, renderbuffer_ms[Depth]);
auto status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if (status == GL_FRAMEBUFFER_COMPLETE) {
std::cout << "fbo status fine!!!" << std::endl;
} else {
std::cout << "Failed:" << status << std::endl;
}
exit(__LINE__);
// render_image();
// std::vector<GLubyte> data(width *height * 4);
// glReadBuffer(GL_COLOR_ATTACHMENT0);
// glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
// write_targa(data.data(), width, height);
glDeleteFramebuffers(1, &framebuffer_ms);
glDeleteRenderbuffers(2, renderbuffer_ms);
free(buffer);
return 0;
}
Just use the post processing to do anti-aliasing. pp_jimenezmlaa and pp_jimenezmlaaa_color
So I've been working on this program for the last month. The original code is from this tutorial https://www.youtube.com/watch?v=KjHKwCZyAhQ&list=PLHm_I0tE5kKPPWXkTTtOn8fkcwEGZNETh&index=3
However, I thought I would turn it into an object oriented program before I went on. Doing rather than copying is the best way to learn. The code generated a bmp file before i divided it up, but not anymore. The program executes but it doesn't create a file. Additionally I added Hello World in my .cpp files to see if they were even being executed and it looks like they aren't. I realize in copying this that I have a lot of code, I think the problem is in the main file so hopefully if anyone is nice enough to help me they can pick it out much more quickly!
*edit
Also in the original code he had the strut as a global variable but wasn't sure which file to implement it in or even how to make something global in an OOP! Would I just put it in main above int main() ?
Output.h
#pragma once
#include "ProProcess.h" //this is just a bunch of preprocessor directives
//this program creats a single color bmp file using red, blue, and green (rgb)
class OutPut
{
public:
OutPut(const int height, std::string file_name, int dpi, int index);
~OutPut();
//savebmp_str(std::string* file_name, const int width, const int height, int dpi, int pixels, struct RGBtype);
//commented this out because I wasn't sure how I should pass all these values. Ultimately I used OutPut Object_Output in bmp.cpp so that these variables could be passed in there
const int Getwidth() { return width; }
const int Setwidth(const int x) { const int width = x; }
private:
struct RGBtype //Could be a global variable but I dont know which file to put it in
{
int r;
int g;
int b;
};
const int width = 1960; //window size
const int height = 1080;
int dpi = 72;
int number_of_pixels = width*height;
int index;
const char* file_name = "Scene.bmp";
RGBtype *pixels = new RGBtype[number_of_pixels];//creates an array so that each pixel is comprised of a mix of rgb
};
Output.cpp
#include "OutPut.h"
#include "ProProcess.h"
OutPut::OutPut(const int height, std::string file_name, int dpi, int index)
{
OutPut::RGBtype color;
for (int x = 0; x < height; x++) //nested for loop that draws out each pixel totalling 1920x1080 in all
{
for (int y = 0; y < width; y++)
{
index = y*height + x;
pixels[index].r = 311;//changing the number here changes the color
pixels[index].g = 311;
pixels[index].b = 311;
}
}
std::cout << "Hello World";
}
OutPut::~OutPut()
{
}
BMP.h
#pragma once
#include "ProProcess.h"
#include "OutPut.h"
struct RGBtype
{
int r;
int g;
int b;
};
class BMP
{
public:
BMP(const char *filename, int passed_width, int passed_height, int dpi, RGBtype* data);
~BMP();
private:
OutPut Object_Output(std::string* file_name, const int width, const int height, int dpi, int pixels, struct RGBtype);//this is to pass the variables declared in output.h so bmp.h and bmp.cpp can use them too. Not sure how I would even verify i am doing this properly!
//const char* savebmp_str();
int passed_width;
int passed_height;
int dpi;
RGBtype *data;
};
BMP.cpp
#include "BMP.h"
#include "ProProcess.h"
#include "OutPut.h"
BMP::BMP(const char *filename, int passed_width, int passed_height, int dpi, RGBtype *data)
{
std::cout << passed_height;
FILE *pFile;
int k = passed_width*passed_height;
std::cout << "The value k is" << k;
int s = 4 * k;
int filesize = 54 + s; //s is a function of width and height
double factor = 39.375;
int m = static_cast<int>(factor);
int ppm = dpi*m;
unsigned char bmpfileheader[14] = { 'B','M',0,0,0,0 ,0,0,0,0, 54,0,0,0 }; //B and M are case sensitive. They make a bmp file
unsigned char bmpinfoheader[40] = { 40,0,0,0, 0,0,0,0 ,0,0,0,0, 1,0,24,0 };// the header size 14 and 40 are part of the BMP format
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
bmpinfoheader[4] = (unsigned char)(passed_width);
bmpinfoheader[5] = (unsigned char)(passed_width >> 8);
bmpinfoheader[6] = (unsigned char)(passed_width >> 16);
bmpinfoheader[7] = (unsigned char)(passed_width >> 24);
bmpinfoheader[8] = (unsigned char)(passed_height);
bmpinfoheader[9] = (unsigned char)(passed_height >> 8);
bmpinfoheader[10] = (unsigned char)(passed_height >> 16);
bmpinfoheader[11] = (unsigned char)(passed_height >> 24);
bmpinfoheader[21] = (unsigned char)(s);
bmpinfoheader[22] = (unsigned char)(s >> 8);
bmpinfoheader[23] = (unsigned char)(s >> 16);
bmpinfoheader[24] = (unsigned char)(s >> 24);
bmpinfoheader[25] = (unsigned char)(ppm);
bmpinfoheader[26] = (unsigned char)(ppm >> 8);
bmpinfoheader[27] = (unsigned char)(ppm >> 16);
bmpinfoheader[28] = (unsigned char)(ppm >> 24);
bmpinfoheader[29] = (unsigned char)(ppm);
bmpinfoheader[30] = (unsigned char)(ppm >> 8);
bmpinfoheader[31] = (unsigned char)(ppm >> 16);
bmpinfoheader[32] = (unsigned char)(ppm >> 24);
pFile = fopen(filename, "wb");
fwrite(bmpfileheader, sizeof(char), 14, pFile);
fwrite(bmpinfoheader, sizeof(char), 40, pFile);
for (int i = 0; i < k; i++)
{
RGBtype rgb = data[i];
double red = (data[i].r);
double green = (data[i].g);
double blue = (data[i].b);
int color[3] = { (int)floor(blue), (int)floor(green), (int)floor(red) };
fwrite(color, 1, 3, pFile);
}
fclose(pFile);
std::cout << "Hello World";
}
BMP::~BMP()
{
}
main.cpp
#include <iostream>
#include "OutPut.h"
#include "ProProcess.h"
#include "BMP.h"
int main()
{
OutPut Pixel_gen();
BMP BMP_Format_Maker();
OutPut Object_Output();
system("Pause");
return 0;
}
I am trying to use the example code from here.
I have made some changes in order to save the images to the computer. When I read the data in MATLAB it seems like values that should be 0 are set to 2047, and overall it does not seem to be correct when I reconstruct the 3D points using the default intrinsic camera parameters.
What I want to achieve is to save the images so that I can use
img = single(imread(depth.png'))/ 1000
and have the depth values in meters, and pixels with no measurements should be zero.
It is the Kinect V1 by the way.
Here is the code with comments where I have tried to change.
#include "libfreenect.hpp"
#include <iostream>
#include <vector>
#include <cmath>
#include <pthread.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace cv;
using namespace std;
class myMutex {
public:
myMutex() {
pthread_mutex_init( &m_mutex, NULL );
}
void lock() {
pthread_mutex_lock( &m_mutex );
}
void unlock() {
pthread_mutex_unlock( &m_mutex );
}
private:
pthread_mutex_t m_mutex;
};
// Should one use FREENECT_DEPTH_REGISTERED instead of FREENECT_DEPTH_11BIT?
class MyFreenectDevice : public Freenect::FreenectDevice {
public:
MyFreenectDevice(freenect_context *_ctx, int _index)
: Freenect::FreenectDevice(_ctx, _index), m_buffer_depth(FREENECT_DEPTH_11BIT),
m_buffer_rgb(FREENECT_VIDEO_RGB), m_gamma(2048), m_new_rgb_frame(false),
m_new_depth_frame(false), depthMat(Size(640,480),CV_16UC1),
rgbMat(Size(640,480), CV_8UC3, Scalar(0)),
ownMat(Size(640,480),CV_8UC3,Scalar(0)) {
for( unsigned int i = 0 ; i < 2048 ; i++) {
float v = i/2048.0;
v = std::pow(v, 3)* 6;
m_gamma[i] = v*6*256;
}
}
// Do not call directly even in child
void VideoCallback(void* _rgb, uint32_t timestamp) {
std::cout << "RGB callback" << std::endl;
m_rgb_mutex.lock();
uint8_t* rgb = static_cast<uint8_t*>(_rgb);
rgbMat.data = rgb;
m_new_rgb_frame = true;
m_rgb_mutex.unlock();
};
// Do not call directly even in child
void DepthCallback(void* _depth, uint32_t timestamp) {
std::cout << "Depth callback" << std::endl;
m_depth_mutex.lock();
uint16_t* depth = static_cast<uint16_t*>(_depth);
// Here I use memcpy instead so I can use uint16
// memcpy(depthMat.data,depth,depthMat.rows*depthMat.cols*sizeof(uint16_t));
depthMat.data = (uchar*) depth;
m_new_depth_frame = true;
m_depth_mutex.unlock();
}
bool getVideo(Mat& output) {
m_rgb_mutex.lock();
if(m_new_rgb_frame) {
cv::cvtColor(rgbMat, output, CV_RGB2BGR);
m_new_rgb_frame = false;
m_rgb_mutex.unlock();
return true;
} else {
m_rgb_mutex.unlock();
return false;
}
}
bool getDepth(Mat& output) {
m_depth_mutex.lock();
if(m_new_depth_frame) {
depthMat.copyTo(output);
m_new_depth_frame = false;
m_depth_mutex.unlock();
return true;
} else {
m_depth_mutex.unlock();
return false;
}
}
private:
// Should it be uint16_t instead or even higher?
std::vector<uint8_t> m_buffer_depth;
std::vector<uint8_t> m_buffer_rgb;
std::vector<uint16_t> m_gamma;
Mat depthMat;
Mat rgbMat;
Mat ownMat;
myMutex m_rgb_mutex;
myMutex m_depth_mutex;
bool m_new_rgb_frame;
bool m_new_depth_frame;
};
int main(int argc, char **argv) {
bool die(false);
string filename("snapshot");
string suffix(".png");
int i_snap(0),iter(0);
Mat depthMat(Size(640,480),CV_16UC1);
Mat depthf (Size(640,480),CV_8UC1);
Mat rgbMat(Size(640,480),CV_8UC3,Scalar(0));
Mat ownMat(Size(640,480),CV_8UC3,Scalar(0));
// The next two lines must be changed as Freenect::Freenect
// isn't a template but the method createDevice:
// Freenect::Freenect<MyFreenectDevice> freenect;
// MyFreenectDevice& device = freenect.createDevice(0);
// by these two lines:
Freenect::Freenect freenect;
MyFreenectDevice& device = freenect.createDevice<MyFreenectDevice>(0);
namedWindow("rgb",CV_WINDOW_AUTOSIZE);
namedWindow("depth",CV_WINDOW_AUTOSIZE);
device.startVideo();
device.startDepth();
while (!die) {
device.getVideo(rgbMat);
device.getDepth(depthMat);
// Here I save the depth images
std::ostringstream file;
file << filename << i_snap << suffix;
cv::imwrite(file.str(),depthMat);
cv::imshow("rgb", rgbMat);
depthMat.convertTo(depthf, CV_8UC1, 255.0/2048.0);
cv::imshow("depth",depthf);
if(iter >= 1000) break;
iter++;
}
device.stopVideo();
device.stopDepth();
return 0;
}
Thanks in advance!
Erik
I dont have any experience with OpenKinect in particular; but should your depth buffer be uint16?
std::vector<uint8_t> m_buffer_depth;
Also; for Matlab, do check if the image that you are reading is a uint16 or uint8. If its the latter then convert it to uint16
uint16(imread('depth.png'));
Sorry couldn't help more. Hope this helps.
The values you have are the raw depth values. You need to remap those into MM for the numbers to make sense. Kinect 1 can see up to 10 meters. So I would go with raw_values/2407*10000.
If the values are saturated at 2047, you are probably using the FREENECT_DEPTH_11BIT_PACKED depth format.
For work in Matlab, it is always easier to use FREENECT_DEPTH_MM or FREENECT_DEPTH_REGISTERED.
Enjoy.
I am trying to write a simple program to take input from user by hterm, when User enters "motor" & "25" the motor will rotate in 25 clockwise and 25 anticlockwise direction
//Define clock-speed and include necessary headers
#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <inttypes.h>
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdint.h>
#include <util/delay.h>
#include <ctype.h>
#define F_CPU 16000000UL
#define BAUD 9600UL
char cmd[40];
void uart_init(void) // initializing UART
{
UBRRH = 0;
UBRRL = ((F_CPU+BAUD*8)/(BAUD*16)-1);
UCSRC |= 0x86; // 8N1 Data
UCSRB = 0x18; // Receiving and Transmitting
}
int uart_putch(char ch, FILE *stream) // Function for sending Data to PC
{
if (ch == '\n')
uart_putch('\r', stream);
while (!(UCSRA & (1<<UDRE)));
UDR=ch;
return 0;
}
int uart_getch(FILE *stream) // Function for receiving Data from PC
{
unsigned char ch; while (!(UCSRA & (1<<RXC)));
ch=UDR;
uart_putch(ch,stream); // Echo the output back to the terminal
return (tolower(ch));
}
FILE uart_str = FDEV_SETUP_STREAM(uart_putch, uart_getch, _FDEV_SETUP_RW); // Important, not deleting
void loeschen() // Delete the String
{
int strnglen = 0;
while (strnglen < 41 && cmd[strnglen] != 0)
{
cmd[strnglen]= 0;
strnglen++;
}
}
// Define the stepping angle
// Note: Divide by 2 if you are doing half-stepping. for filter test 1.8 defult
#define MIN_STEP 1.8
/* Define an array containing values to be sent at the required Port - for Full-stepping
<first four bits> - <last four bits> = <decimal equivalent>
00000001 = 1 ; 01000000 = 4
00000100 = 4 ; 00010000 = 16
00000010 = 2 ; 00001000 = 8
00001000 = 8 ; 00100000 = 32
*/
unsigned short control_array_full[4] = {4,16,8,32};
/* Define an array containing values to be sent at the required Port - for Half-stepping
<first four bits> - <last four bits> = <decimal equivalent>
0000-1001 = 8 + 1 = 9 ; 0010-0100 = 32 + 4 =36
0000-0001 = 1 ; 0000-0100 = 4
0000-0101 = 4 + 1 = 5 ; 00010100 = 16 + 4 = 20
00000100 = 4 ; 00010000 = 16
00000110 = 4 + 2 = 6 ; 00011000 = 16+8=24
0000-0010 = ; 00-001000 = 8
0000-1010 = 8 + 2 = 10 ; 00-101000 = 40
0000-1000 = 8 ; 00-100000 = 32
*/
unsigned short control_array_half[8] = {36,4,20,16,24,8,40,32};
// Adjust this delay to control effective RPM
// Do not make it very small as rotor will not be able to move so fast
// Currently set at 100ms
void delay()
{
_delay_ms(100);
}
void move_clockwise(unsigned short revolutions){
int i=0;
for (i=0; i < (revolutions* 360 /MIN_STEP) ; i++)
{
//Note: Take modulo (%) with 8 when half-stepping and change array too
PORTD = control_array_half[i % 4];
delay();
}
}
void move_anticlockwise(unsigned short revolutions){
int i;
for (i = (revolutions* 360 /MIN_STEP); i > 0 ; i--){
//Note: Take modulo (%) with 8 when half-stepping and change array too
PORTD = control_array_half[i % 4];
delay();
}
}
int main()
{
// Enter infinte loop
// Make changes here to suit your requirements
uart_init(); // initializing UART
stdout = stdin = &uart_str; // Necessary to compare whole Strings
while(1){
scanf("%s",&cmd); // Read String from Data Register
printf ("Please enter number of motor rotation for clockwise and anticlockwise");
items_read = scanf ("%d", &numbers[i]); // Read integer for motor revolution
if(strcmp(cmd, "motor") == 0)
{
DDRD = 0b00111110; //Set PORTD 4 bits for output
//Enter number of revolutions required in brackets
move_clockwise(items_read);
move_anticlockwise(items_read);
}
DDRD = 0b00000000;
}
loeschen();
}
Now, The problem is that when I will delete these lines from main()
items_read = scanf ("%d", &numbers[i]);
scanf ("%d",&i);
& make items_read in move_clockwise(items_read); as:
move_clockwise(25);
move_anticlockwise(25);
Then when user enters "motor" then motor is running move_clockwise(25); but move_anticlockwise(25); is not running, what I would like is to take both "motor", number for clockwise and number for anticlockwise....
I would really appreciate if anyone can help me with this!
Thanks in advance!
First, in my opinion you're only clearing "cmd" in loeschen(), but you never assining any value.
Second "cmd" is NOT any type of UART dataregister.
DDRD is DataDirectionRegister D, that means you can set some pin to input or output mode.
Use PORTD to set a pin high or low, in example PORTD |= 1<<PD0; to set Port D Pin 0 to high.
I guess you prefer german documentation, because you named one function "loeschen()" ;-), so why don't you visit mikrocontroller.net AVR GCC Tutorial (UART)?
If you like more technic detailed youtube-stuff, et voila: Introduction to UART
RXT (ATMEGA16) - for example:
//////////////////////////////////////////////////////////////////////////
// Definitions
//////////////////////////////////////////////////////////////////////////
#define BAUD 9600UL
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
#error Baud to high
#endif
#define UART_MAX_STRING_LENGHT 20 // Max lenght
//////////////////////////////////////////////////////////////////////////
// UART-Receive-Variables
//////////////////////////////////////////////////////////////////////////
volatile uint8_t uart_str_complete = 0; // FLAG - String received
volatile uint8_t uart_str_count = 0; // Current position
volatile char uart_string[UART_MAX_STRING_LENGHT + 1] = ""; // received string
//////////////////////////////////////////////////////////////////////////
// ISR-UART
//////////////////////////////////////////////////////////////////////////
ISR(USART_RXC_vect)
{
unsigned char nextChar;
nextChar = UDR; // read data from buffer
if(uart_str_complete == 0) // UART-String is currently usen
{
if(nextChar != '\n' && nextChar != '\r' && uart_str_count < UART_MAX_STRING_LENGHT)
{
uart_string[uart_str_count] = nextChar;
uart_str_count++;
}
else
{
uart_string[uart_str_count] = '\0';
uart_str_count = 0;
uart_str_complete = 1;
}
}
}
//////////////////////////////////////////////////////////////////////////
// Init UART
//////////////////////////////////////////////////////////////////////////
void Init_UART_Async()
{
UBRRH = UBRR_VAL >> 8;
UBRRL = UBRR_VAL & 0xFF;
UCSRB |= (1<<TXEN); // UART TX high
UCSRB |= (1<<RXEN); // UART RX high
UCSRB |= (1<<RXCIE); // UART RX Interrupt enable
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // Asynchron 8N1
sei(); // Enable interrups
}
//////////////////////////////////////////////////////////////////////////
// Main
//////////////////////////////////////////////////////////////////////////
int main(void)
{
Init_UART_Async();
while(1)
{
HandleCommunication(); // <-- Handle your communication ;-)
// and to some other cool stuff here
}
}
//////////////////////////////////////////////////////////////////////////
// Handle Communication
//////////////////////////////////////////////////////////////////////////
void HandleCommunication()
{
if(uart_str_complete == 1)
{
strcpy(received_string, uart_string); // copy received string
strcpy(uart_string, ""); // empty uart-string
uart_str_complete = 0; // set flag to 0
// handle your communication
}
}
After understanding how UART is working, you should check your codeparts
like "scanf("%s",&cmd);" in an console-application - that's easier to find some errors.
I hope this helps you a little, but I guess the best solution is when you're knowing what you're doing.
-Crazy