I am trying to get the azimuth of the users phone when they take a picture. However, when I put the azimuth to the screen just for debugging purposes currently, it always comes back at 0.0. I am new to using Sensors so I am trying to figure this out. My code is
private void dispatchTakePictureIntent() {
double latitude, longitude;
if (mGpsLocationTracker.canGetLocation()) {
latitude = mGpsLocationTracker.getLatitude();
longitude = mGpsLocationTracker.getLongitude();
} else {
latitude = 0;
longitude = 0;
}
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
Toast.makeText(this, "" + latitude + ", " + longitude, Toast.LENGTH_SHORT).show();
getDirection ();
Toast.makeText(this, Float.toString(degree), Toast.LENGTH_SHORT).show();
}
public void getDirection() {
SensorManager mySensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
List<Sensor> mySensors = mySensorManager.getSensorList(Sensor.TYPE_ORIENTATION);
if(mySensors.size() > 0){
mySensorManager.registerListener(mySensorEventListener, mySensors.get(0), SensorManager.SENSOR_DELAY_UI);
}
}
/*
DOES NOT WORK. NEED TO FIX
*/
private SensorEventListener mySensorEventListener = new SensorEventListener(){
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
float radianValue = Math.round(event.values[0]);
degree = (float) Math.toDegrees(radianValue);
if (degree < 0.0f) {
degree += 360.0f;
}
}
};
public void takePicture (View view) {
dispatchTakePictureIntent();
}
Can anyone help me with what I'm doing wrong
Doesn't the orientation sensor return the angle in degrees? You're assuming radians and converting to degrees. Given that though, it still should't give you 0.
TYPE_ORIENTATION is depreciated and does not give the correct result
if the device is not flat. You need to use TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD to obtain the rotation matrix and then call remapCoordinateSystem before calling getOrientation.
Related
StreetViewPanoramaFragment streetViewFragment = (StreetViewPanoramaFragment) getFragmentManager().findFragmentById(R.id.g_map_street);
streetViewFragment.getStreetViewPanoramaAsync(this);
#Override
public void onStreetViewPanoramaReady(StreetViewPanorama streetViewPanorama) {
streetView = streetViewPanorama;
streetViewPanorama.setPosition(new LatLng(Latitude, Longtitude));
}
I have a value of Heading which returns angle.
https://maps.googleapis.com/maps/api/streetview?size=800x800&location=%s,%s&heading=%s
Using it , I can get Streetview Image properly but not working in StreetViewPanoramaFragment.
Finally , after lots of R&D I found this solution.. and its works for me.
#Override
public void onStreetViewPanoramaReady(StreetViewPanorama streetViewPanorama) {
streetViewPanorama.setPosition(new LatLng(Latitude, Longtitude));
try {
//Change angle of street view
final int DURATION = 1000;
StreetViewPanoramaCamera camera = new StreetViewPanoramaCamera.Builder()
.zoom(streetViewPanorama.getPanoramaCamera().zoom)
.tilt(streetViewPanorama.getPanoramaCamera().tilt)
.bearing(streetViewPanorama.getPanoramaCamera().bearing + angle) // angle value by Maps Api
.build();
streetViewPanorama.animateTo(camera, DURATION);
} catch (Exception e) {
e.printStackTrace();
}
}
I need to get head movements and according to that head turns (rotations). I need to do some work there. This is in case of inserting device in google cardboard.
I have searched the internet but I found no proper information. Please help me out here.
Thanks in advance.
Use Sensor class for this as shown below..
SensorEventListener mSensorListener = new SensorEventListener() {
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
#Override
public void onSensorChanged(SensorEvent event) {
Sensor sensor = event.sensor;
if (sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if (event.values != null && event.values.length > 1) {
accelDataOld = rawAccelData;
rawAccelData = event.values[1];
tweenStep = (rawAccelData - accelData) / TWEEN_TIMING;
}
} else if (sensor.getType() == Sensor.TYPE_GYROSCOPE) {
if (event.values != null && event.values.length > 1) {
rawGyroData += event.values[0];
}
}
}
};
I am trying to control a RC car using accelerometer via my own android studio app.
I managed to get the app to work through buttons by calling functions when a button is pressed.
I am trying to do the same with accelerometer by saying id the valus of x is less then this do this and call the function. but I cant connect to bluetooth the second i include my go foward function or andy functions to send the bluetooth command inside the if statement.
If connection is not success "Connection Failed. Is it a SPP Bluetooth? Try again". I keep getting this message
This is the part of the accelerometer code i have if statements.
#Override
public void onSensorChanged(SensorEvent event) {
// clean current values
displayCleanValues();
// display the current x,y,z accelerometer values
displayCurrentValues();
// display the max x,y,z accelerometer values
displayMaxValues();
// get the change of the x,y,z values of the accelerometer
deltaX =(lastX - event.values[0]);
deltaY = (lastY - event.values[1]);
deltaZ = (lastZ - event.values[2]);
// if the change is below 2, it is just plain noise
if (deltaX < 2)
DownArrow.setVisibility(View.VISIBLE);
else
DownArrow.setVisibility(View.INVISIBLE);
if ((deltaZ > vibrateThreshold) || (deltaY > vibrateThreshold) || (deltaZ > vibrateThreshold)) {
v.vibrate(50);
}
if (deltaX > -4) {
UpArrow.setVisibility(View.VISIBLE);
goForward();
}
if (deltaX < -4)
UpArrow.setVisibility(View.INVISIBLE);
if (deltaX < -7)
DownArrow.setVisibility(View.VISIBLE);
goBackward();
if (deltaX > -7)
DownArrow.setVisibility(View.INVISIBLE);
}
This is the functions I call which sends the bluetooth command.
private void goForward()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("F".toString().getBytes());
}
catch (IOException e)
{
msg("Error");
}
}
}
private void goBackward()
{
if (btSocket!=null)
{
try
{
btSocket.getOutputStream().write("B".toString().getBytes());
}
catch (IOException e)
{
msg("Error");
}
}
}
This is the Bluetooth code
#Override
protected void onPostExecute(Void result) //after the doInBackground, it checks if everything went fine
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
msg("Connection Failed. Is it a SPP Bluetooth? Try again.");
finish();
}
else
{
msg("Connected.");
isBtConnected = true;
}
progress.dismiss();
}
I am doing the same in my button view and it works fine.
btnUp.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
btnUp.setBackgroundResource(R.drawable.button_arrow_green_up_select);
goForward();
return true;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
btnUp.setBackgroundResource(R.drawable.button_arrow_green_up);
Stop();
}
return false;
}
});
Why it keeps failing?
I did a project for fun, Turn on led when any one shake the android mobile. I used arduino and HC-05 in order to communicate android with LED. I think the problem is you are sending "F" and "8" values through bluetooth in UI thread. so create other thread for sending values through bluetooth.
I am sharing part of my code, I think this would be use full.
mmOutputstream=socket.getOutputStream();
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
mGravity = event.values.clone();
// Shake detection
float x = mGravity[0];
float y = mGravity[1];
float z = mGravity[2];
int check=0;
mAccelLast = mAccelCurrent;
mAccelCurrent = FloatMath.sqrt(x*x + y*y + z*z);
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta;
Log.d("TAG",data);
// Make this higher or lower according to how much
// motion you want to detect
if(connection){
if(mAccel<-2.0f)
{
check=10;
}
if(mAccel>-2.4f){
check=0;
}
new arduinosend().execute(check);
}
}
}
class arduinosend extends AsyncTask<Integer, Integer, String>
{
#Override
protected String doInBackground(Integer... params) {
// TODO Auto-generated method stub
try {
mmOutputstream.write(params[0]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
I have implemented a snippet code to calculate the Tesla value of the magnetic field. I have tested it recently and I noticed when I am in the bus the value is 24 but when I am outside the value is about 45. I mean the bus is metal so the value should be higher inside of it. Is there any explanation for this strange behaviour?
I appreciate any help.
Code:
public class MainActivity extends ActionBarActivity implements
SensorEventListener {
String telsaString;
private TextView magneticX;
private TextView magneticY;
private TextView magneticZ;
private TextView magneticT;
private SensorManager sensorManager = null;
private long lastUpdate = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
// Capture magnetic sensor related view elements
magneticX = (TextView) findViewById(R.id.valMag_X);
magneticY = (TextView) findViewById(R.id.valMag_Y);
magneticZ = (TextView) findViewById(R.id.valMag_Z);
magneticT = (TextView) findViewById(R.id.valMag_T);
// Register magnetic sensor
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
// Unregister the listener
sensorManager.unregisterListener(this);
super.onPause();
}
#Override
protected void onStop() {
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
#Override
protected void onResume() {
super.onResume();
// Register magnetic sensor
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent sensorEvent) {
synchronized (this) {
float magX = sensorEvent.values[0];
float magY = sensorEvent.values[1];
float magZ = sensorEvent.values[2];
magneticX.setText(Float.toString(sensorEvent.values[0]));
magneticY.setText(Float.toString(sensorEvent.values[1]));
magneticZ.setText(Float.toString(sensorEvent.values[2]));
int teslaXYZ = (int)(Math.sqrt((magX * magX) + (magY * magY)
+ (magZ * magZ)));
String str = String.valueOf(teslaXYZ);
magneticT.setText(str);
long curTime = System.currentTimeMillis();
if ((curTime - lastUpdate) > 15000) {
lastUpdate = curTime;
try {
JSONObject tesla = new JSONObject();
tesla.put("tesla", teslaXYZ);
//tesla.put("tesla", teslaXYZ);
telsaString = tesla.toString();
new MyAsyncTask().execute(telsaString);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
A vehicle like a bus will contain many metal parts, some of which will be magnetized and have their own magnetic fields. The magnetometer of your device will pick up the superposition of the geomagnetic field and these additional fields and will show bad directions and absolute values compared to when you're standing away from the vehicle.
The engine and electric infrastructure of the car can also cause interference (While testing, I noticed a clear difference in magnetometer readings when starting the engine of my car).
I want to get the orientation of my phone and I have using this code that I find lot of people using it. this is the code
public void onSensorChanged(SensorEvent event) {
//if the data sensor is unreliabel
if(event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
return;
//gets the value
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
gravity = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
geomag = event.values.clone();
break;
}
getOrientation();
}
private void getOrientation(){
//if gravity n geomag have value, find the rotation matrix
if(gravity != null && geomag != null){
//check the rotation matrix found
boolean success = SensorManager.getRotationMatrix(inR, I, gravity, geomag);
if(success){
SensorManager.getOrientation(inR, orientVals);
azimuth = Math.toDegrees(orientVals[0]);
TextView azi = (TextView) findViewById(R.id.textAzi);
azi.setText("azi : " + azimuth);
}
TextView cek = (TextView) findViewById(R.id.cek);
cek.setText("rotation: "+success);
}
but why the getrotationmatrix always return to false?
where is the problem?
I've try again and get the solution
but I change the code to become like below
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
for(int i=0; i<3; i++){
accelValues[i] = event.values[i];
}
if(compassValues[0] != 0)
ready = true;
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for(int i=0; i<3; i++){
compassValues[i] = event.values[i];
}
if(accelValues[2] != 0)
ready = true;
break;
}
if(!ready)
return;
boolean cek = SensorManager.getRotationMatrix(inR, inclineMatrix, accelValues, compassValues);
if(cek){
SensorManager.getOrientation(inR, prefValues);
mInclination = SensorManager.getInclination(inclineMatrix);
//display every 30th values
if(counter++ % 30 == 0){
//do your code, what you want to do to the result
counter = 1;
}
}
and everything work well
Make sure that you have registered your listeners to listen to the accelerometer, magmetic field and gyro (optional). You do this in the onResume method. If you forget to do this you will get "false" return value when calling getRotationMatrix.
I hope this helps!
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
// do more staff here..
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(
this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL );
mSensorManager.registerListener(
this,
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL );
mSensorManager.registerListener(
this,
mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
SensorManager.SENSOR_DELAY_NORMAL );
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
The problem is with this part of code:
if(event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
return;
For accelerometer event.accuracy return SensorManager.SENSOR_STATUS_UNRELIABLE that is why gravity is always null.