Could I thread this for loop - c++

for(unsigned int mBlock = 0; mBlock < coords.size(); mBlock++)
{
WidgetType widgetType;
height = macBlockWidth + coords[mBlock].y;
width = macBlockHeight + coords[mBlock].x;
macBlockParent = new QWidget;
cooefsLink = new QPushButton(macBlockParent);
macBlock = new QWidget(macBlockParent);
widgetType.widget = macBlock;
widgetType.type = (macBlocks[mBlock][2] != 'S')
? (macBlocks[mBlock][0]) : (macBlocks[mBlock][2]);
blockWidgetTypes.push_back(widgetType);
connect(cooefsLink, SIGNAL(released()),
this, SLOT(showCoefficients()));
buttonSignals[cooefsLink] = mBlock;
constructMotionVector(mBlock);
macBlockLayout->addWidget(macBlockParent, height - 16, width - 16);
styleMacroBlocks(mBlock);
}
could I make a function out of this for loop where I could parallel the operation by splitting it into two different for loops both operating on the vector at the same time. One working on the first half items and the second thread building the second half. So for example
Thread 1
for(unsigned int mBlock = 0; mBlock < coords.size() / 2; mBlock++)
{
WidgetType widgetType;
height = macBlockWidth + coords[mBlock].y;
width = macBlockHeight + coords[mBlock].x;
macBlockParent = new QWidget;
cooefsLink = new QPushButton(macBlockParent);
macBlock = new QWidget(macBlockParent);
widgetType.widget = macBlock;
widgetType.type = (macBlocks[mBlock][2] != 'S')
? (macBlocks[mBlock][0]) : (macBlocks[mBlock][2]);
blockWidgetTypes.push_back(widgetType);
connect(cooefsLink, SIGNAL(released()),
this, SLOT(showCoefficients()));
buttonSignals[cooefsLink] = mBlock;
constructMotionVector(mBlock);
macBlockLayout->addWidget(macBlockParent, height - 16, width - 16);
styleMacroBlocks(mBlock);
}
Thread 2
for(unsigned int mBlock = coords.size() / 2; mBlock < coords.size(); mBlock++)
{
WidgetType widgetType;
height = macBlockWidth + coords[mBlock].y;
width = macBlockHeight + coords[mBlock].x;
macBlockParent = new QWidget;
cooefsLink = new QPushButton(macBlockParent);
macBlock = new QWidget(macBlockParent);
widgetType.widget = macBlock;
widgetType.type = (macBlocks[mBlock][2] != 'S')
? (macBlocks[mBlock][0]) : (macBlocks[mBlock][2]);
blockWidgetTypes.push_back(widgetType);
connect(cooefsLink, SIGNAL(released()),
this, SLOT(showCoefficients()));
buttonSignals[cooefsLink] = mBlock;
constructMotionVector(mBlock);
macBlockLayout->addWidget(macBlockParent, height - 16, width - 16);
styleMacroBlocks(mBlock);
}
Because its a real bottleneck for my system and I notice its only using one CPU and its maxing out that CPU. Any help would be great thanks.

Hm... If you have constructions like this: blockWidgetTypes.push_back(widgetType); in both threads, it's seems very dangerous for multithreaded execution.

Related

QChart log axis data not shown

