⑴ android如何實現陀螺儀 sensor 在 android 嗎
設備中的三自由度Orientation
Sensor就是一個可以識別設備相對於地面,繞x、y、z軸轉動角度的感應器(自己的理解,不夠嚴謹)。智能手機,平板電腦有了它,可以實現很多好玩的應用,比如說指南針等。
我們可以用一個磁場感應器(magnetic sensor)來實現。
磁場感應器是用來測量磁場感應強度的。一個3軸的磁sensor
IC可以得到當前環境下X、Y和Z方向上的磁場感應強度,對於Android中間層來說就是讀取該感應器測量到的這3個值。當需要時,上報給上層應用程序。磁感應強度的單位是T(特斯拉)或者是Gs(高斯),1T等於10000Gs。
先來看看android定義的坐標系,在/hardware/libhardware/include/hardware/sensors.h中有個圖。
圖中表示設備的正上方是y軸方向,右邊是x軸方向,垂直設備屏幕平面向上的是Z軸方向,這個很重要。因為應用程序就是根據這樣的定義來寫的,所以我們報給應用的數據要跟這個定義符合。還需要清楚磁sensor晶元貼在板上的坐標系。我們從晶元讀出數據後要把晶元的坐標系轉換為設備的實際坐標系。除非晶元貼在板上剛好跟設備的x、y、z軸方向剛好一致(去感謝你的硬體工程師吧)。
Orientation Sensor的實現是根據磁場感應強度的3個值計算出另外3個值。當需要時,我們計算出這3個值上報給應用程序,Orientation
Sensor的功能就實現了。
⑵ android如何實現陀螺儀 sensor 在 android 嗎
千鋒扣丁學堂Android開發為您解答:
sensors.h中還定義了其他各種sensor。要實現的就是這兩個:
#define SENSOR_TYPE_MAGNETIC_FIELD 2
#define SENSOR_TYPE_ORIENTATION 3
在/hardware/sensors/sensors.cpp 中添加對MAGNETIC_FIELD和ORIENTATION 的支持
[cpp] view plain
//加入需要的宏定義
#define ID_BASE SENSORS_HANDLE_BASE
#define ID_ACCELERATION (ID_BASE+0)
#define ID_MAGNETIC_FIELD (ID_BASE+1)
#define ID_ORIENTATION (ID_BASE+2)
#define S_HANDLE_ACCELEROMETER (1<<ID_ACCELERATION)
#define S_HANDLE_MAGNETIC_FIELD (1<<ID_MAGNETIC_FIELD)
#define S_HANDLE_ORIENTATION (1<<ID_ORIENTATION)
#define SENSORS_NUM 4
#define SUPPORTED_SENSORS ((1<<NUM_SENSORS)-1)
//在 sensor_t sensors_list[] 中添加兩個sensor的信息,
//這些只是一些Sensor的信息,應用程序可以獲取到。
#ifdef MAGNETIC_FIELD
{
name : "XXX 3-axis Magnetic field sensor",
vendor : "XXX company",
version : 1,
handle : S_HANDLE_MAGNETIC_FIELD,
type : SENSOR_TYPE_MAGNETIC_FIELD,
maxRange : 600.0f,//最大范圍
resolution : 30.0f,//最小解析度
power : 6.7f,//這個不太懂
},
#endif
#ifdef ORIENTATION
{
name: "XXX Orientation sensor",
vendor: "XXX company",
version: 1,
handle: S_HANDLE_ORIENTATION,
type: SENSOR_TYPE_ORIENTATION,
maxRange: 360,
resolution: 0.1,
power: 20,
},
#endif
//定義一個結構來保存orientation的信息
static struct orientation{
float azimuth;
float pitch;
float roll;
}orientation;
//在 control__open_data_source()函數中打開設備
static native_handle_t*
control__open_data_source(struct sensors_control_device_t *dev)
{
SensorControl* ctl = (void*)dev;
native_handle_t* handle;
int fd_m = open (MAGNETIC_DATA_DEVICE, O_RDONLY);
LOGD ("Open Magnetic Data source: %d, %d/n", fd_m, errno);
if (fd_m>= 0)
{
dev->fd[ID_MAGNETIC_FIELD] = p(fd_m);
}
return handle;
}
//實現數據的打開和關閉函數
static int
data__data_open(struct sensors_data_device_t *dev, native_handle_t* handle)
{
struct sensors_data_context_t *dev;
dev = (struct sensors_data_context_t *)device;
for(int i=0 ;i<SENSORS_NUM; i++)
{
dev->fd[i] = p(handle->data[i]);
}
native_handle_close(handle);
native_handle_delete(handle);
return 0;
}
static int
data__data_close(struct sensors_data_device_t *dev)
{
struct sensors_data_context_t *dev;
dev = (struct sensors_data_context_t *)device;
for(int i=0 ;i<SENSORS_NUM; i++)
{
if (dev->fd[i] >= 0)
{
close(dev->fd[i]);
}
dev->fd[i] = -1;
}
return 0;
}
//最關鍵的poll函數
static int
data__poll(struct sensors_data_device_t *dev, sensors_data_t* values)
{
SensorData* data = (void*)dev;
int fd = data->events_fd;
//判斷設備是否打開
if(dev->fd[ID_MAGNETIC_FIELD] < 0)
{
LOGD("In %s dev[%d] is not open!/n",__FUNCTION__ ,ID_MAGNETIC_FIELD);
return -1;
}
pollfd pfd[SENSORS_NUM] =
{
//省略其他sensor代碼
{
fd: dev->fd[ID_MAGNETIC_FIELD],
events: POLLIN,
revents: 0
},
//省略其他sensor代碼
};
int err = poll (pfd, SENSORS_NUM, s_timeout);
unsigned int mask = SUPPORTED_SENSORS;
static unsigned int poll_flag=0;
if(poll_flag==0)
{
poll_flag = mask;
}
//省略其他sensor
if(poll_flag&(1<<ID_MAGNETIC_FIELD))
{
if((pfd[ID_MAGNETIC_FIELD].revents&POLLIN) == POLLIN)
{
char rawData[6];
err = read (dev->fd[ID_MAGNETIC_FIELD], &rawData, sizeof(rawData));
if(err<0)
{
LOGE("read magnetic field ret:%d errno:%d/n", err, errno);
return err;
}
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
data->time = timespec_to_ns(&t);
data->sensor = SENSOR_TYPE_MAGNETIC_FIELD;
data->magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
//上報的數據單位要轉換成 uTesla
data->magnetic.x = ( (rawData[1] << 8 ) | rawData[0])/ MAGNETIC_CONVERT;
data->magnetic.y = ( (rawData[3] << 8 ) | rawData[2])/ MAGNETIC_CONVERT;
data->magnetic.z = ( (rawData[5] << 8 ) | rawData[4])/ MAGNETIC_CONVERT;
//把陀螺儀需要的數據計算出來,用atan2(),頭文件要加上#include <math.h>
float azimuth = atan2( (float)(data->magnetic.x ),(float)(data->magnetic.y) );
if(azimuth<0)
{
azimuth = 360 - fabs(azimuth*180/PI);
}
else
{
azimuth = azimuth*180/PI;
}
orientation.azimuth = 360-azimuth;
//rotation around the X axis.+180~-180 degree
orientation.pitch = atan2( (float)(data->magnetic.y ),(float)(data->magnetic.z)
)*180/PI;
//rotation around the Y axis +90~-90 degree
float roll = atan2( (float)(data->magnetic.x ),(float)(data->magnetic.z) )
*180/PI;
if (roll > 90)
{
roll = -(180.0-roll);
}
else if (roll < -90)
{
roll = 180 + roll;
}
orientation.roll = roll;
}
return S_HANDLE_MAGNETIC_FIELD;
}
if(poll_flag&(1<<ID_MAGNETIC_FIELD))
{
//數據已經計算好了直接上報就行
struct timespec t;
clock_gettime(CLOCK_REALTIME, &t);
data->time = timespec_to_ns(&t);
data->sensor = SENSOR_TYPE_ORIENTATION;
data->orientation.azimuth = orientation.azimuth;
data->orientation.pitch = orientation.pitch;
data->orientation.roll = orientation.roll;
poll_flag &= ~(1<<ID_ORIENTATION);
return S_HANDLE_ORIENTATION;
}
}
⑶ android 非上層程序怎麼調用sensor
Android上層應用apk到G-sensor driver的大致流程: Android HAL層,即硬體抽象層,是Google響應廠家「希望不公開源碼」的要求推出的新概念 1,源代碼和目標位置 源代碼: /hardware/libhardware目錄,該目錄的目錄結構如下: /hardware/libhardware/hardware.c編譯成libhardware.so,目標位置為/system/lib目錄 /hardware/libhardware/include/hardware目錄下包含如下頭文件: hardware.h 通用硬體模塊頭文件 bit.h bit模塊頭文件 gralloc.h gralloc模塊頭文件 qemud.h qemud模塊頭文件 sensors.h 感測器模塊頭文件 /hardware/libhardware/moles目錄下定義了很多硬體模塊 這些硬體模塊都編譯成xxx.xxx.so,目標位置為/system/lib/hw目錄 2,Android對於Sensor的API定義在 hardware/libhardware/include/hardware/sensor.h中,要求在sensor.so提供以下8個API函數 [控制方面] int (*open_data_source)(struct sensors_control_device_t *dev); int (*activate)(struct sensors_control_device_t *dev, int handle, int enabled); int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms); int (*wake)(struct sensors_control_device_t *dev); [數據方面] int (*data_open)(struct sensors_data_device_t *dev, int fd); int (*data_close)(struct sensors_data_device_t *dev); int (*poll)(struct sensors_data_device_t *dev, sensors_data_t* data); [模塊方面] int (*get_sensors_list)(struct sensors_mole_t* mole, struct sensor_t const** list); 在java層Sensor的狀態控制由SensorService來負責,它的java代碼和JNI代碼分別位於: frameworks/base/services/java/com/Android/server/SensorService.java frameworks/base/services/jni/com_Android_server_SensorService.cpp 在Java層Sensor的數據控制由SensorManager來負責,它的java代碼和JNI代碼分別位於: frameworks/base/core/java/Android/hardware/SensorManager.java frameworks/base/core/jni/Android_hardware_SensorManager.cpp Android framework中與sensor通信的是sensorService.java和sensorManager.java。 sensorService.java的具體通信是通過JNI調用sensorService.cpp中的方法實現的。 sensorManager.java的具體通信是通過JNI調用sensorManager.cpp中的方法實現的。 sensorService.cpp和sensorManger.cpp通過hardware.c與sensor.so通信。其中sensorService.cpp實現對sensor的狀態控制,sensorManger.cpp實現對sensor的數據控制。 sensor.so通過ioctl控制sensor driver的狀態,通過打開sensor driver對應的設備文件讀取G-sensor採集的數據。 Android SDK提供了4個類來於sensor通信,分別為 sensor,sensorEvent,sensorEventListener,sensorManager。其中 sensorEventListener用來在sensorManager中注冊需要監聽的sensor類型。 sensorManager.java提供registrater(),unregistrater()介面供sensorEventListener使用。 sensorManager.java不斷輪詢從sensor.so中取數據。取到數據後送給負責監聽此類型sensor的 sensorEventListener.java。sensorEventListener.java通過在sensorManager.java中注冊可以監聽特定類型的sensor傳來的數據。 系統啟動時執行systemProcess,會啟動sensorService.java,在sensorService.java的構造函數中調用JNI方法_sensor_control_init()。 sensorService.cpp中相應的方法Android_int()會被執行。該函數會調用hardware.c中的方法hw_get_mole()此函數又通過調用load()函數在system/lib/hw下查找sensor.so 查找時會根據harware.c中定義好的sensor.*.so的擴展名的順序查找,找到第一個匹配的時候即停止,並將該sensor.so中定義好的一個全局變數HAL_MODULE_INFO_SYM帶回。該變數包含的一個 重要信息是它的一個成員結構變數中包含的一個函數指針open,該指針所指函數會對一個device結構變數賦值,從而帶出sensorService.cpp和sensorManager.cpp與sensor通信所需要的全部信息。 device結構變數有兩種變體分別供sensorService.cpp和sensorManaer.cpp使用。其中主要是一些函數指針指向與sensor通信的函數。 sensorService.cpp和sensorManager.cpp在得到HAL_MODULE_INFO_SYM結構後都會調用 sensors.h的inline函數open()通過HAL_MODULE_INFO_SYM的open函數指針將所需的device信息取回。 系統在啟動activityManager.java時,它會啟動sensorManager.java,它也會調用hardware.c中的方法hw_get_mole()帶回HAL_MODULE_INFO_SYM。
⑷ android應用開發中的感測器SensorManager mSensorManager 抽象類定義疑惑
只是轉換類型,例子中,getSystemService(SENSOR_SERVICE)得到的對象已經實例化。