I'm trying to make a force feedback wheel, but software isn't my cup of tea.
This is supposed to toggle button 0 and it doesn't.
typedef struct{
uint8_t buttons;
int8_t relativeMvt;
}steer_t;
steer_t steer = {0, 0};
while (1)
{
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
if(steer.buttons) steer.buttons = 0b00000000;
else steer.buttons = 0b00000001;
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, steer, sizeof(steer));
HAL_Delay(500);
}
My Report descriptor (this is the first time I'm using one):
Running that code, the buttons are static "ON" like so:
They DO change (randomly) only when the "relativeMvt" variable is changed, very weird.
What I've tried:
Swap relativeMvt and buttons in the typeDef
Check the report descriptor size etc
Cry
#define USBD_CUSTOMHID_OUTREPORT_BUF_SIZE 2
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE 45
#define CUSTOM_HID_EPIN_SIZE 2
What do I have to change to make it work? Thanks!
I've solved it. I was missing:
#include "usbd_customhid.h"
and I forgot the "&" when passing my variables:
USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, &steer, sizeof(steer));
Related
I have a CGAL::Point_set_3 point set with point normal and color. I would like to save all properties to a PLY file, using write_ply_with_properties() function.
My goal is to make the full version work (see code below), but even the simple version doesn't compile, with the same error as the full version.
I work on Linux with CGAL release 4.14 and gcc 7.4.0.
Here is the code:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>
#include <tuple> // for std::tie
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;
int main(int argc, char*argv[])
{
Point_set points;
points.insert(Point(1., 2., 3.));
points.insert(Point(4., 5., 6.));
// add normal map
points.add_normal_map();
auto normal_map = points.normal_map();
// add color map
typedef Point_set::Property_map< Vector > ColorMap;
bool success = false;
ColorMap color_map;
std::tie(color_map, success) =
points.add_property_map< Vector >("color");
assert(success);
// populate normal and color map
for(auto it = points.begin(); it != points.end(); ++it)
{
normal_map[*it] = Vector(10., 11., 12.);
color_map[*it] = Vector(20., 21., 22.);
}
std::ofstream out("out.ply");
#if 1
// simple version
if(!out || !CGAL::write_ply_points_with_properties(
out,
points.points(), // const PointRange
CGAL::make_ply_point_writer(points.point_map())))
#else
// full version
if(!out || !CGAL::write_ply_points_with_properties(
out,
points.points(), // const PointRange
CGAL::make_ply_point_writer(points.point_map()),
CGAL::make_ply_normal_writer(points.normal_map()),
std::make_tuple(color_map,
CGAL::PLY_property< double >("red"),
CGAL::PLY_property< double >("green"),
CGAL::PLY_property< double >("blue"))))
#endif
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
The compilation error is:
...
/usr/include/boost/property_map/property_map.hpp:303:54: error: no match for ‘operator[]’ (operand types are ‘const CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Property_map<CGAL::Point_3<CGAL::Epick> >’ and ‘const CGAL::Point_3<CGAL::Epick>’)
Reference v = static_cast<const PropertyMap&>(pa)[k];
CGAL-4.14/include/CGAL/Surface_mesh/Properties.h:567:15: note: candidate: CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::reference CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::operator[](const I&) [with I = CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Index; T = CGAL::Point_3<CGAL::Epick>; CRTP_derived_class = CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Property_map<CGAL::Point_3<CGAL::Epick> >; CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::reference = CGAL::Point_3<CGAL::Epick>&]
reference operator[](const I& i)
^~~~~~~~
CGAL-4.14/include/CGAL/Surface_mesh/Properties.h:567:15: note: no known conversion for argument 1 from ‘const CGAL::Point_3<CGAL::Epick>’ to ‘const CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Index&’
How can I fix it?
The problem in your code is that you are using the method points() of CGAL::Point_set_3 which returns a range of points of type CGAL::Point_set_3::Point_range, whereas the property maps that you use (points.point_map(), etc.) are directly applied to a type CGAL::Point_set_3.
So you should simply call the write_ply_points_with_properties() on points, not on points.points().
Note also that if you store your colors on simple types (for example, using three Point_set_3 properties typed unsigned char), you can take advantage of the function CGAL::write_ply_point_set() that will automatically write all the simply-typed properties it finds, which makes it quite straightforward to use (just do CGAL::write_ply_point_set(out, points) and you're done).
One last thing that is really a detail not related to your problem, but you should avoid using the CGAL::Vector_3 for storing anything else than an actual geometric 3D vector (like colors in your case). That makes your code harder to read and is also quite an ineffective way to store colors if they are encoded as integer values between 0 and 255 (which is what unsigned char is for).
I am using PCL library to visualize a single .ply model. How can I print the Frames per Second (FPS) number shown on the bottom left of the window?
Here is my simple code. We only need to add something like cout<<print(current_fps);
#include <iostream>
//#include <unistd.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_cloud.h>
#include <pcl/console/parse.h>
#include <pcl/common/transforms.h>
#include <pcl/visualization/pcl_visualizer.h>
// Main function
int main(int argc, char **argv)
{
// Fetch point cloud filename in arguments | Works with PLY files
std::vector<int> filenames;
filenames = pcl::console::parse_file_extension_argument(argc, argv, ".ply");
// Load file | Works with PLY files
pcl::PointCloud<pcl::PointXYZRGB>::Ptr source_cloud (new pcl::PointCloud<pcl::PointXYZRGB>());
pcl::io::loadPLYFile(argv[filenames[0]], *source_cloud);
// Visualization
printf("\n Point cloud colors :\n"
" \t white \t = \t original point cloud \n");
pcl::visualization::PCLVisualizer viewer(" Point Cloud Datsets Visualizer");
viewer.setBackgroundColor(0.05, 0.05, 0.05, 0); // Set background to a dark grey
// Define R,G,B colors for the point cloud
pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(source_cloud);
// We add the point cloud to the viewer and pass the color handler
viewer.addPointCloud(source_cloud, rgb, "original_cloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "original_cloud");
//******************************
std::vector<Point, Eigen::aligned_allocator<Point>> points = source_cloud->points;
//******************************
while (!viewer.wasStopped()) { // Display the visualizer until the 'q' key is pressed
viewer.spinOnce();
}
return 0;
} // End main()
You can use getFPS(). The issue was fixed in
https://github.com/PointCloudLibrary/pcl/pull/1974
Then you can do something like
std::cout<<viewer.getFPS();
Which will give you a floating point value with the current rendering framerate.
I have been unable to solve a simple USART transmit/receive program. The problem is that I used this in the past and worked effortlessly but now it returns in my Linux machine question marks and in windows some boxes and Chinese characters. I don´t understand what changed. I have tried a lot of different things like changing the code and the parts but nothing seems to solve it.
I´m using a AVR atmega 328p, and a pololu usb programmer. I flashed it from the atmel studio in windows and from avrdude in linux.
Here is the code:
#define F_CPU 1000000
#define BAUD 9600
#include <avr/io.h>
#include <util/delay.h>
#include <util/setbaud.h>
void init_USART(void);
void transmit_Byte(char data);
char receive_Byte(void);
int main(void)
{
char TEST;
init_USART(); /* Initialize USART */
while (1)
{
TEST = receive_Byte();
transmit_Byte(TEST);
}
}
void init_USART(void)
{
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2x
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
UCSR0B = (1 << TXEN0) | (1 << RXEN0); /* Enable USART
transmitt/receive */
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8 data bits, 1 stop
bit */
}
void transmit_Byte(char data)
{
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait for empty
transmit buffer */
UDR0 = data;
}
char receive_Byte(void)
{
loop_until_bit_is_set(UCSR0A, RXC0);
return(UDR0);
}
This is my first question so I apologize in advanced if I did something wrong.
Thanks a lot for your time!
edit: I have tried a ftdi232 and a mcp2221
edit 2: After addin UL still not as expected but got less unknown characters.
SOLVED: But I don't understand why. I changed the fuse CKDIV8 to 1 and it started working. The datasheet says it comes factory with 8 MHz clock and the CKDIV8=0 so it is set to 1 MHz. So why is it inversed? I also tried previously clock_prescale_set(clock_div_8); as the datasheet suggest for prescaling and it didn't work neither.
What is the difference between setting the CLDIV8 and the avr/power.h function?
I'm interfacing my G2553 to a standard LCD screen using UART. I got it working like a dream at 1MHz, but need the system to run at 16MHz for certain other peripherals. I got it very close to working at 16MHz but there is what I believe to be a baudrate error, as the screen will show almost what I sent it, but miss a character here or there or get a character incorrect. I'll take you through how I wrote my code to see if I made any errors.
The screen expects a baudrate of 9600, so I went to the table in my user guide:
So UCBRx = 1666
and UCBRSx = 6.
The expected % errors on this are actually better than what I was using at the 1MHz clock so I thought this would be OK.
This means UCBR0 = 130 and UCBR1 = 6 (This is just the HEX value of UCBRx spread over two 8-bit registers) and UCBRSx = 6.
Now to enter these I looked at what the user guide tells us about the UART modulation register:
(was going to make this pretty but I don't have the reputation to post images)
So my initialisation code ended up being:
if (CALBC1_16MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
//setup DCO to 16MHZ
BCSCTL1 = CALBC1_16MHZ;
DCOCTL = CALDCO_16MHZ;
P1SEL |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 |= BIT1 + BIT2;
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 130; // 16MHz 9600
UCA0BR1 = 6; // 16MHz 9600
UCA0MCTL = UCBRS2 + UCBRS1; // modulation is 110b or 6
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
However as I stated above this is almost there, for example if I try to display the string "Initialising..." which worked for my 1MHz 9600 baudrate settings, with 16MHz at these settings it might display "Initiali ng..." - something close but obviously some error in there that I don't want.
Thank you for any help you can provide on this.
According to the baud rate calculator at http://mspgcc.sourceforge.net/baudrate.html, UCA0MCTL is supposed to be 0x5B
I want to do an animation for snow flakes using OpenGL. Can anyone suggest me some tutorial or sample code?
You can use transform feedback to calculate the particle physics in the vertex shader and instancing if you want to use 3D snowflakes. Point sprites should make billboards faster and use less memory for storing vertices. (You only need one per snowflake.)
Running the particle system in the vertex shader will make it a few times faster while the math essentially stays the same.
You could also use a 3D texture to offset the damping calculation so you can have visible turbulences.
If you use a heightmap for the ground, you can use that data to reset snowflakes that aren't visible anymore.
Transform feedback and instancing are explained in OpenGL SuperBible (Fifth Edition) in chapter 12, point sprites are in chapter 7. The source code for all examples is available online. The example code for Mac OS X only goes up to chapter 7, but it should be possible to make most of it work.
I couldn't find any good online tutorials, but the code well commented. The transform feedback example is called "flocking". For a snowflake simulation, one vertex shader should be enough for both updating and redering the particles in one pass.
If you want lots of fast moving snow, the water particles from Nvidia's Cascades Demo (starting at page 114) show an interesting approach to faking a large amount of particles.
One possible solution is use a particle system. I once made some explosion effects from it, and I think that is pretty close to what you want.
Here's one of the tutorials I used, and I think this might be helpful (BTW, there are many good tutorials on that site, you could check them out).
Also, for the snow flake generation, you could just use identical flakes, but if you want fancier things (not too fancy, but relatively easy), you could use triangle stripes (which is used by the tutorial) to achieve better effects, since snow flakes are symmetric.
#include <stdlib.h>
#include <GL/gl.h>
#include <GL/glut.h>
#define PEATALS_NUMBER 100
#define X 0
#define Y 1
#define ORG_X 2
#define ORG_Y 3
#define SIZE 4
#define GROWING 5
#define SPEED 5
struct timeval start;
unsigned long int last_idle_time;
GLdouble size=5;
GLboolean growing=true;
GLdouble tab[PEATALS_NUMBER][7];
unsigned int get_ticks(){
struct timeval now;
gettimeofday(&now, NULL);
return (now.tv_sec - start.tv_sec) * 1000 +
(now.tv_usec - start.tv_usec) / 1000;
}
void init(){
for(int i=0;i<PEATALS_NUMBER;i++){
tab[i][X]=-300+rand()%600;
tab[i][Y]=200+rand()%500;
tab[i][ORG_X]=tab[i][X];
tab[i][ORG_Y]=tab[i][Y];
tab[i][SIZE]=1+rand()%9;
tab[i][GROWING]=rand()%1;
tab[i][SPEED]=rand()%10;
}
}
void Idle(){
unsigned long int time_now = get_ticks();
for(int i=0;i<PEATALS_NUMBER;i++){
tab[i][Y] -= (tab[i][SPEED]+40.0) * (time_now - last_idle_time) / 1000.0;
if(tab[i][Y]<-200.0)tab[i][Y]=tab[i][ORG_Y];
if(tab[i][SIZE]>5){
tab[i][GROWING]=0;
}
if(tab[i][SIZE]<1){
tab[i][GROWING]=1;
}
if(tab[i][GROWING]==1.0){
tab[i][SIZE]+=8.0 * (time_now - last_idle_time) / 1000.0;
tab[i][X] -= (tab[i][SPEED]+1.0) * (time_now - last_idle_time) / 1000.0;
}
else{
tab[i][SIZE]-=8.0 * (time_now - last_idle_time) / 1000.0;
tab[i][X] += (tab[i][SPEED]+2.0) * (time_now - last_idle_time) / 1000.0;
}
}
last_idle_time = time_now;
glutPostRedisplay();
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 400);
gettimeofday(&start, NULL);
init();
// size of window
glutCreateWindow(argv[0]);
glutIdleFunc(Idle);
glEnable(GL_POINT_SMOOTH);
glutMainLoop();
return 0;
}