Jump to content

Need help with a stubborn simulated compass


Recommended Posts

I know I have written a lot, but I tried to be as clear as possible. Please don't let that discourage you from reading :(

I'm working on a project, to create a realistic simulated compass. Instead of pointing to North though, it points to an angle specified by the user. This is actually part of a larger project I will work on once I learn C++, but for now I just want to get familar with programming a compass with a language I know.

Currently not everything will be done in AutoIt as it doesn't support some features, at least I don't think. I asked a friend of mine who is good with C++ if he could create for me a visual compass, which will rotate depending on the commands used and variables provided by my AutoIt script. To make things simple, the AutoIt script will copy the variables into the clipboard and the little visual compass proggy will read the clipboard and do what's required. My friend told me he could do everything for me in C++, but I told him that's not the point as I wanted to learn myself the equations needed to automate a compass. Equations don't change from one language to the next, so I can easily transfer them over to C++ once I learn it. My friend won't be back until Tuesday, so for now I have the pleasure of watching numbers on my screen instead of a nice visual compass lol.

So far the compass works great, but there is a bug I can't get around. I may have put too much effort into making this lol. I added a nice little feature, but it came with a side effect and at one point I was so frustrated I was thinking of removing he additional code :ph34r:. Of course I realized that removing code is not a solution as a programmer.

The feature I've implemented to simulate a realistic compass is a little hard to explain. I'm not sure if you guys noticed it on a compass but the pointer never directly goes North. Instead it wobbles a bit left and right before settling towards North. Ya well that's what I did and at one point it's causing problems. The script is written to make the compass slow down before reaching the target angle. The closer it is to the target, the slower it will rotate. Because of the feature I have described above, it will pass the target and rotate the other direction, pass it again, rotating back and then finally settling at the angle specified.

Here's the problem, this does not working very well when the target angle is near North, or 0 or 360deg. I have specified the script to start slowing down the rotation when within 25deg of the target angle. For instance, if the target angle is 180deg, it will slow down starting at 155deg or 205deg depending which way it's rotating, left or right. The compass always rotates in the direction the target angle is closest to. All is well but what if the target angle is 0deg or 360deg, which both are the same angle. See the problem here?

It will start slowing down from either 25deg or 335deg. Once it passes it's target angle and spin the other direction due to the little feature I implemented, it will check how close it is within range of the target angle and adjust the rotation speed acordingly. If my target angle is 0deg and the compass is rotating left, it will pass the 0deg mark and the current angle will now be 359deg or something around it. It will try to check the range again but the numbers 0 and 359 are no where near within a range of 25, even if on a compass we see the angles to be within the same range. AutoIt now mistakenly will speed up the rotation in the opposite direction, flying way past the target angle until it figures it somehow past it again and will rotate back again. Because of the 0 and 360deg confusion, the script will never think it's within a range of 25deg once it passes true North(0deg or 360deg) so it will never fully slow down and settle. As for now, the compass wobbles like mad especially around at true North(0deg). Because of the 25 range specification, the bug effects any target angle from 335deg and 25deg, so relatively in the Northern area.

I have no idea how to counter this 0deg or 360deg confusion. Hopefully someone here who maybe has some experience programming a working compass may suggest some ideas how to make the script know even though it passes true North, it's still close and within range of the target angle which is nearby.

Mucho Gracias for any help on this.

Edited by ravenfyre
Link to comment
Share on other sites

Certainly, here ya go. It's only the part of the script I have trouble with. I didn't want to post the whole thing for a couple reasons. First, it's incredibly long and still disorganized so figuring what does what wouldn't be easy for someone just looking at it ^^. Secondly, I'm trying to focus on getting help on just this one part, I don't want you guys to waste your time going about fixing the rest of my errors lol.

First let me explain the variables and functions used:

$global_gdeg - is the goal or target angle specified by the user

cdeg() - returns the current angle of the compass

$global_turn - specifies which way the compass should rotate (left,right,none)

Buttons used

Numpad6 to rotate compass right

Numpad4 to rotate compass left

When target angle and current angle is > 25, key is held down for full rotation speed