I have a 2Y Axis plo with a QValueAxison the y1 and QLogValueAxis on y2.
The linear plot is shown, the log plot is not shown. The data for both is the same.
I wonder how to set up the ticks and limits for the log axis?
This is the code:
chart = new QChart();
chart->legend()->hide();
chart->setTitle("Histogramm");
axisX = new QValueAxis;
axisX->setLabelFormat("%g");
chart->addAxis(axisX, Qt::AlignBottom);
series = new QLineSeries;
chart->addSeries(series);
axisY = new QValueAxis;
axisY->setTitleText("linear scale");
axisY->setLinePenColor(series->pen().color());
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisX);
series->attachAxis(axisY);
serieslog = new QLineSeries;
chart->addSeries(serieslog);
axisY3 = new QLogValueAxis();
axisY3->setTitleText("logarithmic scale");
axisY3->setBase(10.0);
axisY3->setLinePenColor(serieslog->pen().color());
chart->addAxis(axisY3, Qt::AlignRight);
serieslog->attachAxis(axisX);
serieslog->attachAxis(axisY3);
chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
// Create a layout and add Chart
QGridLayout *layout = new QGridLayout(this);
layout->addWidget(chartView);
void WidgetHistogramm::setData(const std::vector<int> data)
{
if (data.size() <= 0)
{
LOG_DEBUG() << "Histogram Data empty";
return;
}
auto max = *max_element(std::begin(data), std::end(data));
QVector<QPointF> points(data.size());
for(std::vector<int>::size_type i = 0; i != data.size(); ++i) {
points[i] = QPointF(i, data[i]*100/max);
}
series->replace(points);
serieslog->replace(points);
chart->axisX(series)->setRange(0, data.size());
chart->axisY(series)->setRange(0, 100);
chart->axisX(serieslog)->setRange(0, data.size());
chart->axisY(serieslog)->setRange(-1000, 1);
}
The range does not refer to the scaled values, but to the actual values, for example in your case it should be from epsilon to 100. On the other hand the values that are shown in the logarithmic scale must be positive, in your case I see that there is zeros so a possible solution is to add an epsilon:
void WidgetHistogramm::setData(const std::vector<int> data)
{
if (data.size() <= 0){
LOG_DEBUG() << "Histogram Data empty";
return;
}
auto max = *max_element(std::begin(data), std::end(data));
QVector<QPointF> points(data.size());
for(std::vector<int>::size_type i = 0; i != data.size(); ++i) {
points[i] = QPointF(i, data[i]*100.0/max + std::numeric_limits<qreal>::epsilon());
}
series->replace(points);
serieslog->replace(points);
chart->axisX(series)->setRange(0, points.size());
chart->axisY(series)->setRange(0, 100);
chart->axisX(serieslog)->setRange(0, points.size());
chart->axisY(serieslog)->setRange( std::numeric_limits<qreal>::epsilon(), 100);
}

How do I prevent over-correcting in my autonomous driving solution?

I am working on an autonomous driving solution for Euro Truck Simulator 2 with OpenCV in C++.
Here is where we detect the curve of the road:
int bottom_center = 160;
int sum_centerline = 0;
int count_centerline = 0;
int first_centerline = 0;
int last_centerline = 0;
double avr_center_to_left = 0;
double avr_center_to_right = 0;
//#pragma omp parallel for
for (int i = 240; i > 30; i--){
double center_to_right = -1;
double center_to_left = -1;
for (int j = 0; j < 150; j++) {
if (contours.at<uchar>(i, bottom_center + j) == 112 && center_to_right == -1) {
center_to_right = j;
}
if (contours.at<uchar>(i, bottom_center - j) == 112 && center_to_left == -1) {
center_to_left = j;
}
}
if (center_to_left != -1 && center_to_right != -1){
int centerline = (center_to_right - center_to_left + 2 * bottom_center) / 2;
if (first_centerline == 0) {
first_centerline = centerline;
}
cv::circle(outputImg, Point(centerline, i), 1, Scalar(30, 255, 30), 3);
cv::circle(outputImg, Point(centerline + center_to_right+20, i), 1, Scalar(255, 30, 30) , 3);
cv::circle(outputImg, Point(centerline - center_to_left+10, i), 1, Scalar(255, 30, 30) , 3);
sum_centerline += centerline;
avr_center_to_left = (avr_center_to_left * count_centerline + center_to_left) / count_centerline + 1;
avr_center_to_right = (avr_center_to_right * count_centerline + center_to_right) / count_centerline + 1;
last_centerline = centerline;
count_centerline++;
}
else {}
}
And here is my current solution for steering:
int diff = 0;
if (count_centerline != 0) {
diff = sum_centerline / count_centerline - bottom_center;
int degree = atan2(last_centerline - first_centerline, count_centerline) * 180 / PI;
//diff = (90 - degree);
int move_mouse_pixel = diff;
cout << "Steer: " << move_mouse_pixel << "px ";
if (diff <= 20 || diff >= -20){
SetCursorPos(pt.x + (move_mouse_pixel / 10), height / 2);
}
else{
SetCursorPos(pt.x + (move_mouse_pixel / 25), height / 2);
}
}
Finally, here is a video of what my program currently does: https://www.youtube.com/watch?v=rqyvoFuGKKk&feature=youtu.be
The current problem I have is that the steering does not center fast enough, leading it to continually over-correct until it swerves off the lane. I have tried to increase steering sensitivity in-game, to allow for faster or slower turning, but this either makes the truck spin out of control or not turn enough when driving along a large curve.
My current method just divides slight movements (between -20px and 20px) by 10, and large movements by 20. I've also tried reversing this but did not fix the over-correcting problem.
There are two possible solutions that I have found so far:
I could incrementally increase the divider for which we apply to move_mouse_pixel, therefore reducing the force of steering done between small movements.
Or, I could somehow make the program center the steering wheel more quickly. I am not sure how I would implement this.
What do you guys think?
I believe that PID controller would be suitable for this task.
https://en.wikipedia.org/wiki/PID_controller
In your situation it would look similar to this:
diffOld = diff;
diff = sum_centerline / count_centerline - bottom_center;
SetCursorPos(width/2 + Kp* diff + Kd*(diff - diffOld) , height / 2);
Do not use if statement in this controller. You need to keep steering even if there is no error to corect. I would suggest to skip integral part, because your object integrate (when you do not drive straight you integrate error). You need to experimentally choose values of Kp and Kd parameters, for example with Ziegler–Nichols method https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method.

