I'm trying to make a project using the 16x32 RGB Led matrix, from the Adafruit store, but for some reason Visual Studio keeps telling me I've defined the matrix class multiple times.
This all started happening when I started making my own classes for my program (I'm still learning OOP). I have put define protection in the header file where I instantiate the matrix class, so that shouldn't be the problem
I've tried moving the class definition around. When I put it into the cpp file where I wanted to use it I stopped getting the multiple definition error, but then the matrix doesn't draw anything.
I've tried parsing a pointer to the matrix class to the class where I wanted to use the matrix but then I get this weird error where the matrix redraws the first thing it has to draw over and over again and it stops responding to serial input/doesn't give any serial output.
code:
//===========Matrix.h===========
#ifndef MATRIX_H
#define MATRIX_H
#include "RGBmatrixPanel.h"
#include <SPI.h>
#include <Adafruit_I2CDevice.h>
#define CLK 8
#define OE 9
#define LAT 10
#define A A0
#define B A1
#define C A2
RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
#endif
//===========main.cpp===========
#include <Arduino.h>
#include "GuiDrawer.h"
GuiDrawer guiDrawer;
void setup() {
Serial.begin(9600);
guiDrawer.drawBaseGui();
}
void loop() {}
//===========GuiDrawer.h===========
#ifndef GUIDRAWER_H
#define GUIDRAWER_H
#include <Arduino.h>
#include "matrix.h"
class GuiDrawer {
private:
enum COLOURS {
BLACK = 0, //0
WHITE, //1
RED, //2
YELLOW, //3
DARKER_YELLOW, //4
DARKEST_YELLOW, //5
GRAY //6
};
enum SHAPES {
HEART = 0, //0
AMMO, //1
COIN //2
};
const int HEARTSIZE_X = 8;
const int HEARTSIZE_Y = 8;
const int HEARTSHAPE [8][8] = {
{0, 2, 2, 0, 0, 2, 2, 0},
{2, 2, 1, 2, 2, 2, 2, 2},
{2, 1, 2, 2, 2, 2, 2, 2},
{2, 1, 2, 2, 2, 2, 2, 2},
{2, 2, 2, 2, 2, 2, 2, 2},
{0, 2, 2, 2, 2, 2, 2, 0},
{0, 0, 2, 2, 2, 2, 0, 0},
{0, 0, 0, 2, 2, 0, 0, 0},
};
const int COINSIZE_X = 8;
const int COINSIZE_Y = 7;
const int COINSHAPE [8][7] = {
{0, 0, 4, 4, 4, 0, 0},
{0, 4, 3, 3, 3, 4, 0},
{4, 3, 3, 4, 3, 3, 4},
{4, 3, 3, 4, 3, 3, 4},
{4, 3, 3, 4, 3, 3, 4},
{4, 3, 3, 4, 3, 3, 4},
{0, 4, 3, 3, 3, 4, 0},
{0, 0, 4, 4, 4, 0, 0}
};
const int AMMOSIZE_X = 8;
const int AMMOSIZE_Y = 6;
const int AMMOSHAPE [8][6] = {
{0, 6, 0, 0, 6, 0},
{6, 6, 6, 6, 6, 6},
{3, 3, 5, 3, 3, 5},
{3, 3, 5, 3, 3, 5},
{3, 3, 5, 3, 3, 5},
{3, 3, 5, 3, 3, 5},
{3, 3, 5, 3, 3, 5},
{3, 3, 5, 3, 3, 5}
};
void drawShape(SHAPES shape, int startX, int startY);
void pixelDrawer(COLOURS colourToDraw, int drawX, int drawY);
public:
GuiDrawer();
void drawBaseGui();
};
#endif
//===========GuiDrawer.cpp===========
#include <Arduino.h>
#include "GuiDrawer.h"
GuiDrawer::GuiDrawer() {
matrix.begin();
Serial.begin(9600);
}
void GuiDrawer::drawBaseGui() {
drawShape(HEART, 0, 0);
drawShape(COIN, 0, 8);
drawShape(COIN, 25, 8);
Serial.println("drawn base gui");
}
void GuiDrawer::drawShape(SHAPES shape, int startX, int startY) {
switch (shape) {
case HEART:
for (int i = 0; i < HEARTSIZE_X; i++) {
for (int j = 0; j < HEARTSIZE_Y; j++) {
COLOURS pixelToDraw = (COLOURS)HEARTSHAPE[i][j];
pixelDrawer(pixelToDraw, (j + startX), (i + startY));
}
Serial.println();
}
break;
case AMMO:
for (int i = 0; i < AMMOSIZE_X; i++) {
for (int j = 0; j < AMMOSIZE_Y; j++) {
COLOURS pixelToDraw = (COLOURS)AMMOSHAPE[i][j];
pixelDrawer(pixelToDraw, (j + startX), (i + startY));
}
}
break;
case COIN:
for (int i = 0; i < COINSIZE_X; i++) {
for (int j = 0; j < COINSIZE_Y; j++) {
COLOURS pixelToDraw = (COLOURS)COINSHAPE[i][j];
pixelDrawer(pixelToDraw, (j + startX), (i + startY));
}
}
break;
default:
break;
}
}
void GuiDrawer::pixelDrawer(COLOURS colourToDraw, int drawX, int drawY) {
switch (colourToDraw) {
case BLACK:
matrix.drawPixel(drawX, drawY, matrix.Color333(0, 0, 0));
Serial.print("black ");
break;
case WHITE:
matrix.drawPixel(drawX, drawY, matrix.Color333(255, 255, 255));
Serial.print("white ");
break;
case RED:
matrix.drawPixel(drawX, drawY, matrix.Color333(255, 0, 0));
Serial.print("red ");
break;
case YELLOW:
matrix.drawPixel(drawX, drawY, matrix.Color333(255, 255, 0));
break;
case DARKER_YELLOW:
matrix.drawPixel(drawX, drawY, matrix.Color888(16, 16, 0));
break;
default:
break;
}
}
error I am getting:
.pio\build\uno\src\main.cpp.o (symbol from plugin): In function `matrix':
(.text+0x0): multiple definition of `matrix'
.pio\build\uno\src\GuiDrawer.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\uno\firmware.elf] Error 1
led matrix: https://www.adafruit.com/product/420
Related
I want to get the object of the class which is constructed in main() function and use this object in another class.
This is the class I want to take the object of it:
typedef enum {
DOWN = 1,
LEFT = 2,
UP = 3,
RIGHT = 4
} tWaypointDir;
class Waypoint
{
sf::Texture texture;
sf::Sprite sprite;
public:
float x, y;
int dir;
int next1, next2, next3;
Waypoint(tWaypointDir dir, tRoadTileType type, int row, int col, int idx, int next1, int next2, int next3); // Constructor for the class.
// idx: internal index of the waypoints, next1, 2, 3: next waypoints of the current one.
// if there is only next1, next2 and next3 are -1.
int getNext(); //Get next waypoint randomly
void getPosition(float &x, float &y, float &dir) const { x = this->x; y = this->y; dir = this->dir; }
void setPosition(float x, float y, float dir) { this->x = x; this->y = y; this->dir = dir; }
void draw(sf::RenderWindow *window) {window->draw(sprite);}
};
The object I created in the main() function is:
Waypoint waypoints[] = { //CTL: Road at top-left, HOR: horizontal, etc..
{UP, CTL, 0, 0, 0, 1, -1, -1}, {RIGHT, CTL, 0, 0, 1, 0, -1, -1},
{RIGHT, HOR, 0, 1, 0, 3, -1, -1}, {RIGHT, HOR, 0, 1, 1, 2, -1, -1},
{RIGHT, TTOP, 0, 2, 0, 5, 6, -1}, {DOWN, TTOP, 0, 2, 1, 4, 6, -1},
{RIGHT, TTOP, 0, 2, 2, 4, 5, -1}, {RIGHT, HOR, 0, 3, 0, 8, -1, -1}
};
Now, in the class Car, I want to use the waypoints[] object because I move the car in the direction of waypoints. I have a move() function in this class and I used this object in that part. We are not allowed to do the movement in main() function. Hence, I have to implement this in the class.
I tried the Singleton design pattern on the Waypoint class but it gives me errors on the constructor part. How can I implement this on the Car class?
You can pass pointer or reference on Waypoint class as argument in Car class constructor or method. Car class could store this reference or pointer as member. Then you can access this object from Car class
I use this c++ code
#include <iostream>
#include "parmetis.h"
int main(int argc, char **argv)
{
MPI_Init(&argc, &argv);
int np = 3; int ne = 36;
idx_t *elmdist = new idx_t[np+1]; for (int i=0; i<np+1; i++) {elmdist[i] = (i-1)*ne/np;} elmdist[np] = ne;
idx_t *eptr = new idx_t[ne+1]; for (int i=0; i<ne+1; i++) {eptr[i] = (i-1)*3;}
idx_t eind_[] = {13, 14, 15,
13, 16, 17,
2, 17, 6,
4, 15, 10,
13, 15, 19,
13, 17, 18,
13, 19, 16,
13, 18, 14,
1, 5, 16,
3, 9, 14,
7, 8, 18,
11, 12, 19,
1, 20, 12,
3, 21, 8,
7, 18, 23,
11, 19, 22,
2, 23, 17,
4, 22, 15,
14, 25, 15,
16, 24, 17,
15, 22, 19,
17, 23, 18,
1, 16, 20,
3, 14, 21,
5, 24, 16,
9, 25, 14,
16, 19, 20,
14, 18, 21,
6, 17, 24,
10, 15, 25,
5, 6, 24,
9, 10, 25,
8, 21, 18,
12, 20, 19,
2, 7, 23,
4, 11, 22};
idx_t *eind = eind_;
idx_t *elmwgt = NULL;
idx_t wgtflag_[] = {0};
idx_t *wgtflag = wgtflag_;
idx_t numflag_[] = {0};
idx_t *numflag = numflag_;
idx_t ncon_[] = {1};
idx_t *ncon = ncon_;
idx_t ncommonnodes_[] = {2};
idx_t *ncommonnodes = ncommonnodes_;
idx_t nparts_[] = {np};
idx_t *nparts = nparts_;
real_t *tpwgts = new real_t[np*ncon[0]]; for(int i=0; i<np*ncon[0]; i++) {tpwgts[i] = 1.0/np;}
real_t ubvec_[] = {1.05};
real_t *ubvec = ubvec_;
idx_t options_[] ={0, 0, 0};
idx_t *options =options_;
idx_t *edgecut=NULL;
idx_t *part=NULL;
MPI_Comm *comm=NULL;
ParMETIS_V3_PartMeshKway(elmdist, eptr, eind, elmwgt, wgtflag, numflag, ncon, ncommonnodes, nparts, tpwgts, ubvec, options, edgecut, part, comm);
MPI_Finalize();
return 0;
}
In allmet I insert all files from metis and parmetis.
Try to compile using OpenMPI with g++ compiler:
mpicxx -I path/allmet/include -L path/allmet/lib par.cpp
I get error:
undefined reference to `ParMETIS_V3_PartMeshKway'
With cmake:
cmake_minimum_required(VERSION 2.8.9)
project (MetisTest)
find_package(MPI)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
include_directories("path/allmet/include")
link_directories("path/allmet/lib")
add_executable(metisTest par.cpp)
target_link_libraries(metisTest ${MPI_C_LIBRARIES})
I have:
undefined reference to `ParMETIS_V3_PartMeshKway'
in function `MPI::Intracomm::Intracomm()':
undefined reference to `MPI::Comm::Comm()'
and many others
So what I can do? Metis work perfect but with parmetis I can't do anything.
Ubuntu 18.10, gcc 8.2.0.
You also need to link against Parmetis itself:
target_link_libraries(metisTest ${MPI_C_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PARMETIS_LIBS})
Do note that:
link_directories("path/allmet/lib")
Is irrelevant for the link. If you still want to use the command line, you need:
mpicxx -Ipath/allmet/include -Lpath/allmet/lib -lparmetis -lmetis par.cpp
I've studied Opencv's setMouseCallback function.
I understand there are several events, list below:
CV_EVENT_MOUSEMOVE 0,
CV_EVENT_LBUTTONDOWN 1,
CV_EVENT_RBUTTONDOWN 2,
CV_EVENT_MBUTTONDOWN 3,
CV_EVENT_LBUTTONUP 4,
CV_EVENT_RBUTTONUP 5,
CV_EVENT_MBUTTONUP 6,
CV_EVENT_LBUTTONDBLCLK 7,
CV_EVENT_RBUTTONDBLCLK 8,
CV_EVENT_MBUTTONDBLCLK 9,
CV_EVENT_FLAG_LBUTTON 1,
CV_EVENT_FLAG_RBUTTON 2,
CV_EVENT_FLAG_MBUTTON 4,
CV_EVENT_FLAG_CTRLKEY 8,
CV_EVENT_FLAG_SHIFTKEY 16,
CV_EVENT_FLAG_ALTKEY 32,
and with the coordinates I get from these events, I can draw, for example: straight line, circle, ellipse...etc.
But instead of straight line, I want to draw random line, just like the "pencil" or "brush" function in Microsoft Paint.
The CV_EVENT_MOUSEMOVE does return all the coordinates as my mouse move through the image, but I don't know how to combine it with CV_EVENT_LBUTTONDOWN to represent "Start drawing line" and CV_EVENT_LBUTTONUP to represent "Finish drawing line"?
Does anyone know how to achieve my requirement with setMouseCallback?
I figured it out myself,
bool trigger;
Mat img;
void onMouse(int event, int x, int y, int flag, int param)
{
if(event == CV_EVENT_LBUTTONDOWN)
{
img = Mat::zeros(320, 240, CV_8UC3);
trigger = true;
}
if(event == CV_EVENT_LBUTTONUP)
{
trigger = false;
}
if(event == CV_EVENT_MOUSEMOVE)
{
if(trigger == true)
{
line(img, cvPoint(x, y), cvPoint(x, y), Scalar(0, 0, 255), 3, CV_AA, 0);
imshow("Drawing", img);
}
}
}
int main(int argc, char *argv[])
{
.
.
.
cvsetMouseCallback("Origin img", onMouse, NULL);
.
.
.
}
I have one RectangleShape for wall and I draw this one object for every "1" on my 2D map:
int map[5][8] =
{
{ 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 1, 1, 0, 1 },
{ 1, 2, 1, 0, 0, 0, 3, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1 }
};
sf::RectangleShape player;
player.setSize(sf::Vector2f(32,32));
sf::RectangleShape wall;
wall.setSize(sf::Vector2f(32,32));
wall.setFillColor(sf::Color(40, 199, 40));
for (int mapX= 0; mapX< 8; mapX++)
{
for (int mapY= 0; mapY< 5; mapY++)
{
if (map[mapY][mapX] == 1)
{
wall.setPosition(mapX * 32, mapY * 32);
window.draw(wall);
}
}
}
And I checking for collision with code listed down, but this works for only last drawn wall. How to fix this? Theres only one object wall and I want to check collision for all drawned walls for my 2D array map.
if (event.type == sf::Event::TextEntered)
{
fPlayerY_t = fPlayerY;
fPlayerX_t = fPlayerX;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W)) fPlayerY_t = fPlayerY - 32;
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) fPlayerY_t = fPlayerY + 32;
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) fPlayerX_t = fPlayerX + 32;
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)) fPlayerX_t = fPlayerX - 32;
// temp pos
player.setPosition(fPlayerX_t, fPlayerY_t);
// collision with wall
if (player.getPosition().x == wall.getPosition().x &&
player.getPosition().y == wall.getPosition().y)
{
// back to prev position
player.setPosition(fPlayerX, fPlayerY);
}
else
{
// No collision
fPlayerX = fPlayerX_t;
fPlayerY = fPlayerY_t;
}
}
Convert the coordinates of the player in array coordinates then check if map[x][y] == 1.
So do not have to loop through your entire map every game loop.
To convert into array coordinates, use int conversion :
int playerTileX = (int)(playerWorldX / 32);
int playerTileY = (int)(playerWorldY / 32);
if(map[playerTileX ][playerTileY ] == 1)
{
// collision.
}
else
{
// no collision.
}
What I dislike with this solution : it only checks for tiles collision, you have to be sure every wall is the same size (here 32*32).
I need to retrieve the X/Y coordinate of the end of a path drawn in Raphael. I've found a way that works by introspecting the path afterwards in SVG browsers but this approach does not work in VML browsers.
Example:
var paper = Raphael('canvas', 200, 200);
var p = paper.path(['M', 10, 10, 'l', 30, 30, 'a', 20, 30, 0, 1, 0, 40, 10, 'a', 20, 30, 0, 1, 0, 40, 10, 'l', -15, -18]);
var lastP = p.attrs.path[p.attrs.path.length - 1];
paper.circle(lastP[lastP.length - 2], lastP[lastP.length - 1], 3);
http://jsfiddle.net/sY4Up/1/
In Chrome, a circle gets drawn at the endpoint through path introspection. In IE 6/7/8, the circle does not draw because the path definition does not get decomposed/normalized.
use getPointAtLength and getTotalLength to find the position.
window.onload = function() {
var paper = Raphael('canvas', 200, 200);
var p = paper.path(['M', 10, 10, 'l', 30, 30, 'a', 20, 30, 0, 1, 0, 40, 10, 'a', 20, 30, 0, 1, 0, 40, 10, 'l', -15, -18]);
var lastP = p.attrs.path[p.attrs.path.length - 1];
paper.circle(lastP[lastP.length - 2], lastP[lastP.length - 1], 3);
var pt = p.getPointAtLength(p.getTotalLength());
paper.circle(pt.x,pt.y,10);
};