When target angle and current angle is < 25 and > 15, key is tapped quickly to slow down (the closer to target angle, the slower the tapping)

When target angle and current angle is < 15, key is tapped slowly (the closer to target angle, the slower the tapping)

Enough chit chat, here's the code that slows down the rotation.

Do
Sleep(2);

$diff = $global_gdeg - cdeg(); determines the difference between your target angle and current
If $diff < 0 Then
$diff = -($diff); makes the difference positive
EndIf

If $global_turn = "right" Then
  $key = 6;
ElseIf $global_turn = "left" Then
  $key = 4;
EndIF

If $diff > 25 Then; if greater then 25deg, hold button
  $count = 0;
  If $global_turn = "right" Then
    Send("{NUMPAD4 up}");
    Send("{NUMPAD6 down}");
  ElseIf $global_turn = "left" Then
    Send("{NUMPAD6 up}");
    Send("{NUMPAD4 down}");
  ElseIf $global_turn = "none" Then
    Send("{NUMPAD4 up}");
    Send("{NUMPAD6 up}");
  EndIf
ElseIf $diff <= 25 AND $diff > 15 Then; tap button fast, depending on how close
  Send("{NUMPAD4 up}");
  Send("{NUMPAD6 up}");
  $count = $count + 1;
  Sleep($count);
    If $global_turn <> "none" Then
      Send("{NUMPAD"&$key&"}");
    EndIf
ElseIf $diff <= 15 Then; tap button slow, depending on how close
  Send("{NUMPAD4 up}");
  Send("{NUMPAD6 up}");
  $count = (2499-(99*$diff))/24;
  Sleep($count);
    If $global_turn <> "none" Then
      Send("{NUMPAD"&$key&"}");
    EndIf
EndIf

Until $diff <= 1; compass stops within a 1deg difference
EndFunc

As I said, this works great but anywhere except in the norther region of the compass where angle is changed from 360deg to 0deg. This sudden angle change, although being the same angle realisticly, confuses the function of the script because it's looking to slow down when it gets close to the target angle. Unfortunately the numbers 360 and 0 are far from each other and that's what the script thinks, where realisticly they are the same. So when it comes close to 0deg, it slows down and bam once it passes 0deg the current angle becomes 35X and instead of slowly rotating back it will speed up because it will think the target angle is further then it really is. Hope that makes sense ^^. I'm currently thinking of using radians instead of degrees but damn not only I hate working with radians but I gotta rework my entire script and calculations lol. That might fix my problem though, I'm not sure as I always try to avoid radians =).

Edited by ravenfyre
Link to comment
Share on other sites

Take a look at the Mod function for removing extra rotations.

$X = InputBox("Testing", "Enter a degree measure")

$Y = Mod($X, 360)
If $Y < 0 Then $Y = $Y + 360 ;Manage negative values
MsgBox(0, "Testing", "The equivalant angle is " & $Y & " degrees.")

David Nuttall
Nuttall Computer Consulting

An Aquarius born during the Age of Aquarius

AutoIt allows me to re-invent the wheel so much faster.

I'm off to write a wizard, a wonderful wizard of odd...

Link to comment
Share on other sites

The simplest thing seems to be to do an if-then where if the return value is smaller than 0, you add 360 or if larger than 360 you subtract 360.

<{POST_SNAPBACK}>

Hmm, that little trick may work. If turning right within Quadrant 2, about to make the transition to 0deg, the script will think the target is larger then 360deg. A target angle of 10deg would be 370deg. Same for turning left within Quadrant 1, the target angle will be smaller then 0, or negative.

Good thinking, I'll try to test this method now. Thanks this-is-me.

Take a look at the Mod function for removing extra rotations.

$X = InputBox("Testing", "Enter a degree measure")

$Y = Mod($X, 360)
If $Y < 0 Then $Y = $Y + 360;Manage negative values
MsgBox(0, "Testing", "The equivalant angle is " & $Y & " degrees.")

<{POST_SNAPBACK}>

Thanks Nutster, never considered the MOD function a viable solution. Actually, I never used it before ^^. I'll surely read up on it now after you proposed the idea. Edited by ravenfyre
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...