Updating QGridLayouts

Hi guys I'm coding game for my studies and I've big problems with that (My leg was injured and I couldn't go to lessons).
My job is to do simple Battleships game in c++, qt.
I'm in point where logic code is done, but gui is a big mess.
Here's code for gui .cpp file:
#include <QtWidgets>
#include "dialog.h"
Dialog::Dialog()
{
createGraczBox();
createKomputerBox();
createOdpowiedz();
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(graczBox , 0 , 0 );
mainLayout->addWidget(komputerBox , 0 , 1 );
mainLayout->addWidget(Odpowiedz , 0 , 2 );
setLayout(mainLayout);
setFixedSize(800,400);
setWindowTitle(tr("Battleships!"));
}
void Dialog::createGraczBox()
{
graczBox = new QGroupBox(tr("Gracz"));
QGridLayout *layout = new QGridLayout;
for (int j = 0; j < NumGridRows; ++j) {
labels[j] = new QLabel(tr("%0").arg(j+1));
layout->addWidget(labels[j], 0 , j + 1 , Qt::AlignLeft);
}
for (int i = 0; i < NumGridRows; ++i) {
labels[i] = new QLabel(tr("%0").arg(i + 1));
layout->addWidget(labels[i], i + 1, 0);
}
for(int g = 1;g<10;++g)
{
layout->setColumnStretch(g,1);
}
graczBox->setLayout(layout);
}
void Dialog::createKomputerBox()
{
komputerBox = new QGroupBox(tr("Komputer"));
QGridLayout *layout = new QGridLayout;
for (int j = 0; j < NumGridRows; ++j) {
labels[j] = new QLabel(tr("%0").arg(j+1));
layout->addWidget(labels[j], 0 , j + 1 );
}
for (int i = 0; i < NumGridRows; ++i) {
labels[i] = new QLabel(tr("%0").arg(i + 1));
layout->addWidget(labels[i], i + 1, 0);
}
for(int g = 1;g<10;++g)
{
layout->setColumnStretch(g,1);
}
komputerBox->setLayout(layout);
}
void Dialog::createOdpowiedz()
{
Odpowiedz = new QGroupBox(tr("Komendy"));
QFormLayout *layout = new QFormLayout;
xLabel = new QLabel;
QPushButton *zmienna_x_przycisk = new QPushButton(tr("X"));
connect(zmienna_x_przycisk, SIGNAL(clicked()), this, SLOT(setx()));
yLabel = new QLabel;
QPushButton *zmienna_y_przycisk = new QPushButton(tr("Y"));
connect(zmienna_y_przycisk, SIGNAL(clicked()), this, SLOT(sety()));
xLabel->setText(tr("Aktualne X: %1").arg(zmienna_x));
yLabel->setText(tr("Aktualne Y: %1").arg(zmienna_y));
layout->addRow(xLabel);
layout->addRow(zmienna_x_przycisk);
layout->addRow(yLabel);
layout->addRow(zmienna_y_przycisk);
Odpowiedz->setLayout(layout);
}
void Dialog::setx()
{
bool ok_x;
x = QInputDialog::getInt(this, tr("Podaj X:"),
tr(""), 1, 1, 10, 1, &ok_x);
if (ok_x)
x=zmienna_x;
}
void Dialog::sety()
{
bool ok_y;
y = QInputDialog::getInt(this, tr("Podaj Y:"),
tr(""), 1, 1, 10, 1, &ok_y);
if (ok_y)
y=zmienna_y;
}
They way it should work:
I'm choosing x and y by clicking on it.
Choosing numbers in new window.
They should appear in "Aktualne X:/Y:".
When I've x and y, click ok button (he's not there by now).
Computer checking numbers marking it in space Komputer / Gracz.
Reset x and y to 0.
Show text "You missed. Computer missed."
Go on till one'll win.
But I don't know how to make my layout updating itself by other actions. I can't make dowhile work here.
You need to use signals and slots here. Create "OK" button and connect it to a function, that will be used to handle your x and y variables.

