4 Answers, 1 is accepted
0
Hi Pete,
Victor
the Telerik team
Thank you for the question.
A compass cannot be implemented, at least to my knowledge, on the current Windows Phone device. The device has an accelerometer and GPS support. The accelerometer only gives you vector data relative to the center of the Earth and the GPS only gives you spherical coordinates and no orientation data relative to the poles of the Earth.
Please write again if you have other questions.
Victor
the Telerik team
Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
0
ManniAT
Top achievements
Rank 2
answered on 05 Jun 2011, 05:08 PM
Hi,
I already implemented a GPS compass.
The "problem" - it's a GPS related thing.
So what you get is the direction you move to.
If you stop - nothing happens. If you turn the device - nothing happens.
But for the use in a car it works pretty perfect - as long as you are aware what it is - a thing which shows you your driving direction.
I did this compass without the use of RadGauge - just because the main work is the desing.
And than there is an element you rotate.
For this by the way I took the RadGauge compass example and changed the animation code a bit.
BUT - and thats clear - you can also use the compass example from silverlight.
The only thing to mention - GPS gives you the driving direction.
If you want this up (like holding a real compass straight in front of you) you have to subtract the given value from 360 to get a rotation value.
The reason - you get the driving direction - and want the needle to point to north.
And - just to keep you using RadGauge - I also implemented a speedometer.
And for this (of course) I used RadChart.
It gives me current speed, Max Speed, Min Speed and Average Speed - all on one instrument.
Manfred
PS: I attached a screenshot of a test application showing the Compass and the Tacho (RadGauge)
By the way - the orange range is Average speed, the green dot min and the red one max
I already implemented a GPS compass.
The "problem" - it's a GPS related thing.
So what you get is the direction you move to.
If you stop - nothing happens. If you turn the device - nothing happens.
But for the use in a car it works pretty perfect - as long as you are aware what it is - a thing which shows you your driving direction.
I did this compass without the use of RadGauge - just because the main work is the desing.
And than there is an element you rotate.
For this by the way I took the RadGauge compass example and changed the animation code a bit.
BUT - and thats clear - you can also use the compass example from silverlight.
The only thing to mention - GPS gives you the driving direction.
If you want this up (like holding a real compass straight in front of you) you have to subtract the given value from 360 to get a rotation value.
The reason - you get the driving direction - and want the needle to point to north.
And - just to keep you using RadGauge - I also implemented a speedometer.
And for this (of course) I used RadChart.
It gives me current speed, Max Speed, Min Speed and Average Speed - all on one instrument.
Manfred
PS: I attached a screenshot of a test application showing the Compass and the Tacho (RadGauge)
By the way - the orange range is Average speed, the green dot min and the red one max
0
Hello ManniAT,
Victor
the Telerik team
It is great that you figured out how to create a compass. Also thank you for sharing your knowledge. It appears that the Mango update for Windows Phone 7 will have a compass API so implementing a compass should be even easier.
All the best,Victor
the Telerik team
Let us know about your Windows Phone 7 application built with RadControls and we will help you promote it. Learn more>>
0
ManniAT
Top achievements
Rank 2
answered on 06 Jun 2011, 07:45 AM
Hi Victor,
yes Manog will have a compass - if your device has one :)
And the API should also work on "old devices". I'm not sure how it will work in this case.
But anyhow - I'm sure I can use my existing compass with it.
I made a user control with a "Course" property. So if the new API arrives I'll simply bind it to a value provided by the "compass-api" instead of binding it to the GPS course.
Maybe I've to avoid the -360 thing for this.
By the way - I wrote above that I had to change your (teleriks) code I took from the SL compass sample.
The code is there to provide "short way rotation" or in other words, it takes care about situations when your new position is on the other side. So without that code a change from 340 to 20 would turn the compass counterclockwise - "the long way".
Your code checks this situation and divides the rotation animation in two - one from 340 to 360 followed by a second one from 0 to 20.
The problem with the existing code - it simply divides the animation time by two.
So it looks a bit bad when you have animations where the distance difers a lot.
For an example you go from 200 to 20.
It takes the same time from 200 to 360 as it takes from 0 to 20.
I implemented a simple algorithm wich takes care about this.
Here is the code for it:
Maybe this gives you an idea how a compass can be made using RadGauge and WP7 location services.
Manfred
yes Manog will have a compass - if your device has one :)
And the API should also work on "old devices". I'm not sure how it will work in this case.
But anyhow - I'm sure I can use my existing compass with it.
I made a user control with a "Course" property. So if the new API arrives I'll simply bind it to a value provided by the "compass-api" instead of binding it to the GPS course.
Maybe I've to avoid the -360 thing for this.
By the way - I wrote above that I had to change your (teleriks) code I took from the SL compass sample.
The code is there to provide "short way rotation" or in other words, it takes care about situations when your new position is on the other side. So without that code a change from 340 to 20 would turn the compass counterclockwise - "the long way".
Your code checks this situation and divides the rotation animation in two - one from 340 to 360 followed by a second one from 0 to 20.
The problem with the existing code - it simply divides the animation time by two.
So it looks a bit bad when you have animations where the distance difers a lot.
For an example you go from 200 to 20.
It takes the same time from 200 to 360 as it takes from 0 to 20.
I implemented a simple algorithm wich takes care about this.
Here is the code for it:
public
partial
class
GPSCompass : UserControl {
private
BackEase bE;
private
double
m_dSecondFromValue;
private
double
m_dSecondToValue;
public
GPSCompass() {
InitializeComponent();
bE =
new
BackEase();
bE.EasingMode = EasingMode.EaseOut;
bE.Amplitude = 0.6;
}
#region Course handling
public
double
Course {
get
{
return
(
double
)GetValue(CourseProperty); }
set
{ SetValue(CourseProperty, value); }
}
public
static
readonly
DependencyProperty CourseProperty =
DependencyProperty.Register(
"Course"
,
typeof
(
double
),
typeof
(GPSCompass),
new
PropertyMetadata(0.0,
new
PropertyChangedCallback(OnCourseChanged)));
private
static
void
OnCourseChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) {
GPSCompass control = (GPSCompass)obj;
//handle "driving direction always to"
double
dOldValue = 0;
try
{
dOldValue = 360.0 - (
double
)args.OldValue;
}
catch
{
dOldValue = 0;
}
double
dNewValue = 0;
try
{
dNewValue = 360.0 - (
double
)args.NewValue;
}
catch
{
dNewValue = 0;
}
control.SetNewValueToIndicator(dNewValue, dOldValue);
control._TextBoxHeading.Text = ((
double
)args.NewValue).ToString(
"F0"
);
}
#endregion
private
void
SetNewValueToIndicator(
double
newValue,
double
oldValue) {
CreateAndRunAnimation(oldValue, newValue);
}
private
Storyboard CreateAnimation(
double
fromValue,
double
toValue, Duration duration) {
// Create DoubleAnimations and set their properties.
DoubleAnimation daRotationAnimation =
new
DoubleAnimation();
daRotationAnimation.Duration = duration;
Storyboard storyboard =
new
Storyboard();
storyboard.Children.Add(daRotationAnimation);
Storyboard.SetTarget(daRotationAnimation, _HeadingPointer);
if
(duration.TimeSpan.Milliseconds % 10 == 0) {
//ease only on final animation
daRotationAnimation.EasingFunction = bE;
}
Storyboard.SetTargetProperty(daRotationAnimation,
new
PropertyPath(
"(UIElement.RenderTransform).(CompositeTransform.Rotation)"
));
daRotationAnimation.From = (
double
.IsNaN(fromValue) ? 0 : fromValue);
daRotationAnimation.To = toValue;
return
storyboard;
}
private
void
CreateAndRunAnimation(
double
fromValue,
double
toValue) {
double
dFirstDistance=0;
double
dSecondDistance = 0;
Duration duration;
double
distance = Math.Abs(toValue - fromValue);
if
(distance > 180) {
if
(toValue > 180) {
m_dSecondFromValue = 360;
m_dSecondToValue = toValue;
toValue = 0;
dFirstDistance = fromValue;
dSecondDistance = 360 - m_dSecondToValue;
}
else
if
(fromValue > 180) {
m_dSecondFromValue = 0;
m_dSecondToValue = toValue;
toValue = 360;
dFirstDistance = 360 - fromValue;
dSecondDistance = m_dSecondToValue;
}
}
else
{
dFirstDistance = distance;
}
duration =
new
Duration(TimeSpan.FromMilliseconds(CalcDuration(dFirstDistance, dSecondDistance)));
Storyboard storyboard__1 = CreateAnimation(fromValue, toValue, duration);
storyboard__1.Completed += onCompleted;
storyboard__1.Begin();
}
private
int
CalcDuration(
double
dFirstDistance ,
double
dSecondDistance ) {
int
nRet = 100;
double
dPart1 = 0;
double
dPart2 = 0;
dPart1 = Math.Round(dFirstDistance / 180, 2);
if
(dSecondDistance != 0) {
dPart2 = Math.Round(dSecondDistance / 180, 1);
if
(dPart2 < 0.1) {
dPart2 = 0.1;
}
if
(dPart1 < 0.1) {
dPart1 = 0.1;
}
if
((dPart1 + dPart2) < 0.5) {
while
((dPart1 + dPart2) < 0.5) {
dPart1 += 0.1;
dPart2 += 0.1;
}
}
else
if
(dPart2 > 0.8) {
//a bit shorter if double animation
dPart2 = 0.8;
}
if
(dPart1 > 0.8) {
//a bit shorter if double animation
dPart1 = 0.8;
}
}
else
if
(dPart1 < 0.5) {
dPart1 = 0.5;
}
else
if
(dPart1 > 0.9) {
dPart1 = 0.9;
}
nRet = ((
int
)(dPart1 * 1000.0));
nRet += ((
int
)(dPart2 * 10.0));
return
(nRet);
}
private
void
onCompleted(
object
sender, EventArgs e) {
double
dNewTime = 0;
Storyboard stB = sender
as
Storyboard;
if
(stB !=
null
) {
DoubleAnimation dA = stB.Children[0]
as
DoubleAnimation;
if
(dA !=
null
) {
int
nMilli = dA.Duration.TimeSpan.Milliseconds;
int
nSecondSpan = nMilli % 10;
if
(nSecondSpan > 0) {
//animation has two parts?
dNewTime = nSecondSpan;
dNewTime /= 10;
}
}
}
if
(dNewTime>0) {
//second part needed?
Duration duration =
new
Duration(TimeSpan.FromSeconds(dNewTime));
Storyboard storyboard = CreateAnimation(m_dSecondFromValue, m_dSecondToValue, duration);
storyboard.Begin();
}
}
}
Maybe this gives you an idea how a compass can be made using RadGauge and WP7 location services.
Manfred