problem with resetting window while repeat clock at c++
I tried to reset the time using time, chrono. However, the code execution time continued to increase without initialization.
Hello, I'm a student at the Korea Institute of Technology. Use the translator.
Please excuse me for speaking awkwardly.
I'm designing a program that uses the C++ OpenPose library to measure the right PC user tax.
Basically, we've completed the function of floating a pop-up to provide feedback when your right shoulder or left shoulder is crooked.
However, I would like to issue an alert after a certain second rather than a feedback that is sent in the wrong position.
Time should be measured when the supose function is not executed, but when the user is sitting in the wrong position. Time will be measured from the time when the supose function is executed. An event should occur if the same seat is held for 20 seconds from the wrong seat.
The event will occur after 20 seconds, and if the time is not initialized, it will occur as soon as it is recognized as an incorrect posture. I think it's because of when. If the library breaks from where, it ends with 0 code.
Once I've solved the time-related function, I'm going to ask you a question because I'm having a hard time completing the program.
Thank you.
while (!userWantsToExit)
{
// start frame
std::shared_ptr<std::vector<UserDatum>> datumProcessed;
if (opWrapper.waitAndPop(datumProcessed))
{
userWantsToExit = userOutputClass.display(datumProcessed);
userOutputClass.printKeypoints(datumProcessed);
....
//string to int
int subShoulder = stoi(rShoulderY) - stoi(lShoulderY);
//clac keypoint values for posedata
if (50 < subShoulder || -50 > subShoulder)
{
if (stoi(rShoulderY) < stoi(lShoulderY)) {
clock_t t_start, t_end;
int time;
t_start = clock(); //start clock
time = t_start / CLOCKS_PER_SEC;
op::log(time);
if (time > 20) {
t_end = clock(); //end clock
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
cv::imshow("SUPOSE", imgLshoulderDown);
std::string id = "hjw";
std::string pose = "leftShoulder";
httpRequestPose(id, pose);
}
}
else if (stoi(rShoulderY) > stoi(lShoulderY)) {
clock_t t_start, t_end;
int time;
t_start = clock(); //start clock
time = t_start / CLOCKS_PER_SEC;
op::log(time);
if (time > 20) {
cv::imshow("SUPOSE", imgRshoulderDown);
std::string id = "hjw";
std::string pose = "rightShoulder";
httpRequestPose(id, pose);
}
t_end = clock();
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
}
else {
clock_t t_start, t_end;
int time;
t_end = clock();
time = (int)(t_end - t_start) / CLOCKS_PER_SEC;
}
}
}
else {}
//op::log("Processed datum could not be emplaced.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
}
*image
Honestly, it is very hard for me to completely understand your question. However, I was a student and not good at english (even now), i know how struggling it was to find help with google translated paragraphs. Hence, i will make a try.
As I understand, you want to trigger an alert if the shoulder keeps inclining left for more than 20 seconds (same to right incline). Is that correct?
If it is correct, I think the problem is that you keep the variable t_start inside the poseDetect function. It means that everytime the pose is detected the t_start is a new one. The value (t_end - t_start) is always 0. You should declare t_start outside of that function and use a flag to check if it is the first time. I would like to suggest with below pseudo code
bool isLeftIncline = false;
clock_t startLeft=clock(); //get current time
void poseDetect()
{
if (50 < subShoulder || -50 > subShoulder){
if (stoi(rShoulderY) < stoi(lShoulderY)){ // should is inclined to the left
if(!isLeftIncline){ // the first time
startLeft=clock(); // get the starting time
isLeftIncline=true;
//trigger for the first time here
}else { // after the first time
clock_t current=clock();
int timeDiff=current-startLeft;
if(timeDiff>20){ //after 20 second with same pose
// issue an alert
}
//or trigger alert every nearly 20 seconds
//if(timeDiff%20<3){
//trigger
//}
}
}else {
// the shoulder no longer inclines to the left
// reset isLeftIncline time
isLeftIncline = false;
}
// you can apply the same for the right incline here
}
}
Related
Consider the loop below. This is a simplified example of a problem I am trying to solve. I want to limit the number of times doSomething function is called in each second. Since the loop works very fast, I thought I could use a rate limiter. Let's assume that I have found an appropriate value by running it with different x numbers.
unsigned int incrementionRate = x;
unsigned int counter == 0;
while (true) {
double seconds = getElapsedSeconds();
print(seconds);
counter = (counter + 1) % incrementionRate;
if (counter == 0) {
doSomething();
}
}
I wonder if the number of calls to doSomething function would be less if I was working on a lower clock rate. In that case, I would like to limit the number of calls to doSomething function to once for each second. The second loop I have written is below.
float epsilon = 0.0001;
while (true) {
double seconds = getElapsedSeconds();
print(seconds);
if (abs(seconds - floor(seconds)) <= epsilon) {
doSomething();
}
}
Would that do the trick for different clock cycles or are there still problems? Also, I would like to know if there is a better way of doing this. I have never worked with clock rates before and trying to understand how concerns differ when working with limited resources.
Note: Using sleep is not an option.
If I understand the issue proberly, you could use a std::chrono::steady_clock that you just add a second to every time a second has passed.
Example:
#include <chrono>
auto end_time = std::chrono::steady_clock::now();
while (true) {
// only call doSomething once a second
if(end_time < std::chrono::steady_clock::now()) {
doSomething();
// set a new end time a second after the previous one
end_time += std::chrono::seconds(1);
}
// do something else
}
Ted's answer is fine if you are really doing something else in the loop; if not, though, this results in a busy wait which is just consuming up your CPU for nothing.
In such a case you should rather prefer letting your thread sleep:
std::chrono::milliseconds offset(200);
auto next = std::chrono::steady_clock::now();
for(;;)
{
doSomething();
next += offset;
std::this_thread::sleep_until(next);
}
You'll need to include chrono and thread headers for.
I decided to go with a much more simple approach at the end. Used an adjustable time interval and just stored the latest update time, without introducing any new mechanism. Honestly, now I don't know why I couldn't think of it at first. Overthinking is a problem. :)
double lastUpdateTimestamp = 0;
const double updateInterval = 1.0;
while (true) {
double seconds = getElapsedSeconds();
print(seconds);
if ((elapsedSeconds - lastUpdateTimestamp) >= updateInterval) {
doSomething();
lastUpdateTimestamp = elapsedSeconds;
}
}
bool IsGameEnded()
{
static int i = 0;
i++;
if (i == 10)
return true;
return false;
}
int main()
{
bool GameEnd = false;
float ElapsedTime = 0;
while(!GameEnd)
{
chrono::steady_clock::time_point StartingTime = chrono::steady_clock::now();
if (ElapsedTime > 10)
{
ElapsedTime = 0;
draw();
}
GameEnd = IsGameEnded();
chrono::steady_clock::time_point EndingTime = chrono::steady_clock::now();
ElapsedTime = ElapsedTime + chrono::duration_cast<chrono::milliseconds>(EndingTime - StartingTime).count();
}
return 0;
}
I wan't to make a snake game. It will be based on time. For example screen will update every 5 seconds or so. For that I used chrono library. I am not used to this trying o learn it so I might have missed something obvious. But the problem is main function doesn't get get into the if block. So it draws nothing to the console.
I tried debugging (with running line by line). It is not actually like a running program becasue time intervals get long but it enters if block every time. Also if I make the if condition 2 nanoseconds it also works but since cout function can not print so fast I need it to be a lot longer than that. While Debugging I also realised that "StartingTime" and "EndingTime" variables don't get initiated (unless I directly stop on them) . The interesting part is If ı add cout after if block, after a while program starts entering the If block.
When you do:
chrono::duration_cast<chrono::milliseconds>(EndingTime - StartingTime).count();
not enough time has passed, and the count of milliseconds always returns 0. This means you always add 0 to ElapsedTime and it never crosses 10.
One fix is to use a smaller resolution:
chrono::duration_cast<chrono::nanoseconds>(EndingTime - StartingTime).count();
as you mentioned in the question, and adjust the if condition appropriately.
However, the best fix would be to change ElapsedTime from a float to a chrono::duration (of the appropriate unit) since that is the unit that the variable represents. This would let you avoid having to do .count() on the duration as well.
I am getting some unexpected behavior I don't understand. I am trying to implement a fixed variable time step as described from http://gafferongames.com/game-physics/fix-your-timestep/ and http://gameprogrammingpatterns.com/game-loop.html. My inner while loop never evaluates as true when I run the program in visual studio; however, when I uncomment 'this_thread::sleep_for(1s)', the while loop will evaluate as a true after the outer loop executes 10 times or so. I would expect on faster machines, this would be the expected outcome.
So my question is why would the inner loop only evaluate as true when the 'this_thread::sleep_for(1s)' is uncommented? Shouldn't lagTime become greater than fixedDeltaTime regardless of the sleep_for? Does the math take too much time for the computer or something?
int updateCount = 0;
double CLOCKS_PER_MILLISECOND((double)CLOCKS_PER_SEC * 1000.0);
double previousTime = std::clock() / CLOCKS_PER_MILLISECOND;
double newTime = 0, deltaTime = 0, lagTime = 0;
double fixedDeltaTime = 1.0 / 60.0;
while (gameIsRunning)
{
newTime = std::clock() / CLOCKS_PER_MILLISECOND;
deltaTime = newTime - previousTime;
previousTime = newTime;
lagTime += deltaTime;
inputSystem.update();
sceneManager.update();
while(lagTime >= fixedDeltaTime) // never evalutes as true?
{
physicsSystem.update();
lagTime -= fixedDeltaTime;
updateCount++;
}
std::cerr << "-----" << updateCount << "-----" << std::endl;
physicsSystem.interpolate(lagTime / fixedDeltaTime);
renderSystem.update();
audioSystem.update();
updateCount = 0;
//std::this_thread::sleep_for(1s);
}
Thank you for any help!
You're trying to measure time using clock(), but that is a process tick counter that won't advance while all threads in your process are sleeping. The whole point of sleep is to tell the CPU "don't give this process any attention for a while!". As far as your program is concerned, time freezes while it's asleep.
If you waited long enough, lagTime would eventually advance past fixedDeltaTime because the period of time during which your program is not sleeping consumes ticks ... but you'd have to wait for many, many seconds.
Don't use clock() to measure the absolute passage of time.
I have a game with Bullet Physics as the physics engine, the game is online multiplayer so I though to try the Source Engine approach to deal with physics sync over the net. So in the client I use GLFW so the fps limit is working there by default. (At least I think it's because GLFW). But in the server side there is no graphics libraries so I need to "lock" the loop which simulating the world and stepping the physics engine to 60 "ticks" per second.
Is this the right way to lock a loop to run 60 times a second? (A.K.A 60 "fps").
void World::Run()
{
m_IsRunning = true;
long limit = (1 / 60.0f) * 1000;
long previous = milliseconds_now();
while (m_IsRunning)
{
long start = milliseconds_now();
long deltaTime = start - previous;
previous = start;
std::cout << m_Objects[0]->GetObjectState().position[1] << std::endl;
m_DynamicsWorld->stepSimulation(1 / 60.0f, 10);
long end = milliseconds_now();
long dt = end - start;
if (dt < limit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(limit - dt));
}
}
}
Is it ok to use std::thread for this task?
Is this way is efficient enough?
Will the physics simulation will be steped 60 times a second?
P.S
The milliseconds_now() looks like this:
long long milliseconds_now()
{
static LARGE_INTEGER s_frequency;
static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
if (s_use_qpc) {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (1000LL * now.QuadPart) / s_frequency.QuadPart;
}
else {
return GetTickCount();
}
}
Taken from: https://gamedev.stackexchange.com/questions/26759/best-way-to-get-elapsed-time-in-miliseconds-in-windows
If you want to limit the rendering to a maximum FPS of 60, it is very simple :
Each frame, just check if the game is running too fast, if so just wait, for example:
while ( timeLimitedLoop )
{
float framedelta = ( timeNow - timeLast )
timeLast = timeNow;
for each ( ObjectOrCalculation myObjectOrCalculation in allItemsToProcess )
{
myObjectOrCalculation->processThisIn60thOfSecond(framedelta);
}
render(); // if display needed
}
Please note that if vertical sync is enabled, rendering will already be limited to the frequency of your vertical refresh, perhaps 50 or 60 Hz).
If, however, you wish the logic locked at 60fps, that's different matter: you will have to segregate your display and logic code in such a way that the logic runs at a maximum of 60 fps, and modify the code so that you can have a fixed time-interval loop and a variable time-interval loop (as above). Good sources to look at are "fixed timestep" and "variable timestep" ( Link 1 Link 2 and the old trusty Google search).
Note on your code:
Because you are using a sleep for the whole duration of the 1/60th of a second - already elapsed time you can miss the correct timing easily, change the sleep to a loop running as follows:
instead of
if (dt < limit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(limit - dt));
}
change to
while(dt < limit)
{
std::this_thread::sleep_for(std::chrono::milliseconds(limit - (dt/10.0)));
// or 100.0 or whatever fine-grained step you desire
}
Hope this helps, however let me know if you need more info:)
I thought I was jumping over a puddle, but have instead fallen into an ocean :/
I'm trying to implement a 5 second timer (don't need more than milliseconds).
My goal:
// I start the program in gamestate 0...
{
if (button_has_been_pressed == 1)
{
gamestate = 1;
}
}
if (gamestate==1)
{
//wait for 5 seconds and go to gamestate2
gamestate = 2;
}
I've tried the following:
GLUT_TIME_ELAPSED measures time from the beginning of my program. I am unable to 'reset' GLUT_TIME_ELAPSED after entering gamestate1. Otherwise, it would work wonderfully.
gettimeofday gives me much more resolution than I need. At most, milliseconds would be applicable.
Regardless of my resolution needs, I've tried Song Ho's method:
gamestate1_elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms
gamestate1_elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms
// add that elapsed time together, and keep track of its total
//r_gamestate1_elapsedTime_total = gamestate1_elapsedTime;
//if (r_gamestate1_elapsedTime_total > 5 seconds) ...
However, the gamestate1_elapsedTime appears to have some variability to it. Because the output is seldom consistent. I guess it's b/c gettimeofday employs CPU time(?), and I am artificially clamping this with my fps clamp.
I've tried clock() as well, but that also appears to be CPU time - not wall time.
As mentioned above, GLUT_ELAPSED_TIME works well, except that I am unable to reset it midway through my program, and my 5-seconds is no longer dependent upon my initial button click.
I would deeply appreciate even a nudge in the right direction, if you could lend some advice. Thank you very much in advance.
-kropcke
You don't need to "reset" GLUT_ELAPSED_TIME, you just need to copy it somewhere that you can use as an offset. For example:
int timeAtReset = glutGet(GLUT_ELAPSED_TIME);
// I start the program in gamestate 0...
{
if (button_has_been_pressed == 1)
{
gamestate = 1;
timeAtReset = glutGet(GLUT_ELAPSED_TIME);
}
}
if (gamestate==1)
{
int timeSinceReset = glutGet(GLUT_ELAPSED_TIME) - timeAtReset;
// use timeSinceReset, instead of glutGet(GLUT_ELAPSED_TIME), to
// wait for 5 seconds and go to gamestate2
gamestate = 2;
}