Sprite can not move in cocos2d-x

I am new on cocos2d-x, i followed Cocos2d-x Game Development Essentials Ebook and trying to make demo app in iOS. with the help of its guidance,but when i trying to Move Astroids in GameScreen.cpp file as written in book, they actually doesn't move and i can't understand what am i missing?
here is code that i used:
bool GameScene::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
//Add EVENT LISTENER TO HANDLE TOUCH EVENT,
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = CC_CALLBACK_2(GameScene::ontouchBegin,this);
listener->onTouchMoved = CC_CALLBACK_2(GameScene::ontouchMoved, this);
listener->onTouchCancelled = CC_CALLBACK_2(GameScene::ontouchCanceled, this);
listener->onTouchEnded = CC_CALLBACK_2(GameScene::ontouchEnded, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
istouching = false;
touchPosition = 0;
visibleSize = Director::getInstance()->getVisibleSize();
origin = Director::getInstance()->getVisibleOrigin();
auto backgroundSprite = Sprite::create("Game_Screen_Background.png");
backgroundSprite->setPosition(Point((visibleSize.width/2)+origin.x,(visibleSize.height/2)+origin.y));
this->addChild(backgroundSprite, -1);
auto pauseItem =
MenuItemImage::create("Pause_Button.png","Pause_Button(Click).png",CC_CALLBACK_1(GameScene::PushToGamePauseScene, this));
pauseItem->setPosition(Point(pauseItem->getContentSize().width-(pauseItem->getContentSize().width/4)+origin.x,visibleSize.height - pauseItem->getContentSize().height +(pauseItem->getContentSize().width / 4) + origin.y));
auto menu = Menu::create(pauseItem, NULL);
menu->setPosition(Point::ZERO);
this->addChild(menu);
for (int i = 0; i < 2; i ++){
backgroundSpriteArray[i] = Sprite::create("Game_Screen_Background.png");
backgroundSpriteArray[i]->setPosition(Point((visibleSize.width/2)+origin.x,(-1*visibleSize.height*i)+(visibleSize.height/2)+origin.y));
this->addChild(backgroundSpriteArray[i],-2);
}
playerSprite = Sprite::create("Space_Pod.png");
playerSprite->setPosition(Point(visibleSize.width/2,pauseItem->getPosition().y-(pauseItem->getContentSize().height/2)-(playerSprite->getContentSize().height/2)));
this->addChild(playerSprite, 1);
this->schedule(schedule_selector(GameScene::spawnAsteroid), 1.0);
this->scheduleUpdate();
return true;
}
Following is update method
void GameScene::update(float dt){
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
for (int i = 0; i < 2; i ++){
if (backgroundSpriteArray[i]->getPosition().y >=visibleSize.height + (visibleSize.height / 2) -1){
backgroundSpriteArray[i]->setPosition(Point((visibleSize.width / 2) + origin.x, (-1 *visibleSize.height) + (visibleSize.height / 2)));
}
}
for (int i = 0; i < 2; i ++){
backgroundSpriteArray[i]->setPosition(Point(backgroundSpriteArray[i]->getPosition().x,backgroundSpriteArray[i]->getPosition().y + (0.75 *visibleSize.height * dt)));
}
for (int i = 0; i < asteroids.size(); i++){
asteroids[i]->setPosition(Point(asteroids[i]->getPosition().x,asteroids[i]->getPosition().y+(0.75 * visibleSize.height * dt)));
if (asteroids[i]->getPosition().y > visibleSize.height * 2){
this->removeChild(asteroids[i]);
asteroids.erase(asteroids.begin() + i);
}
}
//check for Touching
if(istouching == true){
//now check, which side of the screen is being touched
if(touchPosition < visibleSize.width /2){
//now, move the space pod to left
float positionX = playerSprite->getPosition().x;
playerSprite->setPositionX(positionX - (0.50* visibleSize.width * dt));
positionX = playerSprite->getPositionX();
//prevent space pod to getting off the screen (left side)
if(positionX <= 0+(playerSprite->getContentSize().width/2))
{
playerSprite->setPositionX(playerSprite->getContentSize().width / 2);
}
}
else{
//now, move the space pod to right
float positionX = playerSprite->getPositionX();
playerSprite->setPositionX(positionX + (0.50 * visibleSize.width *dt));
positionX = playerSprite->getPositionX();
// check to prevent the space pod from going off the screen (right side)
if(positionX >= visibleSize.width-(playerSprite->getContentSize().width/2))
{
playerSprite->setPositionX(visibleSize.width-(playerSprite->getContentSize().width/2));
}
}
}
}
For move astroid code:
void GameScene::spawnAsteroid(float dt){
Size visibleSize = Director::getInstance()->getVisibleSize();
Point origin = Director::getInstance()->getVisibleOrigin();
int asteroidIndex = (arc4random() % 3) + 1;
__String* asteroidString = __String::createWithFormat("Asteroid_%i.png",asteroidIndex);
auto *tempAsteroid = Sprite::create(asteroidString->getCString());
int xRandomPosition = (arc4random() % (int)(visibleSize.width - (tempAsteroid->getContentSize().width / 2))) + (tempAsteroid->getContentSize().width / 2);
tempAsteroid->setPosition(Point(xRandomPosition + origin.x, -tempAsteroid->getContentSize().height +origin.y));
asteroids.push_back(tempAsteroid);
this->update(touchPosition);
this->addChild(asteroids[asteroids.size() - 1], -1);
}
That method has been called at run time but don't know that my astroid object does not moved can anybody please help me for figure it out issue and how to fix it.
Edit
OK,i put this->scheduleUpdate() in init(),and starts moving astroids on the screen but when i move my sprite(not astroids) with touchBegin event the astroid got disappear from screen. please guide me on this.
please put this line in your init method
this->scheduleUpdate();
Hope it helps
Sprite->runAction(Sequence::create(MoveTo::create(1.0f, Vec2(100,200)),NULL));

OpenGL When to use Geometry Shaders

I currently have a OpenGL sprite drawing class that buffers up a bunch of sprite data then dumps it with glDrawElements. The problem is, creating the sprites that go into the buffer is cumbersome as I have loads of parameters to pass into the buffer with even more redundancy for the shaders. I was wondering if I could reduce CPU load by only loading the buffer with the essentials, location, orientation, texture coordinates etc... and then let a geometry shader turn that nonsense into quads for the fragment shader.
If theres a different answer, I've added the offending method so you can see what I mean:
void Machine::draw(key num, BoundingBox loc, float angle){
SpriteSyncData* props;
VertexAttribArray* vdata;
GLushort* idata;
SpriteProperties* sprite_props;
int sliceW;
int sliceH;
sprite_props = &spriteList[num];
props = &spriteToSync[sprite_props->atlas];
props->size++;
if(props->size > props->capacity){
props->capacity += COARSE_MEM_SCALE;
props->data = (VertexAttribArray*) realloc((void*) props->data, (sizeof(VertexAttribArray)*4) * props->capacity);
props->i_data = (GLushort*) realloc((void*) props->i_data, (sizeof(GLushort)*4) * props->capacity);
}
vdata = props->data + (props->size - 1) * 4;
idata = props->i_data + (props->size - 1) * 4;
sliceW = sprite_props->location.x1 - sprite_props->location.x0;
sliceH = sprite_props->location.y1 - sprite_props->location.y0;
if(sprite_props->flags & DRAW_TILED){
vdata[0].p = QVector3D(loc.x1, loc.y0, UNIFORM_DEPTH);
vdata[1].p = QVector3D(loc.x0, loc.y0, UNIFORM_DEPTH);
vdata[2].p = QVector3D(loc.x0, loc.y1, UNIFORM_DEPTH);
vdata[3].p = QVector3D(loc.x1, loc.y1, UNIFORM_DEPTH);
vdata[0].s = QVector2D(((float) (loc.x1 - loc.x0)) / sliceW,
((float) (loc.y1 - loc.y0)) / sliceH);
vdata[0].r = QVector2D(0, 0);
vdata[1].r = vdata[0].r;
vdata[2].r = vdata[0].r;
vdata[3].r = vdata[0].r;
}
else{
vdata[0].p = QVector3D(loc.x0 + sliceW, loc.y0, UNIFORM_DEPTH);
vdata[1].p = QVector3D(loc.x0, loc.y0, UNIFORM_DEPTH);
vdata[2].p = QVector3D(loc.x0, loc.y0 + sliceH, UNIFORM_DEPTH);
vdata[3].p = QVector3D(loc.x0 + sliceW, loc.y0 + sliceH, UNIFORM_DEPTH);
vdata[0].s = QVector2D(1, 1);
vdata[0].r = QVector2D(sliceW, sliceH);
vdata[1].r = vdata[0].r;
vdata[2].r = vdata[0].r;
vdata[3].r = vdata[0].r;
}
vdata[0].t = QVector2D(sprite_props->texCoords[2], sprite_props->texCoords[1]);
vdata[1].t = QVector2D(sprite_props->texCoords[0], sprite_props->texCoords[1]);
vdata[2].t = QVector2D(sprite_props->texCoords[0], sprite_props->texCoords[3]);
vdata[3].t = QVector2D(sprite_props->texCoords[2], sprite_props->texCoords[3]);
vdata[1].s = vdata[0].s;
vdata[2].s = vdata[0].s;
vdata[3].s = vdata[0].s;
vdata[0].s_lo = QVector2D(sprite_props->texCoords[0], sprite_props->texCoords[1]);
vdata[0].s_hi = QVector2D(sprite_props->texCoords[2] - sprite_props->texCoords[0],
sprite_props->texCoords[3] - sprite_props->texCoords[1]);
vdata[1].s_lo = vdata[0].s_lo;
vdata[1].s_hi = vdata[0].s_hi;
vdata[2].s_lo = vdata[0].s_lo;
vdata[2].s_hi = vdata[0].s_hi;
vdata[3].s_lo = vdata[0].s_lo;
vdata[3].s_hi = vdata[0].s_hi;
vdata[0].o = (vdata[1].p + vdata[3].p) * 0.5;
vdata[1].o = vdata[0].o;
vdata[2].o = vdata[0].o;
vdata[3].o = vdata[0].o;
vdata[0].a = angle;
vdata[1].a = angle;
vdata[2].a = angle;
vdata[3].a = angle;
idata[0] = (props->size - 1) * 4;
idata[1] = idata[0] + 1;
idata[2] = idata[0] + 2;
idata[3] = idata[0] + 3;
}