From 813d14339aa6c619b873534098ca229f1d9e4bf7 Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Mon, 21 Apr 2014 14:51:42 +0900 Subject: [PATCH 02/13] sensor-framework : Initial commit Sensor Framework on Tizen 3. There have been main features added. Architecture Design: - git repositories have been merged into platform/core/system/sensord - new event driven architecture(before:polling based architecture) - UNIX based sockets for IPC(before:VCONF) - Server tracks the information of the clients - data structure based STL, including map, multimap, list and more Plugin Design: - redefine interfaces related to sensor plugin(sensor_base, sensor_hal) - for every sensor type, only one common plugin is required - redesign architecture simply, removing redundent layers and data structures - sensor device information is expressed with XML - supports both physical and virtual sensor types Other Features: - support sensor hub - proprietary libraries moved to sensord-proprietary git - clean logs/enum types/structures - define interface related to sensor fusion - sensor fusion code to be added in the future Sensor Type: Accelerometer / Gyro / Geomagnetic / Proximity / Light Gravity / Linear Accelerometer / Orientation - they are not supported yet - they should be changed based on iio sub-system Contributed by: Jae Hyun Jo Hyun-sung Ramasamy Kannan Amit Vithalrao Dharmapurikar Kibak Yoon Signed-off-by: Kibak Yoon Change-Id: Ieb622be5db3cd2a0aeb4e5b442ba51dd785616ce --- CMakeLists.txt | 53 ++ LICENSE.APLv2 | 203 ++++++++ libsensord.manifest | 5 + packaging/sensord.service | 12 + packaging/sensord.socket | 10 + packaging/sensord.spec | 117 +++++ sensor_plugins.xml.in | 21 + sensor_plugins_sim.xml.in | 17 + sensord.manifest | 5 + sensors.xml.in | 229 +++++++++ src/CMakeLists.txt | 53 ++ src/accel/CMakeLists.txt | 52 ++ src/accel/accel_sensor.cpp | 420 +++++++++++++++ src/accel/accel_sensor.h | 72 +++ src/accel/accel_sensor_hal.cpp | 633 +++++++++++++++++++++++ src/accel/accel_sensor_hal.h | 78 +++ src/geo/CMakeLists.txt | 52 ++ src/geo/geo_sensor.cpp | 169 ++++++ src/geo/geo_sensor.h | 51 ++ src/geo/geo_sensor_hal.cpp | 504 ++++++++++++++++++ src/geo/geo_sensor_hal.h | 71 +++ src/gravity/CMakeLists.txt | 43 ++ src/gravity/gravity_sensor.cpp | 214 ++++++++ src/gravity/gravity_sensor.h | 62 +++ src/gyro/CMakeLists.txt | 52 ++ src/gyro/gyro_sensor.cpp | 183 +++++++ src/gyro/gyro_sensor.h | 52 ++ src/gyro/gyro_sensor_hal.cpp | 523 +++++++++++++++++++ src/gyro/gyro_sensor_hal.h | 70 +++ src/libsensord/CMakeLists.txt | 69 +++ src/libsensord/client.cpp | 807 +++++++++++++++++++++++++++++ src/libsensord/client_common.cpp | 276 ++++++++++ src/libsensord/client_common.h | 82 +++ src/libsensord/command_channel.cpp | 675 ++++++++++++++++++++++++ src/libsensord/command_channel.h | 64 +++ src/libsensord/creg_event_info.h | 46 ++ src/libsensord/csensor_event_listener.cpp | 818 ++++++++++++++++++++++++++++++ src/libsensord/csensor_event_listener.h | 180 +++++++ src/libsensord/csensor_handle_info.cpp | 153 ++++++ src/libsensord/csensor_handle_info.h | 65 +++ src/libsensord/poller.cpp | 104 ++++ src/libsensord/poller.h | 49 ++ src/libsensord/sensor.h | 218 ++++++++ src/libsensord/sensor.pc.in | 13 + src/libsensord/sensor_accel.h | 98 ++++ src/libsensord/sensor_context.h | 59 +++ src/libsensord/sensor_geomag.h | 65 +++ src/libsensord/sensor_gravity.h | 55 ++ src/libsensord/sensor_gyro.h | 61 +++ src/libsensord/sensor_light.h | 62 +++ src/libsensord/sensor_linear_accel.h | 55 ++ src/libsensord/sensor_motion.h | 141 +++++ src/libsensord/sensor_orientation.h | 56 ++ src/libsensord/sensor_proxi.h | 64 +++ src/light/CMakeLists.txt | 53 ++ src/light/light_sensor.cpp | 223 ++++++++ src/light/light_sensor.h | 55 ++ src/light/light_sensor_hal.cpp | 458 +++++++++++++++++ src/light/light_sensor_hal.h | 65 +++ src/linear_accel/CMakeLists.txt | 44 ++ src/linear_accel/linear_accel_sensor.cpp | 170 +++++++ src/linear_accel/linear_accel_sensor.h | 60 +++ src/proxi/CMakeLists.txt | 53 ++ src/proxi/proxi_sensor.cpp | 182 +++++++ src/proxi/proxi_sensor.h | 53 ++ src/proxi/proxi_sensor_hal.cpp | 396 +++++++++++++++ src/proxi/proxi_sensor_hal.h | 68 +++ src/sensor_fusion/CMakeLists.txt | 43 ++ src/sensor_fusion/lib_sensor_fusion.cpp | 183 +++++++ src/sensor_fusion/lib_sensor_fusion.h | 55 ++ src/server/CMakeLists.txt | 23 + src/server/command_worker.cpp | 592 +++++++++++++++++++++ src/server/command_worker.h | 83 +++ src/server/main.cpp | 66 +++ src/server/server.cpp | 127 +++++ src/server/server.h | 46 ++ src/shared/CMakeLists.txt | 99 ++++ src/shared/cbase_lock.cpp | 125 +++++ src/shared/cbase_lock.h | 78 +++ src/shared/cclient_info_manager.cpp | 373 ++++++++++++++ src/shared/cclient_info_manager.h | 80 +++ src/shared/cclient_sensor_record.cpp | 286 +++++++++++ src/shared/cclient_sensor_record.h | 76 +++ src/shared/cconfig.cpp | 275 ++++++++++ src/shared/cconfig.h | 119 +++++ src/shared/cinterval_info_list.cpp | 89 ++++ src/shared/cinterval_info_list.h | 58 +++ src/shared/cmutex.cpp | 60 +++ src/shared/cmutex.h | 42 ++ src/shared/common.cpp | 155 ++++++ src/shared/common.h | 226 +++++++++ src/shared/cpacket.cpp | 113 +++++ src/shared/cpacket.h | 59 +++ src/shared/crw_lock.cpp | 65 +++ src/shared/crw_lock.h | 45 ++ src/shared/csensor_event_dispatcher.cpp | 384 ++++++++++++++ src/shared/csensor_event_dispatcher.h | 83 +++ src/shared/csensor_event_queue.cpp | 66 +++ src/shared/csensor_event_queue.h | 61 +++ src/shared/csensor_usage.cpp | 75 +++ src/shared/csensor_usage.h | 47 ++ src/shared/csocket.cpp | 437 ++++++++++++++++ src/shared/csocket.h | 86 ++++ src/shared/physical_sensor.cpp | 57 +++ src/shared/physical_sensor.h | 47 ++ src/shared/sensor_base.cpp | 274 ++++++++++ src/shared/sensor_base.h | 112 ++++ src/shared/sensor_common.h | 203 ++++++++ src/shared/sensor_fusion.cpp | 98 ++++ src/shared/sensor_fusion.h | 53 ++ src/shared/sensor_hal.cpp | 62 +++ src/shared/sensor_hal.h | 67 +++ src/shared/sensor_plugin_loader.cpp | 326 ++++++++++++ src/shared/sensor_plugin_loader.h | 102 ++++ src/shared/sensord-server.pc.in | 13 + src/shared/sf_common.h | 162 ++++++ src/shared/sf_common.pc.in | 13 + src/shared/virtual_sensor.cpp | 44 ++ src/shared/virtual_sensor.h | 39 ++ src/shared/worker_thread.cpp | 224 ++++++++ src/shared/worker_thread.h | 85 ++++ 121 files changed, 17102 insertions(+) create mode 100755 CMakeLists.txt create mode 100644 LICENSE.APLv2 create mode 100644 libsensord.manifest create mode 100755 packaging/sensord.service create mode 100644 packaging/sensord.socket create mode 100755 packaging/sensord.spec create mode 100755 sensor_plugins.xml.in create mode 100755 sensor_plugins_sim.xml.in create mode 100755 sensord.manifest create mode 100755 sensors.xml.in create mode 100755 src/CMakeLists.txt create mode 100755 src/accel/CMakeLists.txt create mode 100755 src/accel/accel_sensor.cpp create mode 100755 src/accel/accel_sensor.h create mode 100755 src/accel/accel_sensor_hal.cpp create mode 100755 src/accel/accel_sensor_hal.h create mode 100755 src/geo/CMakeLists.txt create mode 100755 src/geo/geo_sensor.cpp create mode 100755 src/geo/geo_sensor.h create mode 100755 src/geo/geo_sensor_hal.cpp create mode 100755 src/geo/geo_sensor_hal.h create mode 100755 src/gravity/CMakeLists.txt create mode 100755 src/gravity/gravity_sensor.cpp create mode 100755 src/gravity/gravity_sensor.h create mode 100755 src/gyro/CMakeLists.txt create mode 100755 src/gyro/gyro_sensor.cpp create mode 100755 src/gyro/gyro_sensor.h create mode 100755 src/gyro/gyro_sensor_hal.cpp create mode 100755 src/gyro/gyro_sensor_hal.h create mode 100755 src/libsensord/CMakeLists.txt create mode 100755 src/libsensord/client.cpp create mode 100755 src/libsensord/client_common.cpp create mode 100755 src/libsensord/client_common.h create mode 100755 src/libsensord/command_channel.cpp create mode 100755 src/libsensord/command_channel.h create mode 100755 src/libsensord/creg_event_info.h create mode 100755 src/libsensord/csensor_event_listener.cpp create mode 100755 src/libsensord/csensor_event_listener.h create mode 100755 src/libsensord/csensor_handle_info.cpp create mode 100755 src/libsensord/csensor_handle_info.h create mode 100755 src/libsensord/poller.cpp create mode 100755 src/libsensord/poller.h create mode 100755 src/libsensord/sensor.h create mode 100755 src/libsensord/sensor.pc.in create mode 100755 src/libsensord/sensor_accel.h create mode 100755 src/libsensord/sensor_context.h create mode 100755 src/libsensord/sensor_geomag.h create mode 100755 src/libsensord/sensor_gravity.h create mode 100755 src/libsensord/sensor_gyro.h create mode 100755 src/libsensord/sensor_light.h create mode 100755 src/libsensord/sensor_linear_accel.h create mode 100755 src/libsensord/sensor_motion.h create mode 100755 src/libsensord/sensor_orientation.h create mode 100755 src/libsensord/sensor_proxi.h create mode 100755 src/light/CMakeLists.txt create mode 100755 src/light/light_sensor.cpp create mode 100755 src/light/light_sensor.h create mode 100755 src/light/light_sensor_hal.cpp create mode 100755 src/light/light_sensor_hal.h create mode 100755 src/linear_accel/CMakeLists.txt create mode 100755 src/linear_accel/linear_accel_sensor.cpp create mode 100755 src/linear_accel/linear_accel_sensor.h create mode 100755 src/proxi/CMakeLists.txt create mode 100755 src/proxi/proxi_sensor.cpp create mode 100755 src/proxi/proxi_sensor.h create mode 100755 src/proxi/proxi_sensor_hal.cpp create mode 100755 src/proxi/proxi_sensor_hal.h create mode 100755 src/sensor_fusion/CMakeLists.txt create mode 100755 src/sensor_fusion/lib_sensor_fusion.cpp create mode 100755 src/sensor_fusion/lib_sensor_fusion.h create mode 100755 src/server/CMakeLists.txt create mode 100755 src/server/command_worker.cpp create mode 100755 src/server/command_worker.h create mode 100755 src/server/main.cpp create mode 100755 src/server/server.cpp create mode 100755 src/server/server.h create mode 100755 src/shared/CMakeLists.txt create mode 100755 src/shared/cbase_lock.cpp create mode 100755 src/shared/cbase_lock.h create mode 100755 src/shared/cclient_info_manager.cpp create mode 100755 src/shared/cclient_info_manager.h create mode 100755 src/shared/cclient_sensor_record.cpp create mode 100755 src/shared/cclient_sensor_record.h create mode 100755 src/shared/cconfig.cpp create mode 100755 src/shared/cconfig.h create mode 100755 src/shared/cinterval_info_list.cpp create mode 100755 src/shared/cinterval_info_list.h create mode 100755 src/shared/cmutex.cpp create mode 100755 src/shared/cmutex.h create mode 100755 src/shared/common.cpp create mode 100755 src/shared/common.h create mode 100755 src/shared/cpacket.cpp create mode 100755 src/shared/cpacket.h create mode 100755 src/shared/crw_lock.cpp create mode 100755 src/shared/crw_lock.h create mode 100755 src/shared/csensor_event_dispatcher.cpp create mode 100755 src/shared/csensor_event_dispatcher.h create mode 100755 src/shared/csensor_event_queue.cpp create mode 100755 src/shared/csensor_event_queue.h create mode 100755 src/shared/csensor_usage.cpp create mode 100755 src/shared/csensor_usage.h create mode 100755 src/shared/csocket.cpp create mode 100755 src/shared/csocket.h create mode 100755 src/shared/physical_sensor.cpp create mode 100755 src/shared/physical_sensor.h create mode 100755 src/shared/sensor_base.cpp create mode 100755 src/shared/sensor_base.h create mode 100755 src/shared/sensor_common.h create mode 100755 src/shared/sensor_fusion.cpp create mode 100755 src/shared/sensor_fusion.h create mode 100755 src/shared/sensor_hal.cpp create mode 100755 src/shared/sensor_hal.h create mode 100755 src/shared/sensor_plugin_loader.cpp create mode 100755 src/shared/sensor_plugin_loader.h create mode 100755 src/shared/sensord-server.pc.in create mode 100755 src/shared/sf_common.h create mode 100755 src/shared/sf_common.pc.in create mode 100755 src/shared/virtual_sensor.cpp create mode 100755 src/shared/virtual_sensor.h create mode 100755 src/shared/worker_thread.cpp create mode 100755 src/shared/worker_thread.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..fbcfe9a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 2.6) +project(sensord_main CXX) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED glib-2.0 gio-2.0 vconf dlog libxml-2.0 libsystemd-daemon capi-system-info) +add_definitions(${rpkgs_CFLAGS}) + +# to install pkgconfig setup file. +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "2") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + +add_definitions(-Wall -O3 -omit-frame-pointer) +add_definitions(-DUSE_DLOG_LOG) +#add_definitions(-Wall -g -D_DEBUG) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +IF("${ARCH}" MATCHES "^arm.*") + CONFIGURE_FILE(sensor_plugins.xml.in sensor_plugins.xml @ONLY) + CONFIGURE_FILE(sensors.xml.in sensors.xml @ONLY) + install(FILES + sensor_plugins.xml + sensors.xml + DESTINATION etc) +ELSE("${ARCH}" MATCHES "^arm.*") + CONFIGURE_FILE(sensor_plugins_sim.xml.in sensor_plugins.xml @ONLY) + CONFIGURE_FILE(sensors.xml.in sensors.xml @ONLY) + install(FILES + sensor_plugins.xml + sensors.xml + DESTINATION etc) +ENDIF("${ARCH}" MATCHES "^arm.*") + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.APLv2 DESTINATION share/license RENAME sensord) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.APLv2 DESTINATION share/license RENAME libsensord) + +add_subdirectory(src) diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..91cbe82 --- /dev/null +++ b/LICENSE.APLv2 @@ -0,0 +1,203 @@ +Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/libsensord.manifest b/libsensord.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/libsensord.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/sensord.service b/packaging/sensord.service new file mode 100755 index 0000000..d3ab961 --- /dev/null +++ b/packaging/sensord.service @@ -0,0 +1,12 @@ +[Unit] +Description=Sensor Daemon + +[Service] +Type=notify +ExecStart=/usr/bin/sensord +Restart=always +RestartSec=0 +MemoryLimit=10M + +[Install] +WantedBy=multi-user.target diff --git a/packaging/sensord.socket b/packaging/sensord.socket new file mode 100644 index 0000000..5357ca5 --- /dev/null +++ b/packaging/sensord.socket @@ -0,0 +1,10 @@ +[Unit] +Description=Sensor daemon socket + +[Socket] +ListenStream=/tmp/sf_command_socket +SocketMode=0777 +PassCredentials=yes +Accept=false +SmackLabelIPIn=* +SmackLabelIPOut=@ diff --git a/packaging/sensord.spec b/packaging/sensord.spec new file mode 100755 index 0000000..f5fb9fa --- /dev/null +++ b/packaging/sensord.spec @@ -0,0 +1,117 @@ +Name: sensord +Summary: Sensor daemon +Version: 1.0.0 +Release: 0 +Group: System/Sensor Framework +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1: sensord.service +Source2: sensord.socket + +%define accel_state ON +%define gyro_state OFF +%define proxi_state OFF +%define light_state OFF +%define geo_state OFF +%define gravity_state OFF +%define linear_accel_state OFF +%define motion_state OFF + +BuildRequires: cmake +BuildRequires: vconf-keys-devel +BuildRequires: libattr-devel +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(libxml-2.0) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(libsystemd-daemon) +BuildRequires: pkgconfig(capi-system-info) + +%description +Sensor daemon + +%package sensord +Summary: Sensor daemon +Group: System/Sensor Framework +Requires: %{name} = %{version}-%{release} + +%description sensord +Sensor daemon + +%package -n libsensord +Summary: Sensord library +Group: System/Sensor Framework +Requires: %{name} = %{version}-%{release} + +%description -n libsensord +Sensord library + +%package -n libsensord-devel +Summary: Sensord library (devel) +Group: System/Sensor Framework +Requires: %{name} = %{version}-%{release} + +%description -n libsensord-devel +Sensord library (devel) + +%prep +%setup -q + +%build +#CFLAGS+=" -fvisibility=hidden "; export CFLAGS +#CXXFLAGS+=" -fvisibility=hidden -fvisibility-inlines-hidden ";export CXXFLAGS +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DACCEL=%{accel_state} \ + -DGYRO=%{gyro_state} -DPROXI=%{proxi_state} -DLIGHT=%{light_state} \ + -DGEO=%{geo_state} -DGRAVITY=%{gravity_state} \ + -DLINEAR_ACCEL=%{linear_accel_state} -DMOTION=%{motion_state} + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}/usr/share/license +mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants +mkdir -p %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants +install -m 0644 %SOURCE1 %{buildroot}%{_libdir}/systemd/system/ +install -m 0644 %SOURCE2 %{buildroot}%{_libdir}/systemd/system/ +ln -s ../sensord.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/sensord.socket +ln -s ../sensord.service %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants/sensord.service + +%post -p /sbin/ldconfig +systemctl daemon-reload + +%postun -p /sbin/ldconfig +systemctl daemon-reload + +%files -n sensord +%manifest sensord.manifest +%{_bindir}/sensord +%attr(0644,root,root)/usr/etc/sensor_plugins.xml +%attr(0644,root,root)/usr/etc/sensors.xml +%{_libdir}/systemd/system/sensord.service +%{_libdir}/systemd/system/sensord.socket +%{_libdir}/systemd/system/multi-user.target.wants/sensord.service +%{_libdir}/systemd/system/sockets.target.wants/sensord.socket +%license LICENSE.APLv2 +%{_datadir}/license/sensord + +%files -n libsensord +%manifest libsensord.manifest +%defattr(-,root,root,-) +%{_libdir}/libsensor.so.* +%{_libdir}/sensord/*.so* +%{_libdir}/libsensord-share.so +%{_libdir}/libsensord-server.so +%license LICENSE.APLv2 +%{_datadir}/license/libsensord + +%files -n libsensord-devel +%defattr(-,root,root,-) +%{_includedir}/sensor/*.h +%{_includedir}/sf_common/*.h +%{_libdir}/libsensor.so +%{_libdir}/pkgconfig/sensor.pc +%{_libdir}/pkgconfig/sf_common.pc +%{_libdir}/pkgconfig/sensord-server.pc diff --git a/sensor_plugins.xml.in b/sensor_plugins.xml.in new file mode 100755 index 0000000..2e844ff --- /dev/null +++ b/sensor_plugins.xml.in @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/sensor_plugins_sim.xml.in b/sensor_plugins_sim.xml.in new file mode 100755 index 0000000..8f7b40b --- /dev/null +++ b/sensor_plugins_sim.xml.in @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/sensord.manifest b/sensord.manifest new file mode 100755 index 0000000..75b0fa5 --- /dev/null +++ b/sensord.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/sensors.xml.in b/sensors.xml.in new file mode 100755 index 0000000..b4dfa74 --- /dev/null +++ b/sensors.xml.in @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100755 index 0000000..f2872e1 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 2.6) +project(sensord_src CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +include_directories(${CMAKE_SOURCE_DIR}/src/shared) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED glib-2.0 gio-2.0 vconf) +add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE) +add_definitions(-Wall -std=gnu++0x) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + +IF("${ACCEL}" STREQUAL "ON") +add_subdirectory(accel) +ENDIF() +IF("${GYRO}" STREQUAL "ON") +add_subdirectory(gyro) +ENDIF() +IF("${PROXI}" STREQUAL "ON") +add_subdirectory(proxi) +ENDIF() +IF("${LIGHT}" STREQUAL "ON") +add_subdirectory(light) +ENDIF() +IF("${GEO}" STREQUAL "ON") +add_subdirectory(geo) +ENDIF() +IF("${GRAVITY}" STREQUAL "ON") +add_subdirectory(gravity) +ENDIF() +IF("${LINEAR_ACCEL}" STREQUAL "ON") +add_subdirectory(linear_accel) +ENDIF() +IF("${MOTION}" STREQUAL "ON") +add_subdirectory(motion) +ENDIF() +IF("${SENSOR_FUSION}" STREQUAL "ON") +add_subdirectory(sensor_fusion) +ENDIF() + +add_subdirectory(server) +add_subdirectory(libsensord) +add_subdirectory(shared) diff --git a/src/accel/CMakeLists.txt b/src/accel/CMakeLists.txt new file mode 100755 index 0000000..b4dcd9a --- /dev/null +++ b/src/accel/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 2.6) +project(accel CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +SET(SENSOR_NAME accel_sensor) +SET(SENSOR_HAL_NAME accel_sensor_hal) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) +add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET -DHWREV_CHECK") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-DUSE_DLOG_LOG) +add_definitions(-Iinclude) + +add_library(${SENSOR_NAME} SHARED + accel_sensor.cpp + ) + +add_library(${SENSOR_HAL_NAME} SHARED + accel_sensor_hal.cpp + ) + +target_link_libraries(${SENSOR_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") +target_link_libraries(${SENSOR_HAL_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS}) + +install(TARGETS ${SENSOR_NAME} DESTINATION lib/sensord) +install(TARGETS ${SENSOR_HAL_NAME} DESTINATION lib/sensord) diff --git a/src/accel/accel_sensor.cpp b/src/accel/accel_sensor.cpp new file mode 100755 index 0000000..21d256d --- /dev/null +++ b/src/accel/accel_sensor.cpp @@ -0,0 +1,420 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using std::bind1st; +using std::mem_fun; + +#define GRAVITY 9.80665 +#define G_TO_MG 1000 + +#define RAW_DATA_TO_G_UNIT(X) (((float)(X))/((float)G_TO_MG)) +#define RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(X) (GRAVITY * (RAW_DATA_TO_G_UNIT(X))) + +#define SENSOR_NAME "ACCELEROMETER_SENSOR" + +#define ROTATION_CHECK_INTERVAL 200 +#define ROTATION_RULE_CNT 4 +#define TILT_MIN 30 + +#define ROTATION_0 0 +#define ROTATION_90 90 +#define ROTATION_180 180 +#define ROTATION_270 270 +#define ROTATION_360 360 + +#define DEGREE_90 90 +#define DEGREE_180 180 +#define DEGREE_360 360 + +struct rotation_rule { + int tilt; + int angle; +}; + +struct rotation_rule rot_rule[ROTATION_RULE_CNT] = { + {40, 80}, + {50, 70}, + {60, 65}, + {90, 60}, +}; + +accel_sensor::accel_sensor() +: m_sensor_hal(NULL) +, m_interval(POLL_1HZ_MS) +{ + m_name = string(SENSOR_NAME); + + vector supported_events = { + ACCELEROMETER_EVENT_ROTATION_CHECK, + ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME, + ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME, + }; + + for_each(supported_events.begin(), supported_events.end(), + bind1st(mem_fun(&sensor_base::register_supported_event), this)); + + physical_sensor::set_poller(accel_sensor::working, this); +} + +accel_sensor::~accel_sensor() +{ + INFO("accel_sensor is destroyed!"); +} + +bool accel_sensor::init() +{ + m_sensor_hal = sensor_plugin_loader::get_instance().get_sensor_hal(ACCELEROMETER_SENSOR); + + if (!m_sensor_hal) { + ERR("cannot load sensor_hal[%s]", sensor_base::get_name()); + return false; + } + + sensor_properties_t properties; + + if (m_sensor_hal->get_properties(properties) == false) { + ERR("sensor->get_properties() is failed!"); + return false; + } + + m_raw_data_unit = properties.sensor_resolution / GRAVITY * G_TO_MG; + + INFO("m_raw_data_unit accel : [%f]", m_raw_data_unit); + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +sensor_type_t accel_sensor::get_type(void) +{ + return ACCELEROMETER_SENSOR; +} + +bool accel_sensor::working(void *inst) +{ + accel_sensor *sensor = (accel_sensor *)inst; + return sensor->process_event(); +} + +bool accel_sensor::process_event(void) +{ + sensor_data_t raw_data; + + if (!m_sensor_hal->is_data_ready(true)) + return true; + + m_sensor_hal->get_sensor_data(raw_data); + + AUTOLOCK(m_mutex); + AUTOLOCK(m_client_info_mutex); + + if (get_client_cnt(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME)) { + sensor_event_t base_event; + + copy_sensor_data(&raw_data, &(base_event.data)); + + base_event.event_type = ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME; + raw_to_base(base_event.data); + push(base_event); + } + + if (get_client_cnt(ACCELEROMETER_EVENT_ROTATION_CHECK)) { + if (is_rotation_time()) { + sensor_data_t base_data; + float x, y, z; + int rotation; + + copy_sensor_data(&raw_data, &base_data); + raw_to_base(base_data); + + x = base_data.values[0]; + y = base_data.values[1]; + z = base_data.values[2]; + + rotation = get_rotation_event(x, y, z); + + if (rotation != -1) { + AUTOLOCK(m_value_mutex); + + sensor_event_t rotation_event; + rotation_event.event_type = ACCELEROMETER_EVENT_ROTATION_CHECK; + rotation_event.data.timestamp = raw_data.timestamp; + rotation_event.data.values_num = 1; + rotation_event.data.values[0] = rotation; + push(rotation_event); + + INFO("Rotation event occurred, rotation value = %d", rotation); + } + } + } + + if (get_client_cnt(ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME)) { + sensor_event_t orientation_event; + + copy_sensor_data(&raw_data, &(orientation_event.data)); + + orientation_event.event_type = ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME; + raw_to_orientation(raw_data, orientation_event.data); + push(orientation_event); + } + + return true; +} + +bool accel_sensor::on_start(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->enable()) { + ERR("m_sensor_hal start fail"); + return false; + } + + reset_rotation(); + + return start_poll(); +} + +bool accel_sensor::on_stop(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->disable()) { + ERR("m_sensor_hal stop fail"); + return false; + } + + return stop_poll(); +} + +bool accel_sensor::add_client(unsigned int event_type) +{ + AUTOLOCK(m_mutex); + + if (!sensor_base::add_client(event_type)) + return false; + + switch (event_type) { + case ACCELEROMETER_EVENT_ROTATION_CHECK: + if (get_client_cnt(ACCELEROMETER_EVENT_ROTATION_CHECK) == 1) + reset_rotation(); + break; + default: + break; + } + + return true; +} + +long accel_sensor::set_command(const unsigned int cmd, long value) +{ + if (m_sensor_hal->set_command(cmd, value) < 0) { + ERR("m_sensor_hal set_cmd fail"); + return -1; + } + + return 0; +} + +bool accel_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + return m_sensor_hal->get_properties(properties); +} + +int accel_sensor::get_sensor_data(const unsigned int type, sensor_data_t &data) +{ + if (type == ACCELEROMETER_ROTATION_DATA_SET) { + AUTOLOCK(m_value_mutex); + + data.data_accuracy = SENSOR_ACCURACY_NORMAL; + data.data_unit_idx = SENSOR_UNDEFINED_UNIT; + data.values_num = 1; + data.values[0] = m_rotation; + data.timestamp = m_rotation_time; + return 0; + } + + if (m_sensor_hal->get_sensor_data(data) < 0) { + ERR("Failed to get sensor data"); + return -1; + } + + if (type == ACCELEROMETER_BASE_DATA_SET) + raw_to_base(data); + else if (type == ACCELEROMETER_ORIENTATION_DATA_SET) { + sensor_data_t raw; + + copy_sensor_data(&data, &raw); + raw_to_orientation(raw, data); + } else { + ERR("Does not support type: 0x%x", type); + return -1; + } + + return 0; +} + +int accel_sensor::get_rotation_event(float x, float y, float z) +{ + int cur_rotation = ROTATION_UNKNOWN; + + double atan_value; + int acc_theta, acc_pitch; + double realg; + bool is_stable = false; + bool rotation_on = false; + int tilt, angle; + int i; + + atan_value = atan2(x, y); + acc_theta = (int)(atan_value * (RADIAN_VALUE) + DEGREE_360) % DEGREE_360; + realg = (double)sqrt((x * x) + (y * y) + (z * z)); + acc_pitch = ROTATION_90 - abs((int) (asin(z / realg) * RADIAN_VALUE)); + + for (i = 0; i < ROTATION_RULE_CNT; ++i) { + tilt = rot_rule[i].tilt; + + if ((acc_pitch >= TILT_MIN) && (acc_pitch <= tilt)) { + if ((m_rotation == ROTATION_EVENT_0) || (m_rotation == ROTATION_EVENT_180)) + angle = rot_rule[i].angle; + else + angle = ROTATION_90 - rot_rule[i].angle; + + if ((acc_theta >= ROTATION_360 - angle && acc_theta <= ROTATION_360 - 1) || + (acc_theta >= ROTATION_0 && acc_theta <= ROTATION_0 + angle)) { + cur_rotation = ROTATION_EVENT_0; + } else if (acc_theta >= ROTATION_0 + angle && acc_theta <= ROTATION_180 - angle) { + cur_rotation = ROTATION_EVENT_90; + } else if (acc_theta >= ROTATION_180 - angle && acc_theta <= ROTATION_180 + angle) { + cur_rotation = ROTATION_EVENT_180; + } else if (acc_theta >= ROTATION_180 + angle && acc_theta <= ROTATION_360 - angle) { + cur_rotation = ROTATION_EVENT_270; + } + break; + } + } + + m_windowing[m_curr_window_count++] = cur_rotation; + + if (m_curr_window_count == MAX_WINDOW_NUM) + m_curr_window_count = 0; + + for (i = 0; i < MAX_WINDOW_NUM ; i++) { + if (m_windowing[i] == cur_rotation) + is_stable = true; + else { + is_stable = false; + break; + } + } + + rotation_on = (m_rotation != cur_rotation); + + if (rotation_on && is_stable) { + m_rotation = cur_rotation; + m_rotation_time = get_timestamp(); + return m_rotation; + } + + return -1; +} + +void accel_sensor::reset_rotation(void) +{ + int i; + + for (i = 0 ; i < MAX_WINDOW_NUM ; i++) + m_windowing[i] = 0; + + m_curr_window_count = 0; + m_rotation = ROTATION_UNKNOWN; + m_rotation_time = 0; + m_rotation_check_remained_time = ROTATION_CHECK_INTERVAL; +} + +bool accel_sensor::is_rotation_time(void) +{ + AUTOLOCK(m_mutex); + m_rotation_check_remained_time -= m_interval; + + if (m_rotation_check_remained_time <= 0) { + m_rotation_check_remained_time = ROTATION_CHECK_INTERVAL; + return true; + } + + return false; +} + +bool accel_sensor::set_interval(unsigned long interval) +{ + AUTOLOCK(m_mutex); + + m_interval = interval; + INFO("Polling interval is set to %dms", interval); + return m_sensor_hal->set_interval(interval); +} + +void accel_sensor::raw_to_base(sensor_data_t &data) +{ + data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; + data.values_num = 3; + data.values[0] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data.values[0] * m_raw_data_unit); + data.values[1] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data.values[1] * m_raw_data_unit); + data.values[2] = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(data.values[2] * m_raw_data_unit); +} + +void accel_sensor::raw_to_orientation(sensor_data_t &raw, sensor_data_t &orientation) +{ + orientation.timestamp = raw.time_stamp; + orientation.data_accuracy = raw.data_accuracy; + orientation.data_unit_idx = SENSOR_UNIT_DEGREE; + orientation.values_num = 3; + orientation.values[0] = fmodf((atan2(raw.values[0], raw.values[1]) * RADIAN_VALUE + DEGREE_360), DEGREE_360); + orientation.values[1] = fmodf((atan2(raw.values[1], raw.values[2]) * RADIAN_VALUE), DEGREE_180); + orientation.values[2] = fmodf((atan2(raw.values[0], raw.values[2]) * RADIAN_VALUE), DEGREE_180); + + if (orientation.values[2] > DEGREE_90) + orientation.values[2] = DEGREE_180 - orientation.values[2]; + else if (orientation.values[2] < -DEGREE_90) + orientation.values[2] = -DEGREE_180 - orientation.values[2]; +} + +extern "C" void *create(void) +{ + accel_sensor *inst; + + try { + inst = new accel_sensor(); + } catch (int err) { + ERR("Failed to create accel_sensor class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (accel_sensor *)inst; +} diff --git a/src/accel/accel_sensor.h b/src/accel/accel_sensor.h new file mode 100755 index 0000000..dedf8c2 --- /dev/null +++ b/src/accel/accel_sensor.h @@ -0,0 +1,72 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _ACCEL_SENSOR_H_ +#define _ACCEL_SENSOR_H_ + +#include +#include +#include + +class accel_sensor : public physical_sensor +{ +public: + accel_sensor(); + virtual ~accel_sensor(); + + virtual bool init(); + virtual sensor_type_t get_type(void); + + static bool working(void *inst); + + virtual bool on_start(void); + virtual bool on_stop(void); + + bool add_client(unsigned int event_type); + + virtual bool set_interval(unsigned long interval); + virtual long set_command(const unsigned int cmd, long value); + virtual bool get_properties(const unsigned int type, sensor_properties_t &properties); + int get_sensor_data(const unsigned int type, sensor_data_t &data); +private: + sensor_hal *m_sensor_hal; + cmutex m_value_mutex; + + float m_raw_data_unit; + + int m_rotation; + unsigned long long m_rotation_time; + unsigned long m_interval; + int m_curr_window_count; + + static const int RADIAN_VALUE = 57.29747; + static const int MAX_WINDOW_NUM = 2; + long m_windowing[MAX_WINDOW_NUM]; + + int m_rotation_check_remained_time; + + int get_rotation_event(float x, float y, float z); + void reset_rotation(void); + bool is_rotation_time(void); + + void raw_to_base(sensor_data_t &data); + void raw_to_orientation(sensor_data_t &raw, sensor_data_t &orientation); + bool process_event(void); +}; +#endif /*_ACCEL_SENSOR_H_*/ diff --git a/src/accel/accel_sensor_hal.cpp b/src/accel/accel_sensor_hal.cpp new file mode 100755 index 0000000..04032ce --- /dev/null +++ b/src/accel/accel_sensor_hal.cpp @@ -0,0 +1,633 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::ifstream; +using config::CConfig; + +#define NODE_NAME "name" +#define NODE_INPUT "input" +#define NODE_ENABLE "enable" +#define NODE_POLL_DELAY "poll_delay" +#define NODE_ACCEL_POLL_DELAY "accel_poll_delay" +#define SENSOR_NODE "/sys/class/sensors/" +#define SENSORHUB_NODE "/sys/class/sensors/ssp_sensor/" +#define INPUT_DEVICE_NODE "/sys/class/input/" +#define DEV_INPUT_NODE "/dev/input/event/" +#define CALIBRATION_NODE "/sys/class/sensors/accelerometer_sensor/calibration" +#define CALIBRATION_FILE "/csa/sensor/accel_cal_data" +#define CALIBRATION_DIR "/csa/sensor" + +#define INITIAL_VALUE -1 +#define INITIAL_TIME 0 +#define GRAVITY 9.80665 +#define G_TO_MG 1000 +#define RAW_DATA_TO_G_UNIT(X) (((float)(X))/((float)G_TO_MG)) +#define RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(X) (GRAVITY * (RAW_DATA_TO_G_UNIT(X))) + +#define MIN_RANGE(RES) (-((2 << (RES))/2)) +#define MAX_RANGE(RES) (((2 << (RES))/2)-1) + +#define SENSOR_TYPE_ACCEL "ACCEL" +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" +#define ELEMENT_RESOLUTION "RESOLUTION" +#define ATTR_VALUE "value" + +#define INPUT_NAME "accelerometer_sensor" + +accel_sensor_hal::accel_sensor_hal() +: m_x(INITIAL_VALUE) +, m_y(INITIAL_VALUE) +, m_z(INITIAL_VALUE) +, m_node_handle(INITIAL_VALUE) +, m_polling_interval(POLL_1HZ_MS) +, m_fired_time(INITIAL_TIME) +, m_sensorhub_supported(false) +{ + if (!check_hw_node()) { + ERR("check_hw_node() fail"); + throw ENXIO; + } + + CConfig &config = CConfig::get_instance(); + + if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_NAME, m_chip_name)) { + ERR("[NAME] is empty"); + throw ENXIO; + } + + INFO("m_chip_name = %s", m_chip_name.c_str()); + + long resolution; + + if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RESOLUTION, resolution)) { + ERR("[RESOLUTION] is empty"); + throw ENXIO; + } + + m_resolution = (int)resolution; + INFO("m_resolution = %d", m_resolution); + + double raw_data_unit; + + if (!config.get(SENSOR_TYPE_ACCEL, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) { + ERR("[RAW_DATA_UNIT] is empty"); + throw ENXIO; + } + + m_raw_data_unit = (float)(raw_data_unit); + INFO("m_raw_data_unit = %f", m_raw_data_unit); + + if ((m_node_handle = open(m_resource.c_str(), O_RDWR)) < 0) { + ERR("Failed to open handle(%d)", m_node_handle); + throw ENXIO; + } + + int clockId = CLOCK_MONOTONIC; + + if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) { + ERR("Fail to set monotonic timestamp for %s", m_resource.c_str()); + throw ENXIO; + } + + INFO("accel_sensor_hal is created!"); +} + +accel_sensor_hal::~accel_sensor_hal() +{ + close(m_node_handle); + m_node_handle = INITIAL_VALUE; + + INFO("accel_sensor_hal is destroyed!"); +} + +string accel_sensor_hal::get_model_id(void) +{ + return m_model_id; +} + +sensor_type_t accel_sensor_hal::get_type(void) +{ + return ACCELEROMETER_SENSOR; +} + +long accel_sensor_hal::set_command(const unsigned int cmd, long value) +{ + FILE *fp; + + AUTOLOCK(m_mutex); + + switch (cmd) { + case ACCELEROMETER_PROPERTY_SET_CALIBRATION : + if (calibration(CAL_SET)) { + INFO("acc_sensor_calibration OK"); + return 0; + } + + ERR("acc_sensor_calibration FAIL"); + return -1; + case ACCELEROMETER_PROPERTY_CHECK_CALIBRATION_STATUS : + if (calibration(CAL_CHECK)) { + INFO("acc_sensor_calibration check OK"); + return 0; + } + + ERR("acc_sensor_calibration check FAIL"); + return -1; + default: + ERR("Invalid property_cmd"); + break; + } + + return -1; +} + +bool accel_sensor_hal::enable_resource(string &resource_node, bool enable) +{ + int prev_status, status; + FILE *fp = NULL; + fp = fopen(resource_node.c_str(), "r"); + + if (!fp) { + ERR("Fail to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fscanf(fp, "%d", &prev_status) < 0) { + ERR("Failed to get data from %s", resource_node.c_str()); + fclose(fp); + return false; + } + + fclose(fp); + + if (enable) { + if (m_sensorhub_supported) + status = prev_status | (1 << SENSORHUB_ACCELEROMETER_ENABLE_BIT); + else + status = 1; + } else { + if (m_sensorhub_supported) + status = prev_status ^ (1 << SENSORHUB_ACCELEROMETER_ENABLE_BIT); + else + status = 0; + } + + fp = fopen(resource_node.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fprintf(fp, "%d", status) < 0) { + ERR("Failed to enable a resource file: %s", resource_node.c_str()); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + return true; +} + +bool accel_sensor_hal::enable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, true); + set_interval(m_polling_interval); + + m_fired_time = 0; + INFO("Accel sensor real starting"); + return true; +} + +bool accel_sensor_hal::disable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, false); + INFO("Accel sensor real stopping"); + return true; +} + +bool accel_sensor_hal::set_interval(unsigned long val) +{ + unsigned long long polling_interval_ns; + FILE *fp = NULL; + + AUTOLOCK(m_mutex); + + polling_interval_ns = ((unsigned long long)(val) * MS_TO_SEC * MS_TO_SEC); + fp = fopen(m_polling_resource.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", m_polling_resource.c_str()); + return false; + } + + if (fprintf(fp, "%llu", polling_interval_ns) < 0) { + ERR("Failed to set data %llu", polling_interval_ns); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + INFO("Interval is changed from %dms to %dms]", m_polling_interval, val); + m_polling_interval = val; + return true; +} + +bool accel_sensor_hal::update_value(bool wait) +{ + const int TIMEOUT = 1; + int accel_raw[3] = {0,}; + bool x, y, z; + int read_input_cnt = 0; + const int INPUT_MAX_BEFORE_SYN = 10; + unsigned long long fired_time = 0; + bool syn = false; + x = y = z = false; + + struct timeval tv; + fd_set readfds, exceptfds; + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + FD_SET(m_node_handle, &readfds); + FD_SET(m_node_handle, &exceptfds); + + if (wait) { + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + } else { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + + int ret; + ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, &tv); + + if (ret == -1) { + ERR("select error:%s m_node_handle:%d", strerror(errno), m_node_handle); + return false; + } else if (!ret) { + DBG("select timeout: %d seconds elapsed", tv.tv_sec); + return false; + } + + if (FD_ISSET(m_node_handle, &exceptfds)) { + ERR("select exception occurred!"); + return false; + } + + if (FD_ISSET(m_node_handle, &readfds)) { + struct input_event accel_input; + DBG("accel event detection!"); + + while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) { + int len = read(m_node_handle, &accel_input, sizeof(accel_input)); + + if (len != sizeof(accel_input)) { + ERR("accel_file read fail, read_len = %d", len); + return false; + } + + ++read_input_cnt; + + if (accel_input.type == EV_REL) { + switch (accel_input.code) { + case REL_X: + accel_raw[0] = (int)accel_input.value; + x = true; + break; + case REL_Y: + accel_raw[1] = (int)accel_input.value; + y = true; + break; + case REL_Z: + accel_raw[2] = (int)accel_input.value; + z = true; + break; + default: + ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code); + return false; + break; + } + } else if (accel_input.type == EV_SYN) { + syn = true; + fired_time = sensor_hal::get_timestamp(&accel_input.time); + } else { + ERR("accel_input event[type = %d, code = %d] is unknown.", accel_input.type, accel_input.code); + return false; + } + } + } else { + ERR("select nothing to read!!!"); + return false; + } + + if (syn == false) { + ERR("EV_SYN didn't come until %d inputs had come", read_input_cnt); + return false; + } + + AUTOLOCK(m_value_mutex); + + if (x) + m_x = accel_raw[0]; + + if (y) + m_y = accel_raw[1]; + + if (z) + m_z = accel_raw[2]; + + m_fired_time = fired_time; + DBG("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time); + return true; +} + +bool accel_sensor_hal::is_data_ready(bool wait) +{ + bool ret; + ret = update_value(wait); + return ret; +} + +int accel_sensor_hal::get_sensor_data(sensor_data_t &data) +{ + const int chance = 3; + int retry = 0; + + while ((m_fired_time == 0) && (retry++ < chance)) { + INFO("Try usleep for getting a valid BASE DATA value"); + usleep(m_polling_interval * MS_TO_SEC); + } + + if (m_fired_time == 0) { + ERR("get_sensor_data failed"); + return -1; + } + + data.data_accuracy = SENSOR_ACCURACY_GOOD; + data.data_unit_idx = SENSOR_UNIT_VENDOR_UNIT; + data.timestamp = m_fired_time ; + data.values_num = 3; + data.values[0] = m_x; + data.values[1] = m_y; + data.values[2] = m_z; + + return 0; +} + +bool accel_sensor_hal::get_properties(sensor_properties_t &properties) +{ + properties.sensor_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; + properties.sensor_min_range = MIN_RANGE(m_resolution) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit); + properties.sensor_max_range = MAX_RANGE(m_resolution) * RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit); + snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); + snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); + properties.sensor_resolution = RAW_DATA_TO_METRE_PER_SECOND_SQUARED_UNIT(m_raw_data_unit); + return true; +} + +bool accel_sensor_hal::calibration(int cmd) +{ + if (cmd == CAL_CHECK) { + struct calibration_data { + short x; + short y; + short z; + }; + struct calibration_data cal_data; + + if (access(CALIBRATION_FILE, F_OK) == 0) { + FILE *fp = NULL; + fp = fopen(CALIBRATION_FILE, "r"); + + if (!fp) { + ERR("cannot open calibration file"); + return false; + } + + size_t read_cnt; + read_cnt = fread(&cal_data, sizeof(cal_data), 1, fp); + + if (read_cnt != 1) { + ERR("cal_data read fail, read_cnt = %d", read_cnt); + fclose(fp); + return false; + } + + fclose(fp); + INFO("x = [%d] y = [%d] z = [%d]", cal_data.x, cal_data.y, cal_data.z); + + if (cal_data.x == 0 && cal_data.y == 0 && cal_data.z == 0) { + DBG("cal_data values is zero"); + return false; + } else + return true; + } else { + INFO("cannot access calibration file"); + return false; + } + } else if (cmd == CAL_SET) { + if (mkdir(CALIBRATION_DIR, 0755) != 0) + INFO("mkdir fail"); + + FILE *fp; + fp = fopen(CALIBRATION_NODE, "w"); + + if (!fp) { + ERR("Failed to open a calibration file"); + return false; + } + + if (fprintf(fp, "%d", cmd) < 0) { + ERR("Failed to set calibration"); + fclose(fp); + return false; + } + + fclose(fp); + return true; + } else if (cmd == CAL_MKDIR) { + if (mkdir(CALIBRATION_DIR, 0755) != 0) { + ERR("mkdir fail"); + return false; + } + + return true; + } + + ERR("Non supported calibration cmd = %d", cmd); + return false; +} + +bool accel_sensor_hal::is_sensorhub_supported(void) +{ + DIR *main_dir = NULL; + main_dir = opendir(SENSORHUB_NODE); + + if (!main_dir) { + INFO("Sensor Hub is not supported"); + return false; + } + + INFO("It supports sensor hub"); + closedir(main_dir); + return true; +} + +bool accel_sensor_hal::check_hw_node(void) +{ + string name_node; + string hw_name; + DIR *main_dir = NULL; + struct dirent *dir_entry = NULL; + bool find_node = false; + + INFO("======================start check_hw_node============================="); + + m_sensorhub_supported = is_sensorhub_supported(); + main_dir = opendir(SENSOR_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0)) { + name_node = string(SENSOR_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (CConfig::get_instance().is_supported(SENSOR_TYPE_ACCEL, hw_name) == true) { + m_name = m_model_id = hw_name; + INFO("m_model_id = %s", m_model_id.c_str()); + find_node = true; + calibration(CAL_MKDIR); + break; + } + } + } + + closedir(main_dir); + + if (find_node) { + main_dir = opendir(INPUT_DEVICE_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + find_node = false; + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if (strncasecmp(dir_entry->d_name, NODE_INPUT, 5) == 0) { + name_node = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (hw_name == string(INPUT_NAME)) { + INFO("name_node = %s", name_node.c_str()); + DBG("Find H/W for accel_sensor"); + + find_node = true; + string dir_name; + dir_name = string(dir_entry->d_name); + unsigned found = dir_name.find_first_not_of(NODE_INPUT); + m_resource = string(DEV_INPUT_NODE) + dir_name.substr(found); + + if (m_sensorhub_supported) { + m_enable_resource = string(SENSORHUB_NODE) + string(NODE_ENABLE); + m_polling_resource = string(SENSORHUB_NODE) + string(NODE_ACCEL_POLL_DELAY); + } else { + m_enable_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_ENABLE); + m_polling_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_POLL_DELAY); + } + + break; + } + } + } + + closedir(main_dir); + } + + if (find_node) { + INFO("m_resource = %s", m_resource.c_str()); + INFO("m_enable_resource = %s", m_enable_resource.c_str()); + INFO("m_polling_resource = %s", m_polling_resource.c_str()); + } + + return find_node; +} + +extern "C" void *create(void) +{ + accel_sensor_hal *inst; + + try { + inst = new accel_sensor_hal(); + } catch (int err) { + ERR("Failed to create accel_sensor_hal class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (accel_sensor_hal *)inst; +} diff --git a/src/accel/accel_sensor_hal.h b/src/accel/accel_sensor_hal.h new file mode 100755 index 0000000..25a6b3c --- /dev/null +++ b/src/accel/accel_sensor_hal.h @@ -0,0 +1,78 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _ACCEL_SENSOR_HAL_H_ +#define _ACCEL_SENSOR_HAL_H_ + +#include +#include + +using std::string; + +class accel_sensor_hal : public sensor_hal +{ + enum accel_cmd_cal_t { + CAL_CHECK = 0, + CAL_SET, + CAL_MKDIR, + }; + +public: + accel_sensor_hal(); + virtual ~accel_sensor_hal(); + string get_model_id(void); + sensor_type_t get_type(void); + bool enable(void); + bool disable(void); + bool set_interval(unsigned long val); + bool is_data_ready(bool wait); + virtual int get_sensor_data(sensor_data_t &data); + bool get_properties(sensor_properties_t &properties); + bool check_hw_node(void); + long set_command(const unsigned int cmd, long value); + +private: + int m_x; + int m_y; + int m_z; + int m_node_handle; + unsigned long m_polling_interval; + unsigned long long m_fired_time; + bool m_sensorhub_supported; + + string m_model_id; + string m_name; + string m_vendor; + string m_chip_name; + + int m_resolution; + float m_raw_data_unit; + + string m_resource; + string m_enable_resource; + string m_polling_resource; + + cmutex m_value_mutex; + + bool enable_resource(string &resource_node, bool enable); + bool update_value(bool wait); + bool calibration(int cmd); + bool is_sensorhub_supported(void); +}; +#endif /*_ACCEL_SENSOR_HAL_H_*/ diff --git a/src/geo/CMakeLists.txt b/src/geo/CMakeLists.txt new file mode 100755 index 0000000..4478781 --- /dev/null +++ b/src/geo/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 2.6) +project(geo CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +SET(SENSOR_NAME geo_sensor) +SET(SENSOR_HAL_NAME geo_sensor_hal) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) +add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET") + MESSAGE("add -DTARGET") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +add_definitions(-DUSE_DLOG_LOG) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-Iinclude) + +add_library(${SENSOR_NAME} SHARED + geo_sensor.cpp +) + +add_library(${SENSOR_HAL_NAME} SHARED + geo_sensor_hal.cpp +) + +target_link_libraries(${SENSOR_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") +target_link_libraries(${SENSOR_HAL_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS}) + +install(TARGETS ${SENSOR_NAME} DESTINATION lib/sensord) +install(TARGETS ${SENSOR_HAL_NAME} DESTINATION lib/sensord) diff --git a/src/geo/geo_sensor.cpp b/src/geo/geo_sensor.cpp new file mode 100755 index 0000000..6a80591 --- /dev/null +++ b/src/geo/geo_sensor.cpp @@ -0,0 +1,169 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#define SENSOR_NAME "GEOMAGNETIC_SENSOR" + +geo_sensor::geo_sensor() +: m_sensor_hal(NULL) +{ + m_name = string(SENSOR_NAME); + + register_supported_event(GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME); + register_supported_event(GEOMAGNETIC_EVENT_CALIBRATION_NEEDED); + + physical_sensor::set_poller(geo_sensor::working, this); +} + +geo_sensor::~geo_sensor() +{ + INFO("geo_sensor is destroyed!"); +} + +bool geo_sensor::init() +{ + m_sensor_hal = sensor_plugin_loader::get_instance().get_sensor_hal(GEOMAGNETIC_SENSOR); + + if (!m_sensor_hal) { + ERR("cannot load sensor_hal[%s]", sensor_base::get_name()); + return false; + } + + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +sensor_type_t geo_sensor::get_type(void) +{ + return GEOMAGNETIC_SENSOR; +} + +bool geo_sensor::working(void *inst) +{ + geo_sensor *sensor = (geo_sensor *)inst; + return sensor->process_event(); +} + +bool geo_sensor::process_event(void) +{ + sensor_event_t event; + + if (!m_sensor_hal->is_data_ready(true)) + return true; + + m_sensor_hal->get_sensor_data(event.data); + + AUTOLOCK(m_client_info_mutex); + AUTOLOCK(m_mutex); + + if (get_client_cnt(GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME)) { + event.event_type = GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME; + + push(event); + } + + return true; +} + +bool geo_sensor::on_start(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->enable()) { + ERR("m_sensor_hal start fail"); + return false; + } + + return start_poll(); +} + +bool geo_sensor::on_stop(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->disable()) { + ERR("m_sensor_hal stop fail"); + return false; + } + + return stop_poll(); +} + +long geo_sensor::set_command(const unsigned int cmd, long value) +{ + if (m_sensor_hal->set_command(cmd, value) < 0) { + ERR("m_sensor_hal set_cmd fail"); + return -1; + } + + return 0; +} + +bool geo_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + return m_sensor_hal->get_properties(properties); +} + +int geo_sensor::get_sensor_data(const unsigned int type, sensor_data_t &data) +{ + int state; + + if (type != GEOMAGNETIC_BASE_DATA_SET) + return -1; + + state = m_sensor_hal->get_sensor_data(data); + + if (state < 0) { + ERR("m_sensor_hal get struct_data fail"); + return -1; + } + + return 0; +} + +bool geo_sensor::set_interval(unsigned long interval) +{ + AUTOLOCK(m_mutex); + + INFO("Polling interval is set to %dms", interval); + return m_sensor_hal->set_interval(interval); +} + +extern "C" void *create(void) +{ + geo_sensor *inst; + + try { + inst = new geo_sensor(); + } catch (int err) { + ERR("Failed to create geo_sensor class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (geo_sensor *)inst; +} diff --git a/src/geo/geo_sensor.h b/src/geo/geo_sensor.h new file mode 100755 index 0000000..449a4d2 --- /dev/null +++ b/src/geo/geo_sensor.h @@ -0,0 +1,51 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _GEO_SENSOR_H_ +#define _GEO_SENSOR_H_ + +#include +#include +#include + +class geo_sensor : public physical_sensor +{ +public: + geo_sensor(); + virtual ~geo_sensor(); + + virtual bool init(); + virtual sensor_type_t get_type(void); + + static bool working(void *inst); + + virtual bool on_start(void); + virtual bool on_stop(void); + + virtual bool set_interval(unsigned long interval); + virtual long set_command(const unsigned int cmd, long value); + virtual bool get_properties(const unsigned int type, sensor_properties_t &properties); + int get_sensor_data(const unsigned int type, sensor_data_t &data); +private: + sensor_hal *m_sensor_hal; + cmutex m_mutex; + + bool process_event(void); +}; +#endif /*_GEO_SENSOR_H_*/ diff --git a/src/geo/geo_sensor_hal.cpp b/src/geo/geo_sensor_hal.cpp new file mode 100755 index 0000000..b1cadcf --- /dev/null +++ b/src/geo/geo_sensor_hal.cpp @@ -0,0 +1,504 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::ifstream; +using config::CConfig; + +#define NODE_NAME "name" +#define NODE_INPUT "input" +#define NODE_ENABLE "enable" +#define NODE_POLL_DELAY "poll_delay" +#define NODE_MAG_POLL_DELAY "mag_poll_delay" +#define SENSOR_NODE "/sys/class/sensors/" +#define SENSORHUB_NODE "/sys/class/sensors/ssp_sensor/" +#define INPUT_DEVICE_NODE "/sys/class/input/" +#define DEV_INPUT_NODE "/dev/input/event/" + +#define LBS_TO_UTESLA 0.06f + +#define SENSOR_TYPE_MAGNETIC "MAGNETIC" +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ATTR_VALUE "value" + +#define INPUT_NAME "geomagnetic_sensor" + +geo_sensor_hal::geo_sensor_hal() +: m_x(INITIAL_VALUE) +, m_y(INITIAL_VALUE) +, m_z(INITIAL_VALUE) +, m_node_handle(INITIAL_VALUE) +, m_polling_interval(POLL_1HZ_MS) +, m_fired_time(INITIAL_TIME) +, m_sensorhub_supported(false) +{ + if (!check_hw_node()) { + ERR("check_hw_node() fail"); + throw ENXIO; + } + + CConfig &config = CConfig::get_instance(); + + if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_MAGNETIC, m_model_id, ELEMENT_NAME, m_chip_name)) { + ERR("[NAME] is empty"); + throw ENXIO; + } + + INFO("m_chip_name = %s", m_chip_name.c_str()); + + if ((m_node_handle = open(m_resource.c_str(), O_RDWR)) < 0) { + ERR("Failed to open handle(%d)", m_node_handle); + throw ENXIO; + } + + int clockId = CLOCK_MONOTONIC; + + if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) { + ERR("Fail to set monotonic timestamp for %s", m_resource.c_str()); + throw ENXIO; + } + + INFO("geo_sensor_hal is created!"); +} + +geo_sensor_hal::~geo_sensor_hal() +{ + close(m_node_handle); + m_node_handle = INITIAL_VALUE; + + INFO("geo_sensor_hal is destroyed!"); +} + +string geo_sensor_hal::get_model_id(void) +{ + return m_model_id; +} + +sensor_type_t geo_sensor_hal::get_type(void) +{ + return GEOMAGNETIC_SENSOR; +} + +bool geo_sensor_hal::enable_resource(string &resource_node, bool enable) +{ + int prev_status, status; + FILE *fp = NULL; + fp = fopen(resource_node.c_str(), "r"); + + if (!fp) { + ERR("Fail to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fscanf(fp, "%d", &prev_status) < 0) { + ERR("Failed to get data from %s", resource_node.c_str()); + fclose(fp); + return false; + } + + fclose(fp); + + if (enable) { + if (m_sensorhub_supported) + status = prev_status | (1 << SENSORHUB_GEOMAGNETIC_ENABLE_BIT); + else + status = 1; + } else { + if (m_sensorhub_supported) + status = prev_status ^ (1 << SENSORHUB_GEOMAGNETIC_ENABLE_BIT); + else + status = 0; + } + + fp = fopen(resource_node.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fprintf(fp, "%d", status) < 0) { + ERR("Failed to enable a resource file: %s", resource_node.c_str()); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + return true; +} + +bool geo_sensor_hal::enable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, true); + set_interval(m_polling_interval); + + m_fired_time = 0; + INFO("Geo sensor real starting"); + return true; +} + +bool geo_sensor_hal::disable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, false); + INFO("Geo sensor real stopping"); + return true; +} + +bool geo_sensor_hal::set_interval(unsigned long val) +{ + unsigned long long polling_interval_ns; + FILE *fp = NULL; + + AUTOLOCK(m_mutex); + + polling_interval_ns = ((unsigned long long)(val) * MS_TO_SEC * MS_TO_SEC); + fp = fopen(m_polling_resource.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", m_polling_resource.c_str()); + return false; + } + + if (fprintf(fp, "%llu", polling_interval_ns) < 0) { + ERR("Failed to set data %llu", polling_interval_ns); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + INFO("Interval is changed from %dms to %dms]", m_polling_interval, val); + m_polling_interval = val; + return true; +} + +bool geo_sensor_hal::update_value(bool wait) +{ + const int TIMEOUT = 1; + int geo_raw[4] = {0,}; + bool x, y, z, hdst; + int read_input_cnt = 0; + const int INPUT_MAX_BEFORE_SYN = 10; + unsigned long long fired_time = 0; + bool syn = false; + x = y = z = hdst = false; + + struct timeval tv; + fd_set readfds, exceptfds; + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + FD_SET(m_node_handle, &readfds); + FD_SET(m_node_handle, &exceptfds); + + if (wait) { + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + } else { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + + int ret; + ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, &tv); + + if (ret == -1) { + ERR("select error:%s m_node_handle:%d", strerror(errno), m_node_handle); + return false; + } else if (!ret) { + DBG("select timeout: %d seconds elapsed", tv.tv_sec); + return false; + } + + if (FD_ISSET(m_node_handle, &exceptfds)) { + ERR("select exception occurred!"); + return false; + } + + if (FD_ISSET(m_node_handle, &readfds)) { + struct input_event geo_input; + DBG("geo event detection!"); + + while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) { + int len = read(m_node_handle, &geo_input, sizeof(geo_input)); + + if (len != sizeof(geo_input)) { + ERR("geo_file read fail, read_len = %d", len); + return false; + } + + ++read_input_cnt; + + if (geo_input.type == EV_REL) { + switch (geo_input.code) { + case REL_RX: + geo_raw[0] = (int)geo_input.value; + x = true; + break; + case REL_RY: + geo_raw[1] = (int)geo_input.value; + y = true; + break; + case REL_RZ: + geo_raw[2] = (int)geo_input.value; + z = true; + break; + case REL_HWHEEL: + geo_raw[3] = (int)geo_input.value; + hdst = true; + break; + default: + ERR("geo_input event[type = %d, code = %d] is unknown.", geo_input.type, geo_input.code); + return false; + break; + } + } else if (geo_input.type == EV_SYN) { + syn = true; + fired_time = get_timestamp(&geo_input.time); + } else { + ERR("geo_input event[type = %d, code = %d] is unknown.", geo_input.type, geo_input.code); + return false; + } + } + } else { + ERR("select nothing to read!!!"); + return false; + } + + if (syn == false) { + ERR("EV_SYN didn't come until %d inputs had come", read_input_cnt); + return false; + } + + AUTOLOCK(m_value_mutex); + + if (x) + m_x = geo_raw[0]; + + if (y) + m_y = geo_raw[1]; + + if (z) + m_z = geo_raw[2]; + + if (hdst) + m_hdst = geo_raw[3] - 1; /* accuracy bias: -1 */ + + m_fired_time = fired_time; + + DBG("m_x = %d, m_y = %d, m_z = %d, m_hdst = %d, time = %lluus", m_x, m_y, m_z, m_hdst, m_fired_time); + return true; +} + +bool geo_sensor_hal::is_data_ready(bool wait) +{ + bool ret; + ret = update_value(wait); + return ret; +} + +int geo_sensor_hal::get_sensor_data(sensor_data_t &data) +{ + const int chance = 3; + int retry = 0; + + while ((m_fired_time == 0) && (retry++ < chance)) { + INFO("Try usleep for getting a valid BASE DATA value"); + usleep(m_polling_interval * MS_TO_SEC); + } + + if (m_fired_time == 0) { + ERR("get_sensor_data failed"); + return -1; + } + + data.data_accuracy = (m_hdst == 1) ? 0 : m_hdst; /* hdst 0 and 1 are needed to calibrate */ + data.data_unit_idx = SENSOR_UNIT_MICRO_TESLA; + data.timestamp = m_fired_time; + data.values_num = 3; + data.values[0] = (float)m_x * LBS_TO_UTESLA; + data.values[1] = (float)m_y * LBS_TO_UTESLA; + data.values[2] = (float)m_z * LBS_TO_UTESLA; + + return 0; +} + +bool geo_sensor_hal::get_properties(sensor_properties_t &properties) +{ + properties.sensor_unit_idx = SENSOR_UNIT_MICRO_TESLA; + properties.sensor_min_range = -1200; + properties.sensor_max_range = 1200; + snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); + snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); + properties.sensor_resolution = 1; + return true; +} + +bool geo_sensor_hal::is_sensorhub_supported(void) +{ + FILE *fp = NULL; + string mag_polling_resource = string(SENSORHUB_NODE) + string(MAG_POLL_DELAY); + fp = fopen(mag_polling_resource.c_str(), "r"); + + if (!fp) { + ERR("Fail to open a resource file"); + return false; + } + + INFO("Supported by Sensor-Hub"); + fclose(fp); + return true; +} + +bool geo_sensor_hal::check_hw_node(void) +{ + string name_node; + string hw_name; + DIR *main_dir = NULL; + struct dirent *dir_entry = NULL; + bool find_node = false; + + INFO("======================start check_hw_node============================="); + + m_sensorhub_supported = is_sensorhub_supported(); + main_dir = opendir(SENSOR_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0)) { + name_node = string(SENSOR_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (CConfig::get_instance().is_supported(SENSOR_TYPE_MAGNETIC, hw_name) == true) { + m_name = m_model_id = hw_name; + INFO("m_model_id = %s", m_model_id.c_str()); + find_node = true; + break; + } + } + } + + closedir(main_dir); + + if (find_node) { + main_dir = opendir(INPUT_DEVICE_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + find_node = false; + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if (strncasecmp(dir_entry->d_name, NODE_INPUT, 5) == 0) { + name_node = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (hw_name == string(INPUT_NAME)) { + INFO("name_node = %s", name_node.c_str()); + DBG("Find H/W for mag_sensor"); + + find_node = true; + string dir_name; + dir_name = string(dir_entry->d_name); + unsigned found = dir_name.find_first_not_of(NODE_INPUT); + m_resource = string(DEV_INPUT_NODE) + dir_name.substr(found); + + if (m_sensorhub_supported) { + m_enable_resource = string(SENSORHUB_NODE) + string(NODE_ENABLE); + m_polling_resource = string(SENSORHUB_NODE) + string(NODE_MAG_POLL_DELAY); + } else { + m_enable_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_ENABLE); + m_polling_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_POLL_DELAY); + } + + break; + } + } + } + + closedir(main_dir); + } + + if (find_node) { + INFO("m_resource = %s", m_resource.c_str()); + INFO("m_enable_resource = %s", m_enable_resource.c_str()); + INFO("m_polling_resource = %s", m_polling_resource.c_str()); + } + + return find_node; +} + +extern "C" void *create(void) +{ + geo_sensor_hal *inst; + + try { + inst = new geo_sensor_hal(); + } catch (int err) { + ERR("Failed to create geo_sensor_hal class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (geo_sensor_hal *)inst; +} diff --git a/src/geo/geo_sensor_hal.h b/src/geo/geo_sensor_hal.h new file mode 100755 index 0000000..066d672 --- /dev/null +++ b/src/geo/geo_sensor_hal.h @@ -0,0 +1,71 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _GEO_SENSOR_HAL_H_ +#define _GEO_SENSOR_HAL_H_ + +#include +#include + +using std::string; + +class geo_sensor_hal : public sensor_hal +{ +public: + geo_sensor_hal(); + virtual ~geo_sensor_hal(); + string get_model_id(void); + sensor_type_t get_type(void); + bool enable(void); + bool disable(void); + bool set_interval(unsigned long val); + bool is_data_ready(bool wait); + virtual int get_sensor_data(sensor_data_t &data); + bool get_properties(sensor_properties_t &properties); + bool check_hw_node(void); + +private: + long a_x; + long a_y; + long a_z; + double m_x; + double m_y; + double m_z; + int m_hdst; + int m_node_handle; + unsigned long m_polling_interval; + unsigned long long m_fired_time; + bool m_sensorhub_supported; + + string m_model_id; + string m_name; + string m_vendor; + string m_chip_name; + + string m_resource; + string m_enable_resource; + string m_polling_resource; + + cmutex m_value_mutex; + + bool enable_resource(string &resource_node, bool enable); + bool update_value(bool wait); + bool is_sensorhub_supported(void); +}; +#endif /*_GEO_SENSOR_HAL_H_*/ diff --git a/src/gravity/CMakeLists.txt b/src/gravity/CMakeLists.txt new file mode 100755 index 0000000..466f54b --- /dev/null +++ b/src/gravity/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 2.6) +project(gravity CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(VERSION 1.0) + +SET(SENSOR_NAME gravity_sensor) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET -DHWREV_CHECK") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-DUSE_DLOG_LOG) +add_definitions(-Iinclude) + +add_library(${SENSOR_NAME} SHARED + gravity_sensor.cpp + ) + +target_link_libraries(${SENSOR_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") + +install(TARGETS ${SENSOR_NAME} DESTINATION lib/sensord) diff --git a/src/gravity/gravity_sensor.cpp b/src/gravity/gravity_sensor.cpp new file mode 100755 index 0000000..34eee07 --- /dev/null +++ b/src/gravity/gravity_sensor.cpp @@ -0,0 +1,214 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INITIAL_VALUE -1 +#define INITIAL_TIME 0 +#define TIME_CONSTANT 0.18 +#define GRAVITY 9.80665 + +#define SENSOR_NAME "GRAVITY_SENSOR" + +gravity_sensor::gravity_sensor() +: m_accel_sensor(NULL) +, m_x(INITIAL_VALUE) +, m_y(INITIAL_VALUE) +, m_z(INITIAL_VALUE) +, m_time(INITIAL_TIME) +{ + m_name = string(SENSOR_NAME); + + register_supported_event(GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME); +} + +gravity_sensor::~gravity_sensor() +{ + INFO("gravity_sensor is destroyed!"); +} + +bool gravity_sensor::init() +{ + m_accel_sensor = sensor_plugin_loader::get_instance().get_sensor(ACCELEROMETER_SENSOR); + + if (!m_accel_sensor) { + ERR("cannot load accel sensor_hal[%s]", sensor_base::get_name()); + return false; + } + + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +sensor_type_t gravity_sensor::get_type(void) +{ + return GRAVITY_SENSOR; +} + +bool gravity_sensor::on_start(void) +{ + AUTOLOCK(m_mutex); + + m_accel_sensor->add_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME); + m_accel_sensor->start(); + + activate(); + return true; +} + +bool gravity_sensor::on_stop(void) +{ + AUTOLOCK(m_mutex); + + m_accel_sensor->delete_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME); + m_accel_sensor->stop(); + + deactivate(); + return true; +} + +bool gravity_sensor::add_interval(int client_id, unsigned int interval, bool is_processor) +{ + m_accel_sensor->add_interval(client_id, interval, true); + return sensor_base::add_interval(client_id, interval, true); +} + +bool gravity_sensor::delete_interval(int client_id, bool is_processor) +{ + m_accel_sensor->delete_interval(client_id, true); + return sensor_base::delete_interval(client_id, true); +} + +void gravity_sensor::synthesize(const sensor_event_t &event, vector &outs) +{ + if (event.event_type == ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME) { + float x, y, z; + calibrate_gravity(event, x, y, z); + + sensor_event_t event; + event.event_type = GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME; + event.data.data_accuracy = SENSOR_ACCURACY_GOOD; + event.data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; + event.data.timestamp = m_time; + event.data.values_num = 3; + event.data.values[0] = x; + event.data.values[1] = y; + event.data.values[2] = z; + outs.push_back(event); + + AUTOLOCK(m_value_mutex); + m_x = x; + m_y = y; + m_z = z; + + return; + } +} + +int gravity_sensor::get_sensor_data(const unsigned int data_id, sensor_data_t &data) +{ + if (data_id != GRAVITY_BASE_DATA_SET) + return -1; + + AUTOLOCK(m_value_mutex); + + data.data_accuracy = SENSOR_ACCURACY_GOOD; + data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; + data.time_stamp = m_time; + data.values_num = 3; + data.values[0] = m_x; + data.values[1] = m_y; + data.values[2] = m_z; + + return 0; +} + +bool gravity_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + m_accel_sensor->get_properties(type, properties); + + if (type != GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME) + return true; + + properties.sensor_min_range = properties.sensor_min_range / GRAVITY; + properties.sensor_max_range = properties.sensor_max_range / GRAVITY; + properties.sensor_resolution = properties.sensor_resolution / GRAVITY; + strncpy(properties.sensor_name, "Gravity Sensor", MAX_KEY_LENGTH); + + return true; +} + +void gravity_sensor::calibrate_gravity(const sensor_event_t &raw, float &x, float &y, float &z) +{ + unsigned long long timestamp; + float dt; + float alpha; + float last_x = 0, last_y = 0, last_z = 0; + + { + AUTOLOCK(m_value_mutex); + last_x = m_x; + last_y = m_y; + last_z = m_z; + } + + timestamp = get_timestamp(); + dt = (timestamp - m_time) / US_TO_SEC; + m_time = timestamp; + alpha = TIME_CONSTANT / (TIME_CONSTANT + dt); + + if (dt > 1.0) + alpha = 0.0; + + x = (alpha * last_x) + ((1 - alpha) * raw.data.values[0] / GRAVITY); + y = (alpha * last_y) + ((1 - alpha) * raw.data.values[1] / GRAVITY); + z = (alpha * last_z) + ((1 - alpha) * raw.data.values[2] / GRAVITY); +} + +extern "C" void *create(void) +{ + gravity_sensor *inst; + + try { + inst = new gravity_sensor(); + } catch (int ErrNo) { + ERR("Failed to create gravity_sensor class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (gravity_sensor *)inst; +} diff --git a/src/gravity/gravity_sensor.h b/src/gravity/gravity_sensor.h new file mode 100755 index 0000000..0737707 --- /dev/null +++ b/src/gravity/gravity_sensor.h @@ -0,0 +1,62 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _GRAVITY_SENSOR_H_ +#define _GRAVITY_SENSOR_H_ + +#include +#include +#include + +using std::string; + +class gravity_sensor : public virtual_sensor +{ +public: + gravity_sensor(); + virtual ~gravity_sensor(); + + bool init(); + sensor_type_t get_type(void); + + static bool working(void *inst); + + bool on_start(void); + bool on_stop(void); + + void synthesize(const sensor_event_t &event, vector &outs); + + virtual bool add_interval(int client_id, unsigned int interval, bool is_processor = false); + virtual bool delete_interval(int client_id, bool is_processor = false); + + int get_sensor_data(const unsigned int data_id, sensor_data_t &data); + bool get_properties(const unsigned int type, sensor_properties_t &properties); +private: + sensor_base *m_accel_sensor; + cmutex m_value_mutex; + + float m_x; + float m_y; + float m_z; + unsigned long long m_time; + + void calibrate_gravity(const sensor_event_t &raw, float &x, float &y, float &z); +}; + +#endif /*_GRAVITY_SENSOR_H_*/ diff --git a/src/gyro/CMakeLists.txt b/src/gyro/CMakeLists.txt new file mode 100755 index 0000000..afef9f0 --- /dev/null +++ b/src/gyro/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 2.6) +project(gyro CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +SET(SENSOR_NAME gyro_sensor) +SET(SENSOR_HAL_NAME gyro_sensor_hal) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) +add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET -DHWREV_CHECK") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-DUSE_DLOG_LOG) +add_definitions(-Iinclude) + +add_library(${SENSOR_NAME} SHARED + gyro_sensor.cpp + ) +add_library(${SENSOR_HAL_NAME} SHARED + gyro_sensor_hal.cpp + ) + +target_link_libraries(${SENSOR_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") +target_link_libraries(${SENSOR_HAL_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS}) + +install(TARGETS ${SENSOR_NAME} DESTINATION lib/sensord) +install(TARGETS ${SENSOR_HAL_NAME} DESTINATION lib/sensord) diff --git a/src/gyro/gyro_sensor.cpp b/src/gyro/gyro_sensor.cpp new file mode 100755 index 0000000..26b9830 --- /dev/null +++ b/src/gyro/gyro_sensor.cpp @@ -0,0 +1,183 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#define INTIAL_VALUE -1 +#define MS_TO_US 1000 +#define DPS_TO_MDPS 1000 +#define RAW_DATA_TO_DPS_UNIT(X) ((float)(X)/((float)DPS_TO_MDPS)) + +#define SENSOR_NAME "GYROSCOPE_SENSOR" + +gyro_sensor::gyro_sensor() +: m_sensor_hal(NULL) +, m_resolution(INITIAL_VALUE) +{ + m_name = string(SENSOR_NAME); + + register_supported_event(GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME); + + physical_sensor::set_poller(gyro_sensor::working, this); +} + +gyro_sensor::~gyro_sensor() +{ + INFO("gyro_sensor is destroyed!"); +} + +bool gyro_sensor::init() +{ + m_sensor_hal = sensor_plugin_loader::get_instance().get_sensor_hal(GYROSCOPE_SENSOR); + + if (!m_sensor_hal) { + ERR("cannot load sensor_hal[%s]", sensor_base::get_name()); + return false; + } + + sensor_properties_t properties; + + if (m_sensor_hal->get_properties(properties) == false) { + ERR("sensor->get_properties() is failed!"); + return false; + } + + m_resolution = properties.sensor_resolution; + + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +sensor_type_t gyro_sensor::get_type(void) +{ + return GYROSCOPE_SENSOR; +} + +bool gyro_sensor::working(void *inst) +{ + gyro_sensor *sensor = (gyro_sensor *)inst; + return sensor->process_event(); +} + +bool gyro_sensor::process_event(void) +{ + sensor_event_t event; + + if (m_sensor_hal->is_data_ready(true) == false) + return true; + + m_sensor_hal->get_sensor_data(event.data); + + AUTOLOCK(m_client_info_mutex); + + if (get_client_cnt(GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME)) { + event.event_type = GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME; + raw_to_base(event.data); + push(event); + } + + return true; +} + +bool gyro_sensor::on_start(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->enable()) { + ERR("m_sensor_hal start fail"); + return false; + } + + return start_poll(); +} + +bool gyro_sensor::on_stop(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->disable()) { + ERR("m_sensor_hal stop fail"); + return false; + } + + return stop_poll(); +} + +bool gyro_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + return m_sensor_hal->get_properties(properties); +} + +int gyro_sensor::get_sensor_data(const unsigned int type, sensor_data_t &data) +{ + int state; + + if (type != GYRO_BASE_DATA_SET) + return -1; + + state = m_sensor_hal->get_sensor_data(data); + + if (state < 0) { + ERR("m_sensor_hal get struct_data fail"); + return -1; + } + + raw_to_base(data); + + return 0; +} + +bool gyro_sensor::set_interval(unsigned long interval) +{ + AUTOLOCK(m_mutex); + + INFO("Polling interval is set to %dms", interval); + return m_sensor_hal->set_interval(interval); +} + +void gyro_sensor::raw_to_base(sensor_data_t &data) +{ + data.data_unit_idx = SENSOR_UNIT_DEGREE_PER_SECOND; + data.values_num = 3; + data.values[0] = data.values[0] * m_resolution; + data.values[1] = data.values[1] * m_resolution; + data.values[2] = data.values[2] * m_resolution; +} + +extern "C" void *create(void) +{ + gyro_sensor *inst; + + try { + inst = new gyro_sensor(); + } catch (int err) { + ERR("Failed to create gyro_sensor class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (gyro_sensor *)inst; +} diff --git a/src/gyro/gyro_sensor.h b/src/gyro/gyro_sensor.h new file mode 100755 index 0000000..51eb31c --- /dev/null +++ b/src/gyro/gyro_sensor.h @@ -0,0 +1,52 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _GYRO_SENSOR_H_ +#define _GYRO_SENSOR_H_ + +#include +#include +#include + +class gyro_sensor : public physical_sensor +{ +public: + gyro_sensor(); + virtual ~gyro_sensor(); + + virtual bool init(); + virtual sensor_type_t get_type(void); + + static bool working(void *inst); + + virtual bool on_start(void); + virtual bool on_stop(void); + + virtual bool set_interval(unsigned long interval); + virtual bool get_properties(const unsigned int type, sensor_properties_t &properties); + int get_sensor_data(const unsigned int type, sensor_data_t &data); +private: + sensor_hal *m_sensor_hal; + float m_resolution; + + void raw_to_base(sensor_data_t &data); + bool process_event(void); +}; + +#endif /*_GYRO_SENSOR_H_*/ \ No newline at end of file diff --git a/src/gyro/gyro_sensor_hal.cpp b/src/gyro/gyro_sensor_hal.cpp new file mode 100755 index 0000000..0b94ae7 --- /dev/null +++ b/src/gyro/gyro_sensor_hal.cpp @@ -0,0 +1,523 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::ifstream; +using config::CConfig; + +#define NODE_NAME "name" +#define NODE_INPUT "input" +#define NODE_ENABLE "enable" +#define NODE_POLL_DELAY "poll_delay" +#define NODE_ACCEL_POLL_DELAY "gyro_poll_delay" +#define SENSOR_NODE "/sys/class/sensors/" +#define SENSORHUB_NODE "/sys/class/sensors/ssp_sensor/" +#define INPUT_DEVICE_NODE "/sys/class/input/" +#define DEV_INPUT_NODE "/dev/input/event/" + +#define INITIAL_VALUE -1 +#define INITIAL_TIME 0 +#define DPS_TO_MDPS 1000 +#define MIN_RANGE(RES) (-((2 << (RES))/2)) +#define MAX_RANGE(RES) (((2 << (RES))/2)-1) +#define RAW_DATA_TO_DPS_UNIT(X) ((float)(X)/((float)DPS_TO_MDPS)) + +#define SENSOR_TYPE_GYRO "GYRO" +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" +#define ELEMENT_RESOLUTION "RESOLUTION" +#define ATTR_VALUE "value" + +#define INPUT_NAME "gyro_sensor" + +gyro_sensor_hal::gyro_sensor_hal() +: m_x(INITIAL_VALUE) +, m_y(INITIAL_VALUE) +, m_z(INITIAL_VALUE) +, m_node_handle(INITIAL_VALUE) +, m_polling_interval(POLL_1HZ_MS) +, m_fired_time(INITIAL_TIME) +, m_sensorhub_supported(false) +{ + if (!check_hw_node()) { + ERR("check_hw_node() fail"); + throw ENXIO; + } + + CConfig &config = CConfig::get_instance(); + + if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_NAME, m_chip_name)) { + ERR("[NAME] is empty"); + throw ENXIO; + } + + INFO("m_chip_name = %s", m_chip_name.c_str()); + + long resolution; + + if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_RESOLUTION, resolution)) { + ERR("[RESOLUTION] is empty"); + throw ENXIO; + } + + m_resolution = (int)resolution; + INFO("m_resolution = %d", m_resolution); + + double raw_data_unit; + + if (!config.get(SENSOR_TYPE_GYRO, m_model_id, ELEMENT_RAW_DATA_UNIT, raw_data_unit)) { + ERR("[RAW_DATA_UNIT] is empty"); + throw ENXIO; + } + + m_raw_data_unit = (float)(raw_data_unit); + INFO("m_raw_data_unit = %f", m_raw_data_unit); + INFO("RAW_DATA_TO_DPS_UNIT(m_raw_data_unit) = [%f]", RAW_DATA_TO_DPS_UNIT(m_raw_data_unit)); + + if ((m_node_handle = open(m_resource.c_str(), O_RDWR)) < 0) { + ERR("Failed to open handle(%d)", m_node_handle); + throw ENXIO; + } + + int clockId = CLOCK_MONOTONIC; + + if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) { + ERR("Fail to set monotonic timestamp for %s", m_resource.c_str()); + throw ENXIO; + } + + INFO("gyro_sensor_hal is created!"); +} + +gyro_sensor_hal::~gyro_sensor_hal() +{ + close(m_node_handle); + m_node_handle = INITIAL_VALUE; + + INFO("gyro_sensor_hal is destroyed!"); +} + +string gyro_sensor_hal::get_model_id(void) +{ + return m_model_id; +} + +sensor_type_t gyro_sensor_hal::get_type(void) +{ + return GYROSCOPE_SENSOR; +} + +bool gyro_sensor_hal::enable_resource(string &resource_node, bool enable) +{ + int prev_status, status; + FILE *fp = NULL; + fp = fopen(resource_node.c_str(), "r"); + + if (!fp) { + ERR("Fail to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fscanf(fp, "%d", &prev_status) < 0) { + ERR("Failed to get data from %s", resource_node.c_str()); + fclose(fp); + return false; + } + + fclose(fp); + + if (enable) { + if (m_sensorhub_supported) + status = prev_status | (1 << SENSORHUB_GYROSCOPE_ENABLE_BIT); + else + status = 1; + } else { + if (m_sensorhub_supported) + status = prev_status ^ (1 << SENSORHUB_GYROSCOPE_ENABLE_BIT); + else + status = 0; + } + + fp = fopen(resource_node.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fprintf(fp, "%d", status) < 0) { + ERR("Failed to enable a resource file: %s", resource_node.c_str()); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + return true; +} + +bool gyro_sensor_hal::enable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, true); + set_interval(m_polling_interval); + + m_fired_time = 0; + INFO("Gyro sensor real starting"); + return true; +} + +bool gyro_sensor_hal::disable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, false); + INFO("Gyro sensor real stopping"); + return true; +} + +bool gyro_sensor_hal::set_interval(unsigned long val) +{ + unsigned long long polling_interval_ns; + FILE *fp = NULL; + + AUTOLOCK(m_mutex); + + polling_interval_ns = ((unsigned long long)(val) * MS_TO_SEC * MS_TO_SEC); + fp = fopen(m_polling_resource.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", m_polling_resource.c_str()); + return false; + } + + if (fprintf(fp, "%llu", polling_interval_ns) < 0) { + ERR("Failed to set data %llu", polling_interval_ns); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + INFO("Interval is changed from %dms to %dms]", m_polling_interval, val); + m_polling_interval = val; + return true; +} + +bool gyro_sensor_hal::update_value(bool wait) +{ + const int TIMEOUT = 1; + int gyro_raw[3] = {0,}; + bool x, y, z; + int read_input_cnt = 0; + const int INPUT_MAX_BEFORE_SYN = 10; + unsigned long long fired_time = 0; + bool syn = false; + x = y = z = false; + + struct timeval tv; + fd_set readfds, exceptfds; + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + FD_SET(m_node_handle, &readfds); + FD_SET(m_node_handle, &exceptfds); + + if (wait) { + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + } else { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + + int ret; + ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, &tv); + + if (ret == -1) { + ERR("select error:%s m_node_handle:d", strerror(errno), m_node_handle); + return false; + } else if (!ret) { + DBG("select timeout: %d seconds elapsed", tv.tv_sec); + return false; + } + + if (FD_ISSET(m_node_handle, &exceptfds)) { + ERR("select exception occurred!"); + return false; + } + + if (FD_ISSET(m_node_handle, &readfds)) { + struct input_event gyro_input; + DBG("gyro event detection!"); + + while ((syn == false) && (read_input_cnt < INPUT_MAX_BEFORE_SYN)) { + int len = read(m_node_handle, &gyro_input, sizeof(gyro_input)); + + if (len != sizeof(gyro_input)) { + ERR("gyro_file read fail, read_len = %d", len); + return false; + } + + ++read_input_cnt; + + if (gyro_input.type == EV_REL) { + switch (gyro_input.code) { + case REL_RX: + gyro_raw[0] = (int)gyro_input.value; + x = true; + break; + case REL_RY: + gyro_raw[1] = (int)gyro_input.value; + y = true; + break; + case REL_RZ: + gyro_raw[2] = (int)gyro_input.value; + z = true; + break; + default: + ERR("gyro_input event[type = %d, code = %d] is unknown.", gyro_input.type, gyro_input.code); + return false; + break; + } + } else if (gyro_input.type == EV_SYN) { + syn = true; + fired_time = sensor_hal::get_timestamp(&gyro_input.time); + } else { + ERR("gyro_input event[type = %d, code = %d] is unknown.", gyro_input.type, gyro_input.code); + return false; + } + } + } else { + ERR("select nothing to read!!!"); + return false; + } + + if (syn == false) { + ERR("EV_SYN didn't come until %d inputs had come", read_input_cnt); + return false; + } + + AUTOLOCK(m_value_mutex); + + if (x) + m_x = gyro_raw[0]; + + if (y) + m_y = gyro_raw[1]; + + if (z) + m_z = gyro_raw[2]; + + m_fired_time = fired_time; + DBG("m_x = %d, m_y = %d, m_z = %d, time = %lluus", m_x, m_y, m_z, m_fired_time); + return true; +} + +bool gyro_sensor_hal::is_data_ready(bool wait) +{ + bool ret; + ret = update_value(wait); + return ret; +} + +int gyro_sensor_hal::get_sensor_data(sensor_data_t &data) +{ + const int chance = 3; + int retry = 0; + + while ((m_fired_time == 0) && (retry++ < chance)) { + INFO("Try usleep for getting a valid BASE DATA value"); + usleep(m_polling_interval * MS_TO_SEC); + } + + if (m_fired_time == 0) { + ERR("get_sensor_data failed"); + return -1; + } + + data.data_accuracy = SENSOR_ACCURACY_GOOD; + data.data_unit_idx = SENSOR_UNIT_VENDOR_UNIT; + data.timestamp = m_fired_time ; + data.values_num = 3; + data.values[0] = m_x; + data.values[1] = m_y; + data.values[2] = m_z; + + return 0; +} + +bool gyro_sensor_hal::get_properties(sensor_properties_t &properties) +{ + properties.sensor_unit_idx = SENSOR_UNIT_DEGREE_PER_SECOND; + properties.sensor_min_range = MIN_RANGE(m_resolution) * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit); + properties.sensor_max_range = MAX_RANGE(m_resolution) * RAW_DATA_TO_DPS_UNIT(m_raw_data_unit); + snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); + snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); + properties.sensor_resolution = RAW_DATA_TO_DPS_UNIT(m_raw_data_unit); + return true; +} + +bool gyro_sensor_hal::is_sensorhub_supported(void) +{ + DIR *main_dir = NULL; + main_dir = opendir(SENSORHUB_NODE); + + if (!main_dir) { + INFO("Sensor Hub is not supported"); + return false; + } + + INFO("It supports sensor hub"); + closedir(main_dir); + return true; +} + +bool gyro_sensor_hal::check_hw_node(void) +{ + string name_node; + string hw_name; + DIR *main_dir = NULL; + struct dirent *dir_entry = NULL; + bool find_node = false; + + INFO("======================start check_hw_node============================="); + + m_sensorhub_supported = is_sensorhub_supported(); + main_dir = opendir(SENSOR_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0)) { + name_node = string(SENSOR_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (CConfig::get_instance().is_supported(SENSOR_TYPE_GYRO, hw_name) == true) { + m_name = m_model_id = hw_name; + INFO("m_model_id = %s", m_model_id.c_str()); + find_node = true; + break; + } + } + } + + closedir(main_dir); + + if (find_node) { + main_dir = opendir(INPUT_DEVICE_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + find_node = false; + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if (strncasecmp(dir_entry->d_name, NODE_INPUT, 5) == 0) { + name_node = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (hw_name == string(INPUT_NAME)) { + INFO("name_node = %s", name_node.c_str()); + DBG("Find H/W for gyro_sensor"); + + find_node = true; + string dir_name; + dir_name = string(dir_entry->d_name); + unsigned found = dir_name.find_first_not_of(NODE_INPUT); + m_resource = string(DEV_INPUT_NODE) + dir_name.substr(found); + + if (m_sensorhub_supported) { + m_enable_resource = string(SENSORHUB_NODE) + string(NODE_ENABLE); + m_polling_resource = string(SENSORHUB_NODE) + string(NODE_GYRO_POLL_DELAY); + } else { + m_enable_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_ENABLE); + m_polling_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_POLL_DELAY); + } + + break; + } + } + } + + closedir(main_dir); + } + + if (find_node) { + INFO("m_resource = %s", m_resource.c_str()); + INFO("m_enable_resource = %s", m_enable_resource.c_str()); + INFO("m_polling_resource = %s", m_polling_resource.c_str()); + } + + return find_node; +} + +extern "C" void *create(void) +{ + gyro_sensor_hal *inst; + + try { + inst = new gyro_sensor_hal(); + } catch (int err) { + ERR("Failed to create gyro_sensor_hal class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (gyro_sensor_hal *)inst; +} diff --git a/src/gyro/gyro_sensor_hal.h b/src/gyro/gyro_sensor_hal.h new file mode 100755 index 0000000..0a145c3 --- /dev/null +++ b/src/gyro/gyro_sensor_hal.h @@ -0,0 +1,70 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _GYRO_SENSOR_HAL_H_ +#define _GYRO_SENSOR_HAL_H_ + +#include +#include + +using std::string; + +class gyro_sensor_hal : public sensor_hal +{ +public: + gyro_sensor_hal(); + virtual ~gyro_sensor_hal(); + string get_model_id(void); + sensor_type_t get_type(void); + bool enable(void); + bool disable(void); + bool set_interval(unsigned long val); + bool is_data_ready(bool wait); + virtual int get_sensor_data(sensor_data_t &data); + bool get_properties(sensor_properties_t &properties); + bool check_hw_node(void); + +private: + int m_x; + int m_y; + int m_z; + int m_node_handle; + unsigned long m_polling_interval; + unsigned long long m_fired_time; + bool m_sensorhub_supported; + + string m_model_id; + string m_name; + string m_vendor; + string m_chip_name; + + int m_resolution; + float m_raw_data_unit; + + string m_resource; + string m_enable_resource; + string m_polling_resource; + + cmutex m_value_mutex; + + bool enable_resource(string &resource_node, bool enable); + bool update_value(bool wait); + bool is_sensorhub_supported(void); +}; +#endif /*_GYRO_SENSOR_HAL_H_*/ diff --git a/src/libsensord/CMakeLists.txt b/src/libsensord/CMakeLists.txt new file mode 100755 index 0000000..505303e --- /dev/null +++ b/src/libsensord/CMakeLists.txt @@ -0,0 +1,69 @@ +cmake_minimum_required(VERSION 2.6) +project(sensor CXX) + +# to install pkgconfig setup file. +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION_MAJOR 1) +SET(VERSION "${VERSION_MAJOR}.1.0") + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf glib-2.0) +add_definitions(${rpkgs_CFLAGS}) + +#add_definitions(-Wall -O3 -omit-frame-pointer -lm) +#add_definitions(-Wall -g -lma -DUSE_FILE_DEBUG) +#add_definitions(-D_DEBUG) +add_definitions(-Wall -g -lma -DUSE_DLOG_LOG -std=c++0x) +#add_definitions(-fvisibility=hidden -lm -DUSE_DLOG_LOG) +#add_definitions(-fvisibility=hidden -lm) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" STREQUAL "arm") +#ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK -DUSE_MPU3050_GYRO") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET") +ELSE("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" STREQUAL "arm") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(${PROJECT_NAME} SHARED + client.cpp + csensor_event_listener.cpp + csensor_handle_info.cpp + client_common.cpp + command_channel.cpp + poller.cpp +) + +target_link_libraries(${PROJECT_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "sensord-share") +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR}) +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION}) + +configure_file(${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc @ONLY) + +#install(DIRECTORY include/ DESTINATION include/ FILES_MATCHING PATTERN "*.h") +install(TARGETS ${PROJECT_NAME} DESTINATION lib COMPONENT RuntimeLibraries) + +install(FILES sensor.h DESTINATION include/sensor/) +install(FILES poller.h DESTINATION include/sensor/) +install(FILES creg_event_info.h DESTINATION include/sensor/) +install(FILES csensor_event_listener.h DESTINATION include/sensor/) +install(FILES csensor_handle_info.h DESTINATION include/sensor/) +install(FILES client_common.h DESTINATION include/sensor/) +install(FILES sensor_accel.h DESTINATION include/sensor/) +install(FILES sensor_geomag.h DESTINATION include/sensor/) +install(FILES sensor_light.h DESTINATION include/sensor/) +install(FILES sensor_proxi.h DESTINATION include/sensor/) +install(FILES sensor_gyro.h DESTINATION include/sensor/) +install(FILES sensor_gravity.h DESTINATION include/sensor/) +install(FILES sensor_linear_accel.h DESTINATION include/sensor/) +install(FILES sensor_orientation.h DESTINATION include/sensor/) +install(FILES sensor_context.h DESTINATION include/sensor/) +install(FILES ${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) diff --git a/src/libsensord/client.cpp b/src/libsensord/client.cpp new file mode 100755 index 0000000..f978c66 --- /dev/null +++ b/src/libsensord/client.cpp @@ -0,0 +1,807 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef EXTAPI +#define EXTAPI __attribute__((visibility("default"))) +#endif + +static const int OP_SUCCESS = 0; +static const int OP_ERROR = -1; +static const int CMD_ERROR = -2; + +static csensor_event_listener &event_listener = csensor_event_listener::get_instance(); +static cmutex lock; + +static bool g_power_save_state = false; + +static bool get_power_save_state(void); +static void power_save_state_cb(keynode_t *node, void *data); +static void clean_up(void); +static void good_bye(void); +static int change_sensor_rep(sensor_type_t sensor, sensor_rep &prev_rep, sensor_rep &cur_rep); + +void init_client(void) +{ + atexit(good_bye); +} + +static void good_bye(void) +{ + _D("Good bye! %s", get_client_name()); + clean_up(); +} + +static int g_power_save_state_cb_cnt = 0; + +static void set_power_save_state_cb(void) +{ + if (g_power_save_state_cb_cnt < 0) + _E("g_power_save_state_cb_cnt(%d) is wrong", g_power_save_state_cb_cnt); + + ++g_power_save_state_cb_cnt; + + if (g_power_save_state_cb_cnt == 1) { + _D("Power save callback is registered"); + g_power_save_state = get_power_save_state(); + _D("power_save_state = [%s]", g_power_save_state ? "on" : "off"); + vconf_notify_key_changed(VCONFKEY_PM_STATE, power_save_state_cb, NULL); + } +} + +static void unset_power_save_state_cb(void) +{ + --g_power_save_state_cb_cnt; + + if (g_power_save_state_cb_cnt < 0) + _E("g_power_save_state_cb_cnt(%d) is wrong", g_power_save_state_cb_cnt); + + if (g_power_save_state_cb_cnt == 0) { + _D("Power save callback is unregistered"); + vconf_ignore_key_changed(VCONFKEY_PM_STATE, power_save_state_cb); + } +} + +static void clean_up(void) +{ + handle_vector handles; + handle_vector::iterator it_handle; + + event_listener.get_all_handles(handles); + it_handle = handles.begin(); + + while (it_handle != handles.end()) { + sf_disconnect(*it_handle); + ++it_handle; + } +} + +static bool get_power_save_state (void) +{ + int pm_state, ps_state; + + vconf_get_int(VCONFKEY_PM_STATE, &pm_state); + + if ((pm_state == VCONFKEY_PM_STATE_LCDOFF)) + return true; + + return false; +} + +static void power_save_state_cb(keynode_t *node, void *data) +{ + bool cur_power_save_state; + sensor_type_vector sensors; + sensor_rep prev_rep, cur_rep; + + AUTOLOCK(lock); + cur_power_save_state = get_power_save_state(); + + if (cur_power_save_state == g_power_save_state) { + _T("g_power_save_state NOT changed : [%d]", cur_power_save_state); + return; + } + + g_power_save_state = cur_power_save_state; + _D("power_save_state %s noti to %s", g_power_save_state ? "on" : "off", get_client_name()); + + event_listener.get_listening_sensors(sensors); + sensor_type_vector::iterator it_sensor; + it_sensor = sensors.begin(); + + while (it_sensor != sensors.end()) { + event_listener.get_sensor_rep(*it_sensor, prev_rep); + + if (cur_power_save_state) + event_listener.pause_sensor(*it_sensor); + else + event_listener.resume_sensor(*it_sensor); + + event_listener.get_sensor_rep(*it_sensor, cur_rep); + change_sensor_rep(*it_sensor, prev_rep, cur_rep); + ++it_sensor; + } +} + +static bool get_events_diff(event_type_vector &a_vec, event_type_vector &b_vec, event_type_vector &add_vec, event_type_vector &del_vec) +{ + sort(a_vec.begin(), a_vec.end()); + sort(b_vec.begin(), b_vec.end()); + + set_difference(a_vec.begin(), a_vec.end(), b_vec.begin(), b_vec.end(), back_inserter(del_vec)); + set_difference(b_vec.begin(), b_vec.end(), a_vec.begin(), a_vec.end(), back_inserter(add_vec)); + + return !(add_vec.empty() && del_vec.empty()); +} + +static int change_sensor_rep(sensor_type_t sensor, sensor_rep &prev_rep, sensor_rep &cur_rep) +{ + int client_id; + command_channel *cmd_channel; + event_type_vector add_event_types, del_event_types; + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("client %s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + return OP_ERROR; + } + + client_id = event_listener.get_client_id(); + retvm_if ((client_id < 0), OP_ERROR, "Invalid client id : %d, %s, %s", client_id, get_sensor_name(sensor), get_client_name()); + + get_events_diff(prev_rep.event_types, cur_rep.event_types, add_event_types, del_event_types); + + if (cur_rep.active) { + if (prev_rep.option != cur_rep.option) { + if (!cmd_channel->cmd_set_option(cur_rep.option)) { + ERR("Sending cmd_set_option(%d, %s, %d) failed for %s", client_id, get_sensor_name(sensor), cur_rep.option, get_client_name()); + return CMD_ERROR; + } + } + + if (prev_rep.interval != cur_rep.interval) { + unsigned int min_interval; + + if (cur_rep.interval == 0) + min_interval = POLL_MAX_HZ_MS; + else + min_interval = cur_rep.interval; + + if (!cmd_channel->cmd_set_interval(min_interval)) { + ERR("Sending cmd_set_interval(%d, %s, %d) failed for %s", client_id, get_sensor_name(sensor), min_interval, get_client_name()); + return CMD_ERROR; + } + } + + if (!add_event_types.empty()) { + if (!cmd_channel->cmd_register_events(add_event_types)) { + ERR("Sending cmd_register_events(%d, add_event_types) failed for %s", client_id, get_client_name()); + return CMD_ERROR; + } + } + } + + if (prev_rep.active && !del_event_types.empty()) { + if (!cmd_channel->cmd_unregister_events(del_event_types)) { + ERR("Sending cmd_unregister_events(%d, del_event_types) failed for %s", client_id, get_client_name()); + return CMD_ERROR; + } + } + + if (prev_rep.active != cur_rep.active) { + if (cur_rep.active) { + if (!cmd_channel->cmd_start()) { + ERR("Sending cmd_start(%d, %s) failed for %s", client_id, get_sensor_name(sensor), get_client_name()); + return CMD_ERROR; + } + } else { + if (!cmd_channel->cmd_unset_interval()) { + ERR("Sending cmd_unset_interval(%d, %s) failed for %s", client_id, get_sensor_name(sensor), get_client_name()); + return CMD_ERROR; + } + + if (!cmd_channel->cmd_stop()) { + ERR("Sending cmd_stop(%d, %s) failed for %s", client_id, get_sensor_name(sensor), get_client_name()); + return CMD_ERROR; + } + } + } + + return OP_SUCCESS; +} + +EXTAPI int sf_connect(sensor_type_t sensor) +{ + command_channel *cmd_channel = NULL; + int handle; + int client_id; + bool sensor_registered; + bool first_connection = false; + + AUTOLOCK(lock); + + sensor_registered = event_listener.is_sensor_registered(sensor); + handle = event_listener.create_handle(sensor); + + if (handle == MAX_HANDLE) { + ERR("Maximum number of handles reached, sensor: %s in client %s", get_sensor_name(sensor), get_client_name()); + return OP_ERROR; + } + + if (!sensor_registered) { + cmd_channel = new command_channel(); + + if (!cmd_channel->create_channel()) { + ERR("%s failed to create command channel for %s", get_client_name(), get_sensor_name(sensor)); + event_listener.delete_handle(handle); + delete cmd_channel; + return OP_ERROR; + } + + event_listener.set_command_channel(sensor, cmd_channel); + } + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("%s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + event_listener.delete_handle(handle); + return OP_ERROR; + } + + if (!event_listener.has_client_id()) { + first_connection = true; + + if (!cmd_channel->cmd_get_id(client_id)) { + ERR("Sending cmd_get_id() failed for %s", get_sensor_name(sensor)); + event_listener.close_command_channel(sensor); + event_listener.delete_handle(handle); + return CMD_ERROR; + } + + event_listener.set_client_id(client_id); + INFO("%s gets client_id [%d]", get_client_name(), client_id); + event_listener.start_event_listener(); + INFO("%s starts listening events with client_id [%d]", get_client_name(), client_id); + } + + client_id = event_listener.get_client_id(); + cmd_channel->set_client_id(client_id); + + INFO("%s[%d] connects with %s[%d]", get_client_name(), client_id, get_sensor_name(sensor), handle); + event_listener.set_sensor_params(handle, SENSOR_STATE_STOPPED, SENSOR_OPTION_DEFAULT); + + if (!sensor_registered) { + if (!cmd_channel->cmd_hello(sensor)) { + ERR("Sending cmd_hello(%s, %d) failed for %s", get_sensor_name(sensor), client_id, get_client_name()); + event_listener.close_command_channel(sensor); + event_listener.delete_handle(handle); + + if (first_connection) + event_listener.stop_event_listener(); + + return CMD_ERROR; + } + } + + set_power_save_state_cb(); + return handle; +} + +EXTAPI int sf_disconnect(int handle) +{ + command_channel *cmd_channel; + sensor_type_t sensor; + int client_id; + int sensor_state; + + AUTOLOCK(lock); + + if (!event_listener.get_sensor_state(handle, sensor_state) || + !event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("client %s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + return OP_ERROR; + } + + client_id = event_listener.get_client_id(); + retvm_if ((client_id < 0), OP_ERROR, "Invalid client id : %d, handle: %d, %s, %s", client_id, handle, get_sensor_name(sensor), get_client_name()); + INFO("%s disconnects with %s[%d]", get_client_name(), get_sensor_name(sensor), handle); + + if (sensor_state != SENSOR_STATE_STOPPED) { + WARN("Before disconnecting, sensor %s[%d] is forced to stop in client %s", + get_sensor_name(sensor), handle, get_client_name()); + sf_stop(handle); + } + + if (!event_listener.delete_handle(handle)) + return OP_ERROR; + + if (!event_listener.is_sensor_registered(sensor)) { + if (!cmd_channel->cmd_byebye()) { + ERR("Sending cmd_byebye(%d, %s) failed for %s", client_id, get_sensor_name(sensor), get_client_name()); + return CMD_ERROR; + } + + event_listener.close_command_channel(sensor); + } + + if (!event_listener.is_active()) { + INFO("Stop listening events for client %s with client id [%d]", get_client_name(), event_listener.get_client_id()); + event_listener.stop_event_listener(); + } + + unset_power_save_state_cb(); + + return OP_SUCCESS; +} + +EXTAPI int sf_start(int handle, int option) +{ + sensor_type_t sensor; + sensor_rep prev_rep, cur_rep; + AUTOLOCK(lock); + + if (!event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + retvm_if ((option < 0) || (option >= SENSOR_OPTION_END), OP_ERROR, "Invalid option value : %d, handle: %d, %s, %s", + option, handle, get_sensor_name(sensor), get_client_name()); + INFO("%s starts %s[%d], with option: %d%s", get_client_name(), get_sensor_name(sensor), + handle, option, g_power_save_state ? " in power save state" : ""); + + if (g_power_save_state && (option != SENSOR_OPTION_ALWAYS_ON)) { + event_listener.set_sensor_params(handle, SENSOR_STATE_PAUSED, option); + return OP_SUCCESS; + } + + event_listener.get_sensor_rep(sensor, prev_rep); + event_listener.set_sensor_params(handle, SENSOR_STATE_STARTED, option); + event_listener.get_sensor_rep(sensor, cur_rep); + + return change_sensor_rep(sensor, prev_rep, cur_rep); +} + +EXTAPI int sf_stop(int handle) +{ + sensor_type_t sensor; + int sensor_state; + sensor_rep prev_rep, cur_rep; + + AUTOLOCK(lock); + + if (!event_listener.get_sensor_state(handle, sensor_state) || + !event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + retvm_if ((sensor_state == SENSOR_STATE_STOPPED), OP_SUCCESS, "%s already stopped with %s[%d]", + get_client_name(), get_sensor_name(sensor), handle); + + INFO("%s stops sensor %s[%d]", get_client_name(), get_sensor_name(sensor), handle); + + event_listener.get_sensor_rep(sensor, prev_rep); + event_listener.set_sensor_state(handle, SENSOR_STATE_STOPPED); + event_listener.get_sensor_rep(sensor, cur_rep); + return change_sensor_rep(sensor, prev_rep, cur_rep); +} + +EXTAPI int sf_register_event(int handle, unsigned int event_type, event_condition_t *event_condition, sensor_callback_func_t cb, void *cb_data ) +{ + sensor_type_t sensor; + unsigned int interval = BASE_GATHERING_INTERVAL; + sensor_rep prev_rep, cur_rep; + retvm_if ((cb == NULL), OP_ERROR, "callback is NULL"); + + AUTOLOCK(lock); + + if (!event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + if (event_condition != NULL) { + if ((event_condition->cond_op == CONDITION_EQUAL) && (event_condition->cond_value1 > 0)) + interval = event_condition->cond_value1; + } + + INFO("%s registers event %s[0x%x] for sensor %s[%d] with interval: %d, cb: 0x%x, cb_data: 0x%x", get_client_name(), get_event_name(event_type), + event_type, get_sensor_name(sensor), handle, interval, cb, cb_data); + + event_listener.get_sensor_rep(sensor, prev_rep); + event_listener.register_event(handle, event_type, interval, cb, cb_data); + event_listener.get_sensor_rep(sensor, cur_rep); + return change_sensor_rep(sensor, prev_rep, cur_rep); +} + +EXTAPI int sf_unregister_event(int handle, unsigned int event_type) +{ + sensor_type_t sensor; + sensor_rep prev_rep, cur_rep; + + AUTOLOCK(lock); + + if (!event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + INFO("%s unregisters event %s[0x%x] for sensor %s[%d]", get_client_name(), get_event_name(event_type), + event_type, get_sensor_name(sensor), handle); + + event_listener.get_sensor_rep(sensor, prev_rep); + + if (!event_listener.unregister_event(handle, event_type)) { + ERR("%s try to unregister non registered event %s[0x%x] for sensor %s[%d]", + get_client_name(), get_event_name(event_type), event_type, get_sensor_name(sensor), handle); + return OP_ERROR; + } + + event_listener.get_sensor_rep(sensor, cur_rep); + return change_sensor_rep(sensor, prev_rep, cur_rep); +} + +EXTAPI int sf_change_event_condition(int handle, unsigned int event_type, event_condition_t *event_condition) +{ + sensor_type_t sensor; + sensor_rep prev_rep, cur_rep; + unsigned int interval = BASE_GATHERING_INTERVAL; + AUTOLOCK(lock); + + if (!event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + if (event_condition != NULL) { + if ((event_condition->cond_op == CONDITION_EQUAL) && (event_condition->cond_value1 > 0)) + interval = event_condition->cond_value1; + } + + INFO("%s changes interval of event %s[0x%x] for %s[%d] to interval %d", get_client_name(), get_event_name(event_type), + event_type, get_sensor_name(sensor), handle, interval); + event_listener.get_sensor_rep(sensor, prev_rep); + event_listener.set_event_interval(handle, event_type, interval); + event_listener.get_sensor_rep(sensor, cur_rep); + return change_sensor_rep(sensor, prev_rep, cur_rep); +} + +int sf_change_sensor_option(int handle, int option) +{ + sensor_type_t sensor; + sensor_rep prev_rep, cur_rep; + int sensor_state; + AUTOLOCK(lock); + + if (!event_listener.get_sensor_state(handle, sensor_state) || + !event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + retvm_if ((option < 0) || (option >= SENSOR_OPTION_END), OP_ERROR, "Invalid option value : %d, handle: %d, %s, %s", + option, handle, get_sensor_name(sensor), get_client_name()); + event_listener.get_sensor_rep(sensor, prev_rep); + + if (g_power_save_state) { + if ((option == SENSOR_OPTION_ALWAYS_ON) && (sensor_state == SENSOR_STATE_PAUSED)) + event_listener.set_sensor_state(handle, SENSOR_STATE_STARTED); + else if ((option == SENSOR_OPTION_DEFAULT) && (sensor_state == SENSOR_STATE_STARTED)) + event_listener.set_sensor_state(handle, SENSOR_STATE_PAUSED); + } + + event_listener.set_sensor_option(handle, option); + event_listener.get_sensor_rep(sensor, cur_rep); + return change_sensor_rep(sensor, prev_rep, cur_rep); +} + +EXTAPI int sf_send_sensorhub_data(int handle, const char *data, int data_len) +{ + sensor_type_t sensor; + command_channel *cmd_channel; + int client_id; + AUTOLOCK(lock); + + if (!event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + retvm_if (sensor != CONTEXT_SENSOR, OP_ERROR, "%s use this API wrongly, only for CONTEXT_SENSOR not for %s", + get_client_name(), get_sensor_name(sensor)); + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("client %s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + return OP_ERROR; + } + + retvm_if((data_len < 0) || (data == NULL), OP_ERROR, "Invalid data_len: %d, data: 0x%x, handle: %d, %s, %s", + data_len, data, handle, get_sensor_name(sensor), get_client_name()); + client_id = event_listener.get_client_id(); + retvm_if ((client_id < 0), OP_ERROR, "Invalid client id : %d, handle: %d, %s, %s", client_id, handle, get_sensor_name(sensor), get_client_name()); + retvm_if (!event_listener.is_sensor_active(sensor), OP_ERROR, "%s with client_id:%d is not active state for %s with handle: %d", + get_sensor_name(sensor), client_id, get_client_name(), handle); + + if (!cmd_channel->cmd_send_sensorhub_data(data_len, data)) { + ERR("Sending cmd_send_sensorhub_data(%d, %d, 0x%x) failed for %s", + client_id, data_len, data, get_client_name); + return CMD_ERROR; + } + + return OP_SUCCESS; +} + +EXTAPI int sf_is_sensor_event_available (sensor_type_t sensor, unsigned int event) +{ + command_channel *cmd_channel; + int handle; + int client_id; + handle = sf_connect(sensor); + + if (handle < 0) { + return OP_ERROR; + } + + if (event != 0) { + AUTOLOCK(lock); + INFO("%s checks if event %s[0x%x] is registered", get_client_name(), get_event_name(event), event); + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("client %s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + return OP_ERROR; + } + + client_id = event_listener.get_client_id(); + retvm_if ((client_id < 0), OP_ERROR, "Invalid client id : %d, handle: %d, %s, %s", client_id, handle, get_sensor_name(sensor), get_client_name()); + + if (!cmd_channel->cmd_check_event(event)) { + INFO("Sensor event %s is not supported in sensor %s", get_event_name(event), get_sensor_name(sensor)); + return CMD_ERROR; + } + } + + sf_disconnect(handle); + return OP_SUCCESS; +} + +static int server_get_properties(int handle, unsigned int type, void *properties) +{ + command_channel *cmd_channel; + sensor_type_t sensor; + int client_id; + AUTOLOCK(lock); + + if (!event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("client %s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + return OP_ERROR; + } + + client_id = event_listener.get_client_id(); + retvm_if ((client_id < 0), OP_ERROR, "Invalid client id : %d, handle: %d, %s, %s", client_id, handle, get_sensor_name(sensor), get_client_name()); + INFO("%s gets property with %s[%d], property_id: %d", get_client_name(), get_sensor_name(sensor), handle, type); + + if (!cmd_channel->cmd_get_properties(type, properties)) { + ERR("Sending cmd_get_properties(%d, %s, %d, 0x%x) failed for %s", client_id, get_sensor_name(sensor), type, properties, get_client_name()); + return CMD_ERROR; + } + + return OP_SUCCESS; +} + +static int server_set_property(int handle, unsigned int property_id, long value) +{ + command_channel *cmd_channel; + sensor_type_t sensor; + int client_id; + AUTOLOCK(lock); + + if (!event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("client %s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + return OP_ERROR; + } + + client_id = event_listener.get_client_id(); + retvm_if ((client_id < 0), OP_ERROR, "Invalid client id : %d, handle: %d, %s, %s", client_id, handle, get_sensor_name(sensor), get_client_name()); + INFO("%s gets property with %s[%d], property_id: %d", get_client_name(), get_sensor_name(sensor), handle, property_id); + + if (!cmd_channel->cmd_set_command(property_id, value)) { + ERR("Cmd_set_value(%d, %s, %d, %d) failed for %s", client_id, get_sensor_name(sensor), property_id, value, get_client_name()); + return CMD_ERROR; + } + + return OP_SUCCESS; +} + +EXTAPI int sf_get_data_properties(unsigned int data_id, sensor_data_properties_t *return_data_properties) +{ + int handle; + int state = -1; + retvm_if ((!return_data_properties ), -1, "Invalid return properties pointer : %p from %s", + return_data_properties, get_client_name()); + handle = sf_connect((sensor_type_t)(data_id >> 16)); + + if (handle < 0) { + ERR("Sensor connect fail !! for : %x", (data_id >> 16)); + return OP_ERROR; + } else { + state = server_get_properties(handle, data_id, return_data_properties ); + + if (state < 0) + ERR("server_get_properties fail, state : %d", state); + + sf_disconnect(handle); + } + + return state; +} + +static unsigned int get_sensor_property_level(sensor_type_t sensor) +{ + return (sensor << SENSOR_TYPE_SHIFT) | 0x0001; +} + +EXTAPI int sf_get_properties(sensor_type_t sensor, sensor_properties_t *return_properties) +{ + int handle; + int state = -1; + retvm_if ((!return_properties ), -1, "Invalid return properties pointer : %p from %s", + return_properties, get_client_name()); + handle = sf_connect(sensor); + + if (handle < 0) { + ERR("Sensor connect fail !! for : %x", sensor); + return OP_ERROR; + } else { + state = server_get_properties(handle, get_sensor_property_level(sensor), return_properties ); + + if (state < 0) + ERR("server_get_properties fail, state : %d", state); + + sf_disconnect(handle); + } + + return state; +} + +EXTAPI int sf_set_property(sensor_type_t sensor, unsigned int property_id, long value) +{ + int handle; + int state = -1; + handle = sf_connect(sensor); + + if (handle < 0) { + ERR("Sensor connect fail !! for : %x", sensor); + return OP_ERROR; + } else { + state = server_set_property(handle, property_id, value ); + + if (state < 0) + ERR("server_set_property fail, state : %d", state); + + sf_disconnect(handle); + } + + return state; +} + +EXTAPI int sf_get_data(int handle, unsigned int data_id, sensor_data_t *sensor_data) +{ + sensor_type_t sensor; + command_channel *cmd_channel; + int sensor_state; + int client_id; + retvm_if ((!sensor_data), OP_ERROR, "sf_get_data fail, invalid get_values pointer %p", sensor_data); + AUTOLOCK(lock); + + if (!event_listener.get_sensor_state(handle, sensor_state) || + !event_listener.get_sensor_type(handle, sensor)) { + ERR("client %s failed to get handle information", get_client_name()); + return OP_ERROR; + } + + if (!event_listener.get_command_channel(sensor, &cmd_channel)) { + ERR("client %s failed to get command channel for %s", get_client_name(), get_sensor_name(sensor)); + return OP_ERROR; + } + + client_id = event_listener.get_client_id(); + retvm_if ((client_id < 0), OP_ERROR, "Invalid client id : %d, handle: %d, %s, %s", client_id, handle, get_sensor_name(sensor), get_client_name()); + + if (sensor_state != SENSOR_STATE_STARTED) { + ERR("Sensor %s is not started for client %s with handle: %d, sensor_state: %d", get_sensor_name(sensor), get_client_name(), handle, sensor_state); + return OP_ERROR; + } + + if (!cmd_channel->cmd_get_data(data_id, sensor_data)) { + ERR("Cmd_get_struct(%d, %d, 0x%x) failed for %s", client_id, data_id, sensor_data, get_client_name()); + return CMD_ERROR; + } + + return OP_SUCCESS; +} + +EXTAPI int sf_check_rotation(unsigned long *curr_state) +{ + int state = -1; + int handle = 0; + sensor_data_t sensor_data; + retvm_if (curr_state == NULL, -1, "sf_check_rotation fail, invalid curr_state"); + *curr_state = ROTATION_UNKNOWN; + + handle = sf_connect(ACCELEROMETER_SENSOR); + + if (handle < 0) { + ERR("sensor attach fail"); + return OP_ERROR; + } + + state = sf_start(handle, 1); + + if (state < 0) { + ERR("sf_start fail"); + return OP_ERROR; + } + + state = sf_get_data(handle, ACCELEROMETER_ROTATION_DATA_SET, &sensor_data); + + if (state < 0) { + ERR("sf_get_data fail"); + return OP_ERROR; + } + + state = sf_stop(handle); + + if (state < 0) { + ERR("sf_stop fail"); + return OP_ERROR; + } + + state = sf_disconnect(handle); + + if (state < 0) { + ERR("sf_disconnect fail"); + return OP_ERROR; + } + + *curr_state = sensor_data.values[0]; + + INFO("%s gets %s by checking rotation", get_client_name(), get_rotate_name(*curr_state)); + return OP_SUCCESS; +} diff --git a/src/libsensord/client_common.cpp b/src/libsensord/client_common.cpp new file mode 100755 index 0000000..62aa507 --- /dev/null +++ b/src/libsensord/client_common.cpp @@ -0,0 +1,276 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +using std::map; + +#define FILL_LOG_ELEMENT(ID, TYPE, CNT, PRINT_PER_CNT) {ID, TYPE, {#TYPE, CNT, PRINT_PER_CNT} } + +log_element g_log_elements[] = { + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, UNKNOWN_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, ACCELEROMETER_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, GEOMAGNETIC_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, LIGHT_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, PROXIMITY_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, GYROSCOPE_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, MOTION_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, GRAVITY_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, LINEAR_ACCEL_SENSOR, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_SENSOR_TYPE, ORIENTATION_SENSOR, 0, 1), + + FILL_LOG_ELEMENT(LOG_ID_EVENT, ACCELEROMETER_EVENT_ROTATION_CHECK, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, ACCELEROMETER_EVENT_CALIBRATION_NEEDED, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, ACCELEROMETER_EVENT_SET_WAKEUP, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, GEOMAGNETIC_EVENT_CALIBRATION_NEEDED, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, PROXIMITY_EVENT_CHANGE_STATE, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, LIGHT_EVENT_CHANGE_LEVEL, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, MOTION_ENGINE_EVENT_SNAP, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, MOTION_ENGINE_EVENT_SHAKE, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, MOTION_ENGINE_EVENT_DOUBLETAP, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_EVENT, MOTION_ENGINE_EVENT_DIRECT_CALL, 0, 1), + + FILL_LOG_ELEMENT(LOG_ID_EVENT, ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, PROXIMITY_EVENT_STATE_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10), + FILL_LOG_ELEMENT(LOG_ID_EVENT, ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME, 0, 10), + + FILL_LOG_ELEMENT(LOG_ID_DATA, ACCELEROMETER_BASE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, ACCELEROMETER_ORIENTATION_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, ACCELEROMETER_ROTATION_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, GYRO_BASE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, PROXIMITY_BASE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, PROXIMITY_DISTANCE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, GEOMAGNETIC_BASE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, GEOMAGNETIC_RAW_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, GEOMAGNETIC_ATTITUDE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, LIGHT_BASE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, LIGHT_LUX_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, GRAVITY_BASE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, LINEAR_ACCEL_BASE_DATA_SET, 0, 25), + FILL_LOG_ELEMENT(LOG_ID_DATA, ORIENTATION_BASE_DATA_SET, 0, 25), + + FILL_LOG_ELEMENT(LOG_ID_ROTATE, ROTATION_EVENT_0, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_ROTATE, ROTATION_EVENT_90, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_ROTATE, ROTATION_EVENT_180, 0, 1), + FILL_LOG_ELEMENT(LOG_ID_ROTATE, ROTATION_EVENT_270, 0, 1), +}; + +typedef map log_map; +log_map g_log_maps[LOG_ID_END]; + +extern void init_client(void); +static void init_log_maps(void); + +class initiator +{ +public: + initiator() + { + init_log_maps(); + init_client(); + } +} g_initiatior; + +static void init_log_maps(void) +{ + int cnt; + cnt = sizeof(g_log_elements) / sizeof(g_log_elements[0]); + + for (int i = 0; i < cnt; ++i) { + g_log_maps[g_log_elements[i].id][g_log_elements[i].type] = &g_log_elements[i].log_attr; + } +} + +const char *get_log_element_name(log_id id, unsigned int type) +{ + const char *p_unknown = "UNKNOWN"; + log_map::iterator iter; + iter = g_log_maps[id].find(type); + + if (iter == g_log_maps[id].end()) { + INFO("Unknown type value: 0x%x", type); + return p_unknown; + } + + return iter->second->name; +} + +const char *get_sensor_name(sensor_type_t sensor_type) +{ + return get_log_element_name(LOG_ID_SENSOR_TYPE, sensor_type); +} + +const char *get_event_name(unsigned int event_type) +{ + return get_log_element_name(LOG_ID_EVENT, event_type); +} + +const char *get_data_name(unsigned int data_id) +{ + return get_log_element_name(LOG_ID_DATA, data_id); +} + +const char *get_rotate_name(unsigned int rotate_type) +{ + return get_log_element_name(LOG_ID_ROTATE, rotate_type); +} + +bool is_one_shot_event(unsigned int event_type) +{ + switch (event_type) { + case ACCELEROMETER_EVENT_SET_WAKEUP: + return true; + break; + } + + return false; +} + +bool is_ontime_event(unsigned int event_type) +{ + switch (event_type ) { + case ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME: + case ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME: + case GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME: + case GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME: + case GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME: + case LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME: + case LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME: + case PROXIMITY_EVENT_STATE_REPORT_ON_TIME: + case PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME: + case GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME: + case LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME: + case ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME: + return true; + break; + } + + return false; +} + +bool is_panning_event(unsigned int event_type) +{ + return false; +} + +bool is_single_state_event(unsigned int event_type) +{ + switch (event_type) { + case ACCELEROMETER_EVENT_SET_WAKEUP: + case ACCELEROMETER_EVENT_ROTATION_CHECK: + case GEOMAGNETIC_EVENT_CALIBRATION_NEEDED: + case LIGHT_EVENT_CHANGE_LEVEL: + case PROXIMITY_EVENT_CHANGE_STATE: + case MOTION_ENGINE_EVENT_SNAP: + case MOTION_ENGINE_EVENT_SHAKE: + case MOTION_ENGINE_EVENT_DOUBLETAP: + case MOTION_ENGINE_EVENT_DIRECT_CALL: + return true; + break; + } + + return false; +} + +unsigned int get_calibration_event_type(unsigned int event_type) +{ + sensor_type_t sensor; + sensor = (sensor_type_t)(event_type >> SENSOR_TYPE_SHIFT); + + switch (sensor) { + case GEOMAGNETIC_SENSOR: + return GEOMAGNETIC_EVENT_CALIBRATION_NEEDED; + case ORIENTATION_SENSOR: + return ORIENTATION_EVENT_CALIBRATION_NEEDED; + default: + return 0; + } +} + +unsigned long long get_timestamp(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return ((unsigned long long)(t.tv_sec) * NS_TO_SEC + t.tv_nsec) / MS_TO_SEC; +} + +void sensor_event_to_data(sensor_event_t &event, sensor_data_t &data) +{ + data.data_accuracy = event.data.data_accuracy; + data.data_unit_idx = event.data.data_unit_idx; + data.timestamp = event.data.timestamp; + data.values_num = event.data.values_num; + memcpy(data.values, event.data.values, sizeof(event.data.values)); +} + +void sensorhub_event_to_hub_data(sensorhub_event_t &event, sensorhub_data_t &data) +{ + data.version = event.data.version; + data.sensorhub = event.data.sensorhub; + data.type = event.data.type; + data.hub_data_size = event.data.hub_data_size; + data.timestamp = event.data.timestamp; + memcpy(data.hub_data, event.data.hub_data, event.data.hub_data_size); + memcpy(data.data, event.data.data, sizeof(event.data.data)); +} + +void print_event_occurrence_log(csensor_handle_info &sensor_handle_info, creg_event_info &event_info, + sensor_event_data_t &sensor_event_data) +{ + log_attr *log_attr; + log_map::iterator iter; + iter = g_log_maps[LOG_ID_EVENT].find(event_info.m_event_type); + + if (iter == g_log_maps[LOG_ID_EVENT].end()) { + ERR("wrong event_type: 0x%x, handle %d", event_info.m_event_type, sensor_handle_info.m_handle); + return; + } + + log_attr = iter->second; + log_attr->cnt++; + + if ((log_attr->cnt != 1) && ((log_attr->cnt % log_attr->print_per_cnt) != 0)) { + return; + } + + INFO("%s receives %s with %s[%d][state: %d, option: %d count: %d]", get_client_name(), log_attr->name, + get_sensor_name(sensor_handle_info.m_sensor_type), sensor_handle_info.m_handle, sensor_handle_info.m_sensor_state, + sensor_handle_info.m_sensor_option, log_attr->cnt); + + if (event_info.m_event_type == ACCELEROMETER_EVENT_ROTATION_CHECK) { + INFO("%s", get_rotate_name(*(unsigned int *)(sensor_event_data.event_data))); + } + + INFO("0x%x(cb_event_type = %s, &cb_data, client_data = 0x%x)", event_info.m_event_callback, + log_attr->name, event_info.m_cb_data); +} diff --git a/src/libsensord/client_common.h b/src/libsensord/client_common.h new file mode 100755 index 0000000..dc8c78b --- /dev/null +++ b/src/libsensord/client_common.h @@ -0,0 +1,82 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CLIENT_COMMON_H_ +#define CLIENT_COMMON_H_ + +#include +#include +#include +#include + +#define BASE_GATHERING_INTERVAL 100 +#define CLIENT_NAME_SIZE NAME_MAX+10 + +enum log_id { + LOG_ID_START = 0, + LOG_ID_SENSOR_TYPE = 0, + LOG_ID_EVENT, + LOG_ID_DATA, + LOG_ID_PROPERTY, + LOG_ID_ROTATE, + LOG_ID_END, +}; + +struct log_attr { + const char *name; + unsigned long cnt; + const unsigned int print_per_cnt; +}; + +struct log_element { + log_id id; + unsigned int type; + struct log_attr log_attr; +}; + +typedef struct { + int handle; + unsigned int event_type; + sensor_event_data_t ev_data; + int sensor_state; + int sensor_option; + sensor_type_t sensor; + creg_event_info event_info; +} log_info; + +bool is_sensorhub_event(unsigned int event_type); +bool is_one_shot_event(unsigned int event_type); +bool is_ontime_event(unsigned int event_type); +bool is_panning_event(unsigned int event_type); +bool is_single_state_event(unsigned int event_type); +unsigned int get_calibration_event_type(unsigned int event_type); +unsigned long long get_timestamp(void); +void sensor_event_to_data(sensor_event_t &event, sensor_data_t &data); +void sensorhub_event_to_hub_data(sensorhub_event_t &event, sensorhub_data_t &data); + +const char *get_log_element_name(log_id id, unsigned int type); +const char *get_sensor_name(sensor_type_t sensor_type); +const char *get_event_name(unsigned int event_type); +const char *get_data_name(unsigned int data_id); +const char *get_rotate_name(unsigned int rotate_type); +void print_event_occurrence_log(csensor_handle_info &sensor_handle_info, + creg_event_info &event_info, + sensor_event_data_t &event_data); + +#endif /* CLIENT_COMMON_H_ */ diff --git a/src/libsensord/command_channel.cpp b/src/libsensord/command_channel.cpp new file mode 100755 index 0000000..c9c6681 --- /dev/null +++ b/src/libsensord/command_channel.cpp @@ -0,0 +1,675 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +command_channel::command_channel() +: m_client_id(CLIENT_ID_INVALID) +, m_sensor_type(UNKNOWN_SENSOR) +{ +} + +command_channel::~command_channel() +{ + if (m_command_socket.is_valid()) + m_command_socket.close(); +} + +bool command_channel::command_handler(cpacket *packet, void **return_payload) +{ + if (!m_command_socket.is_valid()) { + ERR("Command socket(%d) is not valid for client %s", m_command_socket.get_socket_fd(), get_client_name()); + return false; + } + + if (packet->size() < 0) { + ERR("Packet is not valid for client %s", get_client_name()); + return false; + } + + if (m_command_socket.send(packet->packet(), packet->size()) <= 0) { + ERR("Failed to send command in client %s", get_client_name()); + return false; + } + + packet_header header; + + if (m_command_socket.recv(&header, sizeof(header)) <= 0) { + ERR("Failed to receive header for reply packet in client %s", get_client_name()); + return false; + } + + char *buffer = new char[header.size]; + + if (m_command_socket.recv(buffer, header.size) <= 0) { + ERR("Failed to receive reply packet in client %s", get_client_name()); + delete[] buffer; + return false; + } + + *return_payload = buffer; + return true; +} + +bool command_channel::create_channel(void) +{ + if (!m_command_socket.create(SOCK_STREAM)) + return false; + + if (!m_command_socket.connect(COMMAND_CHANNEL_PATH)) { + ERR("Failed to connect command channel for client %s, command socket fd[%d]", get_client_name(), m_command_socket.get_socket_fd()); + return false; + } + + m_command_socket.set_connection_mode(); + return true; +} + +void command_channel::set_client_id(int client_id) +{ + m_client_id = client_id; +} + +bool command_channel::cmd_get_id(int &client_id) +{ + cpacket *packet; + cmd_get_id_t *cmd_get_id; + cmd_get_id_done_t *cmd_get_id_done; + + packet = new cpacket(sizeof(cmd_get_id_t)); + packet->set_cmd(CMD_GET_ID); + packet->set_payload_size(sizeof(cmd_get_id_t)); + cmd_get_id = (cmd_get_id_t *)packet->data(); + cmd_get_id->pid = getpid(); + + INFO("%s send cmd_get_id()", get_client_name()); + + if (!command_handler(packet, (void **)&cmd_get_id_done)) { + ERR("Client %s failed to send/receive command", get_client_name()); + delete packet; + return false; + } + + if (cmd_get_id_done->client_id < 0) { + ERR("Client %s failed to get client_id[%d] from server", + get_client_name(), cmd_get_id_done->client_id); + delete[] (char *)cmd_get_id_done; + delete packet; + return false; + } + + client_id = cmd_get_id_done->client_id; + + delete[] (char *)cmd_get_id_done; + delete packet; + return true; +} + +bool command_channel::cmd_hello(sensor_type_t sensor) +{ + cpacket *packet; + cmd_hello_t *cmd_hello; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_hello_t)); + packet->set_cmd(CMD_HELLO); + packet->set_payload_size(sizeof(cmd_hello_t)); + cmd_hello = (cmd_hello_t *)packet->data(); + cmd_hello->client_id = m_client_id; + cmd_hello->sensor = sensor; + + INFO("%s send cmd_hello(client_id=%d, %s)", + get_client_name(), m_client_id, get_sensor_name(sensor)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command for sensor[%s]", + get_client_name(), get_sensor_name(sensor)); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("client %s got error[%d] from server with sensor [%s]", + get_client_name(), cmd_done->value, get_sensor_name(sensor)); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + m_sensor_type = sensor; + return true; +} + +bool command_channel::cmd_byebye(void) +{ + cpacket *packet; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_byebye_t)); + packet->set_cmd(CMD_BYEBYE); + packet->set_payload_size(sizeof(cmd_byebye_t)); + + INFO("%s send cmd_byebye(client_id=%d, %s)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command for sensor[%s] with client_id [%d]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server for sensor[%s] with client_id [%d]", + get_client_name(), cmd_done->value, get_sensor_name(m_sensor_type), m_client_id); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + + if (m_command_socket.is_valid()) + m_command_socket.close(); + + m_client_id = CLIENT_ID_INVALID; + m_sensor_type = UNKNOWN_SENSOR; + return true; +} + +bool command_channel::cmd_start(void) +{ + cpacket *packet; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_start_t)); + packet->set_cmd(CMD_START); + packet->set_payload_size(sizeof(cmd_start_t)); + + INFO("%s send cmd_start(client_id=%d, %s)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command for sensor[%s] with client_id [%d]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server for sensor[%s] with client_id [%d]", + get_client_name(), cmd_done->value, get_sensor_name(m_sensor_type), m_client_id); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_stop(void) +{ + cpacket *packet; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_stop_t)); + packet->set_cmd(CMD_STOP); + packet->set_payload_size(sizeof(cmd_stop_t)); + + INFO("%s send cmd_stop(client_id=%d, %s)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command for sensor[%s] with client_id [%d]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server for sensor[%s] with client_id [%d]", + get_client_name(), cmd_done->value, get_sensor_name(m_sensor_type), m_client_id); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_set_option(int option) +{ + cpacket *packet; + cmd_set_option_t *cmd_set_option; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_set_option_t)); + packet->set_cmd(CMD_SET_OPTION); + packet->set_payload_size(sizeof(cmd_set_option_t)); + cmd_set_option = (cmd_set_option_t *)packet->data(); + cmd_set_option->option = option; + + INFO("%s send cmd_set_option(client_id=%d, %s, option=%d)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type), option); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command for sensor[%s] with client_id [%d], option[%]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id, option); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server for sensor[%s] with client_id [%d], option[%]", + get_client_name(), cmd_done->value, get_sensor_name(m_sensor_type), m_client_id, option); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_register_event(unsigned int event_type) +{ + cpacket *packet; + cmd_reg_t *cmd_reg; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_reg_t)); + packet->set_cmd(CMD_REG); + packet->set_payload_size(sizeof(cmd_reg_t)); + cmd_reg = (cmd_reg_t *)packet->data(); + cmd_reg->event_type = event_type; + + INFO("%s send cmd_register_event(client_id=%d, %s)", + get_client_name(), m_client_id, get_event_name(event_type)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command with client_id [%d], event_type[%s]", + get_client_name(), m_client_id, get_event_name(event_type)); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server with client_id [%d], event_type[%s]", + get_client_name(), cmd_done->value, m_client_id, get_event_name(event_type)); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_register_events(event_type_vector &event_vec) +{ + event_type_vector::iterator it_event; + it_event = event_vec.begin(); + + while (it_event != event_vec.end()) { + if (!cmd_register_event(*it_event)) + return false; + + ++it_event; + } + + return true; +} + +bool command_channel::cmd_unregister_event(unsigned int event_type) +{ + cpacket *packet; + cmd_unreg_t *cmd_unreg; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_unreg_t)); + packet->set_cmd(CMD_UNREG); + packet->set_payload_size(sizeof(cmd_unreg_t)); + cmd_unreg = (cmd_unreg_t *)packet->data(); + cmd_unreg->event_type = event_type; + + INFO("%s send cmd_unregister_event(client_id=%d, %s)", + get_client_name(), m_client_id, get_event_name(event_type)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command with client_id [%d], event_type[%s]", + get_client_name(), m_client_id, get_event_name(event_type)); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server with client_id [%d], event_type[%s]", + get_client_name(), cmd_done->value, m_client_id, get_event_name(event_type)); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_unregister_events(event_type_vector &event_vec) +{ + event_type_vector::iterator it_event; + it_event = event_vec.begin(); + + while (it_event != event_vec.end()) { + if (!cmd_unregister_event(*it_event)) + return false; + + ++it_event; + } + + return true; +} + +bool command_channel::cmd_check_event(unsigned int event_type) +{ + cpacket *packet; + cmd_check_event_t *cmd_check_event; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_check_event_t)); + packet->set_cmd(CMD_CHECK_EVENT); + packet->set_payload_size(sizeof(cmd_check_event_t)); + cmd_check_event = (cmd_check_event_t *)packet->data(); + cmd_check_event->event_type = event_type; + + INFO("%s send cmd_check_event(client_id=%d, %s)", + get_client_name(), m_client_id, get_event_name(event_type)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command with client_id [%d], event_type[%s]", + get_client_name(), m_client_id, get_event_name(event_type)); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_set_interval(unsigned int interval) +{ + cpacket *packet; + cmd_set_interval_t *cmd_set_interval; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_set_interval_t)); + packet->set_cmd(CMD_SET_INTERVAL); + packet->set_payload_size(sizeof(cmd_set_interval_t)); + cmd_set_interval = (cmd_set_interval_t *)packet->data(); + cmd_set_interval->interval = interval; + + INFO("%s send cmd_set_interval(client_id=%d, %s, interval=%d)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type), interval); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("%s failed to send/receive command for sensor[%s] with client_id [%d], interval[%d]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id, interval); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("%s got error[%d] from server for sensor[%s] with client_id [%d], interval[%d]", + get_client_name(), cmd_done->value, get_sensor_name(m_sensor_type), m_client_id, interval); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_unset_interval(void) +{ + cpacket *packet; + cmd_done_t *cmd_done; + packet = new cpacket(sizeof(cmd_unset_interval_t)); + packet->set_cmd(CMD_UNSET_INTERVAL); + packet->set_payload_size(sizeof(cmd_unset_interval_t)); + + INFO("%s send cmd_unset_interval(client_id=%d, %s)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type)); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command for sensor[%s] with client_id [%d]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server for sensor[%s] with client_id [%d]", + get_client_name(), cmd_done->value, get_sensor_name(m_sensor_type), m_client_id); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +static bool is_sensor_property(unsigned int type) +{ + return ((type & 0xFFFF) == 1); +} + +bool command_channel::cmd_get_properties(unsigned int type, void *properties) +{ + cpacket *packet; + cmd_get_properties_t *cmd_get_properties; + cmd_properties_done_t *cmd_properties_done; + + packet = new cpacket(sizeof(cmd_get_properties_t)); + packet->set_cmd(CMD_GET_PROPERTIES); + packet->set_payload_size(sizeof(cmd_get_properties_t)); + cmd_get_properties = (cmd_get_properties_t *)packet->data(); + cmd_get_properties->type = type; + + INFO("%s send cmd_get_properties(client_id=%d, %s, %s)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type), get_data_name(type)); + + if (!command_handler(packet, (void **)&cmd_properties_done)) { + ERR("Client %s failed to send/receive command for sensor[%s] with client_id [%d], data_id[%s]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id, get_data_name(type)); + delete packet; + return false; + } + + if (cmd_properties_done->state < 0) { + ERR("Client %s got error[%d] from server for sensor[%s] with client_id [%d], data_id[%s]", + get_client_name(), cmd_properties_done->state, get_sensor_name(m_sensor_type), m_client_id, get_data_name(type)); + delete[] (char *)cmd_properties_done; + delete packet; + return false; + } + + sensor_properties_t *ret_properties; + ret_properties = &cmd_properties_done->properties; + + if (is_sensor_property(type)) { + sensor_properties_t *sensor_properties; + sensor_properties = (sensor_properties_t *)properties; + sensor_properties->sensor_unit_idx = ret_properties->sensor_unit_idx; + sensor_properties->sensor_min_range = ret_properties->sensor_min_range; + sensor_properties->sensor_max_range = ret_properties->sensor_max_range; + sensor_properties->sensor_resolution = ret_properties->sensor_resolution; + strncpy(sensor_properties->sensor_name, ret_properties->sensor_name, strlen(ret_properties->sensor_name)); + strncpy(sensor_properties->sensor_vendor, ret_properties->sensor_vendor, strlen(ret_properties->sensor_vendor)); + } else { + sensor_data_properties_t *data_properies; + data_properies = (sensor_data_properties_t *)properties; + data_properies->sensor_unit_idx = ret_properties->sensor_unit_idx ; + data_properies->sensor_min_range = ret_properties->sensor_min_range; + data_properies->sensor_max_range = ret_properties->sensor_max_range; + data_properies->sensor_resolution = ret_properties->sensor_resolution; + } + + delete[] (char *)cmd_properties_done; + delete packet; + return true; +} + +bool command_channel::cmd_set_command(unsigned int cmd, long value) +{ + cpacket *packet; + cmd_set_command_t *cmd_set_command; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_set_command_t)); + packet->set_cmd(CMD_SET_COMMAND); + packet->set_payload_size(sizeof(cmd_set_command_t)); + cmd_set_command = (cmd_set_command_t *)packet->data(); + cmd_set_command->cmd = cmd; + cmd_set_command->value = value; + + INFO("%s send cmd_set_command(client_id=%d, %s, 0x%x, %ld)", + get_client_name(), m_client_id, get_sensor_name(m_sensor_type), cmd, value); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("Client %s failed to send/receive command for sensor[%s] with client_id [%d], property[0x%x], value[%d]", + get_client_name(), get_sensor_name(m_sensor_type), m_client_id, cmd, value); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("Client %s got error[%d] from server for sensor[%s] with property[0x%x], value[%d]", + get_client_name(), cmd_done->value, get_sensor_name(m_sensor_type), cmd, value); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} + +bool command_channel::cmd_get_data(unsigned int type, sensor_data_t *sensor_data) +{ + cpacket *packet; + cmd_get_data_t *cmd_get_data; + cmd_get_data_done_t *cmd_get_data_done; + + packet = new cpacket(sizeof(cmd_get_data_done_t)); + packet->set_cmd(CMD_GET_DATA); + packet->set_payload_size(sizeof(cmd_get_data_t)); + cmd_get_data = (cmd_get_data_t *)packet->data(); + cmd_get_data->type = type; + + if (!command_handler(packet, (void **)&cmd_get_data_done)) { + ERR("Client %s failed to send/receive command with client_id [%d], data_id[%s]", + get_client_name(), m_client_id, get_data_name(type)); + delete packet; + return false; + } + + if (cmd_get_data_done->state < 0) { + ERR("Client %s got error[%d] from server with client_id [%d], data_id[%s]", + get_client_name(), cmd_get_data_done->state, m_client_id, get_data_name(type)); + sensor_data->data_accuracy = SENSOR_ACCURACY_UNDEFINED; + sensor_data->data_unit_idx = SENSOR_UNDEFINED_UNIT; + sensor_data->timestamp = 0; + sensor_data->values_num = 0; + + delete[] (char *)cmd_get_data_done; + delete packet; + return false; + } + + sensor_data_t *base_data; + base_data = &cmd_get_data_done->base_data; + sensor_data->timestamp = base_data->timestamp; + sensor_data->data_accuracy = base_data->data_accuracy; + sensor_data->data_unit_idx = base_data->data_unit_idx; + sensor_data->values_num = base_data->values_num; + memcpy(sensor_data->values, base_data->values, + sizeof(sensor_data->values[0]) * base_data->values_num); + + delete[] (char *)cmd_get_data_done; + delete packet; + return true; +} + +bool command_channel::cmd_send_sensorhub_data(int data_len, const char *buffer) +{ + cpacket *packet; + cmd_send_sensorhub_data_t *cmd_send_sensorhub_data; + cmd_done_t *cmd_done; + + packet = new cpacket(sizeof(cmd_send_sensorhub_data_t) + data_len); + packet->set_cmd(CMD_SEND_SENSORHUB_DATA); + cmd_send_sensorhub_data = (cmd_send_sensorhub_data_t *)packet->data(); + cmd_send_sensorhub_data->data_len = data_len; + memcpy(cmd_send_sensorhub_data->data, buffer, data_len); + + INFO("%s send cmd_send_sensorhub_data(client_id=%d, data_len = %d, buffer = 0x%x)", + get_client_name(), m_client_id, data_len, buffer); + + if (!command_handler(packet, (void **)&cmd_done)) { + ERR("%s failed to send/receive command with client_id [%d]", + get_client_name(), m_client_id); + delete packet; + return false; + } + + if (cmd_done->value < 0) { + ERR("%s got error[%d] from server with client_id [%d]", + get_client_name(), cmd_done->value, m_client_id); + delete[] (char *)cmd_done; + delete packet; + return false; + } + + delete[] (char *)cmd_done; + delete packet; + return true; +} diff --git a/src/libsensord/command_channel.h b/src/libsensord/command_channel.h new file mode 100755 index 0000000..13d84e1 --- /dev/null +++ b/src/libsensord/command_channel.h @@ -0,0 +1,64 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _COMMAND_CHANNEL_H_ +#define _COMMAND_CHANNEL_H_ +#include +#include +#include +#include +#include + +using std::vector; + +class command_channel +{ +public: + + command_channel(); + ~command_channel(); + + bool create_channel(void); + void set_client_id(int client_id); + + bool cmd_get_id(int &client_id); + bool cmd_hello(sensor_type_t sensor); + bool cmd_byebye(void); + bool cmd_start(void); + bool cmd_stop(void); + bool cmd_set_option(int option); + bool cmd_register_event(unsigned int event_type); + bool cmd_register_events(event_type_vector &event_vec); + bool cmd_unregister_event(unsigned int event_type); + bool cmd_unregister_events(event_type_vector &event_vec); + bool cmd_check_event(unsigned int event_type); + bool cmd_set_interval(unsigned int interval); + bool cmd_unset_interval(void); + bool cmd_get_properties(unsigned int type, void *properties); + bool cmd_set_command(unsigned int cmd, long value); + bool cmd_get_data(unsigned int type, sensor_data_t *values); + bool cmd_send_sensorhub_data(int data_len, const char *buffer); +private: + csocket m_command_socket; + int m_client_id; + sensor_type_t m_sensor_type; + bool command_handler(cpacket *packet, void **return_payload); +}; + +#endif /* COMMAND_CHANNEL_H_ */ diff --git a/src/libsensord/creg_event_info.h b/src/libsensord/creg_event_info.h new file mode 100755 index 0000000..9ccf473 --- /dev/null +++ b/src/libsensord/creg_event_info.h @@ -0,0 +1,46 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CREG_EVENT_INFO_H_ +#define CREG_EVENT_INFO_H_ + +#include +#include + +class creg_event_info +{ +public: + unsigned long long m_id; + int m_handle; + unsigned int m_event_type; + unsigned int m_event_interval; + sensor_callback_func_t m_event_callback; + void *m_cb_data; + unsigned long long m_previous_event_time; + bool m_fired; + + creg_event_info(): m_id(0), m_handle(-1), + m_event_type(0), m_event_interval(POLL_1HZ_MS), + m_event_callback(NULL), m_cb_data(NULL), + m_previous_event_time(0), m_fired(false) {} + + ~creg_event_info() {} +}; + +#endif /* CREG_EVENT_INFO_H_ */ diff --git a/src/libsensord/csensor_event_listener.cpp b/src/libsensord/csensor_event_listener.cpp new file mode 100755 index 0000000..ae0fd4f --- /dev/null +++ b/src/libsensord/csensor_event_listener.cpp @@ -0,0 +1,818 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using std::thread; +using std::pair; + +csensor_event_listener::csensor_event_listener() +: m_client_id(CLIENT_ID_INVALID) +, m_thread_state(THREAD_STATE_TERMINATE) +, m_poller(NULL) +{ +} + +csensor_event_listener::~csensor_event_listener() +{ + stop_event_listener(); +} + +int csensor_event_listener::create_handle(const sensor_type_t sensor) +{ + csensor_handle_info handle_info; + int handle = 0; + + AUTOLOCK(m_handle_info_lock); + + while (m_sensor_handle_infos.count(handle) > 0) + handle++; + + if (handle == MAX_HANDLE) { + ERR("Handles of client %s are full", get_client_name()); + return MAX_HANDLE_REACHED; + } + + handle_info.m_sensor_type = sensor; + handle_info.m_sensor_state = SENSOR_STATE_STOPPED; + handle_info.m_sensor_option = SENSOR_OPTION_DEFAULT; + handle_info.m_handle = handle; + m_sensor_handle_infos.insert(pair (handle, handle_info)); + return handle; +} + +bool csensor_event_listener::delete_handle(const int handle) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + m_sensor_handle_infos.erase(it_handle); + return true; +} + +bool csensor_event_listener::is_active() +{ + AUTOLOCK(m_handle_info_lock); + + return !m_sensor_handle_infos.empty(); +} + +bool csensor_event_listener::start_handle(const int handle) +{ + return set_sensor_state(handle, SENSOR_STATE_STARTED); +} + +bool csensor_event_listener::stop_handle(const int handle) +{ + return set_sensor_state(handle, SENSOR_STATE_STOPPED); +} + +bool csensor_event_listener::register_event(const int handle, const unsigned int event_type, + const unsigned int interval, const sensor_callback_func_t callback, void *cb_data) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + if (!it_handle->second.add_reg_event_info(event_type, interval, callback, cb_data)) + return false; + + return true; +} + +bool csensor_event_listener::unregister_event(const int handle, const unsigned int event_type) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + if (!it_handle->second.delete_reg_event_info(event_type)) + return false; + + return true; +} + +bool csensor_event_listener::change_event_interval(const int handle, const unsigned int event_type, + const unsigned int interval) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + if (!it_handle->second.change_reg_event_interval(event_type, interval)) + return false; + + return true; +} + +bool csensor_event_listener::set_sensor_params(const int handle, int sensor_state, int sensor_option) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + it_handle->second.m_sensor_state = sensor_state; + it_handle->second.m_sensor_option = sensor_option; + + return true; +} + +bool csensor_event_listener::set_sensor_state(const int handle, const int sensor_state) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + it_handle->second.m_sensor_state = sensor_state; + + return true; +} + +bool csensor_event_listener::set_sensor_option(const int handle, const int sensor_option) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + it_handle->second.m_sensor_option = sensor_option; + + return true; +} + +bool csensor_event_listener::set_event_interval(const int handle, const unsigned int event_type, const unsigned int interval) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + if (!it_handle->second.change_reg_event_interval(event_type, interval)) + return false; + + return true; +} + +void csensor_event_listener::get_listening_sensors(sensor_type_vector &sensors) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + sensors.push_back(it_handle->second.m_sensor_type); + ++it_handle; + } + + sort(sensors.begin(), sensors.end()); + unique(sensors.begin(), sensors.end()); +} + +void csensor_event_listener::get_sensor_rep(sensor_type_t sensor, sensor_rep &rep) +{ + AUTOLOCK(m_handle_info_lock); + + rep.active = is_sensor_active(sensor); + rep.option = get_active_option(sensor); + rep.interval = get_active_min_interval(sensor); + get_active_event_types(sensor, rep.event_types); +} + +void csensor_event_listener::pause_sensor(const sensor_type_t sensor) +{ + sensor_handle_info_map::iterator it_handle; + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + if ((it_handle->second.m_sensor_type == sensor) && + (it_handle->second.m_sensor_state == SENSOR_STATE_STARTED) && + (it_handle->second.m_sensor_option != SENSOR_OPTION_ALWAYS_ON)) { + it_handle->second.m_sensor_state = SENSOR_STATE_PAUSED; + INFO("%s's %s[%d] is paused", get_client_name(), get_sensor_name(sensor), it_handle->first); + } + + ++it_handle; + } +} + +void csensor_event_listener::resume_sensor(const sensor_type_t sensor) +{ + sensor_handle_info_map::iterator it_handle; + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + if ((it_handle->second.m_sensor_type == sensor) && + (it_handle->second.m_sensor_state == SENSOR_STATE_PAUSED)) { + it_handle->second.m_sensor_state = SENSOR_STATE_STARTED; + INFO("%s's %s[%d] is resumed", get_client_name(), get_sensor_name(sensor), it_handle->first); + } + + ++it_handle; + } +} + +bool csensor_event_listener::set_command_channel(sensor_type_t sensor, command_channel *cmd_channel) +{ + sensor_command_channel_map::iterator it_channel; + it_channel = m_command_channels.find(sensor); + + if (it_channel != m_command_channels.end()) { + ERR("%s alreay has command_channel for %s", get_client_name(), get_sensor_name(sensor)); + return false; + } + + m_command_channels.insert(pair (sensor, cmd_channel)); + return true; +} + +bool csensor_event_listener::get_command_channel(sensor_type_t sensor, command_channel **cmd_channel) +{ + sensor_command_channel_map::iterator it_channel; + it_channel = m_command_channels.find(sensor); + + if (it_channel == m_command_channels.end()) { + ERR("%s doesn't have command_channel for %s", get_client_name(), get_sensor_name(sensor)); + return false; + } + + *cmd_channel = it_channel->second; + return true; +} + +bool csensor_event_listener::close_command_channel(sensor_type_t sensor) +{ + sensor_command_channel_map::iterator it_channel; + it_channel = m_command_channels.find(sensor); + + if (it_channel == m_command_channels.end()) { + ERR("%s doesn't have command_channel for %s", get_client_name(), get_sensor_name(sensor)); + return false; + } + + delete it_channel->second; + m_command_channels.erase(it_channel); + return true; +} + +bool csensor_event_listener::has_client_id(void) +{ + return (m_client_id != CLIENT_ID_INVALID); +} + +int csensor_event_listener::get_client_id(void) +{ + return m_client_id; +} + +void csensor_event_listener::set_client_id(const int client_id) +{ + m_client_id = client_id; +} + +unsigned int csensor_event_listener::get_active_min_interval(const sensor_type_t sensor) +{ + unsigned int min_interval = POLL_MAX_HZ_MS; + bool active_sensor_found = false; + unsigned int interval; + + AUTOLOCK(m_handle_info_lock); + sensor_handle_info_map::iterator it_handle; + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + if ((it_handle->second.m_sensor_type == sensor) && + (it_handle->second.m_sensor_state == SENSOR_STATE_STARTED)) { + active_sensor_found = true; + interval = it_handle->second.get_min_interval(); + min_interval = (interval < min_interval) ? interval : min_interval; + } + + ++it_handle; + } + + if (!active_sensor_found) + DBG("Active sensor[0x%x] is not found for client %s", sensor, get_client_name()); + + return (active_sensor_found) ? min_interval : 0; +} + +unsigned int csensor_event_listener::get_active_option(const sensor_type_t sensor) +{ + int active_option = SENSOR_OPTION_DEFAULT; + bool active_sensor_found = false; + int option; + AUTOLOCK(m_handle_info_lock); + sensor_handle_info_map::iterator it_handle; + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + if ((it_handle->second.m_sensor_type == sensor) && + (it_handle->second.m_sensor_state == SENSOR_STATE_STARTED)) { + active_sensor_found = true; + option = it_handle->second.m_sensor_option; + active_option = (option > active_option) ? option : active_option; + } + + ++it_handle; + } + + if (!active_sensor_found) + DBG("Active sensor[0x%x] is not found for client %s", sensor, get_client_name()); + + return active_option; +} + +bool csensor_event_listener::get_sensor_type(const int handle, sensor_type_t &sensor) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + sensor = it_handle->second.m_sensor_type; + return true; +} + +bool csensor_event_listener::get_sensor_state(const int handle, int &sensor_state) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) { + ERR("Handle[%d] is not found for client %s", handle, get_client_name()); + return false; + } + + sensor_state = it_handle->second.m_sensor_state; + return true; +} + +void csensor_event_listener::get_active_event_types(const sensor_type_t sensor, + event_type_vector &active_event_types) +{ + event_type_vector event_types; + + AUTOLOCK(m_handle_info_lock); + sensor_handle_info_map::iterator it_handle; + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + if ((it_handle->second.m_sensor_type == sensor) && + (it_handle->second.m_sensor_state == SENSOR_STATE_STARTED)) + it_handle->second.get_reg_event_types(event_types); + + ++it_handle; + } + + if (event_types.empty()) + return; + + sort(event_types.begin(), event_types.end()); + unique_copy(event_types.begin(), event_types.end(), back_inserter(active_event_types)); +} + +void csensor_event_listener::get_all_handles(handle_vector &handles) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + handles.push_back(it_handle->first); + ++it_handle; + } +} + +bool csensor_event_listener::is_sensor_registered(const sensor_type_t sensor) +{ + sensor_handle_info_map::iterator it_handle; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + if (it_handle->second.m_sensor_type == sensor) + return true; + + ++it_handle; + } + + return false; +} + +bool csensor_event_listener::is_sensor_active(const sensor_type_t sensor) +{ + sensor_handle_info_map::iterator it_handle; + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.begin(); + + while (it_handle != m_sensor_handle_infos.end()) { + if ((it_handle->second.m_sensor_type == sensor) && + (it_handle->second.m_sensor_state == SENSOR_STATE_STARTED)) + return true; + + ++it_handle; + } + + return false; +} + +void csensor_event_listener::handle_events(void *event) +{ + const unsigned int MS_TO_US = 1000; + const float MIN_DELIVERY_DIFF_FACTOR = 0.75f; + + unsigned long long cur_time; + long long diff_time; + creg_event_info event_info; + sensor_event_data_t event_data; + int situation; + + sensor_data_t sensor_data; + sensorhub_data_t sensorhub_data; + sensor_panning_data_t panning_data; + int single_state_event_data = 0; + int data_accuracy = SENSOR_ACCURACY_GOOD; + + unsigned int event_type = *((unsigned int *)(event)); + bool is_hub_event = is_sensorhub_event(event_type); + + client_callback_info *callback_info; + vector client_callback_infos; + sensor_handle_info_map::iterator it_handle; + + if (is_hub_event) { + sensorhub_event_t *sensor_hub_event = (sensorhub_event_t *)event; + sensorhub_event_to_hub_data(*sensor_hub_event, sensorhub_data); + event_data.event_data = &sensorhub_data; + event_data.event_data_size = sizeof(sensorhub_data); + situation = sensor_hub_event->situation; + cur_time = sensor_hub_event->data.timestamp; + } else { + sensor_event_t *sensor_event = (sensor_event_t *)event; + situation = sensor_event->situation; + cur_time = sensor_event->data.timestamp; + + if (is_single_state_event(event_type)) { + single_state_event_data = (int) sensor_event->data.values[0]; + event_data.event_data = (void *) & (single_state_event_data); + event_data.event_data_size = sizeof(single_state_event_data); + } else if (is_panning_event(event_type)) { + panning_data.x = (int)sensor_event->data.values[0]; + panning_data.y = (int)sensor_event->data.values[1]; + event_data.event_data = (void *)&panning_data; + event_data.event_data_size = sizeof(panning_data); + } else { + sensor_event_to_data(*sensor_event, sensor_data); + event_data.event_data = (void *)&sensor_data; + event_data.event_data_size = sizeof(sensor_data); + data_accuracy = sensor_event->data.data_accuracy; + } + } + + { /* scope for the lock */ + AUTOLOCK(m_handle_info_lock); + + for (it_handle = m_sensor_handle_infos.begin(); it_handle != m_sensor_handle_infos.end(); ++it_handle) { + csensor_handle_info &sensor_handle_info = it_handle->second; + + if ((sensor_handle_info.m_sensor_state != SENSOR_STATE_STARTED) || !sensor_handle_info.get_reg_event_info(event_type, event_info)) + continue; + + if ((sensor_handle_info.m_sensor_option != SENSOR_OPTION_ALWAYS_ON) && + ((situation == SITUATION_LCD_OFF) || (situation == SITUATION_SURVIVAL_MODE))) + continue; + + if (event_info.m_fired) + continue; + + diff_time = cur_time - event_info.m_previous_event_time; + + if ((diff_time >= event_info.m_event_interval * MS_TO_US * MIN_DELIVERY_DIFF_FACTOR) || ((diff_time > 0) && !is_ontime_event(event_type))) { + unsigned int cal_event_type; + creg_event_info cal_event_info; + event_info.m_previous_event_time = cur_time; + cal_event_type = get_calibration_event_type(event_type); + + if (cal_event_type) { + if ((data_accuracy == SENSOR_ACCURACY_BAD) && !sensor_handle_info.bad_accuracy && + sensor_handle_info.get_reg_event_info(cal_event_type, cal_event_info)) { + sensor_event_data_t cal_event_data; + client_callback_info *cal_callback_info; + + cal_event_info.m_previous_event_time = cur_time; + cal_event_data.event_data = (void *) & (data_accuracy); + cal_event_data.event_data_size = sizeof(data_accuracy); + cal_callback_info = get_callback_info(cal_event_info, cal_event_data); + client_callback_infos.push_back(cal_callback_info); + sensor_handle_info.bad_accuracy = true; + + print_event_occurrence_log(sensor_handle_info, cal_event_info, cal_event_data); + } + + if ((data_accuracy != SENSOR_ACCURACY_BAD) && sensor_handle_info.bad_accuracy) + sensor_handle_info.bad_accuracy = false; + } + + callback_info = get_callback_info(event_info, event_data); + client_callback_infos.push_back(callback_info); + + if (is_one_shot_event(event_type)) + event_info.m_fired = true; + + print_event_occurrence_log(sensor_handle_info, event_info, event_data); + } + } + } + + vector::iterator it_calback_info; + it_calback_info = client_callback_infos.begin(); + + while (it_calback_info != client_callback_infos.end()) { + post_callback_to_main_loop(*it_calback_info); + ++it_calback_info; + } +} + +client_callback_info *csensor_event_listener::get_callback_info(creg_event_info &event_info, sensor_event_data_t &event_data) +{ + client_callback_info *callback_info; + callback_info = new client_callback_info; + callback_info->event_id = event_info.m_id; + callback_info->handle = event_info.m_handle; + callback_info->callback = event_info.m_event_callback; + callback_info->event_type = event_info.m_event_type; + callback_info->event_data.event_data_size = event_data.event_data_size; + callback_info->event_data.event_data = new char[event_data.event_data_size]; + memcpy(callback_info->event_data.event_data, event_data.event_data, event_data.event_data_size); + callback_info->data = event_info.m_cb_data; + return callback_info; +} + +void csensor_event_listener::post_callback_to_main_loop(client_callback_info *cb_info) +{ + g_idle_add_full(G_PRIORITY_DEFAULT, callback_dispatcher, cb_info, NULL); +} + +bool csensor_event_listener::is_event_active(int handle, unsigned int event_type, unsigned long long event_id) +{ + sensor_handle_info_map::iterator it_handle; + creg_event_info event_info; + + AUTOLOCK(m_handle_info_lock); + it_handle = m_sensor_handle_infos.find(handle); + + if (it_handle == m_sensor_handle_infos.end()) + return false; + + if (!it_handle->second.get_reg_event_info(event_type, event_info)) + return false; + + if (event_info.m_id != event_id) + return false; + + return true; +} + +bool csensor_event_listener::is_valid_callback(client_callback_info *cb_info) +{ + return is_event_active(cb_info->handle, cb_info->event_type, cb_info->event_id); +} + +gboolean csensor_event_listener::callback_dispatcher(gpointer data) +{ + client_callback_info *cb_info = (client_callback_info *) data; + + if (csensor_event_listener::get_instance().is_valid_callback(cb_info)) + cb_info->callback(cb_info->event_type, &cb_info->event_data, cb_info->data); + else + WARN("Discard invalid callback cb(0x%x)(%s, 0x%x, 0x%x) with id: %llu", + cb_info->callback, get_event_name(cb_info->event_type), &cb_info->event_data, + cb_info->data, cb_info->event_id); + + delete[] (char *)(cb_info->event_data.event_data); + delete cb_info; + + /* + * To be called only once, it returns false + */ + return false; +} + +bool csensor_event_listener::sensor_event_poll(void *buffer, int buffer_len) +{ + ssize_t len; + len = m_event_socket.recv(buffer, buffer_len); + + if (!len) { + if (!m_poller->poll()) + return false; + + len = m_event_socket.recv(buffer, buffer_len); + + if (!len) { + INFO("%s failed to read after poll!", get_client_name()); + return false; + } + } + + if (len < 0) { + INFO("%s failed to recv event from event socket", get_client_name()); + return false; + } + + return true; +} + +void csensor_event_listener::listen_events(void) +{ + sensorhub_event_t buffer; + + do { + lock l(m_thread_mutex); + + if (m_thread_state == THREAD_STATE_START) { + if (!sensor_event_poll(&buffer, sizeof(buffer))) { + INFO("sensor_event_poll failed"); + break; + } + + handle_events(&buffer); + } else { + break; + } + + } while (true); + + if (m_poller != NULL) { + delete m_poller; + m_poller = NULL; + } + + close_event_channel(); + set_client_id(CLIENT_ID_INVALID); + + lock l(m_thread_mutex); + m_thread_state = THREAD_STATE_TERMINATE; + m_thread_cond.notify_one(); + INFO("Event listener thread is terminated."); +} + +bool csensor_event_listener::create_event_channel(void) +{ + int client_id; + event_channel_ready_t event_channel_ready; + + if (!m_event_socket.create(SOCK_SEQPACKET)) + return false; + + if (!m_event_socket.connect(EVENT_CHANNEL_PATH)) { + ERR("Failed to connect event channel for client %s, event socket fd[%d]", get_client_name(), m_event_socket.get_socket_fd()); + return false; + } + + m_event_socket.set_connection_mode(); + client_id = get_client_id(); + + if (m_event_socket.send(&client_id, sizeof(client_id)) <= 0) { + ERR("Failed to send client id for client %s on event socket[%d]", get_client_name(), m_event_socket.get_socket_fd()); + return false; + } + + if (m_event_socket.recv(&event_channel_ready, sizeof(event_channel_ready)) <= 0) { + ERR("%s failed to recv event_channel_ready packet on event socket[%d] with client id [%d]", + get_client_name(), m_event_socket.get_socket_fd(), client_id); + return false; + } + + if ((event_channel_ready.magic != EVENT_CHANNEL_MAGIC) || (event_channel_ready.client_id != client_id)) { + ERR("Event_channel_ready packet is wrong, magic = 0x%x, client id = %d", + event_channel_ready.magic, event_channel_ready.client_id); + return false; + } + + INFO("Event channel is established for client %s on socket[%d] with client id : %d", + get_client_name(), m_event_socket.get_socket_fd(), client_id); + return true; +} + +void csensor_event_listener::close_event_channel(void) +{ + m_event_socket.close(); +} + +void csensor_event_listener::stop_event_listener(void) +{ + const int THREAD_TERMINATING_TIMEOUT = 2; + ulock u(m_thread_mutex); + + if (m_thread_state != THREAD_STATE_TERMINATE) { + m_thread_state = THREAD_STATE_STOP; + _D("%s is waiting listener thread[state: %d] to be terminated", get_client_name(), m_thread_state); + + if (m_thread_cond.wait_for(u, std::chrono::seconds(THREAD_TERMINATING_TIMEOUT)) == std::cv_status::timeout) + _E("Fail to stop listener thread after waiting %d seconds", THREAD_TERMINATING_TIMEOUT); + else + _D("Listener thread for %s is terminated", get_client_name()); + } +} + +void csensor_event_listener::set_thread_state(thread_state state) +{ + lock l(m_thread_mutex); + m_thread_state = state; +} + +bool csensor_event_listener::start_event_listener(void) +{ + if (!create_event_channel()) { + ERR("Event channel is not established for %s", get_client_name()); + return false; + } + + m_event_socket.set_transfer_mode(); + m_poller = new poller(m_event_socket.get_socket_fd()); + + set_thread_state(THREAD_STATE_START); + thread listener(&csensor_event_listener::listen_events, this); + listener.detach(); + return true; +} diff --git a/src/libsensord/csensor_event_listener.h b/src/libsensord/csensor_event_listener.h new file mode 100755 index 0000000..99ce5a3 --- /dev/null +++ b/src/libsensord/csensor_event_listener.h @@ -0,0 +1,180 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CSENSOR_EVENT_LISTENER_H_ +#define CSENSOR_EVENT_LISTENER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::map; +using std::vector; +using std::string; +using std::queue; +using std::mutex; +using std::lock_guard; +using std::unique_lock; +using std::condition_variable; + +typedef vector handle_vector; +typedef vector sensor_type_vector; +typedef map> handle_events_map; +typedef map sensor_handle_info_map; +typedef map sensor_command_channel_map; + +typedef struct { + unsigned long long event_id; + int handle; + sensor_callback_func_t callback; + unsigned int event_type; + sensor_event_data_t event_data; + void *data; +} client_callback_info; + +typedef struct sensor_rep { + bool active; + int option; + unsigned int interval; + event_type_vector event_types; +} sensor_rep; + +class csensor_event_listener +{ +public: + int create_handle(const sensor_type_t sensor); + bool delete_handle(const int handle); + bool start_handle(const int handle); + bool stop_handle(const int handle); + bool register_event(const int handle, const unsigned int event_type, + const unsigned int interval, + const sensor_callback_func_t callback, void *cb_data); + bool unregister_event(const int handle, const unsigned int event_type); + bool change_event_interval(const int handle, const unsigned int event_type, + const unsigned int interval); + + bool set_sensor_params(const int handle, int sensor_state, int sensor_option); + bool set_sensor_state(const int handle, const int sensor_state); + bool set_sensor_option(const int handle, const int sensor_option); + bool set_event_interval(const int handle, const unsigned int event_type, + const unsigned int interval); + + void get_listening_sensors(sensor_type_vector &sensors); + + void pause_sensor(const sensor_type_t sensor); + void resume_sensor(const sensor_type_t sensor); + + unsigned int get_active_min_interval(const sensor_type_t sensor); + unsigned int get_active_option(const sensor_type_t sensor); + void get_active_event_types(const sensor_type_t sensor, + event_type_vector &active_event_types); + + bool get_sensor_type(const int handle, sensor_type_t &sensor); + bool get_sensor_state(const int handle, int &state); + + void get_sensor_rep(sensor_type_t sensor, sensor_rep &rep); + + bool has_client_id(void); + int get_client_id(void); + void set_client_id(const int client_id); + + bool is_active(void); + bool is_sensor_registered(const sensor_type_t sensor); + bool is_sensor_active(const sensor_type_t sensor); + + bool set_command_channel(sensor_type_t sensor, command_channel *cmd_channel); + bool get_command_channel(sensor_type_t sensor, command_channel **cmd_channel); + bool close_command_channel(sensor_type_t sensor); + + void get_all_handles(handle_vector &handles); + + int get_single_event_count(const unsigned int event_type); + bool start_event_listener(void); + void stop_event_listener(void); + + static csensor_event_listener &get_instance(void) { + static csensor_event_listener inst; + return inst; + } + +private: + enum thread_state { + THREAD_STATE_START, + THREAD_STATE_STOP, + THREAD_STATE_TERMINATE, + }; + typedef lock_guard lock; + typedef unique_lock ulock; + + sensor_handle_info_map m_sensor_handle_infos; + sensor_command_channel_map m_command_channels; + + int m_client_id; + + csocket m_event_socket; + poller *m_poller; + + cmutex m_handle_info_lock; + + thread_state m_thread_state; + mutex m_thread_mutex; + condition_variable m_thread_cond; + + csensor_event_listener(); + ~csensor_event_listener(); + + csensor_event_listener(const csensor_event_listener &) {}; + csensor_event_listener &operator=(const csensor_event_listener &); + + bool create_event_channel(void); + void close_event_channel(void); + + bool sensor_event_poll(void *buffer, int buffer_len); + + void listen_events(void); + void handle_events(void *event); + + client_callback_info *get_callback_info(creg_event_info &event_info, + sensor_event_data_t &event_data); + + unsigned long long renew_event_id(void); + + void post_callback_to_main_loop(client_callback_info *cb_info); + + bool is_event_active(int handle, unsigned int event_type, unsigned long long event_id); + bool is_valid_callback(client_callback_info *cb_info); + static gboolean callback_dispatcher(gpointer data); + + void set_thread_state(thread_state state); +}; +#endif /* CSENSOR_EVENT_LISTENER_H_ */ diff --git a/src/libsensord/csensor_handle_info.cpp b/src/libsensord/csensor_handle_info.cpp new file mode 100755 index 0000000..4b5b5fe --- /dev/null +++ b/src/libsensord/csensor_handle_info.cpp @@ -0,0 +1,153 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +using std::pair; + +unsigned long long csensor_handle_info::m_event_id = 0; + +csensor_handle_info::csensor_handle_info() +: m_handle(0) +, m_sensor_type(UNKNOWN_SENSOR) +, m_sensor_state(SENSOR_STATE_UNKNOWN) +, m_sensor_option(SENSOR_OPTION_DEFAULT) +, bad_accuracy(false) +{ +} + +csensor_handle_info::~csensor_handle_info() +{ + clear_all_events(); +} + +bool csensor_handle_info::get_reg_event_info(unsigned int event_type, creg_event_info &event_info) +{ + event_info_map::iterator it_event; + it_event = m_reg_event_infos.find(event_type); + + if (it_event == m_reg_event_infos.end()) { + DBG("Event %s[0x%x] is not registered for client %s", get_event_name(event_type), event_type, get_client_name()); + return false; + } + + event_info = it_event->second; + return true; +} + +void csensor_handle_info::get_reg_event_types(event_type_vector &event_types) +{ + event_info_map::iterator it_event; + it_event = m_reg_event_infos.begin(); + + while (it_event != m_reg_event_infos.end()) { + event_types.push_back(it_event->first); + ++it_event; + } +} + +bool csensor_handle_info::add_reg_event_info(const unsigned int event_type, const unsigned int interval, + const sensor_callback_func_t callback, void *cb_data) +{ + event_info_map::iterator it_event; + creg_event_info event_info; + it_event = m_reg_event_infos.find(event_type); + + if (it_event != m_reg_event_infos.end()) { + ERR("Event %s[0x%x] is already registered for client %s", get_event_name(event_type), event_type, get_client_name()); + return false; + } + + event_info.m_id = renew_event_id(); + event_info.m_handle = m_handle; + event_info.m_event_type = event_type; + event_info.m_event_interval = interval; + event_info.m_event_callback = callback; + event_info.m_cb_data = cb_data; + m_reg_event_infos.insert(pair (event_type, event_info)); + return true; +} + +bool csensor_handle_info::delete_reg_event_info(const unsigned int event_type) +{ + event_info_map::iterator it_event; + it_event = m_reg_event_infos.find(event_type); + + if (it_event == m_reg_event_infos.end()) { + ERR("Event %s[0x%x] is not registered for client %s", get_event_name(event_type), event_type, get_client_name()); + return false; + } + + m_reg_event_infos.erase(it_event); + return true; +} + +void csensor_handle_info::clear_all_events(void) +{ + m_reg_event_infos.clear(); +} + +unsigned long long csensor_handle_info::renew_event_id(void) +{ + return m_event_id++; +} + +bool csensor_handle_info::change_reg_event_interval(const unsigned int event_type, const unsigned int interval) +{ + event_info_map::iterator it_event; + it_event = m_reg_event_infos.find(event_type); + + if (it_event == m_reg_event_infos.end()) { + ERR("Event %s[0x%x] is not registered for client %s", get_event_name(event_type), event_type, get_client_name()); + return false; + } + + it_event->second.m_id = renew_event_id(); + it_event->second.m_event_interval = interval; + return true; +} + +unsigned int csensor_handle_info::get_min_interval(void) +{ + unsigned int min_interval = POLL_MAX_HZ_MS; + unsigned int interval; + + if (m_reg_event_infos.empty()) { + DBG("No events are registered for client %s", get_client_name()); + return min_interval; + } + + event_info_map::iterator it_event; + it_event = m_reg_event_infos.begin(); + + while (it_event != m_reg_event_infos.end()) { + interval = it_event->second.m_event_interval; + min_interval = (interval < min_interval) ? interval : min_interval; + ++it_event; + } + + return min_interval; +} + +unsigned int csensor_handle_info::get_reg_event_count(void) +{ + return m_reg_event_infos.size(); +} + diff --git a/src/libsensord/csensor_handle_info.h b/src/libsensord/csensor_handle_info.h new file mode 100755 index 0000000..78d5a33 --- /dev/null +++ b/src/libsensord/csensor_handle_info.h @@ -0,0 +1,65 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CSENSOR_HANDLE_INFO_H_ +#define CSENSOR_HANDLE_INFO_H_ + +#include +#include +#include +#include +#include +#include + +using std::map; +using std::vector; + +typedef map event_info_map; + +class csensor_handle_info +{ +public: + int m_handle; + sensor_type_t m_sensor_type; + int m_sensor_state; + int m_sensor_option; + int bad_accuracy; + + csensor_handle_info(); + ~csensor_handle_info(); + + bool add_reg_event_info(const unsigned int event_type, const unsigned int interval, + const sensor_callback_func_t callback, void *cb_data); + bool delete_reg_event_info(const unsigned int event_type); + + bool change_reg_event_interval(const unsigned int event_type, const unsigned int interval); + + bool get_reg_event_info(const unsigned int event_type, creg_event_info &event_info); + void get_reg_event_types(event_type_vector &event_types); + unsigned int get_min_interval(void); + unsigned int get_reg_event_count(void); + + void clear_all_events(void); + static unsigned long long renew_event_id(void); +private: + event_info_map m_reg_event_infos; + static unsigned long long m_event_id; +}; + +#endif /* CSENSOR_HANDLE_INFO_H_ */ diff --git a/src/libsensord/poller.cpp b/src/libsensord/poller.cpp new file mode 100755 index 0000000..8411dcc --- /dev/null +++ b/src/libsensord/poller.cpp @@ -0,0 +1,104 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +poller::poller(int fd) +: m_epfd(-1) +{ + create(fd); +} + +bool poller::create(int fd) +{ + m_epfd = epoll_create(1); + + struct epoll_event event; + event.data.fd = fd; + event.events = EPOLLIN | EPOLLERR | EPOLLHUP; + + if (epoll_ctl(m_epfd, EPOLL_CTL_ADD, fd, &event)) { + ERR("errno : %d , errstr : %s", errno, strerror(errno)); + return false; + } + + return true; +} + +bool poller::fill_event_queue(void) +{ + const int EPOLL_MAX_EVENT = 16; + struct epoll_event event_items[EPOLL_MAX_EVENT]; + int nr_events = epoll_wait(m_epfd, event_items, EPOLL_MAX_EVENT, -1); + + if (nr_events < 0) { + if (errno == EINTR) { + return true; + } + + ERR("Epoll failed errrno : %d , errstr : %s", errno, strerror(errno)); + return false; + } + + if (nr_events == 0) { + ERR("Epoll timeout!"); + return false; + } + + for (int i = 0; i < nr_events; i++) + m_event_queue.push(event_items[i].events); + + return true; +} + +bool poller::poll(void) +{ + while (true) { + if (m_event_queue.empty()) { + if (!fill_event_queue()) + return false; + } + + if (!m_event_queue.empty()) { + int event = m_event_queue.front(); + m_event_queue.pop(); + + if (event & EPOLLERR) { + ERR("Poll error!"); + return false; + } + + if (event & EPOLLHUP) { + INFO("Poll: Connetion is closed from the other side"); + return false; + } + + return true; + } + } +} + +poller::~poller() +{ + if (m_epfd) + close(m_epfd); +} + diff --git a/src/libsensord/poller.h b/src/libsensord/poller.h new file mode 100755 index 0000000..b75fe9a --- /dev/null +++ b/src/libsensord/poller.h @@ -0,0 +1,49 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _POLLER_H_ +#define _POLLER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::queue; + +class poller +{ +public: + poller(int fd); + ~poller(); + + bool poll(void); +private: + int m_epfd; + queue m_event_queue; + + bool create(int fd); + bool fill_event_queue(void); +}; + +#endif /* _POLLER_H_ */ diff --git a/src/libsensord/sensor.h b/src/libsensord/sensor.h new file mode 100755 index 0000000..794a497 --- /dev/null +++ b/src/libsensord/sensor.h @@ -0,0 +1,218 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_H_ +#define _SENSOR_H_ + +#ifndef DEPRECATED +#define DEPRECATED __attribute__((deprecated)) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +/*header for common sensor type*/ +#include + +/*header for each sensor type*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + condition_op_t cond_op; + float cond_value1; +} event_condition_t; + +typedef struct { + size_t event_data_size; + void *event_data; +} sensor_event_data_t; + +typedef void (*sensor_callback_func_t)(unsigned int, sensor_event_data_t *, void *); + +typedef struct { + int x; + int y; + int z; +} sensor_panning_data_t; + +typedef struct { + int sensor_unit_idx; + float sensor_min_range; + float sensor_max_range; + float sensor_resolution; +} sensor_data_properties_t; + +/** + * @fn int sf_is_sensor_event_available(sensor_type_t desired_sensor_type, unsigned int desired_event_type) + * @brief This API loads the in parameter available list with the type of sensor available for operation . Some of the supported types are ACCELEROMETER_SENSOR_TYPE, GEOMAGNETIC_SENSOR_TYPE etc. This API will return 0 when it is available and negative value when it does not available. + * @param[in] desired_sensor_type your desired sensor type to check + * @param[in] desired_event_type your desired event type to check, if you want to check only sensor-available , set "0" value + * @return if it succeed, it return zero value(available), otherwise negative value return (not available) + */ +int sf_is_sensor_event_available(sensor_type_t desired_sensor_type, unsigned int desired_event_type); + +/** + * @fn int sf_get_data_properties(unsigned data_id, sensor_dada_properties_t *return_data_properties) + * @brief This API loads the properties of data ID like unit of sensor data, max/min range of sensor data etc to the output parameter sensor_data_properties. + * @param[in] data_id your desired data ID + * @param[out] return_data_properties property information of your desired data ID + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_get_data_properties(unsigned int data_id, sensor_data_properties_t *return_data_properties); + +/** + * @fn int sf_get_properties(sensor_type_t sensor, sensor_properties_t *return_properties) + * @brief This API loads the properties of sensor type like unit of sensor data, max/min range of sensor data etc to the output parameter sensor_properties. + * @param[in] sensor your desired sensor type + * @param[out] return_properties property information of your desired sensor + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_get_properties(sensor_type_t sensor, sensor_properties_t *return_properties); + +/** + * @fn int sf_set_property(sensor_type_t sensor, unsigned int property_id, long value) + * @brief This API set the property of sensor type like calibration, enable wakeup event, etc + * @param[in] sensor your desired sensor type, property_id your desired property ID, value for property input + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_set_property(sensor_type_t sensor, unsigned int property_id, long value); + +/** + * @fn int sf_connect(sensor_type_t sensor) + * @brief This API connects a sensor type to respective sensor. The application calls with the type of the sensor (ex. ACCELEROMETER_SENSOR) and on basis of that server takes decision of which plug-in to be connected. Once sensor connected application can proceed for data processing. This API returns a positive handle which should be used by application to communicate on sensor type. + * @param[in] sensor your desired sensor type + * @return if it succeed, it return handle value( >=0 ), otherwise negative value return + */ +int sf_connect(sensor_type_t sensor); + +/** + * @fn int sf_disconnect(int handle) + * @brief This API disconnects an attached sensor from an application. Application must use the handle retuned after attaching the sensor. After detaching, the corresponding handle will be released. + * @param[in] handle received handle value by sf_connect() + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_disconnect(int handle); + +/** + * @fn int sf_start(int handle, int option) + * @brief This API sends a start command to sensor server. This intimates server that the client side is ready to handle data and start processing. The parameter option should be '0' for current usages. + * @param[in] handle received handle value by sf_connect() + * @param[in] option With SENSOR_OPTION_DEFAULT, it stops to sense when LCD is off, and with SENSOR_OPTION_ALWAYS_ON, it continues to sense even when LCD is off + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_start(int handle, int option); + +/** + * @fn int sf_stop(int handle) + * @brief This API sends a stop command to the Sensor server indicating that the data processing is stopped from application side for this time. + * @param[in] handle received handle value by sf_connect() + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_stop(int handle); + +/** + * @fn int sf_register_event(int handle, unsigned int event_type, event_conditon_t *event_condition, sensor_callback_func_t cb, void *cb_data) + * @brief This API registers a user defined callback function with a connected sensor for a particular event. This callback function will be called when there is a change in the state of respective sensor. cb_data will be the parameter used during the callback call. Callback interval can be adjusted using even_contion_t argument. + * @param[in] handle received handle value by sf_connect() + * @param[in] event_type your desired event_type to register it + * @param[in] event_condition input event_condition for special event. if you want to register without event_condition, just use a NULL value + * @param[in] cb your define callback function + * @param[in] cb_data your option data that will be send when your define callback function called. if you don't have any option data, just use a NULL value + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_register_event(int handle, unsigned int event_type, event_condition_t *event_condition, sensor_callback_func_t cb, void *cb_data); + +/** + * @fn int sf_unregister_event(int handle, unsigned int event_type) + * @brief This API de-registers a user defined callback function with a sensor registered with the specified handle. After unsubscribe, no event will be sent to the application. + * @param[in] handle received handle value by sf_connect() + * @param[in] event_type your desired event_type that you want to unregister event + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_unregister_event(int handle, unsigned int event_type); + +/** + * @fn int sf_get_data(int handle, unsigned int data_id, sensor_data_t* values) + * @brief This API gets raw data from a sensor with connecting the sensor-server. The type of sensor is supplied and return data is stored in the output parameter values []. + * @param[in] handle received handle value by sf_connect() + * @param[in] data_id predefined data_ID as every sensor in own header - sensor_xxx.h, enum xxx_data_id {} + * @param[out] values return values + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_get_data(int handle, unsigned int data_id, sensor_data_t *values); + +/** + * @fn int sf_check_rotation( unsigned long *curr_state) + * @brief This API used to get the current rotation state. (i.e. ROTATION_EVENT_0, ROTATION_EVENT_90, ROTATION_EVENT_180 & ROTATION_EVENT_270 ). This API will directly access the sensor without connection process with the sensor-server. Result will be stored in the output parameter state. + * @param[out] curr_state it will return enum accelerometer_rotate_state value + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_check_rotation(unsigned long *curr_state); + +/** + * @fn int sf_change_event_condition(int handle, unsigned int event_type, event_condition_t *event_condition) + * @brief This API change a user defined callback function condition with a sensor registered with the specified handle. + * @param[in] handle received handle value by sf_connect() + * @param[in] event_type your desired event_type that you want to unregister event + * @param[in] event_condition your desired event condition that you want to change event + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_change_event_condition(int handle, unsigned int event_type, event_condition_t *event_condition); + +/** + * @fn int sf_change_sensor_option(int handle, int option) + * @brief This API change sensor option . + * @param[in] handle received handle value by sf_connect() + * @param[in] option your desired option that you want to turn on sensor during LCD OFF + * @return if it succeed, it return zero value, otherwise negative value return + */ +int sf_change_sensor_option(int handle, int option); + +/** + * @fn int sf_send_sensorhub_data(int handle, const char* buffer, int data_len) + * @brief This API sends data to sensorhub. + * @param[in] handle received handle by sf_connect() + * @param[in] data it holds data to send to sensorhub + * @param[in] data_len the length of data + * @return if it succeed, it returns zero, otherwise negative value + */ +int sf_send_sensorhub_data(int handle, const char *data, int data_len); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*_SENSOR_H_*/ diff --git a/src/libsensord/sensor.pc.in b/src/libsensord/sensor.pc.in new file mode 100755 index 0000000..10bb017 --- /dev/null +++ b/src/libsensord/sensor.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@/sensor + +Name: libsensord +Description: Sensord library +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lsensor +Cflags: -I${includedir} diff --git a/src/libsensord/sensor_accel.h b/src/libsensord/sensor_accel.h new file mode 100755 index 0000000..32622c4 --- /dev/null +++ b/src/libsensord/sensor_accel.h @@ -0,0 +1,98 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_ACCEL_H_ +#define _SENSOR_ACCEL_H_ + +//! Pre-defined events for the accelometer sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_ACCEL Accelerometer Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Accelerometer sensor. + * @{ + */ + +enum accelerometer_data_id { + ACCELEROMETER_BASE_DATA_SET = (ACCELEROMETER_SENSOR << 16) | 0x0001, + ACCELEROMETER_ORIENTATION_DATA_SET = (ACCELEROMETER_SENSOR << 16) | 0x0002, + ACCELEROMETER_LINEAR_ACCELERATION_DATA_SET = (ACCELEROMETER_SENSOR << 16) | 0x0004, + ACCELEROMETER_GRAVITY_DATA_SET = (ACCELEROMETER_SENSOR << 16) | 0x0008, + ACCELEROMETER_ROTATION_DATA_SET = (ACCELEROMETER_SENSOR << 16) | 0x0010, +}; + +enum accelerometer_event_type { + ACCELEROMETER_EVENT_ROTATION_CHECK = (ACCELEROMETER_SENSOR << 16) | 0x0001, + ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME = (ACCELEROMETER_SENSOR << 16) | 0x0002, + ACCELEROMETER_EVENT_CALIBRATION_NEEDED = (ACCELEROMETER_SENSOR << 16) | 0x0004, + ACCELEROMETER_EVENT_SET_HORIZON = (ACCELEROMETER_SENSOR << 16) | 0x0008, + ACCELEROMETER_EVENT_SET_WAKEUP = (ACCELEROMETER_SENSOR << 16) | 0x0010, + ACCELEROMETER_EVENT_ORIENTATION_DATA_REPORT_ON_TIME = (ACCELEROMETER_SENSOR << 16) | 0x0020, + ACCELEROMETER_EVENT_LINEAR_ACCELERATION_DATA_REPORT_ON_TIME = (ACCELEROMETER_SENSOR << 16) | 0x0040, + ACCELEROMETER_EVENT_GRAVITY_DATA_REPORT_ON_TIME = (ACCELEROMETER_SENSOR << 16) | 0x0080, +}; + +enum accelerometer_rotate_state { + ROTATION_UNKNOWN = 0, + ROTATION_PORTRAIT_TOP = 1, + ROTATION_LANDSCAPE_LEFT = 2, + ROTATION_PORTRAIT_BTM = 3, + ROTATION_LANDSCAPE_RIGHT = 4, + ROTATION_EVENT_0 = 1, /*CCW base*/ + ROTATION_EVENT_90 = 2, /*CCW base*/ + ROTATION_EVENT_180 = 3, /*CCW base*/ + ROTATION_EVENT_270 = 4, /*CCW base*/ +}; + +enum accelerometer_property_id { + ACCELEROMETER_PROPERTY_UNKNOWN = 0, + ACCELEROMETER_PROPERTY_SET_CALIBRATION, + ACCELEROMETER_PROPERTY_CHECK_CALIBRATION_STATUS, + ACCELEROMETER_PROPERTY_SET_WAKEUP, + ACCELEROMETER_PROPERTY_CHECK_WAKEUP_STATUS, + ACCELEROMETER_PROPERTY_CHECK_WAKEUP_SUPPORTED, + ACCELEROMETER_PROPERTY_GET_WAKEUP, +}; + +enum accelerometer_wakeup_state { + WAKEUP_UNSET = 0, + WAKEUP_SET = 1, +}; + +struct rotation_event { + enum accelerometer_rotate_state rotation; + enum accelerometer_rotate_state rm[2]; +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_ACCEL_H_*/ diff --git a/src/libsensord/sensor_context.h b/src/libsensord/sensor_context.h new file mode 100755 index 0000000..ff52265 --- /dev/null +++ b/src/libsensord/sensor_context.h @@ -0,0 +1,59 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_CONTEXT_H_ +#define _SENSOR_CONTEXT_H_ + +//! Pre-defined events for the context sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_CONTEXT Context Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Context sensor. + * @{ + */ + +enum context_data_id { + CONTEXT_BASE_DATA_SET = (CONTEXT_SENSOR << 16) | 0x0001, +}; + +enum context_event_type { + CONTEXT_EVENT_REPORT = (CONTEXT_SENSOR << 16) | 0x0001, +}; + +enum context_property_id { + CONTEXT_PROPERTY_UNKNOWN = 0, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_CONTEXT_H_*/ diff --git a/src/libsensord/sensor_geomag.h b/src/libsensord/sensor_geomag.h new file mode 100755 index 0000000..5270762 --- /dev/null +++ b/src/libsensord/sensor_geomag.h @@ -0,0 +1,65 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_GEOMAG_H_ +#define _SENSOR_GEOMAG_H_ + +//! Pre-defined events for the geomagnetic sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_GEOMAG Geomagnetic Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Geomagnatic sensor. + * @{ + */ + +enum geomag_data_id { + GEOMAGNETIC_BASE_DATA_SET = (GEOMAGNETIC_SENSOR << 16) | 0x0001, + GEOMAGNETIC_RAW_DATA_SET = (GEOMAGNETIC_SENSOR << 16) | 0x0001, + GEOMAGNETIC_ATTITUDE_DATA_SET = (GEOMAGNETIC_SENSOR << 16) | 0x0002, +}; + +enum geomag_evet_type { + GEOMAGNETIC_EVENT_CALIBRATION_NEEDED = (GEOMAGNETIC_SENSOR << 16) | 0x0001, + GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME = (GEOMAGNETIC_SENSOR << 16) | 0x0002, + GEOMAGNETIC_EVENT_ATTITUDE_DATA_REPORT_ON_TIME = (GEOMAGNETIC_SENSOR << 16) | 0x0004, +}; + +enum geomag_property_id { + GEOMAGNETIC_PROPERTY_UNKNOWN = 0, + GEOMAGNETIC_PROPERTY_SET_ACCEL_CALIBRATION, + GEOMAGNETIC_PROPERTY_CHECK_ACCEL_CALIBRATION, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_GEOMAG_H_*/ diff --git a/src/libsensord/sensor_gravity.h b/src/libsensord/sensor_gravity.h new file mode 100755 index 0000000..16a5f82 --- /dev/null +++ b/src/libsensord/sensor_gravity.h @@ -0,0 +1,55 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_GRAVITY_H_ +#define _SENSOR_GRAVITY_H_ + +//! Pre-defined events for the gravity sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_GRAVITY Gravity Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Gravity sensor. + * @{ + */ + +enum gravity_data_id { + GRAVITY_BASE_DATA_SET = (GRAVITY_SENSOR << 16) | 0x0001, +}; + +enum gravity_event_type { + GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME = (GRAVITY_SENSOR << 16) | 0x0002, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_GRAVITY_H_*/ diff --git a/src/libsensord/sensor_gyro.h b/src/libsensord/sensor_gyro.h new file mode 100755 index 0000000..485628f --- /dev/null +++ b/src/libsensord/sensor_gyro.h @@ -0,0 +1,61 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_GYRO_H_ +#define _SENSOR_GYRO_H_ + +//! Pre-defined events for the gyroscope sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_GYRO Gyro Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the gyro sensor. + * @{ + */ + +enum gyro_data_id { + GYRO_BASE_DATA_SET = (GYROSCOPE_SENSOR << 16) | 0x0001, +}; + +enum gyro_event_type { + GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME = (GYROSCOPE_SENSOR << 16) | 0x0001, +}; + +enum gyro_property_id { + GYROSCOPE_PROPERTY_UNKNOWN = 0, + GYROSCOPE_PROPERTY_SET_CALIBRATION, + GYROSCOPE_PROPERTY_CHECK_CALIBRATION, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_GYRO_H_*/ diff --git a/src/libsensord/sensor_light.h b/src/libsensord/sensor_light.h new file mode 100755 index 0000000..86aee82 --- /dev/null +++ b/src/libsensord/sensor_light.h @@ -0,0 +1,62 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_LIGHT_H_ +#define _SENSOR_LIGHT_H_ + +//! Pre-defined events for the light sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_LIGHT Light Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the light sensor. + * @{ + */ + +enum light_data_id { + LIGHT_BASE_DATA_SET = (LIGHT_SENSOR << 16) | 0x0001, + LIGHT_LUX_DATA_SET = (LIGHT_SENSOR << 16) | 0x0002, +}; + +enum light_evet_type { + LIGHT_EVENT_CHANGE_LEVEL = (LIGHT_SENSOR << 16) | 0x0001, + LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME = (LIGHT_SENSOR << 16) | 0x0002, + LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME = (LIGHT_SENSOR << 16) | 0x0004, +}; + +enum light_property_id { + LIGHT_PROPERTY_UNKNOWN = 0, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_LIGHT_H_*/ diff --git a/src/libsensord/sensor_linear_accel.h b/src/libsensord/sensor_linear_accel.h new file mode 100755 index 0000000..4a98503 --- /dev/null +++ b/src/libsensord/sensor_linear_accel.h @@ -0,0 +1,55 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_LINEAR_ACCEL_H_ +#define _SENSOR_LINEAR_ACCEL_H_ + +//! Pre-defined events for the linear accelerometer sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_LINEAR_ACCEL Linear Accelerometer Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Linear Accelerometer sensor. + * @{ + */ + +enum linear_accel_data_id { + LINEAR_ACCEL_BASE_DATA_SET = (LINEAR_ACCEL_SENSOR << 16) | 0x0001, +}; + +enum linear_accel_event_type { + LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME = (LINEAR_ACCEL_SENSOR << 16) | 0x0001, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_LINEAR_ACCEL_H_*/ diff --git a/src/libsensord/sensor_motion.h b/src/libsensord/sensor_motion.h new file mode 100755 index 0000000..d9a51d8 --- /dev/null +++ b/src/libsensord/sensor_motion.h @@ -0,0 +1,141 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_MOTION_H_ +#define _SENSOR_MOTION_H_ + +//! Pre-defined events for the motion sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +enum motion_event_type { + MOTION_ENGINE_EVENT_SNAP = (MOTION_SENSOR << 16) | 0x0001, + MOTION_ENGINE_EVENT_SHAKE = (MOTION_SENSOR << 16) | 0x0002, + MOTION_ENGINE_EVENT_DOUBLETAP = (MOTION_SENSOR << 16) | 0x0004, + MOTION_ENGINE_EVENT_DIRECT_CALL = (MOTION_SENSOR << 16) | 0x0020, + MOTION_ENGINE_EVENT_TILT_TO_UNLOCK = (MOTION_SENSOR << 16) | 0x0040, + MOTION_ENGINE_EVENT_LOCK_EXECUTE_CAMERA = (MOTION_SENSOR << 16) | 0x0080, + MOTION_ENGINE_EVENT_SMART_ALERT = (MOTION_SENSOR << 16) | 0x0100, + MOTION_ENGINE_EVENT_TILT = (MOTION_SENSOR << 16) | 0x0200, + MOTION_ENGINE_EVENT_PANNING_BROWSE = (MOTION_SENSOR << 16) | 0x0400, + MOTION_ENGINE_EVENT_NO_MOVE = (MOTION_SENSOR << 16) | 0x0800, + MOTION_ENGINE_EVENT_SHAKE_ALWAYS_ON = (MOTION_SENSOR << 16) | 0x1000, +}; + +enum motion_snap_event { + MOTION_ENGIEN_SNAP_NONE = 0, + MOTION_ENGIEN_NEGATIVE_SNAP_X = 1, + MOTION_ENGIEN_POSITIVE_SNAP_X = 2, + MOTION_ENGIEN_NEGATIVE_SNAP_Y = 3, + MOTION_ENGIEN_POSITIVE_SNAP_Y = 4, + MOTION_ENGIEN_NEGATIVE_SNAP_Z = 5, + MOTION_ENGIEN_POSITIVE_SNAP_Z = 6, + MOTION_ENGIEN_SNAP_LEFT = MOTION_ENGIEN_NEGATIVE_SNAP_X, + MOTION_ENGIEN_SNAP_RIGHT = MOTION_ENGIEN_POSITIVE_SNAP_X, + MOTION_ENGINE_SNAP_NONE = 0, + MOTION_ENGINE_NEGATIVE_SNAP_X = 1, + MOTION_ENGINE_POSITIVE_SNAP_X = 2, + MOTION_ENGINE_NEGATIVE_SNAP_Y = 3, + MOTION_ENGINE_POSITIVE_SNAP_Y = 4, + MOTION_ENGINE_NEGATIVE_SNAP_Z = 5, + MOTION_ENGINE_POSITIVE_SNAP_Z = 6, + MOTION_ENGINE_SNAP_LEFT = MOTION_ENGINE_NEGATIVE_SNAP_X, + MOTION_ENGINE_SNAP_RIGHT = MOTION_ENGINE_POSITIVE_SNAP_X, +}; + +enum motion_shake_event { + MOTION_ENGIEN_SHAKE_NONE = 0, + MOTION_ENGIEN_SHAKE_DETECTION = 1, + MOTION_ENGIEN_SHAKE_CONTINUING = 2, + MOTION_ENGIEN_SHAKE_FINISH = 3, + MOTION_ENGINE_SHAKE_BREAK = 4, + MOTION_ENGINE_SHAKE_NONE = 0, + MOTION_ENGINE_SHAKE_DETECTION = 1, + MOTION_ENGINE_SHAKE_CONTINUING = 2, + MOTION_ENGINE_SHAKE_FINISH = 3, +}; + +enum motion_doubletap_event { + MOTION_ENGIEN_DOUBLTAP_NONE = 0, + MOTION_ENGIEN_DOUBLTAP_DETECTION = 1, + MOTION_ENGINE_DOUBLTAP_NONE = 0, + MOTION_ENGINE_DOUBLTAP_DETECTION = 1, +}; + +enum motion_top_to_bottom_event { + MOTION_ENGIEN_TOP_TO_BOTTOM_NONE = 0, + MOTION_ENGIEN_TOP_TO_BOTTOM_WAIT = 1, + MOTION_ENGIEN_TOP_TO_BOTTOM_DETECTION = 2, + MOTION_ENGINE_TOP_TO_BOTTOM_NONE = 0, + MOTION_ENGINE_TOP_TO_BOTTOM_WAIT = 1, + MOTION_ENGINE_TOP_TO_BOTTOM_DETECTION = 2, +}; + +enum motion_direct_call_event_t { + MOTION_ENGINE_DIRECT_CALL_NONE, + MOTION_ENGINE_DIRECT_CALL_DETECTION, +}; + +enum motion_tilt_to_unlock_event_t { + MOTION_ENGINE_TILT_TO_UNLOCK_NONE, + MOTION_ENGINE_TILT_TO_UNLOCK_DETECTION, +}; + +enum motion_lock_execute_camera_event_t { + MOTION_ENGINE_LOCK_EXECUTE_CAMERA_NONE, + MOTION_ENGINE_LOCK_EXECUTE_CAMERA_L_DETECTION, + MOTION_ENGINE_LOCK_EXECUTE_CAMERA_R_DETECTION, +}; + +enum motion_smart_alert_t { + MOTION_ENGINE_SMART_ALERT_NONE, + MOTION_ENGINE_SMART_ALERT_DETECTION, +}; + +enum motion_no_move_t { + MOTION_ENGINE_NO_MOVE_NONE, + MOTION_ENGINE_NO_MOVE_DETECTION, +}; + +enum motion_property_id { + MOTION_PROPERTY_UNKNOWN = 0, + MOTION_PROPERTY_CHECK_ACCEL_SENSOR, + MOTION_PROPERTY_CHECK_GYRO_SENSOR, + MOTION_PROPERTY_CHECK_GEO_SENSOR, + MOTION_PROPERTY_CHECK_PRIXI_SENSOR, + MOTION_PROPERTY_CHECK_LIGHT_SENSOR, + MOTION_PROPERTY_CHECK_BARO_SENSOR, + MOTION_PROPERTY_LCD_TOUCH_ON, + MOTION_PROPERTY_LCD_TOUCH_OFF, + MOTION_PROPERTY_CHECK_GYRO_CAL_STATUS, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_MOTION_H_*/ diff --git a/src/libsensord/sensor_orientation.h b/src/libsensord/sensor_orientation.h new file mode 100755 index 0000000..0444887 --- /dev/null +++ b/src/libsensord/sensor_orientation.h @@ -0,0 +1,56 @@ +/* + * libsensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_ORIENTATION_H_ +#define _SENSOR_ORIENTATION_H_ + +//! Pre-defined events for the orientation sensor +//! Sensor Plugin developer can add more event to their own headers + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_ORIENTATION Orientation Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Orientation sensor. + * @{ + */ + +enum orientation_data_id { + ORIENTATION_BASE_DATA_SET = (ORIENTATION_SENSOR << 16) | 0x0001, +}; + +enum orientation_event_type { + ORIENTATION_EVENT_CALIBRATION_NEEDED = (ORIENTATION_SENSOR << 16) | 0x0001, + ORIENTATION_EVENT_RAW_DATA_REPORT_ON_TIME = (ORIENTATION_SENSOR << 16) | 0x0002, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_ORIENTATION_H_*/ diff --git a/src/libsensord/sensor_proxi.h b/src/libsensord/sensor_proxi.h new file mode 100755 index 0000000..ce6b80c --- /dev/null +++ b/src/libsensord/sensor_proxi.h @@ -0,0 +1,64 @@ +/* + * libsensord + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __SENSOR_PROXI_H__ +#define __SENSOR_PROXI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +/** + * @defgroup SENSOR_PROXY Proximity Sensor + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the Proxymaty sensor. + * @{ + */ + +enum proxi_data_id { + PROXIMITY_BASE_DATA_SET = (PROXIMITY_SENSOR << 16) | 0x0001, + PROXIMITY_DISTANCE_DATA_SET = (PROXIMITY_SENSOR << 16) | 0x0002, +}; + +enum proxi_evet_type { + PROXIMITY_EVENT_CHANGE_STATE = (PROXIMITY_SENSOR << 16) | 0x0001, + PROXIMITY_EVENT_STATE_REPORT_ON_TIME = (PROXIMITY_SENSOR << 16) | 0x0002, + PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME = (PROXIMITY_SENSOR << 16) | 0x0004, +}; + +enum proxi_change_state { + PROXIMITY_STATE_FAR = 0, + PROXIMITY_STATE_NEAR = 1, +}; + +enum proxi_property_id { + PROXIMITY_PROPERTY_UNKNOWN = 0, +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_PROXI_H_*/ diff --git a/src/light/CMakeLists.txt b/src/light/CMakeLists.txt new file mode 100755 index 0000000..e32223b --- /dev/null +++ b/src/light/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 2.6) +project(light CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +SET(SENSOR_NAME light_sensor) +SET(SENSOR_HAL_NAME light_sensor_hal) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) +add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET -DHWREV_CHECK") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-DUSE_DLOG_LOG) +add_definitions(-Iinclude) + +add_library(${SENSOR_NAME} SHARED + light_sensor.cpp + ) + +add_library(${SENSOR_HAL_NAME} SHARED + light_sensor_hal.cpp + ) + +target_link_libraries(${SENSOR_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") +target_link_libraries(${SENSOR_HAL_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS}) + +install(TARGETS ${SENSOR_NAME} DESTINATION lib/sensord) +install(TARGETS ${SENSOR_HAL_NAME} DESTINATION lib/sensord) diff --git a/src/light/light_sensor.cpp b/src/light/light_sensor.cpp new file mode 100755 index 0000000..4c8481d --- /dev/null +++ b/src/light/light_sensor.cpp @@ -0,0 +1,223 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using std::bind1st; +using std::mem_fun; + +#define SENSOR_NAME "LIGHT_SENSOR" + +#define INITIAL_VALUE -1 +const int light_sensor::m_light_level[] = {0, 1, 165, 288, 497, 869, 1532, 2692, 4692, 8280, 21428, 65535, 137852}; + +light_sensor::light_sensor() +: m_sensor_hal(NULL) +, m_level(INITIAL_VALUE) +{ + m_name = string(SENSOR_NAME); + + vector supported_events = { + LIGHT_EVENT_CHANGE_LEVEL, + LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME, + LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME, + }; + + for_each(supported_events.begin(), supported_events.end(), + bind1st(mem_fun(&sensor_base::register_supported_event), this)); + + physical_sensor::set_poller(light_sensor::working, this); +} + +light_sensor::~light_sensor() +{ + INFO("light_sensor is destroyed!"); +} + +bool light_sensor::init() +{ + m_sensor_hal = sensor_plugin_loader::get_instance().get_sensor_hal(LIGHT_SENSOR); + + if (!m_sensor_hal) { + ERR("cannot load sensor_hal[%s]", sensor_base::get_name()); + return false; + } + + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +sensor_type_t light_sensor::get_type(void) +{ + return LIGHT_SENSOR; +} + +bool light_sensor::working(void *inst) +{ + light_sensor *sensor = (light_sensor *)inst; + return sensor->process_event(); +} + +bool light_sensor::process_event(void) +{ + sensor_event_t event; + int level; + + if (!m_sensor_hal->is_data_ready(true)) + return true; + + m_sensor_hal->get_sensor_data(event.data); + level = (int) adc_to_light_level((int)event.data.values[0]); + + AUTOLOCK(m_client_info_mutex); + + if (get_client_cnt(LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME)) { + event.event_type = LIGHT_EVENT_LUX_DATA_REPORT_ON_TIME; + push(event); + } + + if (get_client_cnt(LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME)) { + event.event_type = LIGHT_EVENT_LEVEL_DATA_REPORT_ON_TIME; + raw_to_level(event.data); + push(event); + } + + if (m_level != level) { + m_level = level; + + if (get_client_cnt(LIGHT_EVENT_CHANGE_LEVEL)) { + event.event_type = LIGHT_EVENT_CHANGE_LEVEL; + raw_to_level(event.data); + push(event); + } + } + + return true; +} + +int light_sensor::adc_to_light_level(int adc) +{ + int level_cnt = sizeof(m_light_level) / sizeof(m_light_level[0]) - 1; + + for (int i = 0; i < level_cnt; ++i) { + if (adc >= m_light_level[i] && adc < m_light_level[i + 1]) + return i; + } + + return -1; +} + +bool light_sensor::on_start(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->enable()) { + ERR("m_sensor_hal start fail"); + return false; + } + + return start_poll(); +} + +bool light_sensor::on_stop(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->disable()) { + ERR("m_sensor_hal stop fail"); + return false; + } + + return stop_poll(); +} + +bool light_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + m_sensor_hal->get_properties(properties); + + if (type == LIGHT_LUX_DATA_SET) + return 0; + + if (type == LIGHT_BASE_DATA_SET) { + properties.sensor_unit_idx = SENSOR_UNIT_LEVEL; + properties.sensor_min_range = 0; + properties.sensor_max_range = sizeof(m_light_level) / sizeof(m_light_level[0]) - 1; + properties.sensor_resolution = 1; + return 0; + } + + return -1; +} + +int light_sensor::get_sensor_data(const unsigned int type, sensor_data_t &data) +{ + int ret; + ret = m_sensor_hal->get_sensor_data(data); + + if (ret < 0) + return -1; + + if (type == LIGHT_LUX_DATA_SET) + return 0; + + if (type == LIGHT_BASE_DATA_SET) { + raw_to_level(data); + return 0; + } + + return -1; +} + +bool light_sensor::set_interval(unsigned long interval) +{ + AUTOLOCK(m_mutex); + + INFO("Polling interval is set to %dms", interval); + return m_sensor_hal->set_interval(interval); +} + +void light_sensor::raw_to_level(sensor_data_t &data) +{ + data.data_unit_idx = SENSOR_UNIT_LEVEL; + data.values[0] = (int) adc_to_light_level((int)data.values[0]); + data.values_num = 1; +} + +extern "C" void *create(void) +{ + light_sensor *inst; + + try { + inst = new light_sensor(); + } catch (int err) { + ERR("Failed to create light_sensor class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (light_sensor *)inst; +} diff --git a/src/light/light_sensor.h b/src/light/light_sensor.h new file mode 100755 index 0000000..455df3d --- /dev/null +++ b/src/light/light_sensor.h @@ -0,0 +1,55 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _LIGHT_SENSOR_H_ +#define _LIGHT_SENSOR_H_ + +#include +#include +#include + +class light_sensor : public physical_sensor +{ +public: + light_sensor(); + virtual ~light_sensor(); + + virtual bool init(); + virtual sensor_type_t get_type(void); + + static bool working(void *inst); + + virtual bool on_start(void); + virtual bool on_stop(void); + + virtual bool set_interval(unsigned long interval); + virtual bool get_properties(const unsigned int type, sensor_properties_t &properties); + int get_sensor_data(const unsigned int type, sensor_data_t &data); + +private: + static const int m_light_level[]; + sensor_hal *m_sensor_hal; + int m_level; + + int adc_to_light_level(int adc); + void raw_to_level(sensor_data_t &data); + void raw_to_state(sensor_data_t &data); + bool process_event(void); +}; +#endif /*_LIGHT_SENSOR_H_*/ diff --git a/src/light/light_sensor_hal.cpp b/src/light/light_sensor_hal.cpp new file mode 100755 index 0000000..06045db --- /dev/null +++ b/src/light/light_sensor_hal.cpp @@ -0,0 +1,458 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::ifstream; +using config::CConfig; + +#define NODE_NAME "name" +#define NODE_INPUT "input" +#define NODE_ENABLE "enable" +#define NODE_POLL_DELAY "poll_delay" +#define NODE_LIGHT_POLL_DELAY "light_poll_delay" +#define SENSOR_NODE "/sys/class/sensors/" +#define SENSORHUB_NODE "/sys/class/sensors/ssp_sensor/" +#define INPUT_DEVICE_NODE "/sys/class/input/" +#define DEV_INPUT_NODE "/dev/input/event/" + +#define BIAS 1 +#define INITIAL_VALUE -1 +#define INITIAL_TIME 0 + +#define SENSOR_TYPE_LIGHT "LIGHT" +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ELEMENT_RAW_DATA_UNIT "RAW_DATA_UNIT" +#define ELEMENT_RESOLUTION "RESOLUTION" +#define ATTR_VALUE "value" + +#define INPUT_NAME "light_sensor" + +light_sensor_hal::light_sensor_hal() +: m_adc(INITIAL_VALUE) +, m_node_handle(INITIAL_VALUE) +, m_polling_interval(POLL_1HZ_MS) +, m_fired_time(INITIAL_TIME) +, m_sensorhub_supported(false) +{ + if (!check_hw_node()) { + ERR("check_hw_node() fail"); + throw ENXIO; + } + + CConfig &config = CConfig::get_instance(); + + if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_LIGHT, m_model_id, ELEMENT_NAME, m_chip_name)) { + ERR("[NAME] is empty"); + throw ENXIO; + } + + INFO("m_chip_name = %s", m_chip_name.c_str()); + + if ((m_node_handle = open(m_resource.c_str(), O_RDWR)) < 0) { + ERR("Failed to open handle(%d)", m_node_handle); + throw ENXIO; + } + + int clockId = CLOCK_MONOTONIC; + + if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) { + ERR("Fail to set monotonic timestamp for %s", m_resource.c_str()); + throw ENXIO; + } + + INFO("light_sensor_hal is created!"); +} + +light_sensor_hal::~light_sensor_hal() +{ + close(m_node_handle); + m_node_handle = INITIAL_VALUE; + + INFO("light_sensor_hal is destroyed!"); +} + +string light_sensor_hal::get_model_id(void) +{ + return m_model_id; +} + +sensor_type_t light_sensor_hal::get_type(void) +{ + return LIGHT_SENSOR; +} + +bool light_sensor_hal::enable_resource(string &resource_node, bool enable) +{ + int prev_status, status; + FILE *fp = NULL; + fp = fopen(resource_node.c_str(), "r"); + + if (!fp) { + ERR("Fail to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fscanf(fp, "%d", &prev_status) < 0) { + ERR("Failed to get data from %s", resource_node.c_str()); + fclose(fp); + return false; + } + + fclose(fp); + + if (enable) { + if (m_sensorhub_supported) + status = prev_status | (1 << SENSORHUB_LIGHT_ENABLE_BIT); + else + status = 1; + } else { + if (m_sensorhub_supported) + status = prev_status ^ (1 << SENSORHUB_LIGHT_ENABLE_BIT); + else + status = 0; + } + + fp = fopen(resource_node.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fprintf(fp, "%d", status) < 0) { + ERR("Failed to enable a resource file: %s", resource_node.c_str()); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + return true; +} + +bool light_sensor_hal::enable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, true); + set_interval(m_polling_interval); + + m_fired_time = 0; + INFO("Light sensor real starting"); + return true; +} + +bool light_sensor_hal::disable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, false); + INFO("Light sensor real stopping"); + return true; +} + +bool light_sensor_hal::set_interval(unsigned long val) +{ + unsigned long long polling_interval_ns; + FILE *fp = NULL; + + AUTOLOCK(m_mutex); + + polling_interval_ns = ((unsigned long long)(val) * MS_TO_SEC * MS_TO_SEC); + fp = fopen(m_polling_resource.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", m_polling_resource.c_str()); + return false; + } + + if (fprintf(fp, "%llu", polling_interval_ns) < 0) { + ERR("Failed to set data %llu", polling_interval_ns); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + INFO("Interval is changed from %dms to %dms]", m_polling_interval, val); + m_polling_interval = val; + return true; +} + +bool light_sensor_hal::update_value(bool wait) +{ + const int TIMEOUT = 1; + struct timeval tv; + fd_set readfds, exceptfds; + int adc = INITIAL_VALUE; + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + FD_SET(m_node_handle, &readfds); + FD_SET(m_node_handle, &exceptfds); + + if (wait) { + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + } else { + tv.tv_sec = 0; + tv.tv_usec = 0; + } + + int ret; + ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, &tv); + + if (ret == -1) { + ERR("select error:%s m_node_handle:%d", strerror(errno), m_node_handle); + return false; + } else if (!ret) { + DBG("select timeout: %d seconds elapsed", tv.tv_sec); + return false; + } + + if (FD_ISSET(m_node_handle, &exceptfds)) { + ERR("select exception occurred!"); + return false; + } + + if (FD_ISSET(m_node_handle, &readfds)) { + struct input_event light_event; + DBG("light event detection!"); + + int len; + len = read(m_node_handle, &light_event, sizeof(light_event)); + + if (len == -1) { + DBG("read(m_node_handle) is error:%s.", strerror(errno)); + return false; + } + + if (light_event.type == EV_ABS && light_event.code == ABS_MISC) { + adc = light_event.value; + } else if (light_event.type == EV_REL && light_event.code == REL_RX) { + adc = light_event.value - BIAS; + } else { + DBG("light input event[type = %d, code = %d] is unknown.", light_event.type, light_event.code); + return false; + } + + DBG("read event, len : %d, type : %x, code : %x, value : %x", + len, light_event.type, light_event.code, light_event.value); + DBG("update_value, adc : %d", adc); + + AUTOLOCK(m_value_mutex); + m_adc = adc; + m_fired_time = get_timestamp(&light_event.time); + } else { + ERR("select nothing to read!!!"); + return false; + } + + return true; +} + +bool light_sensor_hal::is_data_ready(bool wait) +{ + bool ret; + ret = update_value(wait); + return ret; +} + +int light_sensor_hal::get_sensor_data(sensor_data_t &data) +{ + const int chance = 3; + int retry = 0; + + while ((m_fired_time == 0) && (retry++ < chance)) { + INFO("Try usleep for getting a valid BASE DATA value"); + usleep(m_polling_interval * MS_TO_SEC); + } + + if (m_fired_time == 0) { + ERR("get_sensor_data failed"); + return -1; + } + + AUTOLOCK(m_value_mutex); + data.data_accuracy = SENSOR_ACCURACY_GOOD; + data.data_unit_idx = SENSOR_UNIT_LUX; + data.timestamp = m_fired_time ; + data.values_num = 1; + data.values[0] = (float) m_adc; + + return 0; +} + +bool light_sensor_hal::get_properties(sensor_properties_t &properties) +{ + properties.sensor_unit_idx = SENSOR_UNIT_LUX; + properties.sensor_min_range = 0; + properties.sensor_max_range = 65536; + snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); + snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); + properties.sensor_resolution = 1.0f; + return true; +} + +bool light_sensor_hal::is_sensorhub_supported(void) +{ + DIR *main_dir = NULL; + main_dir = opendir(SENSORHUB_NODE); + + if (!main_dir) { + INFO("Sensor Hub is not supported"); + return false; + } + + INFO("It supports sensor hub"); + closedir(main_dir); + return true; +} + +bool light_sensor_hal::check_hw_node(void) +{ + string name_node; + string hw_name; + DIR *main_dir = NULL; + struct dirent *dir_entry = NULL; + bool find_node = false; + + INFO("======================start check_hw_node============================="); + + m_sensorhub_supported = is_sensorhub_supported(); + main_dir = opendir(SENSOR_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0)) { + name_node = string(SENSOR_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (CConfig::get_instance().is_supported(SENSOR_TYPE_LIGHT, hw_name) == true) { + m_name = m_model_id = hw_name; + INFO("m_model_id = %s", m_model_id.c_str()); + find_node = true; + break; + } + } + } + + closedir(main_dir); + + if (find_node) { + main_dir = opendir(INPUT_DEVICE_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + find_node = false; + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if (strncasecmp(dir_entry->d_name, NODE_INPUT, 5) == 0) { + name_node = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (hw_name == string(INPUT_NAME)) { + INFO("name_node = %s", name_node.c_str()); + DBG("Find H/W for light_sensor"); + + find_node = true; + string dir_name; + dir_name = string(dir_entry->d_name); + unsigned found = dir_name.find_first_not_of(NODE_INPUT); + m_resource = string(DEV_INPUT_NODE) + dir_name.substr(found); + + if (m_sensorhub_supported) { + m_enable_resource = string(SENSORHUB_NODE) + string(NODE_ENABLE); + m_polling_resource = string(SENSORHUB_NODE) + string(NODE_LIGHT_POLL_DELAY); + } else { + m_enable_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_ENABLE); + m_polling_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_POLL_DELAY); + } + + break; + } + } + } + + closedir(main_dir); + } + + if (find_node) { + INFO("m_resource = %s", m_resource.c_str()); + INFO("m_enable_resource = %s", m_enable_resource.c_str()); + INFO("m_polling_resource = %s", m_polling_resource.c_str()); + } + + return find_node; +} + +extern "C" void *create(void) +{ + light_sensor_hal *inst; + + try { + inst = new light_sensor_hal(); + } catch (int err) { + ERR("Failed to create light_sensor_hal class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (light_sensor_hal *)inst; +} diff --git a/src/light/light_sensor_hal.h b/src/light/light_sensor_hal.h new file mode 100755 index 0000000..2cba537 --- /dev/null +++ b/src/light/light_sensor_hal.h @@ -0,0 +1,65 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _LIGHT_SENSOR_HAL_H_ +#define _LIGHT_SENSOR_HAL_H_ + +#include +#include + +using std::string; + +class light_sensor_hal : public sensor_hal +{ +public: + light_sensor_hal(); + virtual ~light_sensor_hal(); + string get_model_id(void); + sensor_type_t get_type(void); + bool enable(void); + bool disable(void); + bool set_interval(unsigned long val); + bool is_data_ready(bool wait); + virtual int get_sensor_data(sensor_data_t &data); + bool get_properties(sensor_properties_t &properties); + bool check_hw_node(void); + +private: + int m_adc; + int m_node_handle; + unsigned long m_polling_interval; + unsigned long long m_fired_time; + bool m_sensorhub_supported; + + string m_model_id; + string m_name; + string m_vendor; + string m_chip_name; + + string m_resource; + string m_enable_resource; + string m_polling_resource; + + cmutex m_value_mutex; + + bool enable_resource(string &resource_node, bool enable); + bool update_value(bool wait); + bool is_sensorhub_supported(void); +}; +#endif /*_LIGHT_SENSOR_HAL_H_*/ \ No newline at end of file diff --git a/src/linear_accel/CMakeLists.txt b/src/linear_accel/CMakeLists.txt new file mode 100755 index 0000000..b158f2b --- /dev/null +++ b/src/linear_accel/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 2.6) +project(linear_accel CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(VERSION 1.0) + +SET(SENSOR_NAME linear_accel_sensor) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET -DHWREV_CHECK") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-DUSE_DLOG_LOG) +add_definitions(-Iinclude) + +add_library(${SENSOR_NAME} SHARED + linear_accel_sensor.cpp + ) + +target_link_libraries(${SENSOR_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") + +install(TARGETS ${SENSOR_NAME} DESTINATION lib/sensord) diff --git a/src/linear_accel/linear_accel_sensor.cpp b/src/linear_accel/linear_accel_sensor.cpp new file mode 100755 index 0000000..7465d61 --- /dev/null +++ b/src/linear_accel/linear_accel_sensor.cpp @@ -0,0 +1,170 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SENSOR_NAME "LINEAR_ACCEL_SENSOR" + +#define INITIAL_VALUE -1 +#define INITIAL_TIME 0 +#define GRAVITY 9.80665 + +linear_accel_sensor::linear_accel_sensor() +: m_gravity_sensor(NULL) +, m_x(INITIAL_VALUE) +, m_y(INITIAL_VALUE) +, m_z(INITIAL_VALUE) +, m_time(INITIAL_TIME) +{ + m_name = string(SENSOR_NAME); + register_supported_event(LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME); +} + +linear_accel_sensor::~linear_accel_sensor() +{ + INFO("linear_accel_sensor is destroyed!"); +} + +bool linear_accel_sensor::init() +{ + m_gravity_sensor = sensor_plugin_loader::get_instance().get_sensor(GRAVITY_SENSOR); + + if (!m_gravity_sensor) { + ERR("cannot load gravity sensor_hal[%s]", sensor_base::get_name()); + return false; + } + + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +sensor_type_t linear_accel_sensor::get_type(void) +{ + return LINEAR_ACCEL_SENSOR; +} + +bool linear_accel_sensor::on_start(void) +{ + AUTOLOCK(m_mutex); + m_gravity_sensor->add_client(GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME); + m_gravity_sensor->start(); + activate(); + return true; +} + +bool linear_accel_sensor::on_stop(void) +{ + AUTOLOCK(m_mutex); + m_gravity_sensor->delete_client(GRAVITY_EVENT_RAW_DATA_REPORT_ON_TIME); + m_gravity_sensor->stop(); + deactivate(); + return true; +} + +bool linear_accel_sensor::add_interval(int client_id, unsigned int interval, bool is_processor) +{ + m_gravity_sensor->add_interval((int)this , interval, true); + return sensor_base::add_interval(client_id, interval, is_processor); +} + +bool linear_accel_sensor::delete_interval(int client_id, bool is_processor) +{ + m_gravity_sensor->delete_interval((int)this , true); + return sensor_base::delete_interval(client_id, is_processor); +} + +void linear_accel_sensor::synthesize(const sensor_event_t &event, vector &outs) +{ + vector gravity_event; + ((virtual_sensor *)m_gravity_sensor)->synthesize(event, gravity_event); + + if (!gravity_event.empty() && event.event_type == ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME) { + AUTOLOCK(m_value_mutex); + + m_time = gravity_event[0].data.timestamp; + gravity_event[0].event_type = LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME; + m_x = event.data.values[0] - gravity_event[0].data.values[0] * GRAVITY; + m_y = event.data.values[1] - gravity_event[0].data.values[1] * GRAVITY; + m_z = event.data.values[2] - gravity_event[0].data.values[2] * GRAVITY; + + gravity_event[0].data.values[0] = m_x; + gravity_event[0].data.values[1] = m_y; + gravity_event[0].data.values[2] = m_z; + outs.push_back(gravity_event[0]); + return; + } +} + +int linear_accel_sensor::get_sensor_data(const unsigned int data_id, sensor_data_t &data) +{ + if (data_id != LINEAR_ACCEL_BASE_DATA_SET) + return -1; + + AUTOLOCK(m_value_mutex); + data.data_accuracy = SENSOR_ACCURACY_GOOD; + data.data_unit_idx = SENSOR_UNIT_METRE_PER_SECOND_SQUARED; + data.time_stamp = m_time; + data.values[0] = m_x; + data.values[1] = m_y; + data.values[2] = m_z; + data.values_num = 3; + return 0; +} + +bool linear_accel_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + m_gravity_sensor->get_properties(type, properties); + + if (type != LINEAR_ACCEL_EVENT_RAW_DATA_REPORT_ON_TIME) + return true; + + strncpy(properties.sensor_name, "Linear Accelerometer Sensor", MAX_KEY_LENGTH); + return true; +} + +extern "C" void *create(void) +{ + linear_accel_sensor *inst; + + try { + inst = new linear_accel_sensor(); + } catch (int ErrNo) { + ERR("Failed to create linear_accel_sensor class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (linear_accel_sensor *)inst; +} diff --git a/src/linear_accel/linear_accel_sensor.h b/src/linear_accel/linear_accel_sensor.h new file mode 100755 index 0000000..2d1e96f --- /dev/null +++ b/src/linear_accel/linear_accel_sensor.h @@ -0,0 +1,60 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _LINEAR_ACCEL_SENSOR_H_ +#define _LINEAR_ACCEL_SENSOR_H_ + +#include +#include +#include + +using std::string; + +class linear_accel_sensor : public virtual_sensor +{ +public: + linear_accel_sensor(); + virtual ~linear_accel_sensor(); + + bool init(); + sensor_type_t get_type(void); + + static bool working(void *inst); + + bool on_start(void); + bool on_stop(void); + + void synthesize(const sensor_event_t &event, vector &outs); + + virtual bool add_interval(int client_id, unsigned int interval, bool is_processor = false); + virtual bool delete_interval(int client_id, bool is_processor = false); + + int get_sensor_data(const unsigned int data_id, sensor_data_t &data); + bool get_properties(const unsigned int type, sensor_properties_t &properties); +private: + sensor_base *m_gravity_sensor; + cmutex m_value_mutex; + + float m_x; + float m_y; + float m_z; + unsigned long long m_time; +}; + +#endif /*_LINEAR_ACCEL_SENSOR_H_*/ diff --git a/src/proxi/CMakeLists.txt b/src/proxi/CMakeLists.txt new file mode 100755 index 0000000..6a52735 --- /dev/null +++ b/src/proxi/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 2.6) +project(proxi CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +SET(SENSOR_NAME proxi_sensor) +SET(SENSOR_HAL_NAME proxi_sensor_hal) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) +add_definitions(${rpkgs_CFLAGS} -DUSE_ONLY_ONE_MODULE) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET -DHWREV_CHECK") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-DUSE_DLOG_LOG) +add_definitions(-Iinclude) + +add_library(${SENSOR_NAME} SHARED + proxi_sensor.cpp +) + +add_library(${SENSOR_HAL_NAME} SHARED + proxi_sensor_hal.cpp +) + +target_link_libraries(${SENSOR_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") +target_link_libraries(${SENSOR_HAL_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS}) + +install(TARGETS ${SENSOR_NAME} DESTINATION lib/sensord) +install(TARGETS ${SENSOR_HAL_NAME} DESTINATION lib/sensord) diff --git a/src/proxi/proxi_sensor.cpp b/src/proxi/proxi_sensor.cpp new file mode 100755 index 0000000..4799da4 --- /dev/null +++ b/src/proxi/proxi_sensor.cpp @@ -0,0 +1,182 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +#define SENSOR_NAME "PROXI_SENSOR" + +proxi_sensor::proxi_sensor() +: m_sensor_hal(NULL) +, m_state(PROXIMITY_STATE_FAR) +{ + m_name = string(SENSOR_NAME); + + register_supported_event(PROXIMITY_EVENT_CHANGE_STATE); + register_supported_event(PROXIMITY_EVENT_STATE_REPORT_ON_TIME); + register_supported_event(PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME); + + physical_sensor::set_poller(proxi_sensor::working, this); +} + +proxi_sensor::~proxi_sensor() +{ + INFO("proxi_sensor is destroyed!"); +} + +bool proxi_sensor::init() +{ + m_sensor_hal = sensor_plugin_loader::get_instance().get_sensor_hal(PROXIMITY_SENSOR); + + if (!m_sensor_hal) { + ERR("cannot load sensor_hal[%s]", sensor_base::get_name()); + return false; + } + + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +sensor_type_t proxi_sensor::get_type(void) +{ + return PROXIMITY_SENSOR; +} + +bool proxi_sensor::working(void *inst) +{ + proxi_sensor *sensor = (proxi_sensor *)inst; + return sensor->process_event(); +} + +bool proxi_sensor::process_event(void) +{ + sensor_event_t event; + int state; + + if (!m_sensor_hal->is_data_ready(true)) + return true; + + m_sensor_hal->get_sensor_data(event.data); + + AUTOLOCK(m_client_info_mutex); + AUTOLOCK(m_mutex); + + if (get_client_cnt(PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME)) { + event.event_type = PROXIMITY_EVENT_DISTANCE_DATA_REPORT_ON_TIME; + raw_to_base(event.data); + push(event); + } + + state = event.data.values[0]; + + if (m_state != state) { + AUTOLOCK(m_value_mutex); + m_state = state; + + if (get_client_cnt(PROXIMITY_EVENT_CHANGE_STATE)) { + event.event_type = PROXIMITY_EVENT_CHANGE_STATE; + raw_to_state(event.data); + push(event); + } + } + + return true; +} + +bool proxi_sensor::on_start(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->enable()) { + ERR("m_sensor_hal start fail"); + return false; + } + + return start_poll(); +} + +bool proxi_sensor::on_stop(void) +{ + AUTOLOCK(m_mutex); + + if (!m_sensor_hal->disable()) { + ERR("m_sensor_hal stop fail"); + return false; + } + + return stop_poll(); +} + +bool proxi_sensor::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + return m_sensor_hal->get_properties(properties); +} + +int proxi_sensor::get_sensor_data(const unsigned int type, sensor_data_t &data) +{ + int state; + + if ((type != PROXIMITY_BASE_DATA_SET) && (type != PROXIMITY_DISTANCE_DATA_SET)) + return -1; + + state = m_sensor_hal->get_sensor_data(data); + + if (state < 0) { + ERR("m_sensor_hal get struct_data fail"); + return -1; + } + + if (type == PROXIMITY_DISTANCE_DATA_SET) { + raw_to_base(data); + return 0; + } + + return 0; +} + +void proxi_sensor::raw_to_base(sensor_data_t &data) +{ + data.values[0] = (float)((PROXIMITY_STATE_NEAR - data.values[0]) * 5); +} + +void proxi_sensor::raw_to_state(sensor_data_t &data) +{ + data.values_num = 1; +} + +extern "C" void *create(void) +{ + proxi_sensor *inst; + + try { + inst = new proxi_sensor(); + } catch (int err) { + ERR("Failed to create proxi_sensor class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (proxi_sensor *)inst; +} diff --git a/src/proxi/proxi_sensor.h b/src/proxi/proxi_sensor.h new file mode 100755 index 0000000..5b8a411 --- /dev/null +++ b/src/proxi/proxi_sensor.h @@ -0,0 +1,53 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _PROXI_SENSOR_H_ +#define _PROXI_SENSOR_H_ + +#include +#include +#include + +class proxi_sensor : public physical_sensor +{ +public: + proxi_sensor(); + virtual ~proxi_sensor(); + + virtual bool init(); + virtual sensor_type_t get_type(void); + + static bool working(void *inst); + + virtual bool on_start(void); + virtual bool on_stop(void); + + virtual bool get_properties(const unsigned int type, sensor_properties_t &properties); + virtual int get_sensor_data(const unsigned int type, sensor_data_t &data); +private: + sensor_hal *m_sensor_hal; + cmutex m_value_mutex; + + int m_state; + + void raw_to_base(sensor_data_t &data); + void raw_to_state(sensor_data_t &data); + bool process_event(void); +}; +#endif /*_PROXI_SENSOR_H_*/ diff --git a/src/proxi/proxi_sensor_hal.cpp b/src/proxi/proxi_sensor_hal.cpp new file mode 100755 index 0000000..eed0c9b --- /dev/null +++ b/src/proxi/proxi_sensor_hal.cpp @@ -0,0 +1,396 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::ifstream; +using config::CConfig; + +#define NODE_NAME "name" +#define NODE_INPUT "input" +#define NODE_ENABLE "enable" +#define SENSOR_NODE "/sys/class/sensors/" +#define SENSORHUB_NODE "/sys/class/sensors/ssp_sensor/" +#define INPUT_DEVICE_NODE "/sys/class/input/" +#define DEV_INPUT_NODE "/dev/input/event/" + +#define INITIAL_VALUE -1 +#define INITIAL_TIME 0 +#define PROXI_CODE 0x0019 + +#define SENSOR_TYPE_PROXI "PROXI" +#define ELEMENT_NAME "NAME" +#define ELEMENT_VENDOR "VENDOR" +#define ATTR_VALUE "value" + +#define INPUT_NAME "proximity_sensor" + +proxi_sensor_hal::proxi_sensor_hal() +: m_state(PROXIMITY_STATE_FAR) +, m_node_handle(INITIAL_VALUE) +, m_fired_time(INITIAL_TIME) +, m_sensorhub_supported(false) +{ + if (!check_hw_node()) { + ERR("check_hw_node() fail"); + throw ENXIO; + } + + CConfig &config = CConfig::get_instance(); + + if (!config.get(SENSOR_TYPE_PROXI, m_model_id, ELEMENT_VENDOR, m_vendor)) { + ERR("[VENDOR] is empty"); + throw ENXIO; + } + + INFO("m_vendor = %s", m_vendor.c_str()); + + if (!config.get(SENSOR_TYPE_PROXI, m_model_id, ELEMENT_NAME, m_chip_name)) { + ERR("[NAME] is empty"); + throw ENXIO; + } + + INFO("m_chip_name = %s", m_chip_name.c_str()); + + if ((m_node_handle = open(m_resource.c_str(), O_RDWR)) < 0) { + ERR("Failed to open handle(%d)", m_node_handle); + throw ENXIO; + } + + int clockId = CLOCK_MONOTONIC; + + if (ioctl(m_node_handle, EVIOCSCLOCKID, &clockId) != 0) { + ERR("Fail to set monotonic timestamp for %s", m_resource.c_str()); + throw ENXIO; + } + + INFO("proxi_sensor_hal is created!"); +} + +proxi_sensor_hal::~proxi_sensor_hal() +{ + close(m_node_handle); + m_node_handle = INITIAL_VALUE; + + INFO("proxi_sensor_hal is destroyed!"); +} + +string proxi_sensor_hal::get_model_id(void) +{ + return m_model_id; +} + +sensor_type_t proxi_sensor_hal::get_type(void) +{ + return PROXIMITY_SENSOR; +} + +bool proxi_sensor_hal::enable_resource(string &resource_node, bool enable) +{ + int prev_status, status; + FILE *fp = NULL; + fp = fopen(resource_node.c_str(), "r"); + + if (!fp) { + ERR("Fail to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fscanf(fp, "%d", &prev_status) < 0) { + ERR("Failed to get data from %s", resource_node.c_str()); + fclose(fp); + return false; + } + + fclose(fp); + + if (enable) { + if (m_sensorhub_supported) + status = prev_status | (1 << SENSORHUB_PROXIMITY_ENABLE_BIT); + else + status = 1; + } else { + if (m_sensorhub_supported) + status = prev_status ^ (1 << SENSORHUB_PROXIMITY_ENABLE_BIT); + else + status = 0; + } + + fp = fopen(resource_node.c_str(), "w"); + + if (!fp) { + ERR("Failed to open a resource file: %s", resource_node.c_str()); + return false; + } + + if (fprintf(fp, "%d", status) < 0) { + ERR("Failed to enable a resource file: %s", resource_node.c_str()); + fclose(fp); + return false; + } + + if (fp) + fclose(fp); + + return true; +} + +bool proxi_sensor_hal::enable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, true); + + m_fired_time = 0; + INFO("Proxi sensor real starting"); + return true; +} + +bool proxi_sensor_hal::disable(void) +{ + AUTOLOCK(m_mutex); + + enable_resource(m_enable_resource, false); + INFO("Proxi sensor real stopping"); + return true; +} + +bool proxi_sensor_hal::update_value(bool wait) +{ + struct input_event proxi_event; + fd_set readfds, exceptfds; + + FD_ZERO(&readfds); + FD_ZERO(&exceptfds); + FD_SET(m_node_handle, &readfds); + FD_SET(m_node_handle, &exceptfds); + + int ret; + ret = select(m_node_handle + 1, &readfds, NULL, &exceptfds, NULL); + + if (ret == -1) { + ERR("select error:%s m_node_handle:d", strerror(errno), m_node_handle); + return false; + } else if (!ret) { + DBG("select timeout"); + return false; + } + + if (FD_ISSET(m_node_handle, &exceptfds)) { + ERR("select exception occurred!"); + return false; + } + + if (FD_ISSET(m_node_handle, &readfds)) { + INFO("proxi event detection!"); + int len = read(m_node_handle, &proxi_event, sizeof(proxi_event)); + + if (len == -1) { + DBG("read(m_node_handle) is error:%s.", strerror(errno)); + return false; + } + + DBG("read event, len : %d , type : %x , code : %x , value : %x", len, proxi_event.type, proxi_event.code, proxi_event.value); + + if ((proxi_event.type == EV_ABS) && (proxi_event.code == PROXI_CODE)) { + AUTOLOCK(m_value_mutex); + + if (proxi_event.value == PROXIMITY_NODE_STATE_FAR) { + INFO("PROXIMITY_STATE_FAR state occured"); + m_state = PROXIMITY_STATE_FAR; + } else if (proxi_event.value == PROXIMITY_NODE_STATE_NEAR) { + INFO("PROXIMITY_STATE_NEAR state occured"); + m_state = PROXIMITY_STATE_NEAR; + } else { + ERR("PROXIMITY_STATE Unknown: %d", proxi_event.value); + return false; + } + + m_fired_time = sensor_hal::get_timestamp(&proxi_event.time); + } else { + return false; + } + } else { + ERR("select nothing to read!!!"); + return false; + } + + return true; +} + +bool proxi_sensor_hal::is_data_ready(bool wait) +{ + bool ret; + ret = update_value(wait); + return ret; +} + +int proxi_sensor_hal::get_sensor_data(sensor_data_t &data) +{ + AUTOLOCK(m_value_mutex); + data.data_accuracy = SENSOR_ACCURACY_UNDEFINED; + data.data_unit_idx = SENSOR_UNIT_STATE_ON_OFF; + data.timestamp = m_fired_time; + data.values_num = 1; + data.values[0] = m_state; + return 0; +} + +bool proxi_sensor_hal::get_properties(sensor_properties_t &properties) +{ + properties.sensor_unit_idx = SENSOR_UNIT_STATE_ON_OFF; + properties.sensor_min_range = 0; + properties.sensor_max_range = 1; + snprintf(properties.sensor_name, sizeof(properties.sensor_name), "%s", m_chip_name.c_str()); + snprintf(properties.sensor_vendor, sizeof(properties.sensor_vendor), "%s", m_vendor.c_str()); + properties.sensor_resolution = 1; + return true; +} + +bool proxi_sensor_hal::is_sensorhub_supported(void) +{ + DIR *main_dir = NULL; + main_dir = opendir(SENSORHUB_NODE); + + if (!main_dir) { + INFO("Sensor Hub is not supported"); + return false; + } + + INFO("It supports sensor hub"); + closedir(main_dir); + return true; +} + +bool proxi_sensor_hal::check_hw_node(void) +{ + string name_node; + string hw_name; + DIR *main_dir = NULL; + struct dirent *dir_entry = NULL; + bool find_node = false; + + INFO("======================start check_hw_node============================="); + + m_sensorhub_supported = is_sensorhub_supported(); + main_dir = opendir(SENSOR_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if ((strncasecmp(dir_entry->d_name , ".", 1 ) != 0) && (strncasecmp(dir_entry->d_name , "..", 2 ) != 0) && (dir_entry->d_ino != 0)) { + name_node = string(SENSOR_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (CConfig::get_instance().is_supported(SENSOR_TYPE_PROXI, hw_name) == true) { + m_name = m_model_id = hw_name; + INFO("m_model_id = %s", m_model_id.c_str()); + find_node = true; + break; + } + } + } + + closedir(main_dir); + + if (find_node) { + main_dir = opendir(INPUT_DEVICE_NODE); + + if (!main_dir) { + ERR("Directory open failed to collect data"); + return false; + } + + find_node = false; + + while ((!find_node) && (dir_entry = readdir(main_dir))) { + if (strncasecmp(dir_entry->d_name, NODE_INPUT, 5) == 0) { + name_node = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_NAME); + ifstream infile(name_node.c_str()); + + if (!infile) + continue; + + infile >> hw_name; + + if (hw_name == string(INPUT_NAME)) { + INFO("name_node = %s", name_node.c_str()); + DBG("Find H/W for proxi_sensor"); + + find_node = true; + string dir_name; + dir_name = string(dir_entry->d_name); + unsigned found = dir_name.find_first_not_of(NODE_INPUT); + m_resource = string(DEV_INPUT_NODE) + dir_name.substr(found); + + if (m_sensorhub_supported) + m_enable_resource = string(SENSORHUB_NODE) + string(NODE_ENABLE); + else + m_enable_resource = string(INPUT_DEVICE_NODE) + string(dir_entry->d_name) + string("/") + string(NODE_ENABLE); + + break; + } + } + } + + closedir(main_dir); + } + + if (find_node) { + INFO("m_resource = %s", m_resource.c_str()); + INFO("m_enable_resource = %s", m_enable_resource.c_str()); + } + + return find_node; +} + +extern "C" void *create(void) +{ + proxi_sensor_hal *inst; + + try { + inst = new proxi_sensor_hal(); + } catch (int err) { + ERR("Failed to create proxi_sensor_hal class, errno : %d, errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (proxi_sensor_hal *)inst; +} diff --git a/src/proxi/proxi_sensor_hal.h b/src/proxi/proxi_sensor_hal.h new file mode 100755 index 0000000..d483814 --- /dev/null +++ b/src/proxi/proxi_sensor_hal.h @@ -0,0 +1,68 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _PROXI_SENSOR_HAL_H_ +#define _PROXI_SENSOR_HAL_H_ + +#include +#include + +using std::string; + +class proxi_sensor_hal : public sensor_hal +{ +public: + enum proxi_node_state_event_t { + PROXIMITY_NODE_STATE_NEAR = 0, + PROXIMITY_NODE_STATE_FAR = 1, + PROXIMITY_NODE_STATE_UNKNOWN = 2, + }; + + proxi_sensor_hal(); + virtual ~proxi_sensor_hal(); + string get_model_id(void); + sensor_type_t get_type(void); + bool enable(void); + bool disable(void); + bool is_data_ready(bool wait); + virtual int get_sensor_data(sensor_data_t &data); + bool get_properties(sensor_properties_t &properties); + bool check_hw_node(void); + +private: + unsigned int m_state; + int m_node_handle; + unsigned long long m_fired_time; + bool m_sensorhub_supported; + + string m_model_id; + string m_name; + string m_vendor; + string m_chip_name; + + string m_resource; + string m_enable_resource; + + cmutex m_value_mutex; + + bool enable_resource(string &resource_node, bool enable); + bool update_value(bool wait); + bool is_sensorhub_supported(void); +}; +#endif /*_PROXI_SENSOR_HAL_H_*/ \ No newline at end of file diff --git a/src/sensor_fusion/CMakeLists.txt b/src/sensor_fusion/CMakeLists.txt new file mode 100755 index 0000000..d03dbde --- /dev/null +++ b/src/sensor_fusion/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 2.6) +project(sensor_fusion CXX) + +# to install pkgconfig setup file. +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(VERSION 1.0) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED vconf) + +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "0") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") +IF("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DTARGET -DHWREV_CHECK") + MESSAGE("add -DTARGET -DHWREV_CHECK") +ELSE("${ARCH}" MATCHES "^arm.*") + ADD_DEFINITIONS("-DSIMULATOR") + MESSAGE("add -DSIMULATOR") +ENDIF("${ARCH}" MATCHES "^arm.*") + +add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-Wall -g -D_DEBUG) +add_definitions(-DUSE_DLOG_LOG) +add_definitions(-Iinclude) + +SET(SENSOR_FUSION_NAME sensor_fusion) + +add_library(${SENSOR_FUSION_NAME} SHARED + lib_sensor_fusion.cpp + ) + +target_link_libraries(${SENSOR_FUSION_NAME} ${rpkgs_LDFLAGS} ${GLES_LDFLAGS} "-lm") + +install(TARGETS ${SENSOR_FUSION_NAME} DESTINATION lib/sensord) diff --git a/src/sensor_fusion/lib_sensor_fusion.cpp b/src/sensor_fusion/lib_sensor_fusion.cpp new file mode 100755 index 0000000..0217c97 --- /dev/null +++ b/src/sensor_fusion/lib_sensor_fusion.cpp @@ -0,0 +1,183 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SENSOR_NAME "Sensor Fusion" + +lib_sensor_fusion::lib_sensor_fusion() +{ + m_name = string(SENSOR_NAME); +} + +lib_sensor_fusion::~lib_sensor_fusion() +{ +} + +bool lib_sensor_fusion::init(void) +{ + m_accel_sensor = sensor_plugin_loader::get_instance().get_sensor(ACCELEROMETER_SENSOR); + m_gyro_sensor = sensor_plugin_loader::get_instance().get_sensor(GYROSCOPE_SENSOR); + m_magnetic_sensor = sensor_plugin_loader::get_instance().get_sensor(GEOMAGNETIC_SENSOR); + + if (!m_accel_sensor || !m_gyro_sensor || !m_magnetic_sensor) { + ERR("Fail to load sensors, accel: 0x%x, gyro: 0x%x, mag: 0x%x", + m_accel_sensor, m_gyro_sensor, m_magnetic_sensor); + return false; + } + + INFO("%s is created!", sensor_base::get_name()); + return true; +} + +bool lib_sensor_fusion::on_start(void) +{ + AUTOLOCK(m_mutex); + + m_accel_sensor->add_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME); + m_accel_sensor->start(); + m_gyro_sensor->add_client(GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME); + m_gyro_sensor->start(); + m_magnetic_sensor->add_client(GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME); + m_magnetic_sensor->start(); + return true; +} + +bool lib_sensor_fusion::on_stop(void) +{ + m_accel_sensor->delete_client(ACCELEROMETER_EVENT_RAW_DATA_REPORT_ON_TIME); + m_accel_sensor->stop(); + m_gyro_sensor->delete_client(GYROSCOPE_EVENT_RAW_DATA_REPORT_ON_TIME); + m_gyro_sensor->stop(); + m_magnetic_sensor->delete_client(GEOMAGNETIC_EVENT_RAW_DATA_REPORT_ON_TIME); + m_magnetic_sensor->stop(); + return true; +} + +bool lib_sensor_fusion::add_interval(int client_id, unsigned int interval) +{ + AUTOLOCK(m_mutex); + + m_accel_sensor->add_interval(client_id, interval, true); + m_gyro_sensor->add_interval(client_id, interval, true); + m_magnetic_sensor->add_interval(client_id, interval, true); + return true; +} + +bool lib_sensor_fusion::delete_interval(int client_id) +{ + AUTOLOCK(m_mutex); + + m_accel_sensor->delete_interval(client_id, true); + m_gyro_sensor->delete_interval(client_id, true); + m_magnetic_sensor->delete_interval(client_id, true); + return true; +} + +bool lib_sensor_fusion::get_properties(sensor_properties_t &properties) +{ + properties.sensor_unit_idx = SENSOR_UNDEFINED_UNIT; + properties.sensor_min_range = 0; + properties.sensor_max_range = 1; + properties.sensor_resolution = 1; + strncpy(properties.sensor_vendor, "Samsung", MAX_KEY_LENGTH); + strncpy(properties.sensor_name, SENSOR_NAME, MAX_KEY_LENGTH); + return true; +} + +void lib_sensor_fusion::fuse(const sensor_event_t &event) +{ + return; +} + +bool lib_sensor_fusion::get_rotation_matrix(arr33_t &rot) +{ + return true; +} + +bool lib_sensor_fusion::get_attitude(float &x, float &y, float &z, float &w) +{ + return true; +} + +bool lib_sensor_fusion::get_gyro_bias(float &x, float &y, float &z) +{ + return true; +} + +bool lib_sensor_fusion::get_rotation_vector(float &x, float &y, float &z, float &w, float &heading_accuracy) +{ + return true; +} + +bool lib_sensor_fusion::get_linear_acceleration(float &x, float &y, float &z) +{ + return true; +} + +bool lib_sensor_fusion::get_gravity(float &x, float &y, float &z) +{ + return true; +} + +bool lib_sensor_fusion::get_rotation_vector_6axis(float &x, float &y, float &z, float &w, float &heading_accuracy) +{ + return true; +} + +bool lib_sensor_fusion::get_geomagnetic_rotation_vector(float &x, float &y, float &z, float &w) +{ + return true; +} + +bool lib_sensor_fusion::get_orientation(float &azimuth, float &pitch, float &roll) +{ + return true; +} + +extern "C" void *create(void) +{ + lib_sensor_fusion *inst; + + try { + inst = new lib_sensor_fusion(); + } catch (int err) { + ERR("lib_sensor_fusion class create fail , errno : %d , errstr : %s", err, strerror(err)); + return NULL; + } + + return (void *)inst; +} + +extern "C" void destroy(void *inst) +{ + delete (lib_sensor_fusion *)inst; +} diff --git a/src/sensor_fusion/lib_sensor_fusion.h b/src/sensor_fusion/lib_sensor_fusion.h new file mode 100755 index 0000000..85ddd3e --- /dev/null +++ b/src/sensor_fusion/lib_sensor_fusion.h @@ -0,0 +1,55 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _LIB_SENSOR_FUSION_H_ +#define _LIB_SENSOR_FUSION_H_ + +#include + +class lib_sensor_fusion : public sensor_fusion +{ +public: + lib_sensor_fusion(); + ~lib_sensor_fusion(); + + bool init(void); + bool on_start(void); + bool on_stop(void); + + bool add_interval(int client_id, unsigned int interval); + bool delete_interval(int client_id); + bool get_properties(sensor_properties_t &properties); + + void fuse(const sensor_event_t &event); + bool get_rotation_matrix(arr33_t &rot); + bool get_attitude(float &x, float &y, float &z, float &w); + bool get_gyro_bias(float &x, float &y, float &z); + bool get_rotation_vector(float &x, float &y, float &z, float &w, float &heading_accuracy); + bool get_linear_acceleration(float &x, float &y, float &z); + bool get_gravity(float &x, float &y, float &z); + bool get_rotation_vector_6axis(float &x, float &y, float &z, float &w, float &heading_accuracy); + bool get_geomagnetic_rotation_vector(float &x, float &y, float &z, float &w); + bool get_orientation(float &azimuth, float &pitch, float &roll); +private: + sensor_base *m_accel_sensor; + sensor_base *m_gyro_sensor; + sensor_base *m_magnetic_sensor; +}; + +#endif /*_LIB_SENSOR_FUSION_H_*/ diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt new file mode 100755 index 0000000..4939cd4 --- /dev/null +++ b/src/server/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 2.6) +project(sensord CXX) + +#add_definitions(-Wall -g -DUSE_FILE_DEBUG) +#add_definitions(-Wall -g -D_DEBUG) +#add_definitions(-Wall -g -pg) +add_definitions(-Wall -std=gnu++0x) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +SET(SERVER_SRCS + server.cpp + command_worker.cpp + main.cpp +) + +add_executable(${PROJECT_NAME} ${SERVER_SRCS}) + +target_link_libraries(${PROJECT_NAME} ${rpkgs_LDFLAGS} "sensord-server") +set(CMAKE_CXX_FLAGS "-lrt -ldl -pthread ${CMAKE_CXX_FLAGS}") + +install(TARGETS ${PROJECT_NAME} DESTINATION bin) diff --git a/src/server/command_worker.cpp b/src/server/command_worker.cpp new file mode 100755 index 0000000..2ef5562 --- /dev/null +++ b/src/server/command_worker.cpp @@ -0,0 +1,592 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +using std::string; + +command_worker::cmd_handler_t command_worker::m_cmd_handlers[]; + +command_worker::command_worker(const csocket &socket) +: m_client_id(CLIENT_ID_INVALID) +, m_socket(socket) +, m_module(NULL) +, m_sensor_type(UNKNOWN_SENSOR) +{ + init_cmd_handlers(); + + m_worker.set_context(this); + m_worker.set_working(working); + m_worker.set_stopped(stopped); +} + +command_worker::~command_worker() +{ + m_socket.close(); +} + +bool command_worker::start(void) +{ + return m_worker.start(); +} + +void command_worker::init_cmd_handlers(void) +{ + static bool init = false; + + if (!init) { + m_cmd_handlers[CMD_GET_ID] = &command_worker::cmd_get_id; + m_cmd_handlers[CMD_HELLO] = &command_worker::cmd_hello; + m_cmd_handlers[CMD_BYEBYE] = &command_worker::cmd_byebye; + m_cmd_handlers[CMD_START] = &command_worker::cmd_start; + m_cmd_handlers[CMD_STOP] = &command_worker::cmd_stop; + m_cmd_handlers[CMD_REG] = &command_worker::cmd_register_event; + m_cmd_handlers[CMD_UNREG] = &command_worker::cmd_unregister_event; + m_cmd_handlers[CMD_CHECK_EVENT] = &command_worker::cmd_check_event; + m_cmd_handlers[CMD_SET_OPTION] = &command_worker::cmd_set_option; + m_cmd_handlers[CMD_SET_INTERVAL] = &command_worker::cmd_set_interval; + m_cmd_handlers[CMD_UNSET_INTERVAL] = &command_worker::cmd_unset_interval; + m_cmd_handlers[CMD_SET_COMMAND] = &command_worker::cmd_set_command; + m_cmd_handlers[CMD_GET_PROPERTIES] = &command_worker::cmd_get_properties; + m_cmd_handlers[CMD_GET_DATA] = &command_worker::cmd_get_data; + m_cmd_handlers[CMD_SEND_SENSORHUB_DATA] = &command_worker::cmd_send_sensorhub_data; + init = true; + } +} + +bool command_worker::working(void *ctx) +{ + int ret; + command_worker *inst = (command_worker *)ctx; + packet_header header; + char *payload; + + if (inst->m_socket.recv(&header, sizeof(header)) <= 0) { + DBG("%s failed to receive header", inst->get_info()); + return false; + } + + if (header.size > 0) { + payload = new char[header.size]; + + if (inst->m_socket.recv(payload, header.size) <= 0) { + DBG("%s failed to receive data of packet", inst->get_info()); + delete[] payload; + return false; + } + } else { + payload = NULL; + } + + ret = inst->dispatch_command(header.cmd, payload); + + if (payload) + delete[] payload; + + return ret; +} + +bool command_worker::stopped(void *ctx) +{ + event_type_vector event_vec; + command_worker *inst = (command_worker *)ctx; + + INFO("%s is stopped", inst->get_info()); + + if ((inst->m_module) && (inst->m_client_id != CLIENT_ID_INVALID)) { + get_client_info_manager().get_registered_events(inst->m_client_id, inst->m_sensor_type, event_vec); + event_type_vector::iterator it_event; + it_event = event_vec.begin(); + + while (it_event != event_vec.end()) { + WARN("Does not unregister event[0x%x] before connection broken for [%s]!!", *it_event, inst->m_module->get_name()); + + if (!inst->m_module->delete_client(*it_event)) + ERR("Unregistering event[0x%x] failed", *it_event); + + ++it_event; + } + + if (get_client_info_manager().is_started(inst->m_client_id, inst->m_sensor_type)) { + WARN("Does not receive cmd_stop before connection broken for [%s]!!", inst->m_module->get_name()); + inst->m_module->delete_interval(inst->m_client_id, false); + inst->m_module->stop(); + } + + if (inst->m_sensor_type) { + if (get_client_info_manager().has_sensor_record(inst->m_client_id, inst->m_sensor_type)) { + INFO("Removing sensor[0x%x] record for client_id[%d]", inst->m_sensor_type, inst->m_client_id); + get_client_info_manager().remove_sensor_record(inst->m_client_id, inst->m_sensor_type); + } + } + } + + delete inst; + return true; +} + +bool command_worker::dispatch_command(int cmd, void *payload) +{ + int ret = false; + + if (!(cmd > 0 && cmd < CMD_CNT)) { + ERR("Unknown command: %d", cmd); + } else { + cmd_handler_t cmd_handler; + cmd_handler = command_worker::m_cmd_handlers[cmd]; + + if (cmd_handler) + ret = (this->*cmd_handler)(payload); + } + + return ret; +} + +bool command_worker::send_cmd_done(long value) +{ + cpacket *ret_packet; + cmd_done_t *cmd_done; + + ret_packet = new cpacket(sizeof(cmd_done_t)); + ret_packet->set_cmd(CMD_DONE); + cmd_done = (cmd_done_t *)ret_packet->data(); + cmd_done->value = value; + + if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) { + ERR("Failed to send a cmd_done to client_id [%d] with value [%ld]", m_client_id, value); + delete ret_packet; + return false; + } + + delete ret_packet; + return true; +} + +bool command_worker::send_cmd_get_id_done(int client_id) +{ + cpacket *ret_packet; + cmd_get_id_done_t *cmd_get_id_done; + + ret_packet = new cpacket(sizeof(cmd_get_id_done_t)); + ret_packet->set_cmd(CMD_GET_ID); + cmd_get_id_done = (cmd_get_id_done_t *)ret_packet->data(); + cmd_get_id_done->client_id = client_id; + + if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) { + ERR("Failed to send a cmd_get_id_done with client_id [%d]", client_id); + delete ret_packet; + return false; + } + + delete ret_packet; + return true; +} + +bool command_worker::send_cmd_properties_done(int state, sensor_properties_t *properties) +{ + cpacket *ret_packet; + cmd_properties_done_t *cmd_properties_done; + + ret_packet = new cpacket(sizeof(cmd_properties_done_t)); + ret_packet->set_cmd(CMD_GET_PROPERTIES); + cmd_properties_done = (cmd_properties_done_t *)ret_packet->data(); + cmd_properties_done->state = state; + memcpy(&cmd_properties_done->properties, properties , sizeof(sensor_properties_t)); + + if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) { + ERR("Failed to send a cmd_get_properties"); + delete ret_packet; + return false; + } + + delete ret_packet; + return true; +} + +bool command_worker::send_cmd_get_data_done(int state, sensor_data_t *data) +{ + cpacket *ret_packet; + cmd_get_data_done_t *cmd_get_data_done; + + ret_packet = new cpacket(sizeof(cmd_get_data_done_t)); + ret_packet->set_cmd(CMD_GET_DATA); + cmd_get_data_done = (cmd_get_data_done_t *)ret_packet->data(); + cmd_get_data_done->state = state; + memcpy(&cmd_get_data_done->base_data , data, sizeof(sensor_data_t)); + + if (m_socket.send(ret_packet->packet(), ret_packet->size()) <= 0) { + ERR("Failed to send a cmd_get_data_done"); + delete ret_packet; + return false; + } + + delete ret_packet; + return true; +} + +bool command_worker::cmd_get_id(void *payload) +{ + DBG("CMD_GET_ID Handler invoked"); + + cmd_get_id_t *cmd; + int client_id; + + cmd = (cmd_get_id_t *)payload; + client_id = get_client_info_manager().create_client_record(); + get_client_info_manager().set_client_info(client_id, cmd->pid); + INFO("New client id [%d] created", client_id); + + if (!send_cmd_get_id_done(client_id)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_hello(void *payload) +{ + DBG("CMD_HELLO Handler invoked"); + + cmd_hello_t *cmd; + long ret_value = OP_ERROR; + + cmd = (cmd_hello_t *)payload; + m_sensor_type = static_cast(cmd->sensor); + m_client_id = cmd->client_id; + DBG("Hello sensor [0x%x], client id [%d]", m_sensor_type, m_client_id); + m_module = (sensor_base *)sensor_plugin_loader::get_instance().get_sensor(m_sensor_type); + + if (m_module) { + get_client_info_manager().create_sensor_record(m_client_id, m_sensor_type); + INFO("New sensor record created for sensor [0x%x], sensor name [%s] on client id [%d]", m_sensor_type, m_module->get_name(), m_client_id); + ret_value = OP_SUCCESS; + } else { + ERR("Sensor type[0x%x] is not supported", m_sensor_type); + + if (!get_client_info_manager().has_sensor_record(m_client_id)) + get_client_info_manager().remove_client_record(m_client_id); + } + + if (!send_cmd_done(ret_value)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_byebye(void *payload) +{ + long ret_value; + DBG("CMD_BYEBYE for client [%d], sensor [0x%x]", m_client_id, m_sensor_type); + + if (!get_client_info_manager().remove_sensor_record(m_client_id, m_sensor_type)) { + ERR("Error removing sensor_record for client [%d]", m_client_id); + ret_value = OP_ERROR; + } else { + m_client_id = CLIENT_ID_INVALID; + ret_value = OP_SUCCESS; + } + + if (!send_cmd_done(ret_value)) + ERR("Failed to send cmd_done to a client"); + + if (ret_value == OP_SUCCESS) + return false; + + return true; +} + +bool command_worker::cmd_start(void *payload) +{ + long value = OP_SUCCESS; + DBG("START Sensor [0x%x], called from client [%d]", m_sensor_type, m_client_id); + DBG("Invoke Module start for []"); + + if (m_module->start()) { + get_client_info_manager().set_start(m_client_id, m_sensor_type, true); + + /* + * Rotation could be changed even LCD is off by pop sync rotation + * and a client listening rotation event with always-on option. + * To reflect the last rotation state, request it to event dispatcher. + */ + get_event_dispathcher().request_last_event(m_client_id, m_sensor_type); + } else { + value = OP_ERROR; + } + + if (!send_cmd_done(value)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_stop(void *payload) +{ + long ret_val = OP_SUCCESS; + DBG("STOP Sensor [0x%x], called from client [%d]", m_sensor_type, m_client_id); + + if (m_module->stop()) { + get_client_info_manager().set_start(m_client_id, m_sensor_type, false); + } + + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_register_event(void *payload) +{ + cmd_reg_t *cmd; + long ret_val = OP_ERROR; + + cmd = (cmd_reg_t *)payload; + + if (!get_client_info_manager().register_event(m_client_id, cmd->event_type)) { + INFO("Failed to register event [0x%x] for client [%d] to client info manager", + cmd->event_type, m_client_id); + goto out; + } + + m_module->add_client(cmd->event_type); + ret_val = OP_SUCCESS; + DBG("Registering Event [0x%x] is done for client [%d]", cmd->event_type, m_client_id); + +out: + + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_unregister_event(void *payload) +{ + cmd_unreg_t *cmd; + long ret_val = OP_ERROR; + cmd = (cmd_unreg_t *)payload; + + if (!get_client_info_manager().unregister_event(m_client_id, cmd->event_type)) { + ERR("Failed to unregister event [0x%x] for client [%d from client info manager", + cmd->event_type, m_client_id); + goto out; + } + + if (!m_module->delete_client(cmd->event_type)) { + ERR("Failed to unregister event [0x%x] for client [%d]", + cmd->event_type, m_client_id); + goto out; + } + + ret_val = OP_SUCCESS; + DBG("Unregistering Event [0x%x] is done for client [%d]", + cmd->event_type, m_client_id); + +out: + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_check_event(void *payload) +{ + cmd_check_event_t *cmd; + long ret_val = OP_ERROR; + cmd = (cmd_check_event_t *)payload; + + if (m_module->is_supported(cmd->event_type)) { + ret_val = OP_SUCCESS; + DBG("Event[0x%x] is supported for client [%d], for sensor [0x%x]", cmd->event_type, m_client_id, (cmd->event_type >> 16)); + } + + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_set_interval(void *payload) +{ + cmd_set_interval_t *cmd; + long ret_val = OP_ERROR; + cmd = (cmd_set_interval_t *)payload; + + if (!get_client_info_manager().set_interval(m_client_id, m_sensor_type, cmd->interval)) { + ERR("Failed to register interval for client [%d], for sensor [0x%x] with interval [%d] to client info manager", + m_client_id, m_sensor_type, cmd->interval); + goto out; + } + + if (!m_module->add_interval(m_client_id, cmd->interval, false)) { + ERR("Failed to set interval for client [%d], for sensor [0x%x] with interval [%d]", + m_client_id, m_sensor_type, cmd->interval); + goto out; + } + + ret_val = OP_SUCCESS; + +out: + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_unset_interval(void *payload) +{ + long ret_val = OP_ERROR; + + if (!get_client_info_manager().set_interval(m_client_id, m_sensor_type, 0)) { + ERR("Failed to unregister interval for client [%d], for sensor [0x%x] to client info manager", + m_client_id, m_sensor_type); + goto out; + } + + if (!m_module->delete_interval(m_client_id, false)) { + ERR("Failed to delete interval for client [%d]", m_client_id); + goto out; + } + + ret_val = OP_SUCCESS; + +out: + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_set_option(void *payload) +{ + cmd_set_option_t *cmd; + long ret_val = OP_ERROR; + cmd = (cmd_set_option_t *)payload; + + if (!get_client_info_manager().set_option(m_client_id, m_sensor_type, cmd->option)) { + ERR("Failed to register interval for client [%d], for sensor [0x%x] with option [%d] to client info manager", + m_client_id, m_sensor_type, cmd->option); + goto out; + } + + ret_val = OP_SUCCESS; + +out: + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_set_command(void *payload) +{ + DBG("CMD_SET_COMMAND Handler invoked"); + + cmd_set_command_t *cmd; + long ret_val = OP_ERROR; + cmd = (cmd_set_command_t *)payload; + ret_val = m_module->set_command(cmd->cmd, cmd->value); + + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_get_properties(void *payload) +{ + DBG("CMD_GET_PROPERTIES Handler invoked"); + int state = OP_ERROR; + cmd_get_properties_t *cmd; + sensor_properties_t sensor_properties; + + cmd = (cmd_get_properties_t *) payload; + memset(&sensor_properties, 0, sizeof(sensor_properties)); + state = m_module->get_properties(cmd->type, sensor_properties); + + if (state != 0) + ERR("processor_module get_property fail"); + + if (!send_cmd_properties_done(state, &sensor_properties)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +bool command_worker::cmd_get_data(void *payload) +{ + DBG("CMD_GET_VALUE Handler invoked"); + cmd_get_data_t *cmd; + int state = OP_ERROR; + sensor_data_t base_data; + + cmd = (cmd_get_data_t *)payload; + state = m_module->get_sensor_data(cmd->type, base_data); + + if (state != 0) + ERR("processor_module cmd_get_data fail"); + + send_cmd_get_data_done(state, &base_data); + return true; +} + +bool command_worker::cmd_send_sensorhub_data(void *payload) +{ + DBG("CMD_SEND_SENSORHUB_DATA Handler invoked"); + cmd_send_sensorhub_data_t *cmd; + long ret_val = OP_ERROR; + + cmd = (cmd_send_sensorhub_data_t *)payload; + ret_val = m_module->send_sensorhub_data(cmd->data, cmd->data_len); + + if (!send_cmd_done(ret_val)) + ERR("Failed to send cmd_done to a client"); + + return true; +} + +const char *command_worker::get_info(void) +{ + static string info; + const char *client_info = NULL; + const char *sensor_info = NULL; + + if (m_client_id != CLIENT_ID_INVALID) + client_info = get_client_info_manager().get_client_info(m_client_id); + + if (m_module) + sensor_info = m_module->get_name(); + + info = string("Command worker for ") + (client_info ? client_info : "Unknown") + "'s " + + (sensor_info ? sensor_info : "Unknown"); + return info.c_str(); +} + +cclient_info_manager &command_worker::get_client_info_manager(void) +{ + return cclient_info_manager::get_instance(); +} + +csensor_event_dispatcher &command_worker::get_event_dispathcher(void) +{ + return csensor_event_dispatcher::get_instance(); +} + diff --git a/src/server/command_worker.h b/src/server/command_worker.h new file mode 100755 index 0000000..9f1d697 --- /dev/null +++ b/src/server/command_worker.h @@ -0,0 +1,83 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef COMMAND_WORKER_H_ +#define COMMAND_WORKER_H_ + +#include +#include +#include +#include + +class command_worker +{ +private: + typedef bool (command_worker::*cmd_handler_t)(void *payload); + + static const int OP_ERROR = -1; + static const int OP_SUCCESS = 0; + + int m_client_id; + csocket m_socket; + worker_thread m_worker; + sensor_base *m_module; + sensor_type_t m_sensor_type; + + static cmd_handler_t m_cmd_handlers[CMD_CNT]; + + static void init_cmd_handlers(void); + + static bool working(void *ctx); + static bool stopped(void *ctx); + + bool dispatch_command(int cmd, void *payload); + + bool send_cmd_done(long value); + bool send_cmd_get_id_done(int client_id); + bool send_cmd_properties_done(int state, sensor_properties_t *properties); + bool send_cmd_get_data_done(int state, sensor_data_t *data); + + bool cmd_get_id(void *payload); + bool cmd_hello(void *payload); + bool cmd_byebye(void *payload); + bool cmd_get_value(void *payload); + bool cmd_start(void *payload); + bool cmd_stop(void *payload); + bool cmd_register_event(void *payload); + bool cmd_unregister_event(void *payload); + bool cmd_check_event(void *payload); + bool cmd_set_interval(void *payload); + bool cmd_unset_interval(void *payload); + bool cmd_set_option(void *payload); + bool cmd_set_command(void *payload); + bool cmd_get_properties(void *payload); + bool cmd_get_data(void *payload); + bool cmd_send_sensorhub_data(void *payload); + + const char *get_info(void); + + static cclient_info_manager &get_client_info_manager(void); + static csensor_event_dispatcher &get_event_dispathcher(void); +public: + command_worker(const csocket &socket); + virtual ~command_worker(); + + bool start(void); +}; +#endif /* COMMAND_WORKER_H_ */ diff --git a/src/server/main.cpp b/src/server/main.cpp new file mode 100755 index 0000000..f1aeb85 --- /dev/null +++ b/src/server/main.cpp @@ -0,0 +1,66 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +static void sig_term_handler(int signo, siginfo_t *info, void *data) +{ + char proc_name[NAME_MAX]; + + get_proc_name(info->si_pid, proc_name); + + ERR("Received SIGTERM(%d) from %s(%d)", signo, proc_name, info->si_pid); + exit(EXIT_SUCCESS); +} + +static void signal_init(void) +{ + struct sigaction sig_act; + + sig_act.sa_handler = SIG_IGN; + sigemptyset(&sig_act.sa_mask); + + sigaction(SIGCHLD, &sig_act, NULL); + sigaction(SIGPIPE, &sig_act, NULL); + + sig_act.sa_handler = NULL; + sig_act.sa_sigaction = sig_term_handler; + sig_act.sa_flags = SA_SIGINFO; + sigaction(SIGTERM, &sig_act, NULL); +} + +int main(int argc, char *argv[]) +{ + signal_init(); + + INFO("Sensord started"); + + sensor_plugin_loader::get_instance().load_plugins(); + + server::get_instance().run(); + server::get_instance().stop(); + + sensor_plugin_loader::get_instance().destroy(); + + INFO("Sensord terminated"); + return 0; +} diff --git a/src/server/server.cpp b/src/server/server.cpp new file mode 100755 index 0000000..892b69a --- /dev/null +++ b/src/server/server.cpp @@ -0,0 +1,127 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using std::thread; + +server::server() +: m_mainloop(NULL) +{ +} + +server::~server() +{ + stop(); +} + +int server::get_systemd_socket(const char *name) +{ + int type = SOCK_STREAM; + const int listening = 1; + size_t length = 0; + int fd = -1; + + if (sd_listen_fds(1) != 1) + return -1; + + fd = SD_LISTEN_FDS_START + 0; + + if (sd_is_socket_unix(fd, type, listening, name, length) > 0) + return fd; + + return -1; +} + +void server::accept_client(void) +{ + command_worker *cmd_worker; + INFO("Client acceptor is started"); + + while (true) { + csocket client_command_socket; + + if (!m_client_accep_socket.accept(client_command_socket)) { + ERR("Failed to accept connection request from a client"); + continue; + } + + DBG("New client (socket_fd : %d) connected", client_command_socket.get_socket_fd()); + cmd_worker = new command_worker(client_command_socket); + + if (!cmd_worker->start()) + delete cmd_worker; + } +} + +void server::run(void) +{ + int sock_fd = -1; + const int MAX_PENDING_CONNECTION = 5; + + m_mainloop = g_main_loop_new(NULL, false); + + sock_fd = get_systemd_socket(COMMAND_CHANNEL_PATH); + + if (sock_fd >= 0) { + INFO("Succeeded to get systemd socket(%d)", sock_fd); + m_client_accep_socket = csocket(sock_fd); + } else { + ERR("Failed to get systemd socket, create it by myself!"); + + if (!m_client_accep_socket.create(SOCK_STREAM)) { + ERR("Failed to create command channel"); + return; + } + + if (!m_client_accep_socket.bind(COMMAND_CHANNEL_PATH)) { + ERR("Failed to bind command channel"); + m_client_accep_socket.close(); + return; + } + + if (!m_client_accep_socket.listen(MAX_PENDING_CONNECTION)) { + ERR("Failed to listen command channel"); + return; + } + } + + csensor_event_dispatcher::get_instance().run(); + + thread client_accepter(&server::accept_client, this); + client_accepter.detach(); + + sd_notify(0, "READY=1"); + + g_main_loop_run(m_mainloop); + g_main_loop_unref(m_mainloop); + return; +} + +void server::stop(void) +{ + if (m_mainloop) + g_main_loop_quit(m_mainloop); + + m_client_accep_socket.close(); +} diff --git a/src/server/server.h b/src/server/server.h new file mode 100755 index 0000000..b31e02f --- /dev/null +++ b/src/server/server.h @@ -0,0 +1,46 @@ +/* + * sensord + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SERVER_H_ +#define _SERVER_H_ + +#include +#include + +class server +{ +private: + GMainLoop *m_mainloop; + csocket m_client_accep_socket; + + server(); + ~server(); + + void accept_client(void); + int get_systemd_socket(const char *name); +public: + void run(void); + void stop(void); + static server &get_instance() { + static server inst; + return inst; + } +}; + +#endif /*_SERVER_H_*/ diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt new file mode 100755 index 0000000..e23eb93 --- /dev/null +++ b/src/shared/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 2.6) +project(sf_common CXX) +# to install pkgconfig setup file. +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") +SET(LIBDIR "\${prefix}/lib") +SET(INCLUDEDIR "\${prefix}/include") +SET(VERSION 1.0) + +#set(CMAKE_INSTALL_PREFIX "$ENV{DATAFS}") +set(PROJECT_MAJOR_VERSION "0") +set(PROJECT_MINOR_VERSION "2") +set(PROJECT_RELEASE_VERSION "1") +set(CMAKE_VERBOSE_MAKEFILE OFF) + +include(FindPkgConfig) +pkg_check_modules(rpkgs REQUIRED dlog libxml-2.0) +add_definitions(${rpkgs_CFLAGS}) + +add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}") +add_definitions(-DLOCALEDIR="$ENV{DATAFS}/share/locale") +add_definitions(-DFACTORYFS="$ENV{FACTORYFS}") +add_definitions(-DDATAFS="$ENV{DATAFS}") +add_definitions(-Wall -std=gnu++0x) +add_definitions(-DUSE_DLOG_LOG) +#add_definitions(-DX1_PROF) +#add_definitions(-D_GETTEXT) +#add_definitions(-Wall -O3 -omit-frame-pointer) +#add_definitions(-D_DEFAULT_FONT_NAME="Vera") +#add_definitions(-Wall -g -DUSE_FILE_DEBUG) +#add_definitions(-Wall -g -D_DEBUG) +#add_definitions(-Wl,--as-needed -Wl,-O1) +#add_definitions(-finstrument-functions) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/src/libsensord) + +add_library(sensord-server SHARED + crw_lock.cpp + worker_thread.cpp + cconfig.cpp + csensor_event_queue.cpp + csensor_event_dispatcher.cpp + csensor_usage.cpp + cclient_info_manager.cpp + cclient_sensor_record.cpp + cinterval_info_list.cpp + sensor_plugin_loader.cpp + sensor_hal.cpp + sensor_base.cpp + physical_sensor.cpp + virtual_sensor.cpp + sensor_fusion.cpp +) + +add_library(sensord-share SHARED + cpacket.cpp + csocket.cpp + cbase_lock.cpp + cmutex.cpp + common.cpp +) + +target_link_libraries(sensord-server ${rpkgs_LDFLAGS} "-lrt -ldl -pthread" "sensord-share") +target_link_libraries(sensord-share ${rpkgs_LDFLAGS} "-lrt -ldl -pthread") +configure_file(sensord-server.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/sensord-server.pc @ONLY) +configure_file(${PROJECT_NAME}.pc.in ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc @ONLY) + +install(TARGETS sensord-server DESTINATION lib) +install(TARGETS sensord-share DESTINATION lib) +install(FILES sensord-server.pc DESTINATION lib/pkgconfig) +install(FILES ${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) +install(FILES + sensor_fusion.h + crw_lock.h + worker_thread.h + cconfig.h + csensor_event_queue.h + cinterval_info_list.h + sensor_plugin_loader.h + sensor_hal.h + sensor_base.h + physical_sensor.h + virtual_sensor.h + sensor_fusion.h + sf_common.h + cpacket.h + csocket.h + cbase_lock.h + cmutex.h + common.h + DESTINATION include/${PROJECT_NAME} +) + +install(FILES + sensor_common.h + DESTINATION include/sensor +) + diff --git a/src/shared/cbase_lock.cpp b/src/shared/cbase_lock.cpp new file mode 100755 index 0000000..52b1993 --- /dev/null +++ b/src/shared/cbase_lock.cpp @@ -0,0 +1,125 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +cbase_lock::cbase_lock() +{ + m_history_mutex = PTHREAD_MUTEX_INITIALIZER; +} + +cbase_lock::~cbase_lock() +{ + pthread_mutex_destroy(&m_history_mutex); +} + +void cbase_lock::lock(lock_type type, const char *expr, const char *module, const char *func, int line) +{ + int ret = 0; + char m_curent_info[OWNER_INFO_LEN]; + struct timeval sv; + unsigned long long lock_waiting_start_time = 0; + unsigned long long lock_acquired_time = 0; + unsigned long long waiting_time = 0; + snprintf(m_curent_info, OWNER_INFO_LEN, "%s:%s(%d)", module, func, line); + + if (type == LOCK_TYPE_MUTEX) + ret = try_lock_impl(); + else if (type == LOCK_TYPE_READ) + ret = try_read_lock_impl(); + else if (type == LOCK_TYPE_WRITE) + ret = try_write_lock_impl(); + + if (ret == 0) { + pthread_mutex_lock(&m_history_mutex); + snprintf(m_owner_info, OWNER_INFO_LEN, "%s", m_curent_info); + pthread_mutex_unlock(&m_history_mutex); + return; + } + + gettimeofday(&sv, NULL); + lock_waiting_start_time = MICROSECONDS(sv); + + pthread_mutex_lock(&m_history_mutex); + INFO("%s is waiting for getting %s(0x%x) owned in %s", + m_curent_info, expr, this, m_owner_info); + pthread_mutex_unlock(&m_history_mutex); + + if (type == LOCK_TYPE_MUTEX) + lock_impl(); + else if (type == LOCK_TYPE_READ) + read_lock_impl(); + else if (type == LOCK_TYPE_WRITE) + write_lock_impl(); + + gettimeofday(&sv, NULL); + lock_acquired_time = MICROSECONDS(sv); + waiting_time = lock_acquired_time - lock_waiting_start_time; + pthread_mutex_lock(&m_history_mutex); + + INFO("%s acquires lock after waiting %lluus, %s(0x%x) was previously owned in %s", + m_curent_info, waiting_time, expr, this, m_owner_info); + snprintf(m_owner_info, OWNER_INFO_LEN, "%s", m_curent_info); + pthread_mutex_unlock(&m_history_mutex); +} + +void cbase_lock::unlock(void) +{ + unlock_impl(); +} + +int cbase_lock::lock_impl(void) +{ + return 0; +} + +int cbase_lock::read_lock_impl(void) +{ + return 0; +} + +int cbase_lock::write_lock_impl(void) +{ + return 0; +} + +int cbase_lock::try_lock_impl(void) +{ + return 0; +} + +int cbase_lock::try_read_lock_impl(void) +{ + return 0; +} + +int cbase_lock::try_write_lock_impl(void) +{ + return 0; +} + +int cbase_lock::unlock_impl(void) +{ + return 0; +} diff --git a/src/shared/cbase_lock.h b/src/shared/cbase_lock.h new file mode 100755 index 0000000..2bebf66 --- /dev/null +++ b/src/shared/cbase_lock.h @@ -0,0 +1,78 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CBASE_LOCK_H_ +#define _CBASE_LOCK_H_ + +#include + +enum lock_type { + LOCK_TYPE_MUTEX, + LOCK_TYPE_READ, + LOCK_TYPE_WRITE, +}; + +#define AUTOLOCK(x) Autolock x##_autolock((x),LOCK_TYPE_MUTEX, #x, __MODULE__, __func__, __LINE__) +#define AUTOLOCK_R(x) Autolock x##_autolock_r((x),LOCK_TYPE_READ, #x, __MODULE__, __func__, __LINE__) +#define AUTOLOCK_W(x) Autolock x##_autolock_w((x),LOCK_TYPE_WRITE, #x, __MODULE__, __func__, __LINE__) +#define LOCK(x) (x).lock(#x, __MODULE__, __func__, __LINE__) +#define LOCK_R(x) (x).lock(LOCK_TYPE_READ, #x, __MODULE__, __func__, __LINE__) +#define LOCK_W(x) (x).lock(LOCK_TYPE_WRITE, #x, __MODULE__, __func__, __LINE__) +#define UNLOCK(x) (x).unlock() + +class cbase_lock +{ +public: + cbase_lock(); + virtual ~cbase_lock(); + + void lock(lock_type type, const char *expr, const char *module, const char *func, int line); + void unlock(void); + +protected: + virtual int lock_impl(void); + virtual int read_lock_impl(void); + virtual int write_lock_impl(void); + + virtual int try_lock_impl(void); + virtual int try_read_lock_impl(void); + virtual int try_write_lock_impl(void); + + virtual int unlock_impl(void); +private: + pthread_mutex_t m_history_mutex; + static const int OWNER_INFO_LEN = 256; + char m_owner_info[OWNER_INFO_LEN]; +}; + +class Autolock +{ +private: + cbase_lock &m_lock; +public: + Autolock(cbase_lock &m, lock_type type, const char *expr, const char *module, const char *func, int line) : m_lock(m) { + m_lock.lock(type, expr, module, func, line); + } + + ~Autolock() { + m_lock.unlock(); + } +}; + +#endif /*_CBASE_LOCK_H_*/ diff --git a/src/shared/cclient_info_manager.cpp b/src/shared/cclient_info_manager.cpp new file mode 100755 index 0000000..19347a0 --- /dev/null +++ b/src/shared/cclient_info_manager.cpp @@ -0,0 +1,373 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +using std::pair; + +cclient_info_manager::cclient_info_manager() +{ +} + +cclient_info_manager::~cclient_info_manager() +{ + m_clients.clear(); +} + +unsigned int cclient_info_manager::get_interval(const int client_id, const sensor_type_t sensor) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return 0; + } + + return it_record->second.get_interval(sensor); +} + +bool cclient_info_manager::is_sensor_used(const sensor_type_t sensor, const event_situation mode) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.begin(); + + while (it_record != m_clients.end()) { + if (it_record->second.is_sensor_used(sensor, mode)) + return true; + + ++it_record; + } + + return false; +} + +bool cclient_info_manager::get_registered_events(const int client_id, const sensor_type_t sensor, event_type_vector &event_vec) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.get_registered_events(sensor, event_vec)) + return false; + + return true; +} + + +bool cclient_info_manager::register_event(const int client_id, const unsigned int event_type) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.register_event(event_type)) + return false; + + return true; +} + +bool cclient_info_manager::unregister_event(const int client_id, const unsigned int event_type) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.unregister_event(event_type)) + return false; + + return true; +} + +bool cclient_info_manager::set_interval(const int client_id, const sensor_type_t sensor, const unsigned int interval) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.set_interval(sensor, interval)) + return false; + + return true; +} + +bool cclient_info_manager::set_option(const int client_id, const sensor_type_t sensor, const int option) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.set_option(sensor, option)) + return false; + + return true; +} + + +bool cclient_info_manager::set_start(const int client_id, const sensor_type_t sensor, bool start) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.set_start(sensor, start)) + return false; + + return true; +} + +bool cclient_info_manager::is_started(const int client_id, const sensor_type_t sensor) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + return it_record->second.is_started(sensor); +} + +int cclient_info_manager::create_client_record(void) +{ + AUTOLOCK(m_mutex); + int client_id = 0; + cclient_sensor_record client_record; + + while (m_clients.count(client_id) > 0) + client_id++; + + if (client_id == MAX_HANDLE) { + ERR("Sensor records of clients are full"); + return MAX_HANDLE_REACHED; + } + + client_record.set_client_id(client_id); + m_clients.insert(pair (client_id, client_record)); + return client_id; +} + + +bool cclient_info_manager::remove_client_record(const int client_id) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + m_clients.erase(it_record); + INFO("Client record for client[%d] is removed from client info manager", client_id); + return true; +} + + +bool cclient_info_manager::has_client_record(int client_id) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + return (it_record != m_clients.end()); +} + + +void cclient_info_manager::set_client_info(int client_id, pid_t pid) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return; + } + + it_record->second.set_client_info(pid); + return; +} + +const char *cclient_info_manager::get_client_info(int client_id) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + DBG("Client[%d] is not found", client_id); + return NULL; + } + + return it_record->second.get_client_info(); +} + +bool cclient_info_manager::create_sensor_record(int client_id, const sensor_type_t sensor) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client record[%d] is not registered", client_id); + return false; + } + + it_record->second.add_sensor_usage(sensor); + return true; +} + +bool cclient_info_manager::remove_sensor_record(const int client_id, const sensor_type_t sensor) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.remove_sensor_usage(sensor)) + return false; + + if (!it_record->second.has_sensor_usage()) + remove_client_record(client_id); + + return true; +} + + +bool cclient_info_manager::has_sensor_record(const int client_id, const sensor_type_t sensor) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + DBG("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.has_sensor_usage(sensor)) + return false; + + return true; +} + +bool cclient_info_manager::has_sensor_record(const int client_id) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + DBG("Client[%d] is not found", client_id); + return false; + } + + if (!it_record->second.has_sensor_usage()) + return false; + + return true; +} + +bool cclient_info_manager::get_listener_ids(const unsigned int event_type, const event_situation mode, client_id_vec &id_vec) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.begin(); + + while (it_record != m_clients.end()) { + if (it_record->second.is_listening_event(event_type, mode)) + id_vec.push_back(it_record->first); + + ++it_record; + } + + return true; +} + +bool cclient_info_manager::get_event_socket(const int client_id, csocket &socket) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + it_record->second.get_event_socket(socket); + return true; +} + +bool cclient_info_manager::set_event_socket(const int client_id, const csocket &socket) +{ + AUTOLOCK(m_mutex); + client_id_sensor_record_map::iterator it_record; + it_record = m_clients.find(client_id); + + if (it_record == m_clients.end()) { + ERR("Client[%d] is not found", client_id); + return false; + } + + it_record->second.set_event_socket(socket); + return true; +} diff --git a/src/shared/cclient_info_manager.h b/src/shared/cclient_info_manager.h new file mode 100755 index 0000000..733b95a --- /dev/null +++ b/src/shared/cclient_info_manager.h @@ -0,0 +1,80 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CCLIENT_INFO_MANAGER_H_ +#define _CCLIENT_INFO_MANAGER_H_ + +#include +#include +#include +#include + +using std::map; + +typedef map client_id_sensor_record_map; +typedef vector client_id_vec; + +class cclient_info_manager +{ +public: + static cclient_info_manager &get_instance() { + static cclient_info_manager inst; + return inst; + } + + int create_client_record(void); + bool remove_client_record(const int client_id); + bool has_client_record(int client_id); + + void set_client_info(int client_id, pid_t pid); + const char *get_client_info(int client_id); + + bool create_sensor_record(int client_id, const sensor_type_t sensor); + bool remove_sensor_record(const int client_id, const sensor_type_t sensor); + bool has_sensor_record(const int client_id, const sensor_type_t sensor); + bool has_sensor_record(const int client_id); + + bool register_event(const int client_id, const unsigned int event_type); + bool unregister_event(const int client_id, const unsigned int event_type); + bool is_sensor_event_registered(const int client_id, const unsigned int event_type); + + bool set_interval(const int client_id, const sensor_type_t sensor, const unsigned int interval); + unsigned int get_interval(const int client_id, const sensor_type_t sensor); + bool set_option(const int client_id, const sensor_type_t sensor, const int option); + + bool set_start(const int client_id, const sensor_type_t sensor, bool start); + bool is_started(const int client_id, const sensor_type_t sensor); + + bool is_sensor_used(const sensor_type_t sensor, const event_situation mode); + bool get_registered_events(const int client_id, const sensor_type_t sensor, event_type_vector &event_vec); + + bool get_listener_ids(const unsigned int event_type, const event_situation mode, client_id_vec &id_vec); + bool get_event_socket(const int client_id, csocket &sock); + bool set_event_socket(const int client_id, const csocket &sock); +private: + client_id_sensor_record_map m_clients; + cmutex m_mutex; + + cclient_info_manager(); + ~cclient_info_manager(); + cclient_info_manager(cclient_info_manager const &) {}; + cclient_info_manager &operator=(cclient_info_manager const &); +}; + +#endif /*_CCLIENT_INFO_MANAGER_H_*/ diff --git a/src/shared/cclient_sensor_record.cpp b/src/shared/cclient_sensor_record.cpp new file mode 100755 index 0000000..9ddee5a --- /dev/null +++ b/src/shared/cclient_sensor_record.cpp @@ -0,0 +1,286 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +using std::pair; + +static sensor_type_t get_sensor_type(const unsigned int event_type) +{ + return (sensor_type_t) (event_type >> SENSOR_TYPE_SHIFT); +} + +cclient_sensor_record::cclient_sensor_record() +: m_client_id(0) +, m_pid(-1) +{ +} + +cclient_sensor_record::~cclient_sensor_record() +{ + m_sensor_usages.clear(); + close_event_socket(); +} + +bool cclient_sensor_record::register_event(const unsigned int event_type) +{ + sensor_usage_map::iterator it_usage; + sensor_type_t sensor = get_sensor_type(event_type); + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + csensor_usage usage; + usage.register_event(event_type); + m_sensor_usages.insert(pair(sensor, usage)); + return true; + } + + if (!it_usage->second.register_event(event_type)) { + ERR("Event[0x%x] is already registered", event_type); + return false; + } + + return true; +} + +bool cclient_sensor_record::unregister_event(const unsigned int event_type) +{ + sensor_usage_map::iterator it_usage; + sensor_type_t sensor = get_sensor_type(event_type); + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + ERR("Sensor[0x%x] is not registered", sensor); + return false; + } + + if (!it_usage->second.unregister_event(event_type)) { + ERR("Event[0x%x] is already registered", event_type); + return false; + } + + return true; +} + +bool cclient_sensor_record::set_interval(const sensor_type_t sensor, const unsigned int interval) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + csensor_usage usage; + usage.m_interval = interval; + m_sensor_usages.insert(pair(sensor, usage)); + } else { + it_usage->second.m_interval = interval; + } + + return true; +} + +bool cclient_sensor_record::set_option(const sensor_type_t sensor, const int option) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + csensor_usage usage; + usage.m_option = option; + m_sensor_usages.insert(pair(sensor, usage)); + } else { + it_usage->second.m_option = option; + } + + return true; +} + +bool cclient_sensor_record::set_start(const sensor_type_t sensor, bool start) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + csensor_usage usage; + usage.m_start = start; + m_sensor_usages.insert(pair(sensor, usage)); + } else { + it_usage->second.m_start = start; + } + + return true; +} + +bool cclient_sensor_record::is_started(const sensor_type_t sensor) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) + return false; + + return it_usage->second.m_start; +} + +unsigned int cclient_sensor_record::get_interval(const sensor_type_t sensor) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + ERR("Sensor[0x%x] is not found", sensor); + return 0; + } + + return it_usage->second.m_interval; +} + +bool cclient_sensor_record::is_sensor_used(const sensor_type_t sensor, const event_situation mode) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) + return false; + + if ((mode == SITUATION_LCD_OFF || mode == SITUATION_SURVIVAL_MODE) && + (it_usage->second.m_option != SENSOR_OPTION_ALWAYS_ON)) + return false; + + return true; +} + +bool cclient_sensor_record::is_listening_event(const unsigned int event_type, const event_situation mode) +{ + sensor_usage_map::iterator it_usage; + sensor_type_t sensor = get_sensor_type(event_type); + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) + return false; + + if ((mode == SITUATION_LCD_OFF || mode == SITUATION_SURVIVAL_MODE) && + (it_usage->second.m_option != SENSOR_OPTION_ALWAYS_ON)) + return false; + + if (it_usage->second.is_event_registered(event_type)) + return true; + + return false; +} + +bool cclient_sensor_record::add_sensor_usage(const sensor_type_t sensor) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage != m_sensor_usages.end()) { + ERR("Sensor[0x%x] is already registered", sensor); + return false; + } + + csensor_usage usage; + m_sensor_usages.insert(pair (sensor, usage)); + return true; +} + +bool cclient_sensor_record::remove_sensor_usage(const sensor_type_t sensor) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + ERR("Sensor[0x%x] is not found", sensor); + return false; + } + + m_sensor_usages.erase(it_usage); + return true; +} + +bool cclient_sensor_record::has_sensor_usage(void) +{ + if (m_sensor_usages.empty()) + return false; + + return true; +} + +bool cclient_sensor_record::has_sensor_usage(const sensor_type_t sensor) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + DBG("Sensor[0x%x] is not found", sensor); + return false; + } + + return true; +} + +bool cclient_sensor_record::get_registered_events(const sensor_type_t sensor, event_type_vector &event_vec) +{ + sensor_usage_map::iterator it_usage; + it_usage = m_sensor_usages.find(sensor); + + if (it_usage == m_sensor_usages.end()) { + DBG("Sensor[0x%x] is not found", sensor); + return false; + } + + copy(it_usage->second.m_reg_events.begin(), it_usage->second.m_reg_events.end(), back_inserter(event_vec)); + return true; +} + +void cclient_sensor_record::set_client_id(int client_id) +{ + m_client_id = client_id; +} + +void cclient_sensor_record::set_client_info(pid_t pid) +{ + char client_info[NAME_MAX + 32]; + char proc_name[NAME_MAX]; + m_pid = pid; + get_proc_name(pid, proc_name); + snprintf(client_info, sizeof(client_info), "%s[pid=%d, id=%d]", proc_name, m_pid, m_client_id); + m_client_info.assign(client_info); +} + +const char *cclient_sensor_record::get_client_info(void) +{ + return m_client_info.c_str(); +} + +void cclient_sensor_record::set_event_socket(const csocket &socket) +{ + m_event_socket = socket; +} + +void cclient_sensor_record::get_event_socket(csocket &socket) +{ + socket = m_event_socket; +} + +bool cclient_sensor_record::close_event_socket(void) +{ + return m_event_socket.close(); +} + diff --git a/src/shared/cclient_sensor_record.h b/src/shared/cclient_sensor_record.h new file mode 100755 index 0000000..17d1341 --- /dev/null +++ b/src/shared/cclient_sensor_record.h @@ -0,0 +1,76 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CCLIENT_SENSOR_RECORD_H_ +#define _CCLIENT_SENSOR_RECORD_H_ + +#include +#include +#include +#include +#include + +using std::map; + +typedef map sensor_usage_map; + +class cclient_sensor_record +{ +public: + cclient_sensor_record(); + ~cclient_sensor_record(); + + void set_client_id(int client_id); + + void set_client_info(pid_t pid); + const char *get_client_info(void); + + bool register_event(const unsigned int event_type); + bool unregister_event(const unsigned int event_type); + + bool set_interval(const sensor_type_t sensor, const unsigned int interval); + unsigned int get_interval(const sensor_type_t sensor); + bool set_option(const sensor_type_t sensor, const int option); + + bool set_start(const sensor_type_t sensor, bool start); + bool is_started(const sensor_type_t sensor); + + bool is_sensor_used(const sensor_type_t sensor, const event_situation mode); + bool is_listening_event(const unsigned int event_type, const event_situation mode); + bool has_sensor_usage(void); + bool has_sensor_usage(const sensor_type_t sensor); + + bool get_registered_events(const sensor_type_t sensor, event_type_vector &event_vec); + + bool add_sensor_usage(const sensor_type_t sensor); + bool remove_sensor_usage(const sensor_type_t sensor); + + void set_event_socket(const csocket &socket); + void get_event_socket(csocket &socket); + bool close_event_socket(void); + +private: + int m_client_id; + pid_t m_pid; + string m_client_info; + csocket m_event_socket; + sensor_usage_map m_sensor_usages; +}; + +#endif /*_CCLIENT_SENSOR_RECORD_H_*/ diff --git a/src/shared/cconfig.cpp b/src/shared/cconfig.cpp new file mode 100755 index 0000000..389ce24 --- /dev/null +++ b/src/shared/cconfig.cpp @@ -0,0 +1,275 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include "common.h" +#include +#include +#include +#include + +using namespace config; + +#define ROOT_ELEMENT "SENSOR" +#define TEXT_ELEMENT "text" +#define MODEL_ID_ATTR "id" +#define DEFAULT_ATTR "value" + +CConfig::CConfig() +{ +} + +bool CConfig::load_config(const string &config_path) +{ + xmlDocPtr doc; + xmlNodePtr cur; + + DBG("CConfig::load_config(\"%s\") is called!", config_path.c_str()); + doc = xmlParseFile(config_path.c_str()); + + if (doc == NULL) { + ERR("There is no %s", config_path.c_str()); + return false; + } + + cur = xmlDocGetRootElement(doc); + + if (cur == NULL) { + ERR("There is no root element in %s", config_path.c_str()); + xmlFreeDoc(doc); + return false; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)ROOT_ELEMENT)) { + ERR("Wrong type document: there is no [%s] root element in %s", ROOT_ELEMENT, config_path.c_str()); + xmlFreeDoc(doc); + return false; + } + + xmlNodePtr model_list_node_ptr; + xmlNodePtr model_node_ptr; + xmlNodePtr element_node_ptr; + xmlAttrPtr attr_ptr; + char *prop = NULL; + model_list_node_ptr = cur->xmlChildrenNode; + + while (model_list_node_ptr != NULL) { + /* skip garbage element, [text] */ + if (!xmlStrcmp(model_list_node_ptr->name, (const xmlChar *)TEXT_ELEMENT)) { + model_list_node_ptr = model_list_node_ptr->next; + continue; + } + + /* insert Model_list to config map */ + m_sensor_config[(const char *)model_list_node_ptr->name]; + DBG("<%s>", (const char *)model_list_node_ptr->name); + + model_node_ptr = model_list_node_ptr->xmlChildrenNode; + + while (model_node_ptr != NULL) { + /* skip garbage element, [text] */ + if (!xmlStrcmp(model_node_ptr->name, (const xmlChar *)TEXT_ELEMENT)) { + model_node_ptr = model_node_ptr->next; + continue; + } + + string model_id; + prop = (char *)xmlGetProp(model_node_ptr, (const xmlChar *)MODEL_ID_ATTR); + model_id = prop; + free(prop); + + /* insert Model to Model_list */ + m_sensor_config[(const char *)model_list_node_ptr->name][model_id]; + DBG("<%s id=\"%s\">", (const char *)model_list_node_ptr->name, model_id.c_str()); + + element_node_ptr = model_node_ptr->xmlChildrenNode; + + while (element_node_ptr != NULL) { + /* skip garbage element, [text] */ + if (!xmlStrcmp(element_node_ptr->name, (const xmlChar *)TEXT_ELEMENT)) { + element_node_ptr = element_node_ptr->next; + continue; + } + + /* insert Element to Model */ + m_sensor_config[(const char *)model_list_node_ptr->name][model_id][(const char *)element_node_ptr->name]; + DBG("<%s id=\"%s\"><%s>", (const char *)model_list_node_ptr->name, model_id.c_str(), (const char *)element_node_ptr->name); + + attr_ptr = element_node_ptr->properties; + + while (attr_ptr != NULL) { + string key, value; + key = (char *)attr_ptr->name; + prop = (char *)xmlGetProp(element_node_ptr, attr_ptr->name); + value = prop; + free(prop); + + /* insert attribute to Element */ + m_sensor_config[(const char *)model_list_node_ptr->name][model_id][(const char *)element_node_ptr->name][key] = value; + DBG("<%s id=\"%s\"><%s \"%s\"=\"%s\">", (const char *)model_list_node_ptr->name, model_id.c_str(), (const char *)element_node_ptr->name, key.c_str(), value.c_str()); + + attr_ptr = attr_ptr->next; + } + + element_node_ptr = element_node_ptr->next; + } + + DBG(""); + model_node_ptr = model_node_ptr->next; + } + + DBG(""); + model_list_node_ptr = model_list_node_ptr->next; + } + + xmlFreeDoc(doc); + return true; +} + +bool CConfig::get(const string &sensor_type, const string &model_id, const string &element, const string &attr, string &value) +{ + Sensor_config::iterator it_model_list; + it_model_list = m_sensor_config.find(sensor_type); + + if (it_model_list == m_sensor_config.end()) { + ERR("There is no <%s> element", sensor_type.c_str()); + return false; + } + + Model_list::iterator it_model; + it_model = it_model_list->second.find(model_id); + + if (it_model == it_model_list->second.end()) { + ERR("There is no <%s id=\"%s\"> element", sensor_type.c_str(), model_id.c_str()); + return false; + } + + Model::iterator it_element; + it_element = it_model->second.find(element); + + if (it_element == it_model->second.end()) { + ERR("There is no <%s id=\"%s\"><%s> element", sensor_type.c_str(), model_id.c_str(), element.c_str()); + return false; + } + + Element::iterator it_attr; + it_attr = it_element->second.find(attr); + + if (it_attr == it_element->second.end()) { + DBG("There is no <%s id=\"%s\"><%s \"%s\">", sensor_type.c_str(), model_id.c_str(), element.c_str(), attr.c_str()); + return false; + } + + value = it_attr->second; + return true; +} + +bool CConfig::get(const string &sensor_type, const string &model_id, const string &element, const string &attr, double &value) +{ + string str_value; + + if (get(sensor_type, model_id, element, attr, str_value) == false) + return false; + + istringstream convert(str_value); + + if ( !(convert >> value)) + value = 0; + + return true; +} + +bool CConfig::get(const string &sensor_type, const string &model_id, const string &element, const string &attr, long &value) +{ + string str_value; + + if (get(sensor_type, model_id, element, attr, str_value) == false) + return false; + + istringstream convert(str_value); + + if ( !(convert >> value)) + value = 0; + + return true; +} + +bool CConfig::get(const string &sensor_type, const string &model_id, const string &element, string &value) +{ + if (get(sensor_type, model_id, element, m_device_id, value)) + return true; + + if (get(sensor_type, model_id, element, DEFAULT_ATTR, value)) + return true; + + return false; +} + +bool CConfig::get(const string &sensor_type, const string &model_id, const string &element, double &value) +{ + if (get(sensor_type, model_id, element, m_device_id, value)) + return true; + + if (get(sensor_type, model_id, element, DEFAULT_ATTR, value)) + return true; + + return false; +} + +bool CConfig::get(const string &sensor_type, const string &model_id, const string &element, long &value) +{ + if (get(sensor_type, model_id, element, m_device_id, value)) + return true; + + if (get(sensor_type, model_id, element, DEFAULT_ATTR, value)) + return true; + + return false; +} + +bool CConfig::is_supported(const string &sensor_type, const string &model_id) +{ + Sensor_config::iterator it_model_list; + it_model_list = m_sensor_config.find(sensor_type); + + if (it_model_list == m_sensor_config.end()) + return false; + + Model_list::iterator it_model; + it_model = it_model_list->second.find(model_id); + + if (it_model == it_model_list->second.end()) + return false; + + return true; +} + +bool CConfig::get_device_id(void) +{ + int ret; + char *device = NULL; + + ret = system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &device); + + if (device) + m_device_id = device; + + free(device); + return (ret == SYSTEM_INFO_ERROR_NONE); +} diff --git a/src/shared/cconfig.h b/src/shared/cconfig.h new file mode 100755 index 0000000..7b14edc --- /dev/null +++ b/src/shared/cconfig.h @@ -0,0 +1,119 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CCONFIG_H_ +#define _CCONFIG_H_ + +#include +#include +#include + +using std::map; +using std::string; +using std::istringstream; + +#define CONFIG_FILE_PATH "/usr/etc/sensors.xml" + +typedef map Element; +/* +* an Element is a group of attributes +* +* +* "value" -> "LSM330DLC" +* +*/ + +typedef map Model; +/* +* a Model is a group of elements to consist of specific vendor's one sensor configuration +* +* +* +* +* +* -> +* +*/ + +typedef map Model_list; +/* +* a Model_list is a group of Model +* +* +* +* +* +* "lsm330dlc_accel" -> +* +*/ + +typedef map Sensor_config; +/* +* a SensorConfig represents sensors.xml +* +* +* +* +* "ACCEL" -> Model_list +* +*/ + +namespace config +{ + class CConfig + { + private: + CConfig(); + CConfig(CConfig const &) {}; + CConfig &operator=(CConfig const &); + bool load_config(const string &config_path = CONFIG_FILE_PATH); + Sensor_config m_sensor_config; + string m_device_id; + public: + static CConfig &get_instance(void) { + static bool load_done = false; + static CConfig inst; + + if (!load_done) { + inst.load_config(); + inst.get_device_id(); + + if (!inst.m_device_id.empty()) + INFO("Device ID = %s", inst.m_device_id.c_str()); + else + ERR("Failed to get Device ID"); + + load_done = true; + } + + return inst; + } + bool get(const string &sensor_type, const string &model_id, const string &element, const string &attr, string &value); + bool get(const string &sensor_type, const string &model_id, const string &element, const string &attr, double &value); + bool get(const string &sensor_type, const string &model_id, const string &element, const string &attr, long &value); + + bool get(const string &sensor_type, const string &model_id, const string &element, string &value); + bool get(const string &sensor_type, const string &model_id, const string &element, double &value); + bool get(const string &sensor_type, const string &model_id, const string &element, long &value); + + bool is_supported(const string &sensor_type, const string &model_id); + bool get_device_id(void); + }; +} +#endif /*_CCONFIG_H_*/ diff --git a/src/shared/cinterval_info_list.cpp b/src/shared/cinterval_info_list.cpp new file mode 100755 index 0000000..a4ba3ee --- /dev/null +++ b/src/shared/cinterval_info_list.cpp @@ -0,0 +1,89 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +bool cinterval_info_list::comp_interval_info(cinterval_info a, cinterval_info b) +{ + return a.interval < b.interval; +} + +cinterval_info_iterator cinterval_info_list::find_if(int client_id, bool is_processor) +{ + cinterval_info_iterator iter; + iter = m_list.begin(); + + while (iter != m_list.end()) { + if ((iter->client_id == client_id) && (iter->is_processor == is_processor)) + break; + + ++iter; + } + + return iter; +} + +bool cinterval_info_list::add_interval(int client_id, unsigned int interval, bool is_processor) +{ + cinterval_info_iterator iter; + iter = find_if(client_id, is_processor); + + if (iter != m_list.end()) + *iter = cinterval_info(client_id, is_processor, interval); + else + m_list.push_back(cinterval_info(client_id, is_processor, interval)); + + return true; +} + +bool cinterval_info_list::delete_interval(int client_id, bool is_processor) +{ + cinterval_info_iterator iter; + iter = find_if(client_id, is_processor); + + if (iter == m_list.end()) + return false; + + m_list.erase(iter); + return true; +} + +unsigned int cinterval_info_list::get_interval(int client_id, bool is_processor) +{ + cinterval_info_iterator iter; + iter = find_if(client_id, is_processor); + + if (iter == m_list.end()) + return 0; + + return iter->interval; +} + +unsigned int cinterval_info_list::get_min(void) +{ + if (m_list.size() == 0) + return 0; + + cinterval_info_iterator iter; + + iter = min_element(m_list.begin(), m_list.end(), comp_interval_info); + return iter->interval; +} + diff --git a/src/shared/cinterval_info_list.h b/src/shared/cinterval_info_list.h new file mode 100755 index 0000000..bfb4240 --- /dev/null +++ b/src/shared/cinterval_info_list.h @@ -0,0 +1,58 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CINTERVAL_INFO_LIST_H_ +#define _CINTERVAL_INFO_LIST_H_ + +#include + +using std::list; + +class cinterval_info +{ +public: + cinterval_info(int client_id, bool is_processor, unsigned int interval) { + this->client_id = client_id; + this->is_processor = is_processor; + this->interval = interval; + } + + int client_id; + bool is_processor; + unsigned int interval; + +}; + +typedef list::iterator cinterval_info_iterator; + +class cinterval_info_list +{ +private: + static bool comp_interval_info(cinterval_info a, cinterval_info b); + cinterval_info_iterator find_if(int client_id, bool is_processor); + + list m_list; + +public: + bool add_interval(int client_id, unsigned int interval, bool is_processor = false); + bool delete_interval(int client_id, bool is_processor = false); + unsigned int get_interval(int client_id, bool is_processor = false); + unsigned int get_min(void); +}; +#endif /*_CINTERVAL_INFO_LIST_H_*/ diff --git a/src/shared/cmutex.cpp b/src/shared/cmutex.cpp new file mode 100755 index 0000000..d4720cf --- /dev/null +++ b/src/shared/cmutex.cpp @@ -0,0 +1,60 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include "common.h" + +cmutex::cmutex() +{ + pthread_mutexattr_t mutex_attr; + pthread_mutexattr_init(&mutex_attr); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_mutex, &mutex_attr); + pthread_mutexattr_destroy(&mutex_attr); +} + +cmutex::~cmutex() +{ + pthread_mutex_destroy(&m_mutex); +} + +void cmutex::lock() +{ + cbase_lock::lock(LOCK_TYPE_MUTEX, "mutex", __MODULE__, __func__, __LINE__); +} + +void cmutex::lock(const char *expr, const char *module, const char *func, int line) +{ + cbase_lock::lock(LOCK_TYPE_MUTEX, expr, module, func, line); +} + +int cmutex::lock_impl(void) +{ + return pthread_mutex_lock(&m_mutex); +} + +int cmutex::try_lock_impl(void) +{ + return pthread_mutex_trylock(&m_mutex); +} + +int cmutex::unlock_impl() +{ + return pthread_mutex_unlock(&m_mutex); +} diff --git a/src/shared/cmutex.h b/src/shared/cmutex.h new file mode 100755 index 0000000..e59fba0 --- /dev/null +++ b/src/shared/cmutex.h @@ -0,0 +1,42 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CMUTEX_H_ +#define _CMUTEX_H_ + +#include "cbase_lock.h" + +class cmutex : public cbase_lock +{ +public: + cmutex(); + virtual ~cmutex(); + + void lock(void); + void lock(const char *expr, const char *module, const char *func, int line); + +protected: + int lock_impl(void); + int try_lock_impl(void); + int unlock_impl(); +private: + pthread_mutex_t m_mutex; +}; + +#endif /*_CMUTEXT_H_*/ diff --git a/src/shared/common.cpp b/src/shared/common.cpp new file mode 100755 index 0000000..d02e20d --- /dev/null +++ b/src/shared/common.cpp @@ -0,0 +1,155 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include +#include +#include + +#ifndef EXTAPI +#define EXTAPI __attribute__((visibility("default"))) +#endif + +#define SF_SERVER_MSG_LOG_FILE "/var/log/messages" +#define FILE_LENGTH 255 + +static int sf_debug_file_fd; +static char sf_debug_file_buf[FILE_LENGTH]; + +EXTAPI void sf_log(int type , int priority , const char *tag , const char *fmt , ...) +{ + va_list ap; + va_start(ap, fmt); + + switch (type) { + case SF_LOG_PRINT_FILE: + sf_debug_file_fd = open(SF_SERVER_MSG_LOG_FILE, O_WRONLY | O_CREAT | O_APPEND, 0644); + + if (sf_debug_file_fd != -1) { + vsnprintf(sf_debug_file_buf, 255, fmt , ap ); + write(sf_debug_file_fd, sf_debug_file_buf, strlen(sf_debug_file_buf)); + close(sf_debug_file_fd); + } + + break; + case SF_LOG_SYSLOG: + int syslog_prio; + + switch (priority) { + case SF_LOG_ERR: + syslog_prio = LOG_ERR | LOG_DAEMON; + break; + case SF_LOG_WARN: + syslog_prio = LOG_WARNING | LOG_DAEMON; + break; + case SF_LOG_DBG: + syslog_prio = LOG_DEBUG | LOG_DAEMON; + break; + case SF_LOG_INFO: + syslog_prio = LOG_INFO | LOG_DAEMON; + break; + default: + syslog_prio = priority; + break; + } + + vsyslog(syslog_prio, fmt, ap); + break; + case SF_LOG_DLOG: + + if (tag) { + switch (priority) { + case SF_LOG_ERR: + SLOG_VA(LOG_ERROR, tag ? tag : "NULL" , fmt ? fmt : "NULL" , ap); + break; + case SF_LOG_WARN: + SLOG_VA(LOG_WARN, tag ? tag : "NULL" , fmt ? fmt : "NULL" , ap); + break; + case SF_LOG_DBG: + SLOG_VA(LOG_DEBUG, tag ? tag : "NULL", fmt ? fmt : "NULL" , ap); + break; + case SF_LOG_INFO: + SLOG_VA(LOG_INFO, tag ? tag : "NULL" , fmt ? fmt : "NULL" , ap); + break; + } + } + + break; + } + + va_end(ap); +} + +bool get_proc_name(pid_t pid, char *process_name) +{ + FILE *fp; + char buf[NAME_MAX]; + char filename[PATH_MAX]; + sprintf(filename, "/proc/%d/stat", pid); + fp = fopen(filename, "r"); + + if (fp == NULL) + return false; + + if (fscanf(fp, "%*s (%[^)]", buf) < 1) { + fclose(fp); + return false; + } + + strncpy(process_name, buf, NAME_MAX - 1); + fclose(fp); + return true; +} + +const char *get_client_name(void) +{ + const int pid_string_size = 10; + static pid_t pid = -1; + static char client_name[NAME_MAX + pid_string_size]; + char proc_name[NAME_MAX]; + + if (pid == -1) { + pid = getpid(); + get_proc_name(pid, proc_name); + snprintf(client_name, sizeof(client_name), "%s(%d)", proc_name, pid); + } + + return client_name; +} + +bool is_sensorhub_event(unsigned int event_type) +{ + return false; +} + +void copy_sensor_data(sensor_data_t *src, sensor_data_t *dest) +{ + dest->data_accuracy = src->data_accuracy; + dest->data_unit_idx = src->data_unit_idx; + dest->timestamp = src->timestamp; + dest->values_num = src->values_num; + memcpy(dest->values, src->values, src->values_num * sizeof(src->values[0])); +} diff --git a/src/shared/common.h b/src/shared/common.h new file mode 100755 index 0000000..a2105ca --- /dev/null +++ b/src/shared/common.h @@ -0,0 +1,226 @@ +/* + * libsensord-share + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#ifndef __cplusplus +#include +#endif /* !__cplusplus */ + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +#include +#include + +#ifndef PATH_MAX +#define PATH_MAX 256 +#endif + +#ifndef NAME_MAX +#define NAME_MAX 256 +#endif + +#define SENSOR_TYPE_SHIFT 16 + +enum sf_log_type { + SF_LOG_PRINT_FILE = 1, + SF_LOG_SYSLOG = 2, + SF_LOG_DLOG = 3, +}; + +enum sf_priority_type { + SF_LOG_ERR = 1, + SF_LOG_DBG = 2, + SF_LOG_INFO = 3, + SF_LOG_WARN = 4, +}; + +void sf_log(int type , int priority , const char *tag , const char *fmt , ...); + +#define MICROSECONDS(tv) ((tv.tv_sec * 1000000ll) + tv.tv_usec) + +#ifndef __MODULE__ +#include +#define __MODULE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#endif + +//for new log system - dlog +#ifdef LOG_TAG + #undef LOG_TAG +#endif +#define LOG_TAG "SENSOR" + +#if defined(_DEBUG) || defined(USE_FILE_DEBUG) + +#define DbgPrint(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG , " [SF_MSG_PRT][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) + +#endif + +#if defined(USE_SYSLOG_DEBUG) + +#define ERR(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define WARN(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define INFO(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define DBG(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) + +#define _E(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _W(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _I(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _D(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _T(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) + + +#elif defined(_DEBUG) || defined(USE_DLOG_DEBUG) + +#define ERR(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define WARN(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define INFO(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define DBG(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) + +#define _E(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _W(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _I(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _D(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _T(fmt, arg...) do { sf_log(SF_LOG_SYSLOG, SF_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) + +#elif defined(USE_FILE_DEBUG) + +#define ERR(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG, "[SF_MSG_ERR][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) +#define WARN(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG, "[SF_MSG_WARN][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) +#define DBG(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG, "[SF_MSG_DBG][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) +#define INFO(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG, "[SF_MSG_INFO][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) + +#define _E(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG ,"[SF_MSG_ERR][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) +#define _W(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG ,"[SF_MSG_WARN][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) +#define _I(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG ,"[SF_MSG_INFO][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) +#define _D(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG ,"[SF_MSG_DBG][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) +#define _T(fmt, arg...) do { sf_log(SF_LOG_PRINT_FILE, 0, LOG_TAG ,"[SF_MSG_TEMP][%s:%d] " fmt"\n",__MODULE__, __LINE__, ##arg); } while(0) + +#elif defined(USE_DLOG_LOG) + +#define ERR(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define WARN(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define INFO(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) + +#define DBG(...) do{} while(0) +#define DbgPrint(...) do{} while(0) + + +#define _E(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _W(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_WARN, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _I(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_INFO, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _D(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_DBG, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _T(...) + +#else +#define ERR(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define WARN(...) do{} while(0) +#define DbgPrint(...) do{} while(0) +#define DBG(...) do{} while(0) +#define INFO(...) do{} while(0) + +#define _E(fmt, arg...) do { sf_log(SF_LOG_DLOG, SF_LOG_ERR, LOG_TAG, "%s:%s(%d)> " fmt, __MODULE__, __func__, __LINE__, ##arg); } while(0) +#define _W(...) do{} while(0) +#define _I(...) do{} while(0) +#define _D(...) do{} while(0) +#define _T(...) do{} while(0) + +#endif + +#if defined(_DEBUG) +# define warn_if(expr, fmt, arg...) do { \ + if(expr) { \ + DBG("(%s) -> " fmt, #expr, ##arg); \ + } \ + } while (0) +# define ret_if(expr) do { \ + if(expr) { \ + DBG("(%s) -> %s() return", #expr, __FUNCTION__); \ + return; \ + } \ + } while (0) +# define retv_if(expr, val) do { \ + if(expr) { \ + DBG("(%s) -> %s() return", #expr, __FUNCTION__); \ + return (val); \ + } \ + } while (0) +# define retm_if(expr, fmt, arg...) do { \ + if(expr) { \ + ERR(fmt, ##arg); \ + DBG("(%s) -> %s() return", #expr, __FUNCTION__); \ + return; \ + } \ + } while (0) +# define retvm_if(expr, val, fmt, arg...) do { \ + if(expr) { \ + ERR(fmt, ##arg); \ + DBG("(%s) -> %s() return", #expr, __FUNCTION__); \ + return (val); \ + } \ + } while (0) + +#else +# define warn_if(expr, fmt, arg...) do { \ + if(expr) { \ + ERR(fmt, ##arg); \ + } \ + } while (0) +# define ret_if(expr) do { \ + if(expr) { \ + return; \ + } \ + } while (0) +# define retv_if(expr, val) do { \ + if(expr) { \ + return (val); \ + } \ + } while (0) +# define retm_if(expr, fmt, arg...) do { \ + if(expr) { \ + ERR(fmt, ##arg); \ + return; \ + } \ + } while (0) +# define retvm_if(expr, val, fmt, arg...) do { \ + if(expr) { \ + ERR(fmt, ##arg); \ + return (val); \ + } \ + } while (0) + +#endif + +struct sensor_data_t; +typedef struct sensor_data_t sensor_data_t; + +const char* get_client_name(void); +bool get_proc_name(pid_t pid, char *process_name); +bool is_sensorhub_event(unsigned int event_type); +void copy_sensor_data(sensor_data_t *src, sensor_data_t *dest); + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_COMMON_H_*/ diff --git a/src/shared/cpacket.cpp b/src/shared/cpacket.cpp new file mode 100755 index 0000000..8bce6e9 --- /dev/null +++ b/src/shared/cpacket.cpp @@ -0,0 +1,113 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +cpacket::cpacket(int size) +{ + char *ptr; + ptr = new(std::nothrow) char[size + sizeof(packet_header)]; + + m_packet = (packet_header *)ptr; + memset(m_packet, 0, size + sizeof(packet_header)); + m_packet->size = size; + m_create = NEW; +} + +cpacket::cpacket(void *data) +{ + m_packet = (packet_header *)data; + m_create = SET; +} + +cpacket::~cpacket() +{ + if (m_create == NEW) { + delete[] (char *)m_packet; + m_packet = NULL; + } +} + +void cpacket::set_payload_size(int size) +{ + if (!m_packet) { + ERR("error m_packet null!!"); + } else { + m_packet->size = size; + } +} + +void cpacket::set_cmd(int cmd) +{ + if (!m_packet) { + ERR("error m_packet null!!"); + } else { + m_packet->cmd = cmd; + } +} + +int cpacket::cmd(void) +{ + if (!m_packet) { + ERR("error m_packet null!!"); + return -1; + } else { + return m_packet->cmd; + } +} + +void *cpacket::data(void) +{ + if ( !m_packet ) { + ERR("error m_packet null!!"); + return NULL; + } + + return m_packet->data; +} + +void *cpacket::packet(void) +{ + return (void *)m_packet; +} + +int cpacket::header_size(void) +{ + return sizeof(packet_header); +} + +int cpacket::size(void) +{ + if (!m_packet) { + ERR("error m_packet null!!"); + return -1; + } else { + return m_packet->size + sizeof(packet_header); + } +} + +int cpacket::payload_size(void) +{ + return m_packet->size; +} diff --git a/src/shared/cpacket.h b/src/shared/cpacket.h new file mode 100755 index 0000000..7eb653a --- /dev/null +++ b/src/shared/cpacket.h @@ -0,0 +1,59 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CPACKET_H_ +#define _CPACKET_H_ + +typedef struct packet_header { + int cmd; + int size; + char data[0]; +} packet_header; + +class cpacket +{ +public: + cpacket(int size); + cpacket(void *data); + virtual ~cpacket(); + + void set_cmd(int cmd); + int cmd(void); + + void *data(void); + void *packet(void); + + int size(void); + int payload_size(void); + void set_payload_size(int size); + + static int header_size(void); + +private: + enum { + NEW = 0x01, + SET = 0x02, + }; + + packet_header *m_packet; + + int m_create; +}; + +#endif /*_CPACKET_H_*/ diff --git a/src/shared/crw_lock.cpp b/src/shared/crw_lock.cpp new file mode 100755 index 0000000..942a034 --- /dev/null +++ b/src/shared/crw_lock.cpp @@ -0,0 +1,65 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "crw_lock.h" +#include "common.h" + +crw_lock::crw_lock() +{ + m_rw_lock = PTHREAD_RWLOCK_INITIALIZER; +} + +crw_lock::~crw_lock() +{ + pthread_rwlock_destroy(&m_rw_lock); +} + +void crw_lock::read_lock() +{ + cbase_lock::lock(LOCK_TYPE_READ, "read lock", __MODULE__, __func__, __LINE__); +} + +void crw_lock::write_lock() +{ + cbase_lock::lock(LOCK_TYPE_WRITE, "write lock", __MODULE__, __func__, __LINE__); +} + +int crw_lock::read_lock_impl(void) +{ + return pthread_rwlock_rdlock(&m_rw_lock); +} +int crw_lock::write_lock_impl(void) +{ + return pthread_rwlock_wrlock(&m_rw_lock); +} + +int crw_lock::try_read_lock_impl(void) +{ + return pthread_rwlock_tryrdlock(&m_rw_lock); +} + +int crw_lock::try_write_lock_impl(void) +{ + return pthread_rwlock_trywrlock(&m_rw_lock); +} + +int crw_lock::unlock_impl() +{ + return pthread_rwlock_unlock(&m_rw_lock); +} diff --git a/src/shared/crw_lock.h b/src/shared/crw_lock.h new file mode 100755 index 0000000..2ec20db --- /dev/null +++ b/src/shared/crw_lock.h @@ -0,0 +1,45 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CRW_LOCK_H_ +#define _CRW_LOCK_H_ + +#include "cbase_lock.h" + +class crw_lock : public cbase_lock +{ +public: + crw_lock(); + virtual ~crw_lock(); + + void read_lock(); + void write_lock(); + +protected: + int read_lock_impl(void); + int write_lock_impl(void); + + int try_read_lock_impl(void); + int try_write_lock_impl(void); + int unlock_impl(); +private: + pthread_rwlock_t m_rw_lock; +}; + +#endif /*_CRW_LOCK_H_*/ diff --git a/src/shared/csensor_event_dispatcher.cpp b/src/shared/csensor_event_dispatcher.cpp new file mode 100755 index 0000000..db5d8c0 --- /dev/null +++ b/src/shared/csensor_event_dispatcher.cpp @@ -0,0 +1,384 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +using std::thread; + +#define MAX_PENDING_CONNECTION 32 + +csensor_event_dispatcher::csensor_event_dispatcher() +: m_lcd_on(true) +{ + m_sensor_fusion = sensor_plugin_loader::get_instance().get_fusion(); +} + +csensor_event_dispatcher::~csensor_event_dispatcher() { } + +bool csensor_event_dispatcher::run(void) +{ + INFO("Starting Event Dispatcher"); + + if (!m_accept_socket.create(SOCK_SEQPACKET)) { + ERR("Listener Socket Creation failed in Server"); + return false; + } + + if (!m_accept_socket.bind(EVENT_CHANNEL_PATH)) { + ERR("Listener Socket Binding failed in Server"); + m_accept_socket.close(); + return false; + } + + if (!m_accept_socket.listen(MAX_PENDING_CONNECTION)) { + ERR("Socket Listen failed in Server"); + return false; + } + + thread accepter(&csensor_event_dispatcher::accept_connections, this); + accepter.detach(); + + thread dispatcher(&csensor_event_dispatcher::dispatch_event, this); + dispatcher.detach(); + + return true; +} + +void csensor_event_dispatcher::accept_event_channel(csocket client_socket) +{ + int client_id; + event_channel_ready_t event_channel_ready; + cclient_info_manager &client_info_manager = get_client_info_manager(); + client_socket.set_connection_mode(); + + if (client_socket.recv(&client_id, sizeof(client_id)) <= 0) { + ERR("Failed to receive client id on socket fd[%d]", client_socket.get_socket_fd()); + return; + } + + client_socket.set_transfer_mode(); + AUTOLOCK(m_mutex); + + if (!get_client_info_manager().set_event_socket(client_id, client_socket)) { + ERR("Failed to store event socket[%d] for %s", client_socket.get_socket_fd(), + client_info_manager.get_client_info(client_id)); + return; + } + + event_channel_ready.magic = EVENT_CHANNEL_MAGIC; + event_channel_ready.client_id = client_id; + + INFO("Event channel is accepted for %s on socket[%d]", + client_info_manager.get_client_info(client_id), client_socket.get_socket_fd()); + + if (client_socket.send(&event_channel_ready, sizeof(event_channel_ready)) <= 0) { + ERR("Failed to send event_channel_ready packet to %s on socket fd[%d]", + client_info_manager.get_client_info(client_id), client_socket.get_socket_fd()); + return; + } +} + +void csensor_event_dispatcher::accept_connections(void) +{ + INFO("Event channel acceptor is started."); + + while (true) { + csocket client_socket; + + if (!m_accept_socket.accept(client_socket)) { + ERR("Accepting socket failed in Server"); + continue; + } + + INFO("New client connected (socket_fd : %d)", client_socket.get_socket_fd()); + thread event_channel_creator(&csensor_event_dispatcher::accept_event_channel, this, client_socket); + event_channel_creator.detach(); + } +} + +void csensor_event_dispatcher::dispatch_event(void) +{ + const int MAX_EVENT_PER_SENSOR = 16; + const int MAX_SENSOR_EVENT = 1 + (sensor_plugin_loader::get_instance().get_virtual_sensors().size() + * MAX_EVENT_PER_SENSOR); + const int MAX_SYNTH_PER_SENSOR = 5; + INFO("Event Dispatcher started"); + m_lcd_on = is_lcd_on(); + + if (vconf_notify_key_changed(VCONFKEY_PM_STATE, situation_watcher, this) != 0) + ERR("Fail to set notify callback for %s", VCONFKEY_PM_STATE); + + while (true) { + bool is_hub_event = false; + event_situation situation; + void *seed_event = get_event_queue().pop(); + unsigned int event_type = *((unsigned int *)(seed_event)); + + if (is_sensorhub_event(event_type)) + is_hub_event = true; + + if (m_lcd_on) + situation = SITUATION_LCD_ON; + else + situation = SITUATION_LCD_OFF; + + if (is_hub_event) { + sensorhub_event_t *sensorhub_event = (sensorhub_event_t *)seed_event; + sensorhub_event->situation = situation; + send_sensor_events(sensorhub_event, 1, true, situation); + } else { + sensor_event_t sensor_events[MAX_SENSOR_EVENT]; + unsigned int event_cnt = 0; + sensor_events[event_cnt++] = *((sensor_event_t *)seed_event); + + if (m_sensor_fusion) { + if (m_sensor_fusion->is_started()) + m_sensor_fusion->fuse(*((sensor_event_t *)seed_event)); + } + + virtual_sensors v_sensors = get_active_virtual_sensors(); + virtual_sensors::iterator it_v_sensor; + it_v_sensor = v_sensors.begin(); + vector v_sensor_events; + v_sensor_events.reserve(MAX_SYNTH_PER_SENSOR); + + while (it_v_sensor != v_sensors.end()) { + int synthesized_cnt; + v_sensor_events.clear(); + (*it_v_sensor)->synthesize(*((sensor_event_t *)seed_event), v_sensor_events); + synthesized_cnt = v_sensor_events.size(); + + for (int i = 0; i < synthesized_cnt; ++i) + sensor_events[event_cnt++] = v_sensor_events[i]; + + ++it_v_sensor; + } + + sort_sensor_events(sensor_events, event_cnt); + + for (int i = 0; i < event_cnt; ++i) { + sensor_events[i].situation = situation; + + if (is_record_event(sensor_events[i].event_type)) + put_last_event(sensor_events[i].event_type, sensor_events[i]); + } + + send_sensor_events(sensor_events, event_cnt, false, situation); + } + + if (is_hub_event) + delete (sensorhub_event_t *)seed_event; + else + delete (sensor_event_t *)seed_event; + } +} + +void csensor_event_dispatcher::send_sensor_events(void *events, int event_cnt, bool is_hub_event, event_situation situation) +{ + sensor_event_t *sensor_events; + sensorhub_event_t *sensor_hub_events; + cclient_info_manager &client_info_manager = get_client_info_manager(); + + if (is_hub_event) + sensor_hub_events = (sensorhub_event_t *)events; + else + sensor_events = (sensor_event_t *)events; + + for (int i = 0; i < event_cnt; ++i) { + client_id_vec id_vec; + unsigned int event_type; + + if (is_hub_event) + event_type = sensor_hub_events[i].event_type; + else + event_type = sensor_events[i].event_type; + + client_info_manager.get_listener_ids(event_type, situation, id_vec); + client_id_vec::iterator it_client_id; + it_client_id = id_vec.begin(); + + while (it_client_id != id_vec.end()) { + csocket client_socket; + client_info_manager.get_event_socket(*it_client_id, client_socket); + bool ret; + + if (is_hub_event) + ret = (client_socket.send(sensor_hub_events + i, sizeof(sensorhub_event_t)) > 0); + else + ret = (client_socket.send(sensor_events + i, sizeof(sensor_event_t)) > 0); + + if (ret) + DBG("Event[0x%x] sent to %s on socket[%d]", event_type, client_info_manager.get_client_info(*it_client_id), client_socket.get_socket_fd()); + else + ERR("Failed to send event[0x%x] to %s on socket[%d]", event_type, client_info_manager.get_client_info(*it_client_id), client_socket.get_socket_fd()); + + ++it_client_id; + } + } +} + +bool csensor_event_dispatcher::is_lcd_on(void) +{ + int lcd_state; + + if (vconf_get_int(VCONFKEY_PM_STATE, &lcd_state) != 0) { + ERR("Can't get the value of VCONFKEY_PM_STATE"); + return true; + } + + if (lcd_state == VCONFKEY_PM_STATE_LCDOFF) + return false; + + return true; +} + +cclient_info_manager &csensor_event_dispatcher::get_client_info_manager(void) +{ + return cclient_info_manager::get_instance(); +} + +csensor_event_queue &csensor_event_dispatcher::get_event_queue(void) +{ + return csensor_event_queue::get_instance(); +} + +bool csensor_event_dispatcher::is_record_event(unsigned int event_type) +{ + switch (event_type) { + case ACCELEROMETER_EVENT_ROTATION_CHECK: + return true; + break; + default: + break; + } + + return false; +} + +void csensor_event_dispatcher::put_last_event(unsigned int event_type, const sensor_event_t &event) +{ + AUTOLOCK(m_last_events_mutex); + m_last_events[event_type] = event; +} + +bool csensor_event_dispatcher::get_last_event(unsigned int event_type, sensor_event_t &event) +{ + AUTOLOCK(m_last_events_mutex); + event_type_last_event_map::iterator it_event; + it_event = m_last_events.find(event_type); + + if (it_event == m_last_events.end()) + return false; + + event = it_event->second; + return true; +} + +bool csensor_event_dispatcher::has_active_virtual_sensor(virtual_sensor *sensor) +{ + AUTOLOCK(m_active_virtual_sensors_mutex); + virtual_sensors::iterator it_v_sensor; + it_v_sensor = find(m_active_virtual_sensors.begin(), m_active_virtual_sensors.end(), sensor); + return (it_v_sensor != m_active_virtual_sensors.end()); +} + +virtual_sensors csensor_event_dispatcher::get_active_virtual_sensors(void) +{ + AUTOLOCK(m_active_virtual_sensors_mutex); + return m_active_virtual_sensors; +} + +bool csensor_event_dispatcher::compare_by_timestamp(const sensor_event_t &a, const sensor_event_t &b) +{ + return a.data.timestamp < b.data.timestamp; +} + +void csensor_event_dispatcher::sort_sensor_events(sensor_event_t *events, unsigned int cnt) +{ + std::sort(events, events + cnt, compare_by_timestamp); +} + +void csensor_event_dispatcher::request_last_event(int client_id, const sensor_type_t sensor) +{ + cclient_info_manager &client_info_manager = get_client_info_manager(); + event_type_vector event_vec; + csocket client_socket; + + if (client_info_manager.get_registered_events(client_id, sensor, event_vec)) { + client_info_manager.get_event_socket(client_id, client_socket); + event_type_vector::iterator it_event; + it_event = event_vec.begin(); + + while (it_event != event_vec.end()) { + sensor_event_t event; + + if (is_record_event(*it_event) && get_last_event(*it_event, event)) { + if (client_socket.send(&event, sizeof(event)) > 0) + INFO("Send the last event[0x%x] to %s on socket[%d]", event.event_type, + client_info_manager.get_client_info(client_id), client_socket.get_socket_fd()); + else + ERR("Failed to send event[0x%x] to %s on socket[%d]", event.event_type, + client_info_manager.get_client_info(client_id), client_socket.get_socket_fd()); + } + + ++it_event; + } + } +} + +bool csensor_event_dispatcher::add_active_virtual_sensor(virtual_sensor *sensor) +{ + AUTOLOCK(m_active_virtual_sensors_mutex); + + if (has_active_virtual_sensor(sensor)) { + ERR("[%s] sensor is already added on active virtual sensors", sensor->get_name()); + return false; + } + + m_active_virtual_sensors.push_back(sensor); + return true; +} + +bool csensor_event_dispatcher::delete_active_virtual_sensor(virtual_sensor *sensor) +{ + AUTOLOCK(m_active_virtual_sensors_mutex); + virtual_sensors::iterator it_v_sensor; + it_v_sensor = find(m_active_virtual_sensors.begin(), m_active_virtual_sensors.end(), sensor); + + if (it_v_sensor == m_active_virtual_sensors.end()) { + ERR("Fail to delete non-existent [%s] sensor on active virtual sensors", sensor->get_name()); + return false; + } + + m_active_virtual_sensors.erase(it_v_sensor); + return true; +} + +void csensor_event_dispatcher::situation_watcher(keynode_t *node, void *user_data) +{ + csensor_event_dispatcher *dispatcher = (csensor_event_dispatcher *) user_data; + + if (!strcmp(vconf_keynode_get_name(node), VCONFKEY_PM_STATE)) + dispatcher->m_lcd_on = dispatcher->is_lcd_on(); +} diff --git a/src/shared/csensor_event_dispatcher.h b/src/shared/csensor_event_dispatcher.h new file mode 100755 index 0000000..569d134 --- /dev/null +++ b/src/shared/csensor_event_dispatcher.h @@ -0,0 +1,83 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_EVENT_DISPATCHER_H_ +#define _SENSOR_EVENT_DISPATCHER_H_ + +#include +#include +#include +#include +#include +#include +#include + +typedef map event_type_last_event_map; +typedef list virtual_sensors; + +class csensor_event_dispatcher +{ +private: + bool m_lcd_on; + csocket m_accept_socket; + cmutex m_mutex; + cmutex m_last_events_mutex; + event_type_last_event_map m_last_events; + virtual_sensors m_active_virtual_sensors; + cmutex m_active_virtual_sensors_mutex; + sensor_fusion *m_sensor_fusion; + + csensor_event_dispatcher(); + ~csensor_event_dispatcher(); + csensor_event_dispatcher(csensor_event_dispatcher const &) {}; + csensor_event_dispatcher &operator=(csensor_event_dispatcher const &); + + void accept_connections(void); + void accept_event_channel(csocket client_socket); + + void dispatch_event(void); + void send_sensor_events(void *events, int event_cnt, bool is_hub_event, event_situation situation); + static void situation_watcher(keynode_t *node, void *user_data); + bool is_lcd_on(void); + static cclient_info_manager &get_client_info_manager(void); + static csensor_event_queue &get_event_queue(void); + + bool is_record_event(unsigned int event_type); + void put_last_event(unsigned int event_type, const sensor_event_t &event); + bool get_last_event(unsigned int event_type, sensor_event_t &event); + + bool has_active_virtual_sensor(virtual_sensor *sensor); + virtual_sensors get_active_virtual_sensors(void); + + static bool compare_by_timestamp(const sensor_event_t &a, const sensor_event_t &b); + void sort_sensor_events(sensor_event_t *events, unsigned int cnt); +public: + static csensor_event_dispatcher &get_instance() { + static csensor_event_dispatcher inst; + return inst; + } + + bool run(void); + void request_last_event(int client_id, const sensor_type_t sensor); + + bool add_active_virtual_sensor(virtual_sensor *sensor); + bool delete_active_virtual_sensor(virtual_sensor *sensor); +}; + +#endif /*_CSENSOR_EVENT_DISPATCHER_H_*/ diff --git a/src/shared/csensor_event_queue.cpp b/src/shared/csensor_event_queue.cpp new file mode 100755 index 0000000..e190005 --- /dev/null +++ b/src/shared/csensor_event_queue.cpp @@ -0,0 +1,66 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include "common.h" + +csensor_event_queue::csensor_event_queue() +{ +} + +void csensor_event_queue::push(sensor_event_t const &event) +{ + sensor_event_t *new_event = new sensor_event_t; + *new_event = event; + push_internal(new_event); +} + +void csensor_event_queue::push(sensorhub_event_t const &event) +{ + sensorhub_event_t *new_event = new sensorhub_event_t; + *new_event = event; + push_internal(new_event); +} + +void csensor_event_queue::push_internal(void *event) +{ + lock l(m_mutex); + bool wake = m_queue.empty(); + + if (m_queue.size() >= QUEUE_FULL_SIZE) { + ERR("Queue is full"); + } else + m_queue.push(event); + + if (wake) + m_cond_var.notify_one(); +} + +void *csensor_event_queue::pop(void) +{ + ulock u(m_mutex); + + while (m_queue.empty()) + m_cond_var.wait(u); + + void *event = m_queue.front(); + m_queue.pop(); + return event; +} + diff --git a/src/shared/csensor_event_queue.h b/src/shared/csensor_event_queue.h new file mode 100755 index 0000000..890e179 --- /dev/null +++ b/src/shared/csensor_event_queue.h @@ -0,0 +1,61 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _CSENSOR_EVENT_QUEUE_H_ +#define _CSENSOR_EVENT_QUEUE_H_ + +#include +#include +#include +#include + +using std::queue; +using std::mutex; +using std::lock_guard; +using std::unique_lock; +using std::condition_variable; + +class csensor_event_queue +{ +private: + static const unsigned int QUEUE_FULL_SIZE = 1000; + + queue m_queue; + mutex m_mutex; + condition_variable m_cond_var; + + typedef lock_guard lock; + typedef unique_lock ulock; + + csensor_event_queue(); + csensor_event_queue(csensor_event_queue const &) {}; + csensor_event_queue &operator=(csensor_event_queue const &); + void push_internal(void *event); + +public: + static csensor_event_queue &get_instance() { + static csensor_event_queue inst; + return inst; + } + void push(sensor_event_t const &event); + void push(sensorhub_event_t const &event); + void *pop(void); +}; + +#endif /*_CSENSOR_EVENT_QUEUE_H_*/ diff --git a/src/shared/csensor_usage.cpp b/src/shared/csensor_usage.cpp new file mode 100755 index 0000000..9f35198 --- /dev/null +++ b/src/shared/csensor_usage.cpp @@ -0,0 +1,75 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +csensor_usage::csensor_usage() +: m_interval(POLL_MAX_HZ_MS) +, m_option(SENSOR_OPTION_DEFAULT) +, m_start(false) +{ +} + +csensor_usage::~csensor_usage() +{ + m_reg_events.clear(); +} + +bool csensor_usage::register_event(const unsigned int event_type) +{ + reg_event_vector::iterator it_event; + it_event = find(m_reg_events.begin(), m_reg_events.end(), event_type); + + if (it_event != m_reg_events.end()) { + ERR("Event[0x%x] is already registered", event_type); + return false; + } + + m_reg_events.push_back(event_type); + return true; +} + +bool csensor_usage::unregister_event(const unsigned int event_type) +{ + reg_event_vector::iterator it_event; + it_event = find(m_reg_events.begin(), m_reg_events.end(), event_type); + + if (it_event == m_reg_events.end()) { + ERR("Event[0x%x] is not found", event_type); + return false; + } + + m_reg_events.erase(it_event); + return true; +} + +bool csensor_usage::is_event_registered(const unsigned int event_type) +{ + reg_event_vector::iterator it_event; + it_event = find (m_reg_events.begin(), m_reg_events.end(), event_type); + + if (it_event == m_reg_events.end()) { + DBG("Event[0x%x] is not registered", event_type); + return false; + } + + return true; +} diff --git a/src/shared/csensor_usage.h b/src/shared/csensor_usage.h new file mode 100755 index 0000000..aed055f --- /dev/null +++ b/src/shared/csensor_usage.h @@ -0,0 +1,47 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CSENSOR_USAGE_H_ +#define CSENSOR_USAGE_H_ + +#include +#include +#include + +using std::vector; + +typedef vector reg_event_vector; + +class csensor_usage +{ +public: + unsigned int m_interval; + int m_option; + reg_event_vector m_reg_events; + bool m_start; + + csensor_usage(); + ~csensor_usage(); + + bool register_event(const unsigned int event_type); + bool unregister_event(const unsigned int event_type); + bool is_event_registered(const unsigned int event_type); +}; + +#endif /* CSENSOR_USAGE_H_ */ diff --git a/src/shared/csocket.cpp b/src/shared/csocket.cpp new file mode 100755 index 0000000..96d50fe --- /dev/null +++ b/src/shared/csocket.cpp @@ -0,0 +1,437 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +csocket::csocket() +: m_sock_fd(-1) +, m_sock_type(SOCK_STREAM) +, m_send_flags(MSG_NOSIGNAL) +, m_recv_flags(MSG_NOSIGNAL) +{ + memset(&m_addr, 0, sizeof(m_addr)); +} + +csocket::csocket(int sock_fd) +: m_send_flags(MSG_NOSIGNAL) +, m_recv_flags(MSG_NOSIGNAL) +{ + m_sock_fd = sock_fd; + set_sock_type(); + memset(&m_addr, 0, sizeof(m_addr)); +} + +csocket::csocket(const csocket &sock) +{ + if (this == &sock) + return; + + m_sock_fd = sock.m_sock_fd; + m_sock_type = sock.m_sock_type; + m_send_flags = sock.m_send_flags; + m_recv_flags = sock.m_recv_flags; + + memcpy(&m_addr, &sock.m_addr, sizeof(sockaddr_un)); +} + +csocket::~csocket() +{ +} + +bool csocket::create(int sock_type) +{ + m_sock_fd = socket(AF_UNIX, sock_type, 0); + + if (!is_valid()) { + ERR("Failed to create socket for %s, errno : %d , errstr : %s ", + get_client_name(), errno, strerror(errno)); + return false; + } + + m_sock_type = sock_type; + return true; +} + +bool csocket::bind (const char *sock_path) +{ + int length; + mode_t socket_mode; + + if (!is_valid()) { + ERR("%s's socket is invalid", get_client_name()); + return false; + } + + if ((fsetxattr(m_sock_fd, "security.SMACK64IPOUT", "@", 2, 0)) < 0) { + if (errno != EOPNOTSUPP) { + close(); + ERR("security.SMACK64IPOUT error = [%d][%s]", errno, strerror(errno) ); + return false; + } + } + + if ((fsetxattr(m_sock_fd, "security.SMACK64IPIN", "*", 2, 0)) < 0) { + if (errno != EOPNOTSUPP) { + close(); + ERR("security.SMACK64IPIN error = [%d][%s]", errno, strerror(errno) ); + return false; + } + } + + if (!access(sock_path, F_OK)) { + unlink(sock_path); + } + + m_addr.sun_family = AF_UNIX; + strcpy(m_addr.sun_path, sock_path); + length = strlen(m_addr.sun_path) + sizeof(m_addr.sun_family); + + if (::bind(m_sock_fd, (struct sockaddr *)&m_addr, length) < 0) { + ERR("Binding failed for socket(%d), errno : %d , errstr : %s", m_sock_fd, errno, strerror(errno)); + close(); + return false; + } + + socket_mode = ( S_IRWXU | S_IRWXG | S_IRWXO ); + + if (chmod(sock_path, socket_mode) < 0) { + ERR("chmod failed for socket(%d), errno : %d , errstr : %s", m_sock_fd, errno, strerror(errno)); + close(); + return false; + } + + return true; +} + +bool csocket::listen(const int max_connections) +{ + if (!is_valid()) { + ERR("Socket(%d) is invalid", m_sock_fd); + return false; + } + + if (::listen(m_sock_fd, max_connections) < 0) { + ERR("Listening failed for socket(%d), errno : %d , errstr : %s", m_sock_fd, errno, strerror(errno)); + close(); + return false; + } + + return true; +} + +bool csocket::accept(csocket &client_socket) const +{ + int addr_length = sizeof(m_addr); + client_socket.m_sock_fd = ::accept(m_sock_fd, (sockaddr *)&m_addr, (socklen_t *)&addr_length); + + if (!client_socket.is_valid()) { + ERR("Accept failed for socket(%d), errno : %d , errstr : %s", m_sock_fd, errno, strerror(errno)); + return false; + } + + return true; +} + +ssize_t csocket::send_for_seqpacket(void const *buffer, size_t size) const +{ + ssize_t err, len; + + do { + len = ::send(m_sock_fd, buffer, size, m_send_flags); + err = len < 0 ? errno : 0; + } while (err == EINTR); + + if (err) { + ERR("send(%d, 0x%x, %d, 0x%x) = %d cause = %s(%d)", + m_sock_fd, buffer, size, m_send_flags, len, strerror(errno), errno); + } + + return err == 0 ? len : -err; +} + +ssize_t csocket::recv_for_seqpacket(void *buffer, size_t size) const +{ + ssize_t err, len; + + do { + len = ::recv(m_sock_fd, buffer, size, m_recv_flags); + + if (len > 0) { + err = 0; + } else if (len == 0) { + ERR("recv(%d, 0x%p , %d) = %d, because the peer performed shutdown!", + m_sock_fd, buffer, size, len); + err = 1; + } else { + err = errno; + } + } while (err == EINTR); + + if ((err == EAGAIN) || (err == EWOULDBLOCK)) { + DBG("recv(%d, 0x%x, %d, 0x%x) = %d cause = %s(%d)", + m_sock_fd, buffer, size, m_recv_flags, len, strerror(errno), errno); + return 0; + } + + if (err) { + ERR("recv(%d, 0x%x, %d, 0x%x) = %d cause = %s(%d)", + m_sock_fd, buffer, size, m_recv_flags, len, strerror(errno), errno); + } + + return err == 0 ? len : -err; +} + +ssize_t csocket::send_for_stream(void const *buffer, size_t size) const +{ + ssize_t len; + ssize_t err = 0; + ssize_t total_sent_size = 0; + + do { + len = ::send(m_sock_fd, buffer + total_sent_size, size - total_sent_size, m_send_flags); + + if (len >= 0) { + total_sent_size += len; + err = 0; + } else { + ERR("send(%d, 0x%p + %d, %d - %d) = %d, error: %s(%d) for %s", + m_sock_fd, buffer, total_sent_size, size, total_sent_size, + len, strerror(errno), errno, get_client_name()); + + if (errno != EINTR) { + err = errno; + break; + } + } + } while (total_sent_size < size); + + return err == 0 ? total_sent_size : -err; +} + +ssize_t csocket::recv_for_stream(void *buffer, size_t size) const +{ + ssize_t len; + ssize_t err = 0; + ssize_t total_recv_size = 0; + + do { + len = ::recv(m_sock_fd, buffer + total_recv_size, size - total_recv_size, m_recv_flags); + + if (len > 0) { + total_recv_size += len; + } else if (len == 0) { + ERR("recv(%d, 0x%p + %d, %d - %d) = %d, because the peer of %s performed shutdown!", + m_sock_fd, buffer, total_recv_size, size, total_recv_size, len, get_client_name()); + err = 1; + break; + } else { + ERR("recv(%d, 0x%p + %d, %d - %d) = %d, error: %s(%d) for %s", + m_sock_fd, buffer, total_recv_size, size, total_recv_size, + len, strerror(errno), errno, get_client_name()); + + if (errno != EINTR) { + err = errno; + break; + } + } + } while (total_recv_size < size); + + return err == 0 ? total_recv_size : -err; +} + +ssize_t csocket::send(void const *buffer, size_t size) const +{ + if (m_sock_type == SOCK_STREAM) + return send_for_stream(buffer, size); + + return send_for_seqpacket(buffer, size); +} + +ssize_t csocket::recv(void *buffer, size_t size) const +{ + if (m_sock_type == SOCK_STREAM) + return recv_for_stream(buffer, size); + + return recv_for_seqpacket(buffer, size); +} + +bool csocket::connect(const char *sock_path) +{ + const int TIMEOUT = 3; + fd_set write_fds; + struct timeval tv; + int addr_len; + bool prev_blocking_mode; + + if (!is_valid()) { + ERR("%s's socket is invalid", get_client_name()); + return false; + } + + prev_blocking_mode = is_blocking_mode(); + set_blocking_mode(false); + + m_addr.sun_family = AF_UNIX; + strcpy(m_addr.sun_path, sock_path); + addr_len = strlen(m_addr.sun_path) + sizeof(m_addr.sun_family); + + if (::connect(m_sock_fd, (sockaddr *) &m_addr, addr_len) < 0) { + ERR("connect error: %s sock_fd: %d for %s", strerror(errno), m_sock_fd, get_client_name()); + return false; + } + + FD_ZERO(&write_fds); + FD_SET(m_sock_fd, &write_fds); + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + + int ret; + ret = select(m_sock_fd + 1, NULL, &write_fds, NULL, &tv); + + if (ret == -1) { + ERR("select error: %s sock_fd: %d for %s", strerror(errno), m_sock_fd, get_client_name()); + close(); + return false; + } else if (!ret) { + ERR("select timeout: %d seconds elapsed for %s", tv.tv_sec, get_client_name()); + close(); + return true; + } + + if (!FD_ISSET(m_sock_fd, &write_fds)) { + ERR("select failed for %s, nothing to write, m_sock_fd : %d", get_client_name(), m_sock_fd); + close(); + return false; + } + + int so_error; + socklen_t len = sizeof(so_error); + + if (getsockopt(m_sock_fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) { + ERR("getsockopt failed for %s, m_sock_fd : %d, errno : %d , errstr : %s", + get_client_name(), m_sock_fd, errno, strerror(errno)); + close(); + return false; + } + + if (so_error) { + ERR("SO_ERROR occurred for %s, m_sock_fd : %d, so_error : %d", + get_client_name(), m_sock_fd, so_error); + close(); + return false; + } + + if (prev_blocking_mode) + set_blocking_mode(true); + + return true; +} + +bool csocket::set_blocking_mode(bool blocking) +{ + int flags; + flags = fcntl(m_sock_fd, F_GETFL); + + if (flags == -1) { + ERR("fcntl(F_GETFL) failed for %s, m_sock_fd: %d, errno : %d , errstr : %s", get_client_name(), m_sock_fd, errno, strerror(errno)); + return false; + } + + flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); + flags = fcntl(m_sock_fd, F_SETFL, flags); + + if (flags == -1) { + ERR("fcntl(F_SETFL) failed for %s, m_sock_fd: %d, errno : %d , errstr : %s", get_client_name(), m_sock_fd, errno, strerror(errno)); + return false; + } + + return true; +} + +bool csocket::set_sock_type(void) +{ + socklen_t opt_len; + int sock_type; + opt_len = sizeof(sock_type); + + if (getsockopt(m_sock_fd, SOL_SOCKET, SO_TYPE, &sock_type, &opt_len) < 0) { + ERR("getsockopt(SOL_SOCKET, SO_TYPE) failed for %s, m_sock_fd: %d, errno : %d , errstr : %s", get_client_name(), m_sock_fd, errno, strerror(errno)); + return false; + } + + m_sock_type = sock_type; + return true; +} + +bool csocket::set_connection_mode(void) +{ + struct timeval tv; + const int TIMEOUT = 3; + set_blocking_mode(true); + tv.tv_sec = TIMEOUT; + tv.tv_usec = 0; + + if (setsockopt(m_sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { + ERR("Set SO_RCVTIMEO failed for %s, m_sock_fd : %d, errno : %d , errstr : %s", + get_client_name(), m_sock_fd, errno, strerror(errno)); + close(); + return false; + } + + m_send_flags = MSG_NOSIGNAL; + m_recv_flags = MSG_NOSIGNAL; + return true; +} + +bool csocket::set_transfer_mode(void) +{ + set_blocking_mode(false); + m_send_flags = MSG_DONTWAIT | MSG_NOSIGNAL; + m_recv_flags = MSG_DONTWAIT | MSG_NOSIGNAL; + return true; +} + +bool csocket::is_blocking_mode(void) +{ + int flags; + flags = fcntl(m_sock_fd, F_GETFL); + + if (flags == -1) { + ERR("fcntl(F_GETFL) failed for %s, m_sock_fd: %d, errno : %d , errstr : %s", get_client_name(), m_sock_fd, errno, strerror(errno)); + return false; + } + + return !(flags & O_NONBLOCK); +} + +bool csocket::close(void) +{ + if (m_sock_fd >= 0) { + if (::close(m_sock_fd) < 0) { + ERR("Socket(%d) close failed, errno : %d , errstr : %s", m_sock_fd, errno, strerror(errno)); + return false; + } + + m_sock_fd = -1; + } + + return true; +} diff --git a/src/shared/csocket.h b/src/shared/csocket.h new file mode 100755 index 0000000..2d9e3ce --- /dev/null +++ b/src/shared/csocket.h @@ -0,0 +1,86 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef CSOCKET_H_ +#define CSOCKET_H_ + +#include +#include +#include +#include +#include +#include +#include "common.h" +#include + +using std::string; + +class csocket +{ +public: + csocket(); + virtual ~csocket(); + csocket(int sock_fd); + csocket(const csocket &sock); + + //Server + bool create(int sock_type); + bool bind (const char *sock_path); + bool listen(const int max_connections); + bool accept(csocket &client_socket) const; + + //Client + bool connect(const char *sock_path); + + //Data Transfer + ssize_t send(void const *buffer, size_t size) const; + ssize_t recv(void *buffer, size_t size) const; + + bool set_connection_mode(void); + bool set_transfer_mode(void); + bool is_blocking_mode(void); + + //check if socket is created + bool is_valid(void) const { + return (m_sock_fd >= 0); + } + int get_socket_fd(void) const { + return m_sock_fd; + } + + bool close(void); + bool is_block_mode(void); + +private: + bool set_blocking_mode(bool blocking); + bool set_sock_type(void); + + ssize_t send_for_seqpacket(void const *buffer, size_t size) const; + ssize_t send_for_stream(void const *buffer, size_t size) const; + ssize_t recv_for_seqpacket(void *buffer, size_t size) const; + ssize_t recv_for_stream(void *buffer, size_t size) const; + + int m_sock_fd; + int m_sock_type; + sockaddr_un m_addr; + int m_send_flags; + int m_recv_flags; +}; + +#endif /* CSOCKET_H_ */ diff --git a/src/shared/physical_sensor.cpp b/src/shared/physical_sensor.cpp new file mode 100755 index 0000000..a81e33f --- /dev/null +++ b/src/shared/physical_sensor.cpp @@ -0,0 +1,57 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +physical_sensor::physical_sensor() +{ +} + +physical_sensor::~physical_sensor() +{ +} + +bool physical_sensor::push(sensor_event_t const &event) +{ + csensor_event_queue::get_instance().push(event); + return true; +} + +bool physical_sensor::push(sensorhub_event_t const &event) +{ + csensor_event_queue::get_instance().push(event); + return true; +} + +void physical_sensor::set_poller(working_func_t func, void *arg) +{ + m_sensor_data_poller.set_context(arg); + m_sensor_data_poller.set_working(func); +} + +bool physical_sensor::start_poll(void) +{ + return m_sensor_data_poller.start(); +} + +bool physical_sensor::stop_poll(void) +{ + return m_sensor_data_poller.pause(); +} diff --git a/src/shared/physical_sensor.h b/src/shared/physical_sensor.h new file mode 100755 index 0000000..d4438ce --- /dev/null +++ b/src/shared/physical_sensor.h @@ -0,0 +1,47 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _PHYSICAL_SENSOR_H_ +#define _PHYSICAL_SENSOR_H_ + +#include +#include +#include + +class physical_sensor : public sensor_base +{ +public: + typedef worker_thread::trans_func_t working_func_t; + +private: + worker_thread m_sensor_data_poller; + +protected: + physical_sensor(); + virtual ~physical_sensor(); + + bool push(sensor_event_t const &event); + bool push(sensorhub_event_t const &event); + + void set_poller(working_func_t func, void *arg); + bool start_poll(void); + bool stop_poll(void); +}; + +#endif /*_PHYSICAL_SENSOR_H_*/ diff --git a/src/shared/sensor_base.cpp b/src/shared/sensor_base.cpp new file mode 100755 index 0000000..17ad75f --- /dev/null +++ b/src/shared/sensor_base.cpp @@ -0,0 +1,274 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#define UNKNOWN_NAME "UNKNOWN_SENSOR" + +sensor_base::sensor_base() +: m_client(0) +, m_started(false) +{ +} + +sensor_base::~sensor_base() +{ +} + +bool sensor_base::init() +{ + return true; +} + +bool sensor_base::is_virtual() +{ + return false; +} + +bool sensor_base::is_fusion(void) +{ + return false; +} + +sensor_type_t sensor_base::get_type() +{ + return UNKNOWN_SENSOR; +} + +const char *sensor_base::get_name() +{ + if (m_name.empty()) + return UNKNOWN_NAME; + + return m_name.c_str(); +} + +bool sensor_base::on_start() +{ + return true; +} + +bool sensor_base::on_stop() +{ + return true; +} + +bool sensor_base::start() +{ + AUTOLOCK(m_mutex); + AUTOLOCK(m_client_mutex); + ++m_client; + + if (m_client == 1) { + if (!on_start()) { + ERR("[%s] sensor failed to start", get_name()); + return false; + } + + m_started = true; + } + + INFO("[%s] sensor started, #client = %d", get_name(), m_client); + return true; +} + +bool sensor_base::stop(void) +{ + AUTOLOCK(m_mutex); + AUTOLOCK(m_client_mutex); + --m_client; + + if (m_client == 0) { + if (!on_stop()) { + ERR("[%s] sensor faild to stop", get_name()); + return false; + } + + m_started = false; + } + + INFO("[%s] sensor stopped, #client = %d", get_name(), m_client); + return true; +} + +bool sensor_base::is_started(void) +{ + AUTOLOCK(m_mutex); + AUTOLOCK(m_client_mutex); + return m_started; +} + +bool sensor_base::add_client(unsigned int event_type) +{ + if (!is_supported(event_type)) { + ERR("Invaild event type: 0x%x", event_type); + return false; + } + + AUTOLOCK(m_client_info_mutex); + ++(m_client_info[event_type]); + return true; +} + +bool sensor_base::delete_client(unsigned int event_type) +{ + if (!is_supported(event_type)) { + ERR("Invaild event type: 0x%x", event_type); + return false; + } + + AUTOLOCK(m_client_info_mutex); + client_info::iterator iter; + iter = m_client_info.find(event_type); + + if (iter == m_client_info.end()) + return false; + + if (iter->second == 0) + return false; + + --(iter->second); + return true; +} + +bool sensor_base::add_interval(int client_id, unsigned int interval, bool is_processor) +{ + unsigned int cur_min; + AUTOLOCK(m_interval_info_list_mutex); + cur_min = m_interval_info_list.get_min(); + + if (!m_interval_info_list.add_interval(client_id, interval, is_processor)) + return false; + + if ((interval < cur_min) || !cur_min) { + INFO("Min interval for sensor[0x%x] is changed from %dms to %dms" + " by%sclient[%d] adding interval", + get_type(), cur_min, interval, + is_processor ? " processor " : " ", client_id); + set_interval(interval); + } + + return true; +} + +bool sensor_base::delete_interval(int client_id, bool is_processor) +{ + unsigned int prev_min, cur_min; + AUTOLOCK(m_interval_info_list_mutex); + prev_min = m_interval_info_list.get_min(); + + if (!m_interval_info_list.delete_interval(client_id, is_processor)) + return false; + + cur_min = m_interval_info_list.get_min(); + + if (!cur_min) { + INFO("No interval for sensor[0x%x] by%sclient[%d] deleting interval, " + "so set to default %dms", + get_type(), is_processor ? " processor " : " ", + client_id, POLL_1HZ_MS); + set_interval(POLL_1HZ_MS); + } else if (cur_min != prev_min) { + INFO("Min interval for sensor[0x%x] is changed from %dms to %dms" + " by%sclient[%d] deleting interval", + get_type(), prev_min, cur_min, + is_processor ? " processor " : " ", client_id); + set_interval(cur_min); + } + + return true; +} + +unsigned int sensor_base::get_interval(int client_id, bool is_processor) +{ + AUTOLOCK(m_interval_info_list_mutex); + return m_interval_info_list.get_interval(client_id, is_processor); +} + +bool sensor_base::get_properties(const unsigned int type, sensor_properties_t &properties) +{ + ERR("Invalid type: 0x%x", type); + return false; +} + +bool sensor_base::is_supported(unsigned int event_type) +{ + vector::iterator iter; + iter = find(m_supported_event_info.begin(), m_supported_event_info.end(), event_type); + + if (iter == m_supported_event_info.end()) + return false; + + return true; +} + +long sensor_base::set_command(const unsigned int cmd, long value) +{ + return -1; +} + +int sensor_base::send_sensorhub_data(const char *data, int data_len) +{ + return -1; +} + +int sensor_base::get_sensor_data(const unsigned int type, sensor_data_t &data) +{ + return -1; +} + +void sensor_base::register_supported_event(unsigned int event_type) +{ + m_supported_event_info.push_back(event_type); +} + +unsigned int sensor_base::get_client_cnt(unsigned int event_type) +{ + AUTOLOCK(m_client_info_mutex); + client_info::iterator iter; + iter = m_client_info.find(event_type); + + if (iter == m_client_info.end()) + return 0; + + return iter->second; +} + +bool sensor_base::set_interval(unsigned long val) +{ + return true; +} + +unsigned long long sensor_base::get_timestamp(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return ((unsigned long long)(t.tv_sec) * NS_TO_SEC + t.tv_nsec) / MS_TO_SEC; +} + +unsigned long long sensor_base::get_timestamp(timeval *t) +{ + if (!t) { + ERR("t is NULL"); + return 0; + } + + return ((unsigned long long)(t->tv_sec) * US_TO_SEC + t->tv_usec); +} diff --git a/src/shared/sensor_base.h b/src/shared/sensor_base.h new file mode 100755 index 0000000..1d60077 --- /dev/null +++ b/src/shared/sensor_base.h @@ -0,0 +1,112 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_BASE_H_ +#define _SENSOR_BASE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::string; +using std::mutex; +using std::recursive_mutex; +using std::lock_guard; +using std::list; +using std::map; +using std::vector; +using std::unique_lock; +using std::condition_variable; + +class sensor_base +{ +private: + typedef map client_info; + +public: + sensor_base(); + virtual ~sensor_base(); + + virtual bool init(void); + virtual sensor_type_t get_type(void); + virtual const char *get_name(void); + virtual bool is_virtual(void); + virtual bool is_fusion(void); + + virtual bool on_start(void); + virtual bool on_stop(void); + + bool start(void); + bool stop(void); + bool is_started(void); + + virtual bool add_client(unsigned int event_type); + virtual bool delete_client(unsigned int event_type); + + virtual bool add_interval(int client_id, unsigned int interval, bool is_processor = false); + virtual bool delete_interval(int client_id, bool is_processor = false); + unsigned int get_interval(int client_id, bool is_processor = false); + + virtual bool get_properties(const unsigned int type, sensor_properties_t &properties); + bool is_supported(unsigned int event_type); + + virtual long set_command(const unsigned int cmd, long value); + virtual int send_sensorhub_data(const char *data, int data_len); + + virtual int get_sensor_data(const unsigned int type, sensor_data_t &data); + + void register_supported_event(unsigned int event_type); +protected: + typedef lock_guard lock; + typedef lock_guard rlock; + typedef unique_lock ulock; + + cinterval_info_list m_interval_info_list; + cmutex m_interval_info_list_mutex; + + cmutex m_mutex; + + unsigned int m_client; + cmutex m_client_mutex; + + client_info m_client_info; + cmutex m_client_info_mutex; + + vector m_supported_event_info; + + bool m_started; + + string m_name; + + unsigned int get_client_cnt(unsigned int event_type); + virtual bool set_interval(unsigned long val); + + unsigned long long get_timestamp(void); + unsigned long long get_timestamp(timeval *t); +}; + +#endif /*_SENSOR_BASE_H_*/ diff --git a/src/shared/sensor_common.h b/src/shared/sensor_common.h new file mode 100755 index 0000000..3c218d6 --- /dev/null +++ b/src/shared/sensor_common.h @@ -0,0 +1,203 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_COMMON_H_ +#define _SENSOR_COMMON_H_ + +#ifndef DEPRECATED +#define DEPRECATED __attribute__((deprecated)) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /*__cplusplus*/ + +#define MAX_KEY_LENGTH 64 +#define MAX_VALUE_SIZE 12 +#define SENSORHUB_TYPE_CONTEXT 1 +#define SENSORHUB_TYPE_GESTURE 2 +#define MS_TO_SEC 1000 +#define US_TO_SEC 1000000 +#define NS_TO_SEC 1000000000 + +/** + * @defgroup SENSOR_FRAMEWORK SensorFW + * To support the unified API for the various sensors + */ + +/** + * @defgroup SENSOR_FRAMEWORK_COMMON Sensor Framework Common API + * @ingroup SENSOR_FRAMEWORK + * + * These APIs are used to control the sensors. + * @{ + */ + +typedef enum { + UNKNOWN_SENSOR = 0, + ACCELEROMETER_SENSOR, + GEOMAGNETIC_SENSOR, + LIGHT_SENSOR, + PROXIMITY_SENSOR, + THERMOMETER_SENSOR, + GYROSCOPE_SENSOR, + PRESSURE_SENSOR, + MOTION_SENSOR, + FUSION_SENSOR, + PEDOMETER_SENSOR, + CONTEXT_SENSOR, + FLAT_SENSOR, + BIO_SENSOR, + BIO_HRM_SENSOR, + AUTO_ROTATION_SENSOR, + GRAVITY_SENSOR, + LINEAR_ACCEL_SENSOR, + ROTATION_VECTOR_SENSOR, + ORIENTATION_SENSOR, +} sensor_type_t; + +typedef struct sensor_data_t { + int data_accuracy; + int data_unit_idx; +/* + * Use "timestamp" instead of "time_stamp" + * which is going to be removed soon + */ + union { + unsigned long long time_stamp; + unsigned long long timestamp; + }; + int values_num; + float values[MAX_VALUE_SIZE]; +} sensor_data_t; + +typedef struct sensor_event_t { + unsigned int event_type; + int situation; + sensor_data_t data; +} sensor_event_t; + +#define HUB_DATA_MAX_SIZE 4096 + +typedef struct { + int version; + int sensorhub; + int type; + int hub_data_size; + long long timestamp; + char hub_data[HUB_DATA_MAX_SIZE]; + float data[16]; +} sensorhub_data_t; + +typedef struct sensorhub_event_t { + unsigned int event_type; + int situation; + sensorhub_data_t data; +} sensorhub_event_t; + +typedef struct { + int sensor_unit_idx; + float sensor_min_range; + float sensor_max_range; + float sensor_resolution; + char sensor_name[MAX_KEY_LENGTH]; + char sensor_vendor[MAX_KEY_LENGTH]; +} sensor_properties_t; + +enum sensor_data_unit_idx { + SENSOR_UNDEFINED_UNIT, + SENSOR_UNIT_METRE_PER_SECOND_SQUARED, + SENSOR_UNIT_MICRO_TESLA, + SENSOR_UNIT_DEGREE, + SENSOR_UNIT_LUX, + SENSOR_UNIT_CENTIMETER, + SENSOR_UNIT_LEVEL, + SENSOR_UNIT_STATE_ON_OFF, + SENSOR_UNIT_DEGREE_PER_SECOND, + SENSOR_UNIT_HECTOPASCAL, + SENSOR_UNIT_CELSIUS, + SENSOR_UNIT_METER, + SENSOR_UNIT_STEP, + SENSOR_UNIT_VENDOR_UNIT = 100, + SENSOR_UNIT_FILTER_CONVERTED, + SENSOR_UNIT_SENSOR_END +}; + +enum sensor_data_accuracy { + SENSOR_ACCURACY_UNDEFINED = -1, + SENSOR_ACCURACY_BAD = 0, + SENSOR_ACCURACY_NORMAL =1, + SENSOR_ACCURACY_GOOD = 2, + SENSOR_ACCURACY_VERYGOOD = 3 +}; + +enum sensor_start_option { + SENSOR_OPTION_DEFAULT = 0, + SENSOR_OPTION_ALWAYS_ON = 1, + SENSOR_OPTION_END +}; + +enum _sensor_current_state { + SENSOR_STATE_UNKNOWN = -1, + SENSOR_STATE_STOPPED = 0, + SENSOR_STATE_STARTED = 1, + SENSOR_STATE_PAUSED = 2 +}; + +enum _sensor_wakeup_state { + SENSOR_WAKEUP_UNKNOWN = -1, + SENSOR_WAKEUP_UNSETTED = 0, + SENSOR_WAKEUP_SETTED = 1, +}; + +enum _sensor_poweroff_state { + SENSOR_POWEROFF_UNKNOWN = -1, + SENSOR_POWEROFF_AWAKEN = 1, +}; + +enum event_situation { + SITUATION_LCD_ON, + SITUATION_LCD_OFF, + SITUATION_SURVIVAL_MODE +}; + +enum poll_value_t { + POLL_100HZ_MS = 10, + POLL_50HZ_MS = 20, + POLL_25HZ_MS = 40, + POLL_20HZ_MS = 50, + POLL_10HZ_MS = 100, + POLL_5HZ_MS = 200, + POLL_1HZ_MS = 1000, + POLL_MAX_HZ_MS = POLL_1HZ_MS, +}; + +typedef enum { + CONDITION_NO_OP, + CONDITION_EQUAL, + CONDITION_GREAT_THAN, + CONDITION_LESS_THAN, +} condition_op_t; + +#ifdef __cplusplus +} +#endif /*__cplusplus*/ + +#endif /*_SENSOR_COMMON_H_*/ diff --git a/src/shared/sensor_fusion.cpp b/src/shared/sensor_fusion.cpp new file mode 100755 index 0000000..1189575 --- /dev/null +++ b/src/shared/sensor_fusion.cpp @@ -0,0 +1,98 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +sensor_fusion::sensor_fusion() +{ +} + +sensor_fusion::~sensor_fusion() +{ +} + +bool sensor_fusion::is_data_ready(void) +{ + return true; +} + +bool sensor_fusion::get_properties(sensor_properties_t &properties) +{ + return false; +} + +bool sensor_fusion::add_interval(int client_id, unsigned int interval) +{ + return true; +} + +bool sensor_fusion::delete_interval(int client_id) +{ + return true; +} + +bool sensor_fusion::get_rotation_matrix(arr33_t &rot) +{ + return false; +} + +bool sensor_fusion::get_attitude(float &x, float &y, float &z, float &w) +{ + return false; +} + +bool sensor_fusion::get_gyro_bias(float &x, float &y, float &z) +{ + return false; +} + +bool sensor_fusion::get_rotation_vector(float &x, float &y, float &z, float &w, float &heading_accuracy) +{ + return false; +} + +bool sensor_fusion::get_linear_acceleration(float &x, float &y, float &z) +{ + return false; +} + +bool sensor_fusion::get_gravity(float &x, float &y, float &z) +{ + return false; +} + +bool sensor_fusion::get_rotation_vector_6axis(float &x, float &y, float &z, float &w, float &heading_accuracy) +{ + return false; +} + +bool sensor_fusion::get_geomagnetic_rotation_vector(float &x, float &y, float &z, float &w) +{ + return false; +} + +bool sensor_fusion::get_orientation(float &azimuth, float &pitch, float &roll) +{ + return false; +} + +bool sensor_fusion::is_fusion(void) +{ + return true; +} diff --git a/src/shared/sensor_fusion.h b/src/shared/sensor_fusion.h new file mode 100755 index 0000000..3375dcb --- /dev/null +++ b/src/shared/sensor_fusion.h @@ -0,0 +1,53 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_FUSION_H_ +#define _SENSOR_FUSION_H_ + +#include +#include + +typedef std::array , 3> arr33_t; + +class sensor_fusion : public sensor_base +{ +public: + sensor_fusion(); + virtual ~sensor_fusion(); + + virtual void fuse(const sensor_event_t &event) = 0; + virtual bool is_data_ready(void); + virtual bool add_interval(int client_id, unsigned int interval); + virtual bool delete_interval(int client_id); + virtual bool get_properties(sensor_properties_t &properties); + + virtual bool get_rotation_matrix(arr33_t &rot); + virtual bool get_attitude(float &x, float &y, float &z, float &w); + virtual bool get_gyro_bias(float &x, float &y, float &z); + virtual bool get_rotation_vector(float &x, float &y, float &z, float &w, float &heading_accuracy); + virtual bool get_linear_acceleration(float &x, float &y, float &z); + virtual bool get_gravity(float &x, float &y, float &z); + virtual bool get_rotation_vector_6axis(float &x, float &y, float &z, float &w, float &heading_accuracy); + virtual bool get_geomagnetic_rotation_vector(float &x, float &y, float &z, float &w); + virtual bool get_orientation(float &azimuth, float &pitch, float &roll); + + bool is_fusion(void); +}; + +#endif /*_SENSOR_FUSION_H_*/ diff --git a/src/shared/sensor_hal.cpp b/src/shared/sensor_hal.cpp new file mode 100755 index 0000000..d91a2ec --- /dev/null +++ b/src/shared/sensor_hal.cpp @@ -0,0 +1,62 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +bool sensor_hal::set_interval(unsigned long val) +{ + return true; +} + +long sensor_hal::set_command(const unsigned int cmd, long val) +{ + return -1; +} + +int sensor_hal::send_sensorhub_data(const char *data, int data_len) +{ + return -1; +} + +int sensor_hal::get_sensor_data(sensor_data_t &data) +{ + return -1; +} + +int sensor_hal::get_sensor_data(sensorhub_data_t &data) +{ + return -1; +} + +unsigned long long sensor_hal::get_timestamp(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return ((unsigned long long)(t.tv_sec) * NS_TO_SEC + t.tv_nsec) / MS_TO_SEC; +} + +unsigned long long sensor_hal::get_timestamp(timeval *t) +{ + if (!t) { + ERR("t is NULL"); + return 0; + } + + return ((unsigned long long)(t->tv_sec) * US_TO_SEC + t->tv_usec); +} diff --git a/src/shared/sensor_hal.h b/src/shared/sensor_hal.h new file mode 100755 index 0000000..8e8fed6 --- /dev/null +++ b/src/shared/sensor_hal.h @@ -0,0 +1,67 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_HAL_H_ +#define _SENSOR_HAL_H_ + +#include +#include +#include +#include +#include +#include + +using std::string; + +/* +* As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock +* Current kernel-headers package doesn't have it so we should define it here. +*/ + +#ifndef EVIOCSCLOCKID +#define EVIOCSCLOCKID _IOW('E', 0xa0, int) /* Set clockid to be used for timestamps */ +#endif + +class sensor_hal +{ +public: + sensor_hal() {} + virtual ~sensor_hal() {} + + virtual bool init(void *data = NULL) { + return true; + } + virtual string get_model_id(void) = 0; + virtual sensor_type_t get_type(void) = 0; + virtual bool enable(void) = 0; + virtual bool disable(void) = 0; + virtual bool set_interval(unsigned long val); + virtual bool is_data_ready(bool wait) = 0; + virtual bool get_properties(sensor_properties_t &properties) = 0; + virtual int get_sensor_data(sensor_data_t &data); + virtual int get_sensor_data(sensorhub_data_t &data); + virtual long set_command(const unsigned int cmd, long val); + virtual int send_sensorhub_data(const char *data, int data_len); +protected: + cmutex m_mutex; + + unsigned long long get_timestamp(void); + unsigned long long get_timestamp(timeval *t); +}; +#endif /*_SENSOR_HAL_H_*/ diff --git a/src/shared/sensor_plugin_loader.cpp b/src/shared/sensor_plugin_loader.cpp new file mode 100755 index 0000000..368278a --- /dev/null +++ b/src/shared/sensor_plugin_loader.cpp @@ -0,0 +1,326 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::make_pair; + +#define ROOT_ELEMENT "PLUGIN" +#define TEXT_ELEMENT "text" +#define PATH_ATTR "path" +#define HAL_ELEMENT "HAL" +#define SENSOR_ELEMENT "SENSOR" + +sensor_plugin_loader::sensor_plugin_loader() +{ +} + +void *sensor_plugin_loader::load_module(const char *path) +{ + void *handle = dlopen(path, RTLD_NOW); + + if (!handle) { + DBG("Target file is %s , dlerror : %s", path, dlerror()); + return NULL; + } + + dlerror(); + + typedef void *create_t(void); + typedef void destroy_t(void *); + create_t *init_module = (create_t *) dlsym(handle, "create"); + const char *dlsym_error = dlerror(); + + if (dlsym_error) { + ERR("Failed to find \"create\" %s", dlsym_error); + dlclose(handle); + return NULL; + } + + destroy_t *exit_module = (destroy_t *) dlsym(handle, "destroy"); + dlsym_error = dlerror(); + + if (dlsym_error) { + ERR("Failed to find \"destroy\" %s", dlsym_error); + dlclose(handle); + return NULL; + } + + void *module = init_module(); + + if (!module) { + ERR("Failed to init the module => dlerror : %s , Target file is %s", dlerror(), path); + dlclose(handle); + return NULL; + } + + return module; +} + +bool sensor_plugin_loader::insert_module(const char *node_name, const char *path) +{ + if (strcmp(node_name, HAL_ELEMENT) == 0) { + DBG("insert sensor plugin [%s]", path); + sensor_hal *module; + module = (sensor_hal *)load_module(path); + + if (!module) + return false; + + sensor_type_t sensor_type = module->get_type(); + m_sensor_hals.insert(make_pair(sensor_type, module)); + } + + if (strcmp(node_name, SENSOR_ELEMENT) == 0) { + DBG("insert sensor plugin [%s]", path); + sensor_base *module; + module = (sensor_base *)load_module(path); + + if (!module) + return false; + + if (!module->init()) { + ERR("Failed to init [%s] module", module->get_name()); + delete module; + return false; + } + + DBG("init [%s] module", module->get_name()); + sensor_type_t sensor_type = module->get_type(); + + if (module->is_fusion()) + m_fusions.push_back((sensor_fusion *) module); + else + m_sensors.insert(make_pair(sensor_type, module)); + } + + return true; +} + +bool sensor_plugin_loader::load_plugins(const string &plugins_path) +{ + xmlDocPtr doc; + xmlNodePtr cur; + + DBG("sensor_plugin_load::load_plugins(\"%s\") is called!", plugins_path.c_str()); + doc = xmlParseFile(plugins_path.c_str()); + + if (doc == NULL) { + ERR("There is no %s", plugins_path.c_str()); + return false; + } + + cur = xmlDocGetRootElement(doc); + + if (cur == NULL) { + ERR("There is no root element in %s", plugins_path.c_str()); + xmlFreeDoc(doc); + return false; + } + + if (xmlStrcmp(cur->name, (const xmlChar *)ROOT_ELEMENT)) { + ERR("Wrong type document: there is no [%s] root element in %s", ROOT_ELEMENT, plugins_path.c_str()); + xmlFreeDoc(doc); + return false; + } + + xmlNodePtr plugin_list_node_ptr; + xmlNodePtr module_node_ptr; + char *prop = NULL; + plugin_list_node_ptr = cur->xmlChildrenNode; + + while (plugin_list_node_ptr != NULL) { + //skip garbage element, [text] + if (!xmlStrcmp(plugin_list_node_ptr->name, (const xmlChar *)TEXT_ELEMENT)) { + plugin_list_node_ptr = plugin_list_node_ptr->next; + continue; + } + + DBG("<%s>", (const char *)plugin_list_node_ptr->name); + + module_node_ptr = plugin_list_node_ptr->xmlChildrenNode; + + while (module_node_ptr != NULL) { + if (!xmlStrcmp(module_node_ptr->name, (const xmlChar *)TEXT_ELEMENT)) { + module_node_ptr = module_node_ptr->next; + continue; + } + + string path; + prop = (char *)xmlGetProp(module_node_ptr, (const xmlChar *)PATH_ATTR); + path = prop; + free(prop); + DBG("<%s path=\"%s\">", (const char *) module_node_ptr->name, path.c_str()); + bool error = insert_module((const char *) plugin_list_node_ptr->name, path.c_str()); + + if (!error) { + //ERR("Fail to insert module : [%s]", path.c_str()) ; + } + + DBG(""); + module_node_ptr = module_node_ptr->next; + } + + DBG(""); + plugin_list_node_ptr = plugin_list_node_ptr->next; + } + + xmlFreeDoc(doc); + show_sensor_info(); + return true; +} + +void sensor_plugin_loader::show_sensor_info(void) +{ + int index = 0; + sensor_plugins::iterator it = m_sensors.begin(); + + INFO("========== Loaded sensor information =========="); + + while (it != m_sensors.end()) { + sensor_base *sensor = it->second; + sensor_properties_t properties; + int default_type = sensor->get_type() << SENSOR_TYPE_SHIFT | 0x1; + + if (sensor->get_properties(default_type, properties)) { + INFO("[%d] %s", ++index, sensor->get_name()); + INFO("name : %s", properties.sensor_name); + INFO("vendor : %s", properties.sensor_vendor); + INFO("unit_idx : %d", properties.sensor_unit_idx); + INFO("min_range : %f", properties.sensor_min_range); + INFO("max_range : %f", properties.sensor_max_range); + INFO("resolution : %f", properties.sensor_resolution); + } + + it++; + } + + INFO("==============================================="); +} + +sensor_hal *sensor_plugin_loader::get_sensor_hal(sensor_type_t type) +{ + sensor_hal_plugins::iterator it_plugins; + it_plugins = m_sensor_hals.find(type); + + if (it_plugins == m_sensor_hals.end()) + return NULL; + + return it_plugins->second; +} + +vector sensor_plugin_loader::get_sensor_hals(sensor_type_t type) +{ + vector sensor_hal_list; + pair ret; + ret = m_sensor_hals.equal_range(type); + sensor_hal_plugins::iterator it; + + for (it = ret.first; it != ret.second; ++it) { + sensor_hal_list.push_back(it->second); + } + + return sensor_hal_list; +} + +sensor_base *sensor_plugin_loader::get_sensor(sensor_type_t type) +{ + sensor_plugins::iterator it_plugins; + it_plugins = m_sensors.find(type); + + if (it_plugins == m_sensors.end()) + return NULL; + + return it_plugins->second; +} + +vector sensor_plugin_loader::get_sensors(sensor_type_t type) +{ + vector sensor_list; + pair ret; + ret = m_sensors.equal_range(type); + sensor_plugins::iterator it; + + for (it = ret.first; it != ret.second; ++it) { + sensor_list.push_back(it->second); + } + + return sensor_list; +} + +vector sensor_plugin_loader::get_virtual_sensors(void) +{ + vector virtual_list; + sensor_plugins::iterator sensor_it; + sensor_base *module; + + for (sensor_it = m_sensors.begin(); sensor_it != m_sensors.end(); ++sensor_it) { + module = sensor_it->second; + + if (module && module->is_virtual() == true) { + virtual_list.push_back(module); + } + } + + return virtual_list; +} + +sensor_fusion *sensor_plugin_loader::get_fusion(void) +{ + if (m_fusions.empty()) + return NULL; + + return m_fusions.front(); +} + +vector sensor_plugin_loader::get_fusions(void) +{ + return m_fusions; +} + +bool sensor_plugin_loader::destroy() +{ + sensor_base *sensor; + sensor_plugins::iterator sensor_it; + + for (sensor_it = m_sensors.begin(); sensor_it != m_sensors.end(); ++sensor_it) { + sensor = sensor_it->second; + delete sensor; + } + + sensor_hal *sensor_hal; + sensor_hal_plugins::iterator sensor_hal_it; + + for (sensor_hal_it = m_sensor_hals.begin(); sensor_hal_it != m_sensor_hals.end(); ++sensor_hal_it) { + sensor_hal = sensor_hal_it->second; + delete sensor_hal; + } + + m_sensors.clear(); + m_sensor_hals.clear(); + return true; +} + diff --git a/src/shared/sensor_plugin_loader.h b/src/shared/sensor_plugin_loader.h new file mode 100755 index 0000000..fd380df --- /dev/null +++ b/src/shared/sensor_plugin_loader.h @@ -0,0 +1,102 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SENSOR_PLUGIN_LOADER_H_ +#define _SENSOR_PLUGIN_LOADER_H_ + +#include +#include +#include +#include +#include +#include + +class sensor_hal; +class sensor_base; +class sensor_fusion; + +using std::pair; +using std::vector; +using std::multimap; +using std::string; +using std::istringstream; + +#define PLUGINS_FILE_PATH "/usr/etc/sensor_plugins.xml" + +typedef multimap sensor_hal_plugins; +/* +* a hal_plugins is a group of hal plugin +* +* ... +* +* +*/ + +typedef multimap sensor_plugins; +/* +* a sensor_plugins is a group of sensor plugin +* +* ... +* +* +*/ + +typedef vector fusion_plugins; +/* +* a fusion_plugins is a group of fusion plugin +* +* ... +* +* +*/ + +class sensor_plugin_loader +{ +private: + sensor_plugin_loader(); + + void *load_module(const char *path); + bool insert_module(const char *node_name, const char *path); + void show_sensor_info(void); + + sensor_hal_plugins m_sensor_hals; + sensor_plugins m_sensors; + fusion_plugins m_fusions; + +public: + static sensor_plugin_loader &get_instance() { + static sensor_plugin_loader inst; + return inst; + } + bool load_plugins(const string &plugins_path = PLUGINS_FILE_PATH); + + sensor_hal *get_sensor_hal(sensor_type_t type); + vector get_sensor_hals(sensor_type_t type); + + sensor_base *get_sensor(sensor_type_t type); + vector get_sensors(sensor_type_t type); + + vector get_virtual_sensors(void); + + sensor_fusion *get_fusion(void); + vector get_fusions(void); + + bool destroy(); +}; +#endif /*_SENSOR_PLUGIN_LOADER_H_*/ diff --git a/src/shared/sensord-server.pc.in b/src/shared/sensord-server.pc.in new file mode 100755 index 0000000..d03b10f --- /dev/null +++ b/src/shared/sensord-server.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@/sf_common + +Name: libsensord-server +Description: Commonly used code and defintions for sensord and sensord-proprietary +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lsensord-server +Cflags: -I${includedir} diff --git a/src/shared/sf_common.h b/src/shared/sf_common.h new file mode 100755 index 0000000..caa7260 --- /dev/null +++ b/src/shared/sf_common.h @@ -0,0 +1,162 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _SF_COMMON_H_ +#define _SF_COMMON_H_ + +#include +#include +#include +#include + +#define COMMAND_CHANNEL_PATH "/tmp/sf_command_socket" +#define EVENT_CHANNEL_PATH "/tmp/sf_event_socket" + +#define MAX_VALUE_SIZE 12 +#define MAX_HANDLE 64 +#define MAX_HANDLE_REACHED -2 +#define CLIENT_ID_INVALID -1 + +enum packet_type_t { + CMD_NONE = 0, + CMD_GET_ID, + CMD_HELLO, + CMD_BYEBYE, + CMD_WAIT_EVENT, + CMD_DONE, + CMD_START, + CMD_STOP, + CMD_REG, + CMD_UNREG, + CMD_CHECK_EVENT, + CMD_SET_OPTION, + CMD_SET_INTERVAL, + CMD_UNSET_INTERVAL, + CMD_SET_COMMAND, + CMD_GET_PROPERTIES, + CMD_GET_DATA, + CMD_SEND_SENSORHUB_DATA, + CMD_CNT, +}; + +typedef struct { + pid_t pid; +} cmd_get_id_t; + +typedef struct { + int client_id; + int sensor; +} cmd_hello_t; + +typedef struct { +} cmd_byebye_t; + +typedef struct { + unsigned int type; +} cmd_get_data_t; + +typedef struct { + unsigned int type; +} cmd_get_properties_t; + +typedef struct { + long value; +} cmd_done_t; + +typedef struct { + int client_id; +} cmd_get_id_done_t; + +typedef struct { + int state; + sensor_properties_t properties; +} cmd_properties_done_t; + +typedef struct { + int state; + sensor_data_t base_data; +} cmd_get_data_done_t; + +typedef struct { +} cmd_start_t; + +typedef struct { +} cmd_stop_t; + +typedef struct { + unsigned int event_type; +} cmd_reg_t; + +typedef struct { + unsigned int event_type; +} cmd_unreg_t; + +typedef struct { + unsigned int event_type; +} cmd_check_event_t; + +typedef struct { + unsigned int interval; +} cmd_set_interval_t; + +typedef struct { +} cmd_unset_interval_t; + +typedef struct { + int option; +} cmd_set_option_t; + +typedef struct { + unsigned int cmd; + long value; +} cmd_set_command_t; + +typedef struct { + int data_len; + char data[0]; +} cmd_send_sensorhub_data_t; + +#define EVENT_CHANNEL_MAGIC 0xCAFECAFE + +typedef struct { + unsigned int magic; + int client_id; +} event_channel_ready_t; + +typedef void *(*cmd_func_t)(void *data, void *cb_data); + +typedef std::vector event_type_vector; + +enum sensorhub_enable_bit { + SENSORHUB_ACCELEROMETER_ENABLE_BIT = 0, + SENSORHUB_GYROSCOPE_ENABLE_BIT, + SENSORHUB_GEOMAGNETIC_UNCALIB_ENABLE_BIT, + SENSORHUB_GEOMAGNETIC_RAW_ENABLE_BIT, + SENSORHUB_GEOMAGNETIC_ENABLE_BIT, + SENSORHUB_GESTURE_ENABLE_BIT, + SENSORHUB_PROXIMITY_ENABLE_BIT, + SENSORHUB_LIGHT_ENABLE_BIT, + SENSORHUB_PROXIMITY_RAW_ENABLE_BIT, + SENSORHUB_ORIENTATION_ENABLE_BIT, + SENSORHUB_GYRO_UNCALIB_ENABLE_BIT, + SENSORHUB_GAME_ROTATION_VECTOR_ENABLE_BIT = 15, + SENSORHUB_ENABLE_BIT_MAX, +}; + +#endif /*_SF_COMMON_H_*/ diff --git a/src/shared/sf_common.pc.in b/src/shared/sf_common.pc.in new file mode 100755 index 0000000..3c6eddc --- /dev/null +++ b/src/shared/sf_common.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@/sf_common + +Name: libsf_common +Description: Commonly used code and defintions for the sensor framework. +Version: @VERSION@ +Requires: +Libs: -L${libdir} -lsensord-share +Cflags: -I${includedir} diff --git a/src/shared/virtual_sensor.cpp b/src/shared/virtual_sensor.cpp new file mode 100755 index 0000000..c205fac --- /dev/null +++ b/src/shared/virtual_sensor.cpp @@ -0,0 +1,44 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +virtual_sensor::virtual_sensor() +{ +} + +virtual_sensor::~virtual_sensor() +{ +} + +bool virtual_sensor::is_virtual(void) +{ + return true; +} + +bool virtual_sensor::activate(void) +{ + return csensor_event_dispatcher::get_instance().add_active_virtual_sensor(this); +} + +bool virtual_sensor::deactivate(void) +{ + return csensor_event_dispatcher::get_instance().delete_active_virtual_sensor(this); +} diff --git a/src/shared/virtual_sensor.h b/src/shared/virtual_sensor.h new file mode 100755 index 0000000..2fd1bf2 --- /dev/null +++ b/src/shared/virtual_sensor.h @@ -0,0 +1,39 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _VIRTUAL_SENSOR_H_ +#define _VIRTUAL_SENSOR_H_ + +#include + +class virtual_sensor : public sensor_base +{ +public: + virtual_sensor(); + virtual ~virtual_sensor(); + + virtual void synthesize(const sensor_event_t &event, vector &outs) = 0; + bool is_virtual(void); + +protected: + bool activate(void); + bool deactivate(void); +}; + +#endif /*_VIRTUAL_SENSOR_H_*/ diff --git a/src/shared/worker_thread.cpp b/src/shared/worker_thread.cpp new file mode 100755 index 0000000..2982cf6 --- /dev/null +++ b/src/shared/worker_thread.cpp @@ -0,0 +1,224 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +using std::thread; + +worker_thread::worker_thread() +: m_state(WORKER_STATE_INITIAL) +, m_context(NULL) +, m_thread_created(false) +{ + for (int i = 0; i < TRANS_FUNC_CNT; ++i) + m_trans_func[i] = NULL; +} + +worker_thread::~worker_thread() +{ + stop(); +} + +bool worker_thread::transition_function(trans_func_index index) +{ + if (m_trans_func[index] != NULL) { + if (!m_trans_func[index](m_context)) { + _T("Transition[%d] function returning false", index); + return false; + } + } + + return true; +} + +worker_thread::worker_state_t worker_thread::get_state(void) +{ + lock l(m_mutex); + return m_state; +} + +bool worker_thread::start(void) +{ + lock l(m_mutex); + + if (m_state == WORKER_STATE_WORKING) { + _T("Worker thread is already working"); + return true; + } + + if ((m_state == WORKER_STATE_INITIAL) || (m_state == WORKER_STATE_STOPPED)) { + m_state = WORKER_STATE_WORKING; + + if (!m_thread_created) { + thread th(&worker_thread::main, this); + th.detach(); + } + + return true; + } else if (m_state == WORKER_STATE_PAUSED) { + m_state = WORKER_STATE_WORKING; + m_cond_working.notify_one(); + return true; + } + + _T("Failed to start, because current state(%d) is not for START", m_state); + return false; +} + +bool worker_thread::stop(void) +{ + lock l(m_mutex); + + if (m_state == WORKER_STATE_STOPPED) { + _T("Worker thread is already stopped"); + return true; + } + + if ((m_state == WORKER_STATE_WORKING) || (m_state == WORKER_STATE_PAUSED)) { + if (m_state == WORKER_STATE_PAUSED) + m_cond_working.notify_one(); + + m_state = WORKER_STATE_STOPPED; + return true; + } + + _T("Failed to stop, because current state(%d) is not for STOP", m_state); + return false; +} + +bool worker_thread::pause(void) +{ + lock l(m_mutex); + + if (m_state == WORKER_STATE_PAUSED) { + _T("Worker thread is already paused"); + return true; + } + + if (m_state == WORKER_STATE_WORKING) { + m_state = WORKER_STATE_PAUSED; + return true; + } + + _T("Failed to pause, because current state(%d) is not for PAUSE", m_state); + return false; +} + +bool worker_thread::resume(void) +{ + lock l(m_mutex); + + if (m_state == WORKER_STATE_WORKING) { + _T("Worker thread is already working"); + return true; + } + + if (m_state == WORKER_STATE_PAUSED) { + m_state = WORKER_STATE_WORKING; + m_cond_working.notify_one(); + return true; + } + + _T("Failed to resume, because current state(%d) is not for RESUME", m_state); + return false; +} + + +/* + * After state changed to STOPPED, it should not access member fields, + * because some transition funciton of STOPPED delete this pointer + */ + +void worker_thread::main(void) +{ + _T("Worker thread(0x%x) is created", std::this_thread::get_id()); + transition_function(STARTED); + + while (true) { + worker_state_t state; + state = get_state(); + + if (state == WORKER_STATE_WORKING) { + if (!transition_function(WORKING)) { + m_state = WORKER_STATE_STOPPED; + _T("Worker thread(0x%x) exits from working state", std::this_thread::get_id()); + m_thread_created = false; + transition_function(STOPPED); + break; + } + + continue; + } + + ulock u(m_mutex); + + if (m_state == WORKER_STATE_PAUSED) { + transition_function(PAUSED); + _T("Worker thread(0x%x) is paused", std::this_thread::get_id()); + m_cond_working.wait(u); + + if (m_state == WORKER_STATE_WORKING) { + transition_function(RESUMED); + _T("Worker thread(0x%x) is resumed", std::this_thread::get_id()); + } else if (m_state == WORKER_STATE_STOPPED) { + m_thread_created = false; + transition_function(STOPPED); + break; + } + } else if (m_state == WORKER_STATE_STOPPED) { + m_thread_created = false; + transition_function(STOPPED); + break; + } + } + + _T("Worker thread(0x%x)'s main is terminated", std::this_thread::get_id()); +} + +void worker_thread::set_started(trans_func_t func) +{ + m_trans_func[STARTED] = func; +} + +void worker_thread::set_stopped(trans_func_t func) +{ + m_trans_func[STOPPED] = func; +} + +void worker_thread::set_paused(trans_func_t func) +{ + m_trans_func[PAUSED] = func; +} + +void worker_thread::set_resumed(trans_func_t func) +{ + m_trans_func[RESUMED] = func; +} + +void worker_thread::set_working(trans_func_t func) +{ + m_trans_func[WORKING] = func; +} + +void worker_thread::set_context(void *ctx) +{ + m_context = ctx; +} diff --git a/src/shared/worker_thread.h b/src/shared/worker_thread.h new file mode 100755 index 0000000..63f2082 --- /dev/null +++ b/src/shared/worker_thread.h @@ -0,0 +1,85 @@ +/* + * libsensord-share + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef _WORKER_THREAD_H_ +#define _WORKER_THREAD_H_ + +#include +#include + +using std::mutex; +using std::lock_guard; +using std::unique_lock; +using std::condition_variable; + +class worker_thread +{ +public: + enum worker_state_t { + WORKER_STATE_INITIAL, + WORKER_STATE_WORKING, + WORKER_STATE_PAUSED, + WORKER_STATE_STOPPED, + }; + + typedef bool(*trans_func_t)(void *data); +private: + enum trans_func_index { + STARTED = 0, + STOPPED, + PAUSED, + RESUMED, + WORKING, + TRANS_FUNC_CNT, + }; + + typedef lock_guard lock; + typedef unique_lock ulock; + + worker_state_t m_state; + void *m_context; + mutex m_mutex; + condition_variable m_cond_working; + bool m_thread_created; + + trans_func_t m_trans_func[TRANS_FUNC_CNT]; + + bool transition_function(trans_func_index index); + void main(void); +public: + worker_thread(); + virtual ~worker_thread(); + + bool start(void); + bool stop(void); + bool pause(void); + bool resume(void); + + worker_state_t get_state(void); + + void set_started(trans_func_t func); + void set_stopped(trans_func_t func); + void set_paused(trans_func_t func); + void set_resumed(trans_func_t func); + void set_working(trans_func_t func); + + void set_context(void *ctx); +}; + +#endif /*_WORKER_THREAD_H_*/ -- 2.7.4 From 844e9adaba356988ae63928a8f04fc8fa669dc5d Mon Sep 17 00:00:00 2001 From: Amit Dharmapurikar Date: Thu, 24 Apr 2014 17:35:07 +0530 Subject: [PATCH 03/13] Added command to install sensor_motion.h required by sensor.h sensor.h includes sensor_motion.h file which needs to be installed in /usr/include/sensor/ directory. Signed-off-by: Amit Dharmapurikar Change-Id: I89fe7188df7720fe50b1bbafdf3b1e7b8ec7e1d0 --- src/libsensord/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsensord/CMakeLists.txt b/src/libsensord/CMakeLists.txt index 505303e..a9534c9 100755 --- a/src/libsensord/CMakeLists.txt +++ b/src/libsensord/CMakeLists.txt @@ -66,4 +66,5 @@ install(FILES sensor_gravity.h DESTINATION include/sensor/) install(FILES sensor_linear_accel.h DESTINATION include/sensor/) install(FILES sensor_orientation.h DESTINATION include/sensor/) install(FILES sensor_context.h DESTINATION include/sensor/) +install(FILES sensor_motion.h DESTINATION include/sensor/) install(FILES ${PROJECT_NAME}.pc DESTINATION lib/pkgconfig) -- 2.7.4 From d4eeef474f0cf716eb44d9bbd02cd95734347bcc Mon Sep 17 00:00:00 2001 From: "kibak.yoon" Date: Fri, 25 Apr 2014 16:52:50 +0900 Subject: [PATCH 04/13] sensord: substitute %{_libdir}/systemd/system/ for %{_unitdir} Signed-off-by: kibak.yoon Change-Id: Ia264fdf3fc6fa8c129503df87c815a01ca7067f4 --- packaging/sensord.spec | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packaging/sensord.spec b/packaging/sensord.spec index f5fb9fa..3c657d9 100755 --- a/packaging/sensord.spec +++ b/packaging/sensord.spec @@ -72,12 +72,12 @@ rm -rf %{buildroot} %make_install mkdir -p %{buildroot}/usr/share/license -mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants -mkdir -p %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants -install -m 0644 %SOURCE1 %{buildroot}%{_libdir}/systemd/system/ -install -m 0644 %SOURCE2 %{buildroot}%{_libdir}/systemd/system/ -ln -s ../sensord.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/sensord.socket -ln -s ../sensord.service %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants/sensord.service +mkdir -p %{buildroot}%{_unitdir}/sockets.target.wants +mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants +install -m 0644 %SOURCE1 %{buildroot}%{_unitdir} +install -m 0644 %SOURCE2 %{buildroot}%{_unitdir} +ln -s ../sensord.socket %{buildroot}%{_unitdir}/sockets.target.wants/sensord.socket +ln -s ../sensord.service %{buildroot}%{_unitdir}/multi-user.target.wants/sensord.service %post -p /sbin/ldconfig systemctl daemon-reload @@ -90,10 +90,10 @@ systemctl daemon-reload %{_bindir}/sensord %attr(0644,root,root)/usr/etc/sensor_plugins.xml %attr(0644,root,root)/usr/etc/sensors.xml -%{_libdir}/systemd/system/sensord.service -%{_libdir}/systemd/system/sensord.socket -%{_libdir}/systemd/system/multi-user.target.wants/sensord.service -%{_libdir}/systemd/system/sockets.target.wants/sensord.socket +%{_unitdir}/sensord.service +%{_unitdir}/sensord.socket +%{_unitdir}/multi-user.target.wants/sensord.service +%{_unitdir}/sockets.target.wants/sensord.socket %license LICENSE.APLv2 %{_datadir}/license/sensord -- 2.7.4 From 1fa3736729e5c53b84553c0f3163c711bc816595 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Fri, 25 Apr 2014 14:53:39 +0530 Subject: [PATCH 05/13] Moving sensor fusion octave code to sensord - Moving octave sensor fusion design related directory from sensor-framework.git to sensord.git. - Renamed all files and folders to lower case. - removed carriage return \r from all files signed-off-by: Ramasamy Change-Id: Ib5421200ca5bf0d8cb64fdbb40faae0e474455b8 --- .../design/data/100ms/pitch/accel.txt | 671 ++++++++++++ src/sensor_fusion/design/data/100ms/pitch/gyro.txt | 672 ++++++++++++ .../design/data/100ms/pitch/magnetic.txt | 673 ++++++++++++ src/sensor_fusion/design/data/100ms/roll/accel.txt | 840 +++++++++++++++ src/sensor_fusion/design/data/100ms/roll/gyro.txt | 840 +++++++++++++++ .../design/data/100ms/roll/magnetic.txt | 842 +++++++++++++++ .../design/data/100ms/roll_pitch_yaw/accel.txt | 1095 +++++++++++++++++++ .../design/data/100ms/roll_pitch_yaw/gyro.txt | 1095 +++++++++++++++++++ .../design/data/100ms/roll_pitch_yaw/magnetic.txt | 1096 ++++++++++++++++++++ src/sensor_fusion/design/data/100ms/yaw/accel.txt | 664 ++++++++++++ src/sensor_fusion/design/data/100ms/yaw/gyro.txt | 664 ++++++++++++ .../design/data/100ms/yaw/magnetic.txt | 664 ++++++++++++ src/sensor_fusion/design/lib/quat2euler.m | 32 + src/sensor_fusion/design/lib/quat2rot_mat.m | 30 + src/sensor_fusion/design/lib/quat_prod.m | 25 + src/sensor_fusion/design/lib/rot_mat2quat.m | 44 + src/sensor_fusion/design/sf_orien.m | 491 +++++++++ 17 files changed, 10438 insertions(+) create mode 100755 src/sensor_fusion/design/data/100ms/pitch/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/pitch/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/pitch/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/roll/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/roll/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/roll/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/roll_pitch_yaw/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/roll_pitch_yaw/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/roll_pitch_yaw/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/yaw/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/yaw/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/yaw/magnetic.txt create mode 100755 src/sensor_fusion/design/lib/quat2euler.m create mode 100755 src/sensor_fusion/design/lib/quat2rot_mat.m create mode 100755 src/sensor_fusion/design/lib/quat_prod.m create mode 100755 src/sensor_fusion/design/lib/rot_mat2quat.m create mode 100755 src/sensor_fusion/design/sf_orien.m diff --git a/src/sensor_fusion/design/data/100ms/pitch/accel.txt b/src/sensor_fusion/design/data/100ms/pitch/accel.txt new file mode 100755 index 0000000..c6b5cb9 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/pitch/accel.txt @@ -0,0 +1,671 @@ +0.007178 0.178265 10.127622 451630336.000000 +0.016750 0.196211 10.155140 451730528.000000 +0.007178 0.197408 10.128819 451830528.000000 +0.013161 0.205783 10.173084 451930368.000000 +0.043071 0.210568 10.180264 452030528.000000 +0.062213 0.223729 10.005588 452130400.000000 +0.010768 0.220140 10.171888 452230464.000000 +-0.003589 0.208176 10.173084 452330464.000000 +0.023928 0.180658 10.131211 452430624.000000 +0.014357 0.208176 10.179067 452530496.000000 +0.008375 0.216550 10.143176 452630496.000000 +0.063410 0.229711 9.850054 452730592.000000 +-0.221336 0.211765 10.161121 452830624.000000 +0.248854 0.210568 9.456435 452930592.000000 +-0.129212 0.192622 10.177871 453030592.000000 +-0.021535 0.222532 10.048658 453130432.000000 +-0.005982 0.228515 10.168301 453230528.000000 +0.021535 0.177069 10.200603 453330496.000000 +0.001196 0.183051 10.205389 453430464.000000 +-0.014357 0.202193 10.206585 453530432.000000 +-0.010768 0.196211 10.173084 453630496.000000 +-0.037089 0.238086 10.162319 453730496.000000 +-0.052642 0.195015 10.177871 453830400.000000 +-0.001196 0.208176 10.168301 453930528.000000 +-0.037089 0.206979 10.156336 454030592.000000 +-0.040678 0.210568 10.152746 454130656.000000 +-0.028714 0.216550 10.194620 454230592.000000 +-0.044267 0.221336 10.159925 454330464.000000 +-0.059821 0.206979 10.211370 454430400.000000 +-0.037089 0.183051 10.191031 454530528.000000 +-0.035892 0.199801 10.180264 454630688.000000 +-0.008375 0.198604 10.222138 454730368.000000 +-0.022732 0.230907 10.159925 454830560.000000 +-0.015553 0.227318 10.186246 454930336.000000 +-0.032303 0.214158 10.171888 455030432.000000 +-0.047856 0.220140 10.195816 455130560.000000 +-0.162712 0.200997 10.430314 455230400.000000 +-0.056231 0.206979 10.200603 455330496.000000 +-0.063410 0.204586 10.183852 455430496.000000 +-0.057428 0.205783 10.223334 455530464.000000 +-0.077767 0.203390 10.199407 455630528.000000 +-0.040678 0.199801 10.157533 455732288.000000 +-0.118445 0.205783 10.143176 455831552.000000 +-0.050249 0.202193 10.158729 455933216.000000 +-0.045464 0.205783 10.145569 456031008.000000 +-0.040678 0.217747 10.157533 456130464.000000 +-0.037089 0.197408 10.228121 456230656.000000 +-0.040678 0.210568 10.206585 456330432.000000 +-0.055035 0.210568 10.177871 456430400.000000 +-0.040678 0.190229 10.177871 456530528.000000 +-0.045464 0.209372 10.189835 456630496.000000 +-0.049053 0.185444 10.255639 456730560.000000 +-0.029910 0.215354 10.223334 456830528.000000 +-0.014357 0.203390 10.194620 456930656.000000 +-0.035892 0.199801 10.211370 457030592.000000 +-0.049053 0.205783 10.155140 457130528.000000 +-0.047856 0.202193 10.243673 457234528.000000 +-0.043071 0.234497 10.176675 457330400.000000 +-0.044267 0.218943 10.213763 457430464.000000 +-0.071785 0.208176 10.214959 457530432.000000 +-0.129212 0.209372 10.153944 457630368.000000 +-0.167498 0.190229 10.163515 457730400.000000 +-0.312263 0.215354 10.164711 457830400.000000 +-0.417548 0.204586 10.134801 457930336.000000 +-0.295514 0.206979 10.171888 458030336.000000 +-0.317049 0.223729 10.176675 458130368.000000 +-0.337388 0.203390 10.213763 458230464.000000 +-0.319442 0.223729 10.195816 458330496.000000 +-0.309871 0.224925 10.183852 458430528.000000 +-0.285942 0.220140 10.170692 458530560.000000 +-0.318245 0.191426 10.191031 458630464.000000 +-0.151944 0.259621 10.219746 458730496.000000 +-0.580260 0.289532 10.150353 458830496.000000 +-0.467797 0.199801 10.168301 458930528.000000 +-0.476172 0.089731 10.246067 459030624.000000 +-1.087538 0.156730 10.226924 459130496.000000 +-1.720440 0.045464 10.188639 459230496.000000 +-3.052045 0.031107 9.704092 459330400.000000 +-4.717450 -0.043071 8.742178 459430560.000000 +-5.868398 -0.253639 8.449057 459530624.000000 +-6.966703 0.470190 7.647461 459630368.000000 +-7.871190 0.235693 5.802595 459730432.000000 +-9.527023 0.118445 3.693322 459830368.000000 +-9.221939 0.221336 3.815356 459930336.000000 +-10.169496 -0.003589 -0.813560 460030368.000000 +-9.064013 0.269193 -3.354738 460130368.000000 +-9.375079 0.508475 -3.477968 460230368.000000 +-5.471189 -0.122034 -6.757331 460330336.000000 +-4.788038 0.033500 -8.306684 460430400.000000 +-4.076173 -0.033500 -8.766105 460530432.000000 +-3.410969 -0.285942 -9.625129 460630400.000000 +-0.494118 -0.448654 -9.288938 460730400.000000 +-2.587838 0.400798 -9.416953 460830336.000000 +-1.015753 0.015553 -8.715857 460930784.000000 +-1.068395 -0.357727 -9.430114 461030400.000000 +-0.271585 0.122034 -9.288938 461130592.000000 +-0.302692 -0.173480 -9.381061 461230368.000000 +-0.382852 -0.186640 -9.677772 461330432.000000 +0.447458 -0.208176 -9.582059 461430816.000000 +0.293121 0.447458 -10.328619 461530464.000000 +2.014757 -0.320638 -10.899307 461630496.000000 +2.815156 0.480957 -8.903693 461730528.000000 +5.720042 -0.132802 -6.196214 461830528.000000 +7.356733 -0.020339 -3.546163 461930496.000000 +9.084351 0.069392 -3.223132 462030624.000000 +9.561719 0.071785 -1.398605 462130432.000000 +9.693325 0.106481 0.329013 462230336.000000 +9.477970 0.119641 1.421337 462330368.000000 +8.524430 -0.081356 3.509074 462430400.000000 +4.892126 0.166301 8.878569 462530368.000000 +1.146162 -0.167498 7.907083 462630368.000000 +0.485743 0.723829 1.707279 462730560.000000 +0.002393 0.290728 1.862812 462830368.000000 +0.411566 0.205783 9.049655 462930496.000000 +-0.287139 0.325424 12.192628 463030560.000000 +0.717847 0.125623 9.159724 463130400.000000 +0.831506 0.118445 10.147961 463230464.000000 +0.214158 0.307478 10.250853 463330368.000000 +0.646062 0.734596 10.265208 463430432.000000 +-0.317049 0.065803 10.197014 463530624.000000 +0.162712 0.184247 10.207782 463630528.000000 +-0.029910 0.098106 10.205389 463730528.000000 +0.014357 0.162712 10.229317 463830528.000000 +0.001196 0.228515 10.217353 463930560.000000 +0.016750 0.222532 10.194620 464030464.000000 +0.013161 0.212961 10.189835 464130528.000000 +0.027517 0.217747 10.200603 464230400.000000 +-0.001196 0.199801 10.174281 464330496.000000 +0.016750 0.215354 10.201799 464430368.000000 +-0.003589 0.218943 10.183852 464530624.000000 +-0.004786 0.216550 10.201799 464630368.000000 +-0.015553 0.233300 10.168301 464730528.000000 +-0.025125 0.193819 10.214959 464830528.000000 +0.015553 0.229711 10.258030 464930496.000000 +-0.015553 0.198604 10.246067 465030624.000000 +-0.001196 0.203390 10.217353 465130496.000000 +0.011964 0.209372 10.210175 465230496.000000 +-0.104088 0.203390 10.688738 465330464.000000 +0.035892 0.220140 10.182656 465430496.000000 +-0.022732 0.223729 10.219746 465530400.000000 +0.002393 0.224925 10.195816 465630400.000000 +-0.002393 0.206979 10.223334 465730432.000000 +0.003589 0.205783 10.205389 465830368.000000 +0.009571 0.206979 10.216157 465930400.000000 +-0.009571 0.212961 10.158729 466030432.000000 +-0.191426 0.181855 10.887343 466130368.000000 +-0.009571 0.221336 10.199407 466230400.000000 +-0.008375 0.171087 10.177871 466330368.000000 +0.005982 0.206979 10.193424 466430432.000000 +0.005982 0.215354 10.192227 466530688.000000 +0.028714 0.216550 10.167104 466630592.000000 +-0.010768 0.222532 10.220942 466731904.000000 +0.022732 0.187837 10.224532 466830752.000000 +-0.019143 0.217747 10.236496 466930464.000000 +-0.071785 0.216550 10.194620 467030496.000000 +-0.122034 0.210568 10.189835 467130496.000000 +-0.061017 0.227318 10.158729 467230496.000000 +-0.159123 0.221336 10.064213 467331680.000000 +-0.561117 0.229711 9.968499 467430592.000000 +-1.146162 -0.479761 10.456635 467531200.000000 +-3.384648 -0.355334 10.413565 467630400.000000 +-4.758128 0.092124 9.249455 467730496.000000 +-7.435696 0.069392 6.502496 467830496.000000 +-9.347562 0.032303 3.840480 467931200.000000 +-8.685946 0.196211 4.989035 468031520.000000 +-9.603594 -0.019143 -0.329013 468130368.000000 +-8.499306 0.580260 -4.051049 468230336.000000 +-6.498906 0.196211 -7.299305 468330400.000000 +-4.298706 0.360120 -9.523434 468433024.000000 +-1.002593 -0.527617 -9.785448 468531136.000000 +-2.002793 0.216550 -9.000603 468630368.000000 +-2.136791 -0.169890 -7.482357 468730432.000000 +-0.022732 0.040678 -9.595219 468830400.000000 +1.578066 -0.239282 -9.373882 468930784.000000 +-0.588634 0.037089 -9.620343 469030368.000000 +0.507278 0.035892 -10.267602 469130432.000000 +0.865005 0.136391 -9.674182 469230400.000000 +2.287539 -0.167498 -9.415757 469330944.000000 +4.560720 2.484946 -9.846465 469430400.000000 +5.898308 -0.251246 -4.991428 469530400.000000 +8.534002 -0.116052 -2.538785 469630496.000000 +9.311669 0.062213 -1.680958 469730496.000000 +9.284152 -0.144766 0.401994 469830528.000000 +9.010174 0.419940 3.909872 469930880.000000 +4.587041 -0.716650 2.145165 470030432.000000 +4.737789 3.328416 9.590433 470130336.000000 +4.439882 0.393619 9.404989 470230368.000000 +2.991028 0.831506 8.804391 470330624.000000 +1.998007 0.588634 9.477970 470430688.000000 +1.801795 0.206979 7.554141 470530528.000000 +0.722632 0.110070 9.558130 470630496.000000 +0.399601 0.197408 10.231709 470730624.000000 +0.445065 0.235693 10.295119 470830496.000000 +0.003589 0.283549 9.781858 470930592.000000 +-0.203390 0.161516 10.850254 471030560.000000 +0.154337 0.181855 9.719646 471130432.000000 +0.050249 0.209372 9.957731 471230432.000000 +0.023928 0.208176 10.191031 471330464.000000 +-0.010768 0.224925 10.150353 471430464.000000 +-0.027517 0.205783 10.235298 471530496.000000 +0.014357 0.209372 10.230514 471630464.000000 +-0.259621 0.192622 10.692327 471730432.000000 +-0.027517 0.221336 10.202995 471830368.000000 +-0.040678 0.228515 10.206585 471930368.000000 +-0.094516 0.218943 10.296316 472030464.000000 +-0.123230 0.190229 10.211370 472130400.000000 +-0.114855 0.215354 10.183852 472230368.000000 +-0.092124 0.209372 10.241282 472330432.000000 +-0.092124 0.208176 10.230514 472430368.000000 +-0.081356 0.195015 10.224532 472530432.000000 +-0.092124 0.198604 10.223334 472630368.000000 +-0.100499 0.227318 10.218549 472730368.000000 +-0.080160 0.216550 10.262815 472830368.000000 +-0.063410 0.208176 10.266404 472930496.000000 +-0.095713 0.218943 10.232906 473030528.000000 +-0.104088 0.197408 10.211370 473130688.000000 +-0.072981 0.215354 10.204191 473230656.000000 +-0.044267 0.361316 10.161121 473330464.000000 +-0.041874 0.336192 10.212566 473430560.000000 +-1.028914 -0.056231 10.195816 473530496.000000 +-2.745764 -0.047856 10.175477 473630432.000000 +-5.813363 0.497707 9.270991 473730624.000000 +-8.378469 -0.015553 5.584848 473830528.000000 +-9.212367 0.082552 2.816352 473930432.000000 +-9.784252 0.136391 0.139980 474032256.000000 +-9.103494 0.934397 -2.213361 474131264.000000 +-6.787241 -1.210768 -7.428517 474231936.000000 +-4.155137 0.318245 -8.780463 474330400.000000 +-2.938386 0.022732 -9.516255 474430496.000000 +-1.385444 1.123430 -8.178668 474530560.000000 +-1.673779 -0.138784 -9.229117 474630592.000000 +-0.689133 -0.150748 -9.378669 474730496.000000 +-0.056231 0.045464 -9.028119 474830432.000000 +0.156730 -0.104088 -9.476774 474930496.000000 +0.320638 0.147159 -9.397811 475030496.000000 +0.355334 0.324227 -9.501899 475130528.000000 +0.862613 0.002393 -9.553344 475230528.000000 +-0.056231 0.143569 -9.793823 475330528.000000 +6.922436 -0.764507 -9.623933 475430528.000000 +2.362912 -0.467797 -9.330812 475530720.000000 +4.019942 0.715454 -8.379664 475630464.000000 +7.604390 -0.098106 -3.326023 475730528.000000 +8.611769 -0.020339 -2.548356 475830528.000000 +9.416953 -0.008375 -0.214158 475930592.000000 +9.208777 0.416351 1.989632 476030592.000000 +7.171289 -0.125623 1.663012 476130400.000000 +8.039884 1.745564 10.872985 476230368.000000 +3.667001 0.564706 10.663614 476330368.000000 +2.388037 0.114855 9.353544 476430368.000000 +1.741975 0.267996 9.381061 476530784.000000 +1.631905 0.131605 11.519048 476630464.000000 +0.722632 0.169890 10.089336 476731008.000000 +0.311067 0.211765 9.913465 476830720.000000 +0.123230 0.222532 9.993625 476930560.000000 +-0.096909 0.205783 10.567901 477030752.000000 +0.033500 0.217747 10.241282 477130560.000000 +0.008375 0.211765 10.266404 477230656.000000 +-0.136391 0.216550 10.320245 477330368.000000 +-0.010768 0.204586 10.189835 477430432.000000 +-0.045464 0.196211 10.199407 477530496.000000 +-0.010768 0.189033 10.246067 477630528.000000 +-0.081356 0.181855 10.271191 477730592.000000 +-0.038285 0.227318 10.199407 477830464.000000 +-0.041874 0.185444 10.216157 477930592.000000 +-0.031107 0.195015 10.236496 478030496.000000 +-0.020339 0.183051 10.262815 478130528.000000 +0.049053 0.284746 9.550952 478230720.000000 +-0.007178 0.227318 10.206585 478330464.000000 +-0.046660 0.228515 10.253245 478430592.000000 +-0.013161 0.216550 10.176675 478530688.000000 +-0.055035 0.205783 10.236496 478630496.000000 +-0.089731 0.217747 10.198210 478730432.000000 +-0.032303 0.224925 10.195816 478830912.000000 +-0.037089 0.221336 10.188639 478930528.000000 +-0.089731 0.212961 10.201799 479032928.000000 +-0.041874 0.212961 10.207782 479130528.000000 +-0.031107 0.204586 10.238889 479230528.000000 +0.005982 0.192622 10.191031 479330496.000000 +-0.011964 0.200997 10.213763 479430880.000000 +-0.055035 0.198604 10.225728 479530496.000000 +-0.007178 0.241675 10.252048 479630496.000000 +0.013161 0.208176 10.238889 479730624.000000 +-0.038285 0.214158 10.185050 479830528.000000 +-0.011964 0.205783 10.159925 479930464.000000 +-0.114855 0.210568 10.255639 480030560.000000 +-0.034696 0.191426 10.281959 480130784.000000 +-0.005982 0.181855 10.214959 480230464.000000 +-0.005982 0.217747 10.235298 480330784.000000 +0.011964 0.189033 10.130014 480430464.000000 +0.095713 0.215354 9.878768 480530816.000000 +0.309871 0.218943 10.023535 480630496.000000 +0.161516 0.214158 10.352547 480730880.000000 +0.616152 0.160319 10.247264 480830464.000000 +1.079163 0.031107 9.428917 480930784.000000 +1.905883 -0.241675 9.095119 481030464.000000 +4.545166 0.240479 10.593026 481130784.000000 +5.643472 0.226122 7.972885 481230464.000000 +6.128019 0.568295 7.734799 481330784.000000 +7.982457 0.357727 6.899704 481430464.000000 +8.251649 0.126820 5.450850 481531040.000000 +9.399008 -0.111266 2.397608 481630464.000000 +9.215956 0.574277 1.178465 481730560.000000 +5.120641 -0.976272 -6.786045 481830624.000000 +4.794020 0.443869 -9.330812 481930976.000000 +3.838088 0.307478 -7.231110 482030464.000000 +3.553342 0.177069 -8.319844 482130496.000000 +2.976671 0.972682 -6.527620 482230592.000000 +-2.224128 -0.162712 -19.601404 482330496.000000 +0.014357 -0.016750 -9.305687 482430784.000000 +-0.050249 0.014357 -9.364311 482530464.000000 +-0.049053 0.033500 -9.408579 482630528.000000 +-0.049053 0.031107 -9.430114 482730528.000000 +-0.038285 0.027517 -9.442079 482830560.000000 +-0.028714 0.031107 -9.439686 482930528.000000 +-0.027517 0.023928 -9.455239 483030720.000000 +-0.016750 0.019143 -9.438489 483130528.000000 +0.007178 0.071785 -9.458827 483230432.000000 +0.144766 -0.023928 -9.434900 483330592.000000 +-0.599402 0.132802 -9.570094 483430528.000000 +-0.649651 -0.210568 -8.750552 483530560.000000 +2.793620 -0.425922 -9.389436 483630528.000000 +0.049053 -0.258425 -9.390633 483730592.000000 +0.923629 -0.486939 -9.467202 483830528.000000 +-0.731007 0.461815 -9.393025 483930560.000000 +0.070588 0.200997 -9.446864 484030528.000000 +-1.707279 -0.029910 -9.415757 484130560.000000 +-0.312263 0.132802 -9.439686 484230496.000000 +0.967897 -0.573081 -9.541381 484330528.000000 +-0.290728 -0.107677 -9.422935 484430496.000000 +-1.707279 -0.151944 -9.247063 484530720.000000 +-2.630908 0.007178 -9.342775 484630528.000000 +-4.999803 -0.287139 -7.440482 484730592.000000 +-9.053245 0.659223 -3.099902 484830496.000000 +-9.664611 0.447458 -1.415355 484930528.000000 +-7.563712 -0.284746 4.612165 485030368.000000 +-6.731010 -0.302692 7.195218 485130528.000000 +-3.489932 -0.364905 9.287741 485230528.000000 +-1.182054 -0.928415 10.759327 485330496.000000 +0.058624 -0.246461 11.819347 485430848.000000 +1.210768 0.758525 7.477571 485530528.000000 +0.614955 0.260818 6.078966 485630816.000000 +0.751346 0.151944 8.134400 485730528.000000 +0.053839 0.202193 10.107283 485830496.000000 +0.090927 0.211765 10.218549 485930880.000000 +0.069392 0.196211 10.101300 486030464.000000 +0.049053 0.206979 10.224532 486130464.000000 +0.033500 0.193819 10.149158 486230432.000000 +0.011964 0.212961 10.216157 486330528.000000 +-0.044267 0.204586 10.174281 486430816.000000 +0.049053 0.214158 10.141978 486530528.000000 +0.035892 0.184247 10.174281 486630496.000000 +0.027517 0.217747 10.207782 486730592.000000 +-0.083749 0.197408 10.223334 486830848.000000 +-0.041874 0.203390 10.260423 486930560.000000 +-0.094516 0.234497 10.515260 487030592.000000 +0.032303 0.203390 10.109675 487130720.000000 +0.244068 0.168694 10.164711 487230592.000000 +0.367298 0.198604 10.271191 487330848.000000 +0.138784 0.397209 10.347760 487430496.000000 +1.179662 -0.754936 9.570094 487530944.000000 +0.540778 0.868595 11.084750 487630528.000000 +2.907279 -0.460618 10.698310 487730496.000000 +3.725625 0.254836 9.097511 487830560.000000 +5.621937 -0.325424 9.725628 487930880.000000 +6.460621 0.446261 8.203793 488030752.000000 +7.840084 0.196211 6.125626 488130496.000000 +8.746964 0.521635 4.956732 488230592.000000 +8.858230 0.227318 2.842674 488330976.000000 +6.327819 -0.276371 -4.819145 488430528.000000 +5.169693 0.605384 -5.665007 488530624.000000 +3.131008 0.080160 -9.342775 488630784.000000 +3.022135 0.766900 -9.504292 488730528.000000 +0.781257 0.343370 -1.844866 488830624.000000 +-0.137587 -0.238086 -9.006584 488930816.000000 +-0.037089 0.056231 -9.631111 489030656.000000 +-0.055035 0.040678 -9.376275 489130752.000000 +-0.041874 0.034696 -9.488738 489230752.000000 +-0.029910 0.017946 -9.410972 489330816.000000 +-0.186640 0.068195 -9.420543 489430560.000000 +-0.050249 0.057428 -9.452846 489530496.000000 +-0.330210 -0.046660 -9.501899 489630816.000000 +0.058624 0.017946 -9.442079 489730560.000000 +-0.827917 0.005982 -9.354740 489830496.000000 +-1.922633 0.096909 -9.521042 489930880.000000 +-5.190032 0.422333 -7.759924 490030528.000000 +-3.907479 -0.165105 -8.648857 490130816.000000 +-4.423133 -0.148355 -8.416754 490230752.000000 +-6.841080 0.260818 -6.802795 490330816.000000 +-8.132008 0.270389 -5.197211 490430528.000000 +-9.455239 0.235693 -1.493121 490530624.000000 +-8.194221 -0.589831 4.633701 490630912.000000 +-7.566105 -0.747757 7.718050 490730496.000000 +-3.911068 0.535992 9.408579 490830784.000000 +-2.914458 0.190229 9.650253 490930560.000000 +-7.228717 0.832702 19.601404 491030912.000000 +-1.173679 0.455833 13.068400 491130752.000000 +-0.539581 0.226122 11.148161 491230880.000000 +-0.528814 0.222532 11.217552 491330560.000000 +-0.368495 0.156730 11.273784 491430624.000000 +0.111266 0.227318 10.268798 491530816.000000 +0.218943 0.202193 9.156136 491630528.000000 +0.143569 0.200997 10.314261 491730624.000000 +0.058624 0.210568 10.287941 491830944.000000 +0.084945 0.206979 10.210175 491930784.000000 +0.065803 0.210568 10.195816 492030688.000000 +0.063410 0.217747 10.137194 492130496.000000 +0.062213 0.210568 10.247264 492230400.000000 +0.037089 0.217747 10.253245 492330528.000000 +0.041874 0.204586 10.260423 492430592.000000 +0.045464 0.221336 10.281959 492530400.000000 +0.040678 0.172283 10.199407 492630464.000000 +0.046660 0.212961 10.207782 492730560.000000 +0.032303 0.233300 10.192227 492830784.000000 +0.041874 0.202193 10.248460 492930368.000000 +0.039482 0.227318 10.185050 493030400.000000 +0.016750 0.186640 10.265208 493130528.000000 +0.038285 0.200997 10.194620 493230752.000000 +0.017946 0.239282 10.199407 493330432.000000 +0.016750 0.203390 10.223334 493430432.000000 +0.059821 0.222532 10.182656 493530624.000000 +0.055035 0.217747 10.188639 493630752.000000 +0.045464 0.198604 10.273583 493730528.000000 +0.043071 0.211765 10.241282 493830880.000000 +0.027517 0.206979 10.200603 493930752.000000 +-0.025125 0.221336 10.211370 494030464.000000 +-0.001196 0.211765 10.217353 494130720.000000 +-0.302692 0.209372 10.581062 494230528.000000 +0.928415 0.224925 9.968499 494330784.000000 +1.792224 0.144766 12.059827 494430528.000000 +2.766103 0.483350 9.466006 494530784.000000 +3.766303 0.013161 7.747960 494630752.000000 +4.072584 0.887737 9.254241 494730880.000000 +5.142176 0.381655 8.602197 494830560.000000 +5.737988 -0.283549 7.873583 494930464.000000 +7.292127 0.403191 6.490531 495031104.000000 +8.963513 0.272782 4.131208 495130720.000000 +9.821341 -1.342373 -2.282753 495230560.000000 +7.001399 -0.196211 -7.282556 495330656.000000 +4.613362 0.191426 -8.074579 495430560.000000 +4.345366 -0.136391 -8.703892 495530688.000000 +2.873780 -0.019143 -8.084151 495630560.000000 +1.972882 1.147358 -2.313859 495730688.000000 +0.392423 -0.485743 -9.479167 495830560.000000 +-0.049053 -0.020339 -9.408579 495930688.000000 +-0.010768 0.037089 -9.457631 496030592.000000 +-0.026321 0.016750 -9.379865 496130656.000000 +-0.022732 0.019143 -9.439686 496230560.000000 +1.867598 0.082552 -9.475577 496330496.000000 +0.090927 0.019143 -9.611969 496430528.000000 +-0.591027 0.116052 -9.509077 496530752.000000 +-1.789831 -0.446261 -9.521042 496630880.000000 +-4.310670 0.236889 -8.974281 496730720.000000 +-5.497510 -0.120838 -7.750352 496830560.000000 +-6.203393 -0.063410 -7.215556 496930496.000000 +-7.972885 0.077767 -5.420939 497030560.000000 +-8.268399 -0.171087 -4.814359 497130464.000000 +-10.699506 -0.440279 -1.794617 497230912.000000 +-8.745767 -0.133998 3.245864 497330496.000000 +-7.111469 0.500100 7.320841 497430848.000000 +-4.959125 0.045464 8.714661 497530528.000000 +-4.473382 1.783849 6.927221 497630624.000000 +-2.752943 -0.052642 9.939785 497730944.000000 +-0.271585 0.409173 11.071590 497830496.000000 +-0.573081 0.192622 10.902896 497930624.000000 +-1.822134 0.382852 11.331212 498031296.000000 +1.392623 0.111266 9.643075 498130528.000000 +0.033500 0.197408 10.177871 498230528.000000 +0.009571 0.209372 10.211370 498330880.000000 +-0.013161 0.204586 10.225728 498430752.000000 +-0.050249 0.208176 10.204191 498530944.000000 +-0.010768 0.236889 10.185050 498630432.000000 +-0.049053 0.224925 10.161121 498730528.000000 +-0.017946 0.216550 10.180264 498831104.000000 +-0.173480 0.190229 10.849058 498930432.000000 +-0.077767 0.244068 10.180264 499031744.000000 +-0.050249 0.223729 10.228121 499130560.000000 +-0.055035 0.198604 10.212566 499230560.000000 +-0.070588 0.202193 10.176675 499330400.000000 +-0.004786 0.193819 10.220942 499430528.000000 +-0.033500 0.212961 10.231709 499530656.000000 +-0.057428 0.190229 10.198210 499630368.000000 +-0.021535 0.208176 10.224532 499730400.000000 +-0.041874 0.208176 10.202995 499830528.000000 +-0.052642 0.232104 10.202995 499930752.000000 +-0.027517 0.205783 10.080962 500030432.000000 +-0.025125 0.228515 10.212566 500130496.000000 +-0.031107 0.210568 10.214959 500230528.000000 +-0.075374 0.215354 10.198210 500330912.000000 +0.110070 0.217747 10.128819 500430400.000000 +0.008375 0.210568 10.220942 500530720.000000 +0.008375 0.198604 10.173084 500630592.000000 +-0.088534 0.214158 10.350154 500730752.000000 +0.004786 0.189033 9.973285 500830880.000000 +-0.044267 0.202193 10.193424 500930752.000000 +-0.045464 0.209372 10.224532 501030592.000000 +-0.019143 0.196211 10.231709 501130912.000000 +-0.040678 0.202193 10.223334 501230496.000000 +-0.035892 0.191426 10.252048 501330624.000000 +-0.034696 0.198604 10.185050 501431008.000000 +-0.023928 0.206979 10.163515 501530496.000000 +-0.031107 0.190229 10.169496 501630880.000000 +-0.049053 0.184247 10.183852 501730496.000000 +-0.009571 0.200997 10.181459 501830752.000000 +-0.046660 0.216550 10.224532 501930624.000000 +-0.020339 0.230907 10.194620 502030816.000000 +-0.029910 0.196211 10.214959 502130752.000000 +-0.034696 0.214158 10.177871 502230624.000000 +-0.113659 0.197408 10.411172 502330400.000000 +-0.029910 0.205783 10.189835 502430368.000000 +0.003589 0.214158 10.152746 502530752.000000 +-0.003589 0.184247 10.230514 502631040.000000 +-0.017946 0.202193 10.237692 502730720.000000 +-0.008375 0.212961 10.030712 502830400.000000 +-0.034696 0.200997 10.206585 502930752.000000 +0.199801 0.187837 9.385847 503030400.000000 +-0.080160 0.217747 10.482956 503130400.000000 +-0.331406 0.203390 10.838290 503230400.000000 +0.186640 0.216550 9.583255 503330400.000000 +-0.253639 0.193819 10.807183 503430752.000000 +-0.059821 0.234497 10.474581 503530400.000000 +-0.124427 0.196211 10.494920 503631040.000000 +0.309871 0.214158 9.073583 503730400.000000 +-0.348156 0.220140 10.989038 503830752.000000 +-0.179462 0.200997 11.391031 503930528.000000 +0.373280 0.198604 8.791230 504030912.000000 +-0.090927 0.216550 10.914860 504130592.000000 +-0.166301 0.193819 10.826326 504230624.000000 +0.023928 0.250050 10.095319 504330496.000000 +0.111266 0.211765 9.619147 504430848.000000 +0.064606 0.208176 9.992428 504530496.000000 +-0.003589 0.205783 10.181459 504630656.000000 +-0.033500 0.218943 10.237692 504730912.000000 +-0.050249 0.233300 10.204191 504830496.000000 +-0.019143 0.209372 10.228121 504930816.000000 +-0.034696 0.218943 10.218549 505030496.000000 +-0.040678 0.209372 10.177871 505130656.000000 +-0.025125 0.193819 10.214959 505230944.000000 +-0.023928 0.204586 10.211370 505330528.000000 +-0.002393 0.226122 10.188639 505430656.000000 +-0.038285 0.215354 10.201799 505530912.000000 +-0.027517 0.232104 10.197014 505630624.000000 +-0.008375 0.222532 10.220942 505730528.000000 +-0.041874 0.217747 10.216157 505830784.000000 +-0.026321 0.216550 10.219746 505930624.000000 +-0.022732 0.226122 10.250853 506030720.000000 +-0.011964 0.224925 10.206585 506130464.000000 +-0.027517 0.198604 10.216157 506230784.000000 +-0.023928 0.226122 10.200603 506330592.000000 +-0.033500 0.217747 10.180264 506430720.000000 +-0.019143 0.208176 10.207782 506530496.000000 +-0.019143 0.212961 10.202995 506630944.000000 +-0.034696 0.204586 10.234102 506730528.000000 +-0.041874 0.224925 10.213763 506830496.000000 +-0.026321 0.208176 10.180264 506931104.000000 +0.028714 0.247657 9.907482 507030464.000000 +-0.001196 0.228515 10.164711 507130464.000000 +-0.059821 0.189033 10.334601 507230368.000000 +-0.084945 0.215354 10.319048 507330624.000000 +-0.023928 0.236889 10.186246 507430560.000000 +-0.009571 0.197408 10.220942 507530528.000000 +0.100499 0.199801 9.790234 507630464.000000 +-0.149551 0.195015 10.606186 507730464.000000 +-0.071785 0.244068 10.335798 507830464.000000 +-0.038285 0.199801 10.170692 507930368.000000 +-0.045464 0.196211 10.162319 508030336.000000 +-0.009571 0.230907 10.259227 508130368.000000 +0.086142 0.275175 9.870394 508230368.000000 +-0.076570 0.191426 10.403993 508330368.000000 +0.001196 0.241675 10.183852 508430336.000000 +0.021535 0.227318 10.138390 508530400.000000 +0.363709 0.185444 8.860621 508630368.000000 +0.025125 0.193819 10.036695 508730368.000000 +0.009571 0.200997 10.124033 508830464.000000 +-0.010768 0.222532 10.107283 508930848.000000 +-0.025125 0.185444 10.134801 509030720.000000 +-0.028714 0.193819 10.202995 509130560.000000 +-0.056231 0.220140 10.150353 509230624.000000 +-0.031107 0.195015 10.171888 509330624.000000 +-0.023928 0.172283 10.248460 509430528.000000 +-0.029910 0.210568 10.234102 509530624.000000 +-0.025125 0.240479 10.182656 509631040.000000 +-0.009571 0.218943 10.234102 509730528.000000 +-0.039482 0.193819 10.232906 509830496.000000 +0.005982 0.224925 10.194620 509930784.000000 +-0.032303 0.186640 10.258030 510030880.000000 +-0.044267 0.204586 10.225728 510130624.000000 +-0.047856 0.197408 10.198210 510230528.000000 +-0.026321 0.195015 10.198210 510330624.000000 +-0.025125 0.205783 10.180264 510430912.000000 +-0.039482 0.200997 10.147961 510530496.000000 +-0.034696 0.204586 10.225728 510630624.000000 +-0.013161 0.202193 10.247264 510731040.000000 +-0.021535 0.229711 10.230514 510830752.000000 +-0.009571 0.203390 10.208978 510930496.000000 +-0.057428 0.193819 10.248460 511030912.000000 +-0.034696 0.202193 10.199407 511130496.000000 +0.187837 0.221336 9.419346 511230848.000000 +-0.015553 0.210568 10.252048 511330912.000000 +0.022732 0.206979 10.130014 511430432.000000 +-0.039482 0.199801 10.238889 511530880.000000 +-0.020339 0.208176 10.179067 511630528.000000 +-0.148355 0.160319 10.831112 511730400.000000 +-0.193819 0.212961 10.779665 511830528.000000 +-0.086142 0.211765 10.380065 511930496.000000 +-0.032303 0.203390 10.223334 512030816.000000 +-0.032303 0.214158 10.185050 512130944.000000 +0.034696 0.236889 10.293922 512230368.000000 +-0.061017 0.212961 10.321441 512330368.000000 +-0.058624 0.223729 10.299905 512430592.000000 +-0.041874 0.242871 10.204191 512530496.000000 +-0.180658 0.203390 10.610972 512630400.000000 +-0.075374 0.222532 10.426724 512730400.000000 +-0.090927 0.205783 10.413565 512830560.000000 +-0.070588 0.238086 10.271191 512930528.000000 +-0.003589 0.189033 10.210175 513030464.000000 +0.206979 0.223729 9.483953 513130368.000000 +0.144766 0.220140 9.711270 513230528.000000 +0.056231 0.217747 9.932607 513330592.000000 +0.004786 0.200997 10.078569 513430400.000000 +-0.123230 0.212961 10.634900 513530400.000000 +-0.161516 0.203390 10.741381 513630368.000000 +-0.110070 0.211765 10.447062 513730592.000000 +-0.051446 0.220140 10.372886 513830464.000000 +-0.082552 0.218943 10.412368 513930400.000000 +-0.028714 0.189033 10.157533 514030656.000000 +-0.020339 0.204586 10.226924 514130592.000000 +-0.037089 0.197408 10.246067 514230944.000000 +-0.034696 0.184247 10.174281 514330464.000000 +-0.020339 0.214158 10.206585 514430816.000000 +-0.033500 0.197408 10.210175 514531424.000000 +-0.022732 0.192622 10.192227 514630624.000000 +-0.033500 0.199801 10.202995 514730624.000000 +-0.004786 0.220140 10.202995 514830976.000000 +-0.032303 0.226122 10.238889 514930496.000000 +-0.056231 0.206979 10.237692 515030656.000000 +-0.044267 0.184247 10.244871 515131008.000000 +-0.023928 0.204586 10.210175 515230752.000000 +-0.017946 0.198604 10.228121 515330688.000000 +-0.052642 0.211765 10.211370 515430624.000000 +-0.035892 0.239282 10.194620 515530528.000000 +-0.059821 0.228515 10.252048 515630816.000000 +-0.035892 0.202193 10.206585 515730496.000000 +-0.053839 0.197408 10.208978 515830816.000000 +-0.026321 0.218943 10.223334 515930560.000000 +-0.059821 0.197408 10.171888 516030752.000000 +-0.010768 0.227318 10.212566 516130528.000000 +-0.029910 0.197408 10.207782 516230656.000000 +-0.038285 0.196211 10.195816 516331200.000000 +-0.017946 0.196211 10.247264 516430528.000000 +-0.043071 0.195015 10.204191 516530912.000000 +-0.020339 0.205783 10.187442 516630496.000000 +-0.015553 0.200997 10.242477 516730688.000000 +-0.014357 0.227318 10.211370 516830560.000000 +-0.004786 0.208176 10.219746 516930912.000000 +-0.040678 0.214158 10.210175 517030752.000000 +-0.023928 0.239282 10.211370 517130784.000000 +-0.016750 0.216550 10.189835 517230464.000000 +-0.023928 0.232104 10.218549 517330816.000000 +-0.035892 0.205783 10.244871 517531072.000000 +-0.019143 0.228515 10.256834 517630560.000000 +-0.019143 0.227318 10.219746 517730528.000000 +-0.005982 0.206979 10.195816 517831104.000000 +-0.028714 0.214158 10.208978 517930496.000000 +-0.027517 0.206979 10.187442 518031520.000000 +-0.041874 0.223729 10.207782 518130464.000000 +-0.027517 0.252443 10.220942 518230720.000000 +-0.019143 0.189033 10.182656 518330560.000000 +-0.031107 0.208176 10.119246 518431200.000000 +-0.007178 0.217747 10.247264 518530496.000000 +-0.027517 0.220140 10.104890 518730592.000000 +-0.010768 0.215354 10.212566 518830496.000000 diff --git a/src/sensor_fusion/design/data/100ms/pitch/gyro.txt b/src/sensor_fusion/design/data/100ms/pitch/gyro.txt new file mode 100755 index 0000000..648c75c --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/pitch/gyro.txt @@ -0,0 +1,672 @@ +1.890000 0.472500 -0.472500 451587136.000000 +-1.785000 0.927500 -15.225000 451685472.000000 +-5.022500 0.297500 2.275000 451785504.000000 +-5.040000 0.297500 2.310000 451885600.000000 +-5.022500 0.332500 2.275000 451985728.000000 +-4.987500 0.052500 2.275000 452085504.000000 +-5.075000 0.892500 2.292500 452185408.000000 +-5.057500 0.017500 2.292500 452285408.000000 +-5.057500 0.192500 2.310000 452385408.000000 +-5.057500 0.262500 2.292500 452485408.000000 +-5.075000 0.297500 2.292500 452585408.000000 +-5.057500 1.977500 2.275000 452685504.000000 +-5.075000 11.427500 2.082500 452785632.000000 +-5.057500 -21.437500 2.782500 452885632.000000 +-5.232500 12.127500 1.872500 452985536.000000 +-5.092500 -1.277500 1.820000 453085568.000000 +-5.110000 1.312500 2.240000 453185472.000000 +-5.110000 -0.332500 2.310000 453285536.000000 +-5.127500 0.892500 2.275000 453385376.000000 +-5.127500 -0.227500 2.257500 453485440.000000 +-5.092500 0.612500 2.660000 453585376.000000 +-5.127500 0.542500 2.607500 453685440.000000 +-5.110000 0.507500 2.222500 453785376.000000 +-5.127500 0.402500 2.607500 453885408.000000 +-5.127500 0.087500 2.380000 453985568.000000 +-5.110000 0.332500 2.275000 454085632.000000 +-5.127500 0.192500 2.257500 454185536.000000 +-5.110000 0.157500 2.240000 454285632.000000 +-5.075000 1.382500 2.222500 454385376.000000 +-5.145000 -0.647500 2.310000 454485376.000000 +-5.110000 0.087500 2.275000 454585792.000000 +-5.110000 0.017500 2.222500 454685632.000000 +-5.110000 0.087500 2.257500 454785504.000000 +-5.127500 0.227500 2.240000 454885632.000000 +-5.092500 1.102500 2.240000 454985888.000000 +-5.110000 0.157500 2.257500 455085408.000000 +-5.057500 3.097500 2.240000 455185408.000000 +-5.180000 -0.892500 2.257500 455285536.000000 +-5.127500 -0.087500 2.257500 455385504.000000 +-5.127500 0.297500 2.240000 455485504.000000 +-5.145000 -0.052500 2.275000 455585472.000000 +-5.145000 0.017500 2.257500 455685408.000000 +-5.127500 -0.227500 2.275000 455785408.000000 +-5.162500 1.417500 3.640000 455885440.000000 +-5.145000 -0.332500 2.275000 455985504.000000 +-5.145000 0.087500 2.240000 456085440.000000 +-5.180000 0.017500 2.257500 456186336.000000 +-5.180000 0.472500 2.257500 456285472.000000 +-5.162500 0.682500 2.240000 456385664.000000 +-5.162500 0.542500 2.362500 456485472.000000 +-5.180000 -0.542500 2.257500 456585408.000000 +-5.127500 0.402500 2.222500 456685472.000000 +-5.162500 0.297500 2.257500 456785472.000000 +-5.110000 -0.122500 2.257500 456885472.000000 +-5.162500 0.402500 2.257500 456985504.000000 +-5.127500 0.157500 2.257500 457085504.000000 +-5.162500 0.472500 2.222500 457185472.000000 +-5.162500 -0.017500 2.240000 457285376.000000 +-5.127500 0.402500 2.222500 457385376.000000 +-5.145000 0.612500 2.205000 457485344.000000 +-5.092500 2.187500 2.187500 457585440.000000 +-5.110000 1.487500 2.240000 457685632.000000 +-5.110000 4.532500 2.467500 457785376.000000 +-5.075000 10.622500 1.995000 457885344.000000 +-5.092500 7.472500 2.502500 457985344.000000 +-5.180000 -5.407500 2.642500 458085344.000000 +-5.232500 1.557500 2.362500 458185344.000000 +-5.215000 0.332500 2.782500 458285440.000000 +-5.180000 -0.297500 2.747500 458385504.000000 +-5.197500 -0.472500 2.222500 458485504.000000 +-5.250000 0.927500 2.695000 458585472.000000 +-5.232500 4.637500 3.447500 458685664.000000 +-5.705000 8.697500 5.145000 458785536.000000 +-5.705000 4.007500 2.642500 458885504.000000 +-5.967500 2.852500 4.655000 458985536.000000 +-8.627500 12.057500 4.567500 459085728.000000 +-10.325000 24.517500 -3.412500 459185600.000000 +-6.947500 42.507500 9.625000 459286944.000000 +-7.997500 83.947502 11.270000 459385376.000000 +-6.335000 101.377502 5.162500 459485472.000000 +-4.830000 72.607498 5.442500 459587648.000000 +5.862500 86.362503 -4.095000 459685408.000000 +-5.267500 166.687500 6.002500 459785440.000000 +-12.495000 140.017502 5.845000 459885344.000000 +3.307500 139.912506 0.332500 459985376.000000 +30.117500 140.822495 7.175000 460085344.000000 +21.139999 235.182495 13.352500 460185728.000000 +11.410000 152.547501 18.690001 460285376.000000 +8.015000 113.417503 21.332500 460385376.000000 +-0.157500 35.507500 10.027500 460485376.000000 +-6.965000 80.552498 9.327500 460585664.000000 +-9.677500 50.382500 -6.947500 460685344.000000 +-8.330000 27.002501 -7.945000 460785504.000000 +-9.012500 18.812500 -3.220000 460885376.000000 +5.442500 69.072502 -18.445000 460985376.000000 +-2.940000 10.902500 2.537500 461085344.000000 +-2.957500 17.832500 1.960000 461186240.000000 +-3.132500 23.152500 2.607500 461285344.000000 +-14.402500 12.687500 -5.932500 461385504.000000 +-5.355000 11.777500 -6.422500 461485504.000000 +-4.567500 56.367500 -1.522500 461585536.000000 +-3.150000 162.697495 -6.597500 461685504.000000 +-6.352500 187.932495 5.320000 461785536.000000 +-13.037500 241.517502 8.452500 461885536.000000 +-13.912500 157.727493 5.162500 461985504.000000 +-10.990000 102.287498 1.680000 462085760.000000 +-5.180000 82.372498 -0.070000 462185376.000000 +9.135000 80.272499 1.172500 462285376.000000 +-10.500000 112.927498 -2.292500 462385600.000000 +-40.792500 296.117493 -19.057501 462485440.000000 +-8.557500 328.457489 10.342500 462585376.000000 +-9.082500 212.327499 53.112499 462685472.000000 +-4.322500 1.942500 39.480000 462785600.000000 +-4.655000 9.327500 3.955000 462885536.000000 +-5.040000 15.592500 2.012500 462985664.000000 +-5.180000 -13.457500 -2.397500 463085408.000000 +-5.005000 4.952500 -18.865000 463185728.000000 +-4.987500 -2.257500 -15.715000 463285632.000000 +-5.372500 1.662500 9.765000 463385440.000000 +-5.267500 -0.367500 0.595000 463486496.000000 +-5.197500 0.122500 -2.467500 463585600.000000 +-5.320000 -0.577500 6.860000 463685504.000000 +-5.320000 -0.472500 6.335000 463789568.000000 +-5.267500 0.402500 4.987500 463885536.000000 +-5.250000 0.682500 2.152500 463985536.000000 +-5.285000 1.067500 2.082500 464085504.000000 +-5.232500 -0.542500 2.117500 464185504.000000 +-5.320000 2.082500 2.205000 464285440.000000 +-5.285000 0.332500 2.205000 464385376.000000 +-5.250000 0.822500 2.205000 464485472.000000 +-5.267500 0.402500 2.240000 464585408.000000 +-5.302500 0.647500 2.240000 464685504.000000 +-5.285000 0.507500 2.222500 464785472.000000 +-5.285000 0.122500 2.205000 464885440.000000 +-5.232500 -0.402500 2.257500 464985536.000000 +-5.302500 -0.227500 2.257500 465085568.000000 +-5.267500 0.122500 2.240000 465185472.000000 +-5.267500 0.822500 2.205000 465285504.000000 +-5.302500 3.132500 3.850000 465385376.000000 +-5.320000 -3.447500 2.397500 465485376.000000 +-5.267500 0.857500 2.240000 465585376.000000 +-5.250000 0.017500 2.240000 465685440.000000 +-5.267500 0.297500 2.222500 465785696.000000 +-5.267500 1.102500 2.222500 465885376.000000 +-5.250000 0.367500 2.222500 465985376.000000 +-5.267500 -0.157500 2.240000 466085376.000000 +-5.127500 0.927500 2.222500 466185824.000000 +-5.355000 0.262500 2.205000 466285376.000000 +-5.285000 0.297500 2.205000 466385344.000000 +-5.285000 0.192500 2.205000 466485536.000000 +-5.285000 0.122500 2.170000 466585632.000000 +-5.302500 -0.402500 2.240000 466685536.000000 +-5.267500 0.262500 2.205000 466785504.000000 +-5.285000 0.262500 2.205000 466885440.000000 +-5.302500 1.312500 2.310000 466985504.000000 +-5.267500 2.467500 2.432500 467085504.000000 +-5.285000 -0.472500 3.745000 467185504.000000 +-5.232500 2.222500 4.007500 467285600.000000 +-5.180000 7.332500 2.047500 467386528.000000 +-5.302500 25.462500 0.490000 467485344.000000 +-15.942500 39.987499 9.257500 467585408.000000 +-8.522500 93.957497 14.577500 467685696.000000 +9.555000 143.517502 -3.185000 467785472.000000 +-4.935000 153.247498 5.075000 467885536.000000 +-38.447498 196.122498 15.172500 467985408.000000 +-8.505000 227.517502 -2.660000 468085440.000000 +2.660000 201.337494 0.070000 468185344.000000 +19.600000 354.217499 20.895000 468285344.000000 +-2.975000 115.202499 5.547500 468385408.000000 +1.697500 85.592499 16.485001 468485536.000000 +-8.960000 81.007500 -12.495000 468585408.000000 +-6.230000 86.782501 -6.265000 468685408.000000 +-4.970000 59.237499 2.607500 468785376.000000 +-5.337500 0.472500 11.305000 468885376.000000 +-5.075000 1.312500 4.690000 468985632.000000 +-5.460000 3.727500 -3.185000 469085376.000000 +-5.040000 12.267500 -4.077500 469186304.000000 +-4.585000 97.842499 -3.955000 469285408.000000 +-2.975000 153.352493 -2.835000 469385376.000000 +-3.570000 221.112503 2.625000 469485344.000000 +-7.280000 194.302505 0.175000 469585536.000000 +-14.630000 146.457504 6.107500 469685536.000000 +-26.320000 147.472504 2.730000 469785504.000000 +-12.005000 163.607498 0.070000 469885696.000000 +27.492500 243.897507 4.497500 469985440.000000 +-31.570000 381.342499 -17.412500 470085504.000000 +-9.257500 54.057499 -1.995000 470185376.000000 +-3.220000 34.317501 1.942500 470285504.000000 +-5.950000 41.807499 10.360000 470385376.000000 +-3.395000 34.107502 11.480000 470485472.000000 +1.645000 88.602501 15.015000 470585472.000000 +-2.975000 12.967500 -1.242500 470685472.000000 +-5.337500 2.222500 2.187500 470785504.000000 +-5.355000 3.622500 2.240000 470885472.000000 +-5.530000 28.717501 3.307500 470985472.000000 +-5.477500 -8.382500 2.397500 471085504.000000 +-5.372500 2.432500 2.170000 471185472.000000 +-5.337500 0.612500 2.205000 471285888.000000 +-5.337500 0.752500 2.205000 471385408.000000 +-5.337500 1.452500 2.205000 471485536.000000 +-5.320000 0.542500 2.170000 471585920.000000 +-5.180000 3.727500 2.187500 471685504.000000 +-5.407500 -1.207500 2.292500 471785472.000000 +-5.355000 0.192500 2.187500 471885344.000000 +-5.320000 0.437500 2.187500 471985760.000000 +-5.110000 8.382500 2.205000 472085440.000000 +-5.425000 -2.852500 2.310000 472185792.000000 +-5.337500 -0.262500 2.205000 472285440.000000 +-5.320000 -0.017500 2.222500 472385376.000000 +-5.355000 0.122500 2.187500 472485376.000000 +-5.337500 0.297500 2.345000 472585440.000000 +-5.320000 0.157500 2.187500 472685376.000000 +-5.320000 0.122500 2.240000 472785408.000000 +-5.320000 0.052500 2.170000 472885376.000000 +-5.337500 0.192500 2.257500 472985696.000000 +-5.337500 1.067500 2.677500 473085568.000000 +-5.390000 2.502500 3.010000 473185568.000000 +-5.372500 -0.157500 3.640000 473285536.000000 +-5.372500 0.997500 1.942500 473385472.000000 +-5.320000 15.067500 1.960000 473485472.000000 +-12.547500 38.202499 6.177500 473585472.000000 +-10.342500 101.867500 6.650000 473685376.000000 +-1.382500 185.097504 -4.865000 473785376.000000 +12.932500 221.777496 -2.152500 473885376.000000 +15.015000 259.192505 -9.257500 473985376.000000 +4.637500 190.242508 -4.025000 474085472.000000 +-16.397501 251.947495 -4.410000 474185504.000000 +-1.855000 360.762512 -0.612500 474285376.000000 +15.645000 210.157501 35.297501 474385344.000000 +-7.105000 15.522500 -3.045000 474485568.000000 +-22.049999 74.497498 1.312500 474585696.000000 +9.677500 19.792500 -2.712500 474685440.000000 +-4.620000 43.417500 6.597500 474785440.000000 +-5.267500 59.237499 -5.337500 474885472.000000 +-5.022500 0.507500 -0.052500 474985600.000000 +-5.145000 0.402500 -14.297500 475085984.000000 +-5.512500 2.082500 1.085000 475185568.000000 +-4.515000 10.937500 -7.315000 475286016.000000 +-4.392500 15.172500 -18.007500 475385568.000000 +-0.612500 70.927498 -71.889999 475485536.000000 +-16.100000 202.737503 39.900002 475590656.000000 +-29.557501 299.477509 30.817501 475690816.000000 +-14.332500 200.532501 5.477500 475790848.000000 +-3.552500 172.357498 -0.682500 475890880.000000 +24.674999 135.852493 1.102500 475990880.000000 +36.715000 150.727493 7.262500 476090624.000000 +-65.169998 431.182495 -51.240002 476190752.000000 +-12.950000 88.952499 -1.960000 476290624.000000 +0.105000 93.887497 3.570000 476390624.000000 +-2.905000 63.192501 11.217500 476490880.000000 +2.257500 77.822502 24.307501 476590720.000000 +-2.135000 17.902500 2.852500 476690816.000000 +-5.530000 9.782500 -0.455000 476790656.000000 +-5.617500 12.862500 2.012500 476890944.000000 +-5.442500 6.177500 2.117500 476990976.000000 +-5.355000 -2.222500 2.257500 477091104.000000 +-5.337500 0.822500 2.187500 477191424.000000 +-5.250000 7.052500 2.152500 477290656.000000 +-5.512500 -4.182500 2.380000 477390720.000000 +-5.390000 0.157500 2.240000 477490752.000000 +-5.390000 0.717500 2.240000 477590752.000000 +-5.372500 1.312500 2.187500 477690848.000000 +-5.355000 0.437500 2.222500 477790816.000000 +-5.372500 0.507500 2.222500 477890848.000000 +-5.355000 0.437500 2.222500 477990976.000000 +-5.407500 0.402500 2.205000 478090880.000000 +-5.355000 -0.157500 2.222500 478190656.000000 +-5.285000 1.032500 2.730000 478290752.000000 +-5.407500 0.822500 2.187500 478390656.000000 +-5.372500 0.087500 2.257500 478490816.000000 +-5.355000 0.612500 2.240000 478591008.000000 +-5.355000 0.157500 2.240000 478690624.000000 +-5.442500 -0.017500 2.257500 478790624.000000 +-5.372500 0.332500 2.205000 478890944.000000 +-5.390000 -0.192500 2.240000 478990592.000000 +-5.390000 -0.192500 2.240000 479090816.000000 +-5.372500 0.612500 2.450000 479190880.000000 +-5.372500 -0.017500 2.222500 479290880.000000 +-5.372500 0.367500 2.222500 479390816.000000 +-5.390000 -0.087500 2.222500 479490688.000000 +-5.372500 0.297500 2.345000 479591360.000000 +-5.407500 0.052500 2.467500 479690912.000000 +-5.355000 0.507500 2.205000 479790944.000000 +-5.372500 0.297500 2.205000 479891392.000000 +-5.355000 0.122500 2.240000 479990944.000000 +-5.372500 0.577500 2.205000 480091072.000000 +-5.390000 0.927500 3.080000 480190816.000000 +-5.390000 -0.437500 2.310000 480290816.000000 +-5.390000 1.627500 2.187500 480390720.000000 +-5.372500 -0.542500 2.257500 480490816.000000 +-5.425000 -1.767500 2.275000 480590720.000000 +-5.127500 -16.677500 2.257500 480690816.000000 +-5.372500 4.812500 2.170000 480790720.000000 +-5.320000 -15.907500 2.275000 480890816.000000 +-12.565000 -30.957500 1.592500 480990720.000000 +-5.057500 -72.502502 8.767500 481090816.000000 +-8.750000 -116.987503 0.280000 481190720.000000 +-12.145000 -150.307495 -12.950000 481290816.000000 +-3.692500 -74.042503 -0.682500 481390720.000000 +3.535000 -85.032501 8.190000 481490816.000000 +-3.062500 -131.022507 5.722500 481590880.000000 +24.447500 -178.307495 14.490000 481691360.000000 +-10.132500 -154.577499 5.530000 481790912.000000 +-68.425003 -417.112488 24.587500 481890944.000000 +-8.715000 -33.267502 8.067500 481990752.000000 +-10.097500 -54.652500 11.567500 482091616.000000 +-6.475000 -60.287498 5.757500 482190912.000000 +25.655001 -200.182495 -12.757500 482290912.000000 +-8.977500 2.747500 -0.577500 482390816.000000 +-27.650000 -0.787500 -0.997500 482490720.000000 +-5.337500 0.297500 2.257500 482590816.000000 +-5.355000 0.297500 2.275000 482690912.000000 +-5.372500 0.297500 2.257500 482790976.000000 +-5.355000 0.297500 2.222500 482890912.000000 +-5.425000 0.192500 2.310000 482990976.000000 +-5.337500 0.297500 2.310000 483091072.000000 +-5.460000 -0.017500 2.170000 483190976.000000 +-5.792500 -3.622500 -4.147500 483290912.000000 +-5.355000 -10.692500 -11.130000 483390912.000000 +-5.477500 -25.322500 -2.152500 483490976.000000 +-5.495000 37.922501 104.370003 483590912.000000 +-5.897500 0.192500 41.685001 483690944.000000 +-5.057500 0.332500 -19.162500 483790912.000000 +-4.217500 0.472500 -63.822502 483890976.000000 +-5.110000 0.192500 -29.907499 483990912.000000 +-5.040000 0.227500 -19.022501 484090976.000000 +-5.705000 -2.397500 -3.587500 484190944.000000 +-5.337500 -4.077500 -13.107500 484290976.000000 +-5.477500 -16.957500 -16.082500 484390944.000000 +-5.775000 -38.622501 -8.137500 484490976.000000 +-6.195000 -92.627502 -1.172500 484591072.000000 +-6.405000 -275.432495 2.380000 484690944.000000 +-10.885000 -282.222504 2.940000 484790912.000000 +-0.140000 -244.002502 6.317500 484895872.000000 +-18.987499 -284.602509 2.817500 484995456.000000 +27.632500 -292.897491 -40.232502 485095392.000000 +-11.497500 -366.852509 -50.242500 485195488.000000 +21.297501 -70.962502 3.010000 485295488.000000 +4.812500 -70.122498 9.135000 485395456.000000 +12.862500 -37.082500 7.857500 485495392.000000 +-4.340000 8.382500 2.975000 485595488.000000 +-6.125000 19.687500 2.012500 485695392.000000 +-5.302500 1.417500 2.380000 485795520.000000 +-5.302500 -0.087500 2.257500 485895456.000000 +-5.302500 0.192500 2.222500 485995392.000000 +-5.267500 2.607500 2.170000 486095616.000000 +-5.320000 0.262500 2.222500 486195392.000000 +-5.302500 0.927500 2.222500 486295520.000000 +-5.302500 0.822500 2.327500 486395488.000000 +-5.320000 0.612500 2.450000 486495648.000000 +-5.162500 -0.402500 2.275000 486595424.000000 +-5.337500 0.787500 2.240000 486695424.000000 +-5.285000 0.542500 2.240000 486795488.000000 +-5.267500 3.622500 3.027500 486895712.000000 +-5.302500 0.437500 2.835000 486995616.000000 +-5.285000 -1.137500 2.310000 487095584.000000 +-5.285000 -2.397500 2.327500 487195520.000000 +-5.040000 -22.172501 1.540000 487295456.000000 +-5.425000 0.087500 4.707500 487395392.000000 +-6.107500 -8.872500 2.660000 487495520.000000 +-13.335000 -34.947498 8.487500 487595456.000000 +-3.185000 -24.692499 16.695000 487695520.000000 +-3.325000 -79.957497 7.665000 487795488.000000 +-7.122500 -93.677498 -1.347500 487895488.000000 +-1.872500 -101.657501 13.615000 487995392.000000 +-15.645000 -137.427505 -18.462500 488095520.000000 +0.647500 -108.062500 6.247500 488195488.000000 +8.942500 -117.337502 11.865000 488295488.000000 +7.752500 -194.057495 10.202500 488395424.000000 +12.477500 -392.717499 7.927500 488495488.000000 +-6.545000 -304.902496 3.832500 488595520.000000 +-6.002500 -142.537506 2.257500 488695424.000000 +-12.127500 -86.957497 18.182501 488795488.000000 +11.865000 -104.457497 9.275000 488895520.000000 +1.732500 -84.507500 8.820000 488995424.000000 +-32.095001 -0.367500 7.210000 489095904.000000 +-5.267500 0.367500 2.310000 489195360.000000 +-5.337500 0.297500 2.275000 489295488.000000 +-5.372500 0.227500 2.275000 489395424.000000 +-5.460000 0.052500 9.030000 489495488.000000 +-5.565000 -2.432500 -5.022500 489596096.000000 +-5.407500 -14.927500 -7.997500 489695392.000000 +-5.652500 -25.217501 -3.202500 489795488.000000 +-6.527500 -66.237503 -6.107500 489895520.000000 +-9.135000 -141.032501 -9.817500 489995392.000000 +6.965000 -73.237503 29.592501 490095456.000000 +2.502500 -70.507500 16.170000 490195360.000000 +-7.962500 -99.907501 0.402500 490295488.000000 +-11.497500 -144.252502 -2.327500 490395456.000000 +-8.575000 -190.837494 2.590000 490495488.000000 +-11.655000 -410.497498 11.445000 490595680.000000 +20.615000 -378.927490 -27.335001 490695360.000000 +-5.337500 -173.442505 -6.405000 490795488.000000 +-7.245000 -40.162498 6.457500 490895392.000000 +-5.775000 -123.847504 0.402500 490995456.000000 +8.662500 -76.597504 5.687500 491095392.000000 +-5.792500 -13.317500 2.660000 491195488.000000 +-5.285000 0.507500 2.275000 491295392.000000 +-5.372500 -2.992500 2.327500 491395488.000000 +-5.425000 -6.702500 2.380000 491495520.000000 +-5.232500 -8.872500 2.485000 491595392.000000 +-5.320000 2.607500 9.030000 491695488.000000 +-5.267500 -0.087500 2.292500 491795520.000000 +-5.302500 0.647500 2.292500 491895424.000000 +-5.320000 1.837500 2.222500 491995360.000000 +-5.285000 -0.297500 2.275000 492095648.000000 +-5.337500 0.227500 2.275000 492195424.000000 +-5.285000 -0.507500 2.292500 492295520.000000 +-5.285000 0.647500 2.222500 492395520.000000 +-5.285000 1.172500 2.222500 492495392.000000 +-5.337500 0.052500 2.275000 492595648.000000 +-5.267500 0.752500 2.222500 492695488.000000 +-5.302500 0.752500 2.240000 492795488.000000 +-5.302500 0.647500 2.240000 492895520.000000 +-5.285000 0.297500 2.222500 492995360.000000 +-5.302500 0.297500 2.117500 493095424.000000 +-5.302500 0.612500 2.222500 493195456.000000 +-5.285000 0.857500 2.257500 493295456.000000 +-5.267500 0.192500 2.240000 493395360.000000 +-5.320000 0.017500 2.240000 493495584.000000 +-5.285000 0.262500 1.750000 493595744.000000 +-5.285000 0.997500 2.397500 493695488.000000 +-5.302500 1.417500 2.660000 493795488.000000 +-5.302500 0.227500 2.310000 493895392.000000 +-5.302500 0.262500 2.257500 493995488.000000 +-5.302500 0.052500 2.240000 494095456.000000 +-5.320000 -0.297500 2.240000 494195392.000000 +-5.232500 -5.022500 0.035000 494295520.000000 +-7.437500 -34.352501 8.715000 494395424.000000 +-14.857500 -33.792500 21.525000 494495488.000000 +-0.315000 -105.577499 27.299999 494595392.000000 +5.372500 -86.957497 25.165001 494695488.000000 +-7.157500 -46.987499 -2.467500 494795392.000000 +-12.285000 -53.882500 -11.077500 494895488.000000 +-9.450000 -108.097504 -10.290000 494995520.000000 +-2.800000 -137.077499 2.362500 495095424.000000 +-1.330000 -170.922501 6.790000 495195552.000000 +8.312500 -348.477509 10.447500 495295488.000000 +-14.437500 -403.847504 11.777500 495395552.000000 +-4.760000 -140.997498 1.890000 495495456.000000 +-11.480000 -94.762497 13.755000 495595552.000000 +-9.590000 -28.332500 11.550000 495695488.000000 +-11.620000 -124.477501 22.767500 495795552.000000 +-6.212500 -114.257500 8.802500 495895488.000000 +-15.260000 -0.017500 5.652500 495995552.000000 +-5.215000 0.262500 -3.850000 496095488.000000 +-5.320000 0.262500 2.275000 496195616.000000 +-5.302500 0.297500 2.275000 496295488.000000 +-5.652500 0.157500 18.375000 496395488.000000 +-5.127500 -0.017500 7.735000 496495456.000000 +-6.160000 -27.982500 -14.647500 496595680.000000 +-6.160000 -63.157501 -7.717500 496695392.000000 +-5.197500 -139.247498 3.430000 496795488.000000 +0.822500 -110.162498 11.497500 496895456.000000 +-2.415000 -79.222504 6.772500 496995488.000000 +-8.942500 -121.397499 0.770000 497095456.000000 +-3.272500 -193.427505 4.270000 497195488.000000 +15.960000 -420.017487 3.885000 497295424.000000 +17.745001 -247.257507 -14.402500 497395488.000000 +4.235000 -197.242508 -14.192500 497495392.000000 +-10.832500 -266.157501 -30.712500 497595488.000000 +4.672500 -0.122500 1.067500 497695456.000000 +3.727500 -56.367500 20.457500 497795392.000000 +-5.145000 6.457500 38.167500 497895488.000000 +-5.740000 2.397500 11.007500 497995456.000000 +-5.670000 -20.842501 55.562500 498095456.000000 +-5.250000 -3.097500 1.942500 498195520.000000 +-5.320000 2.082500 2.240000 498295488.000000 +-5.285000 0.787500 2.275000 498395520.000000 +-5.180000 6.457500 2.450000 498495360.000000 +-5.407500 -2.327500 2.275000 498595392.000000 +-5.285000 -0.332500 2.205000 498695392.000000 +-5.320000 -0.437500 2.065000 498795456.000000 +-5.145000 1.102500 2.257500 498895584.000000 +-5.390000 -0.297500 2.240000 498995392.000000 +-5.302500 0.367500 2.222500 499095424.000000 +-5.302500 0.997500 2.222500 499195456.000000 +-5.372500 0.892500 2.205000 499295424.000000 +-5.302500 -0.437500 2.047500 499395392.000000 +-5.267500 -0.962500 1.575000 499495456.000000 +-5.302500 1.067500 2.205000 499595840.000000 +-5.512500 0.227500 2.257500 499695360.000000 +-5.302500 -0.262500 2.082500 499795488.000000 +-5.320000 0.577500 2.222500 499895456.000000 +-4.917500 0.962500 2.275000 499995360.000000 +-5.337500 0.612500 2.240000 500095424.000000 +-5.320000 -0.542500 2.205000 500195488.000000 +-5.320000 -0.122500 2.082500 500295488.000000 +-4.952500 0.262500 2.135000 500395392.000000 +-5.355000 0.647500 2.012500 500495392.000000 +-5.285000 -0.367500 1.890000 500595520.000000 +-5.320000 2.047500 2.152500 500695488.000000 +-5.302500 -1.522500 2.292500 500795456.000000 +-5.337500 0.682500 2.240000 500895392.000000 +-5.302500 0.507500 2.222500 500995488.000000 +-5.320000 0.332500 2.240000 501095616.000000 +-5.337500 0.297500 2.257500 501195424.000000 +-5.337500 0.297500 2.240000 501295456.000000 +-5.285000 0.297500 2.240000 501395456.000000 +-5.320000 0.332500 2.240000 501495424.000000 +-5.372500 0.262500 2.240000 501595456.000000 +-5.372500 0.192500 2.240000 501695424.000000 +-5.320000 0.262500 2.257500 501795488.000000 +-5.337500 0.262500 2.240000 501895488.000000 +-5.320000 0.332500 2.240000 501995456.000000 +-5.320000 0.332500 2.240000 502095392.000000 +-5.337500 0.332500 2.222500 502195520.000000 +-5.320000 0.297500 2.257500 502295488.000000 +-5.250000 2.572500 2.240000 502395392.000000 +-5.372500 -1.592500 2.310000 502495360.000000 +-5.302500 0.052500 2.257500 502595584.000000 +-5.337500 0.262500 2.240000 502695360.000000 +-5.337500 0.332500 2.257500 502795424.000000 +-5.320000 -0.087500 2.257500 502895712.000000 +-5.285000 0.542500 2.257500 502995360.000000 +-5.302500 -2.747500 2.327500 503095392.000000 +-5.337500 5.617500 2.205000 503195520.000000 +-5.302500 3.867500 2.205000 503295328.000000 +-5.425000 -6.457500 2.415000 503395456.000000 +-5.320000 2.572500 2.205000 503495456.000000 +-5.390000 1.697500 2.240000 503595392.000000 +-5.337500 -0.542500 2.327500 503695392.000000 +-5.110000 -9.747500 2.450000 503795392.000000 +-5.337500 12.932500 2.030000 503895520.000000 +-5.250000 3.202500 2.187500 503995456.000000 +-5.320000 -12.582500 2.485000 504095584.000000 +-5.302500 2.887500 2.240000 504195456.000000 +-5.215000 7.507500 2.117500 504295520.000000 +-5.355000 1.452500 2.222500 504395456.000000 +-5.285000 1.137500 2.257500 504495424.000000 +-5.302500 0.892500 2.275000 504595488.000000 +-5.285000 0.542500 2.275000 504695456.000000 +-5.285000 0.437500 2.257500 504795392.000000 +-5.302500 0.332500 2.257500 504895456.000000 +-5.320000 0.262500 2.222500 504995392.000000 +-5.302500 0.297500 2.257500 505095488.000000 +-5.302500 0.332500 2.275000 505195520.000000 +-5.302500 0.297500 2.275000 505295392.000000 +-5.320000 0.297500 2.240000 505395488.000000 +-5.302500 0.332500 2.292500 505495488.000000 +-5.302500 0.332500 2.275000 505595584.000000 +-5.302500 0.297500 2.275000 505695520.000000 +-5.285000 0.297500 2.257500 505795488.000000 +-5.267500 0.332500 2.275000 505895488.000000 +-5.320000 0.297500 2.257500 505995456.000000 +-5.320000 0.262500 2.275000 506095360.000000 +-5.285000 0.297500 2.292500 506195488.000000 +-5.285000 0.297500 2.310000 506295392.000000 +-5.320000 0.297500 2.275000 506395456.000000 +-5.267500 0.332500 2.240000 506495360.000000 +-5.302500 0.332500 2.257500 506595488.000000 +-5.302500 0.297500 2.275000 506695360.000000 +-5.285000 0.297500 2.240000 506795520.000000 +-5.267500 0.262500 2.257500 506895456.000000 +-5.302500 0.297500 2.275000 506995424.000000 +-5.267500 -0.752500 2.292500 507095552.000000 +-5.372500 0.647500 2.240000 507195392.000000 +-5.285000 0.997500 2.257500 507295456.000000 +-5.320000 0.332500 2.257500 507395552.000000 +-5.285000 0.157500 2.292500 507495456.000000 +-5.250000 0.017500 2.240000 507595424.000000 +-5.337500 0.822500 2.222500 507695424.000000 +-5.320000 0.437500 2.240000 507795424.000000 +-5.285000 0.017500 2.257500 507895456.000000 +-5.320000 0.087500 2.257500 507995360.000000 +-5.250000 -0.577500 2.275000 508095360.000000 +-5.320000 2.082500 2.205000 508195360.000000 +-5.320000 0.822500 2.222500 508295392.000000 +-5.320000 -0.682500 2.257500 508395360.000000 +-5.302500 -0.227500 2.240000 508495360.000000 +-5.390000 -5.617500 2.415000 508595456.000000 +-5.372500 7.647500 2.117500 508695392.000000 +-5.355000 -0.297500 2.257500 508795328.000000 +-5.337500 -0.017500 2.240000 508895456.000000 +-5.320000 -0.052500 2.222500 508995584.000000 +-5.302500 0.402500 2.205000 509095520.000000 +-5.320000 0.332500 2.205000 509195456.000000 +-5.320000 0.297500 2.222500 509295488.000000 +-5.320000 0.332500 2.205000 509395488.000000 +-5.355000 0.297500 2.205000 509495488.000000 +-5.337500 0.297500 2.275000 509595488.000000 +-5.355000 0.297500 2.222500 509695360.000000 +-5.320000 0.297500 2.222500 509795520.000000 +-5.337500 0.332500 2.222500 509895488.000000 +-5.355000 0.332500 2.257500 509995488.000000 +-5.355000 0.297500 2.240000 510095552.000000 +-5.355000 0.297500 2.222500 510195520.000000 +-5.337500 0.297500 2.240000 510295488.000000 +-5.355000 0.297500 2.240000 510395456.000000 +-5.337500 0.297500 2.222500 510495392.000000 +-5.337500 0.297500 2.222500 510595488.000000 +-5.320000 0.332500 2.240000 510695488.000000 +-5.355000 0.332500 2.240000 510795392.000000 +-5.320000 0.297500 2.222500 510895520.000000 +-5.355000 0.297500 2.240000 510995488.000000 +-5.355000 0.332500 2.257500 511095424.000000 +-5.337500 0.297500 2.257500 511195744.000000 +-5.320000 0.052500 2.275000 511295424.000000 +-5.372500 -0.157500 2.275000 511395392.000000 +-5.320000 0.787500 2.222500 511495488.000000 +-5.337500 0.367500 2.257500 511595552.000000 +-5.355000 0.367500 2.205000 511695584.000000 +-5.320000 4.287500 2.187500 511795360.000000 +-5.407500 -2.502500 2.345000 511895360.000000 +-5.337500 -0.122500 2.275000 511995488.000000 +-5.355000 0.017500 2.240000 512095488.000000 +-5.390000 -1.347500 2.292500 512195712.000000 +-5.337500 1.627500 2.240000 512295360.000000 +-5.337500 0.682500 2.257500 512395456.000000 +-5.355000 0.402500 2.240000 512495520.000000 +-5.232500 1.242500 2.222500 512595488.000000 +-5.425000 -1.802500 2.310000 512695392.000000 +-5.355000 1.207500 2.222500 512795360.000000 +-5.355000 0.542500 2.205000 512895488.000000 +-5.355000 0.087500 2.240000 512995488.000000 +-5.320000 -3.832500 2.310000 513095552.000000 +-5.337500 4.182500 2.152500 513195552.000000 +-5.372500 0.542500 2.240000 513295552.000000 +-5.355000 0.332500 2.187500 513395520.000000 +-5.425000 1.487500 2.222500 513495392.000000 +-5.390000 -1.452500 2.275000 513595392.000000 +-5.337500 0.822500 2.205000 513695488.000000 +-5.372500 0.577500 2.240000 513795552.000000 +-5.320000 0.612500 2.222500 513895392.000000 +-5.355000 0.052500 2.257500 513995424.000000 +-5.372500 0.017500 2.240000 514095392.000000 +-5.355000 0.437500 2.205000 514195584.000000 +-5.372500 0.262500 2.187500 514295456.000000 +-5.372500 0.297500 2.205000 514395456.000000 +-5.372500 0.297500 2.205000 514495456.000000 +-5.355000 0.297500 2.240000 514595552.000000 +-5.372500 0.297500 2.222500 514695488.000000 +-5.390000 0.297500 2.222500 514795456.000000 +-5.355000 0.297500 2.205000 514895424.000000 +-5.372500 0.297500 2.222500 514995488.000000 +-5.390000 0.297500 2.222500 515095488.000000 +-5.372500 0.332500 2.240000 515195392.000000 +-5.355000 0.332500 2.240000 515295488.000000 +-5.337500 0.297500 2.240000 515395360.000000 +-5.390000 0.297500 2.240000 515495456.000000 +-5.390000 0.262500 2.292500 515595520.000000 +-5.355000 0.332500 2.240000 515695392.000000 +-5.372500 0.332500 2.257500 515795520.000000 +-5.372500 0.297500 2.257500 515895392.000000 +-5.355000 0.297500 2.257500 515995456.000000 +-5.337500 0.297500 2.240000 516095680.000000 +-5.355000 0.332500 2.222500 516195488.000000 +-5.337500 0.332500 2.257500 516295456.000000 +-5.355000 0.297500 2.257500 516395392.000000 +-5.372500 0.332500 2.257500 516495488.000000 +-5.337500 0.297500 2.222500 516595392.000000 +-5.355000 0.297500 2.257500 516695488.000000 +-5.355000 0.297500 2.240000 516795488.000000 +-5.337500 0.297500 2.292500 516895456.000000 +-5.355000 0.332500 2.257500 516995360.000000 +-5.355000 0.297500 2.222500 517095488.000000 +-5.355000 0.332500 2.222500 517195360.000000 +-5.337500 0.332500 2.275000 517295488.000000 +-5.355000 0.297500 2.240000 517395392.000000 +-5.302500 0.332500 2.257500 517495456.000000 +-5.355000 0.297500 2.257500 517595456.000000 +-5.337500 0.297500 2.240000 517695520.000000 +-5.320000 0.297500 2.240000 517795488.000000 +-5.355000 0.297500 2.257500 517895424.000000 +-5.355000 0.297500 2.240000 517995680.000000 +-5.337500 0.297500 2.257500 518095456.000000 +-5.372500 0.332500 2.275000 518195520.000000 +-5.337500 0.332500 2.240000 518295360.000000 +-5.337500 0.297500 2.240000 518495360.000000 +-5.320000 0.297500 2.257500 518595488.000000 +-5.355000 0.332500 2.257500 518695392.000000 +-5.302500 0.367500 2.257500 518795520.000000 diff --git a/src/sensor_fusion/design/data/100ms/pitch/magnetic.txt b/src/sensor_fusion/design/data/100ms/pitch/magnetic.txt new file mode 100755 index 0000000..70cc637 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/pitch/magnetic.txt @@ -0,0 +1,673 @@ +6.187500 -41.437500 -13.312500 451589600.000000 +7.562500 -42.125000 -13.500000 451689600.000000 +7.562500 -43.000000 -14.000000 451789600.000000 +7.000000 -42.562500 -13.687500 451889600.000000 +7.187500 -42.750000 -13.875000 451989600.000000 +6.500000 -42.312500 -13.625000 452089600.000000 +6.625000 -42.000000 -13.062500 452189600.000000 +6.437500 -42.062500 -13.125000 452289600.000000 +6.250000 -41.875000 -12.750000 452389600.000000 +5.562500 -41.500000 -12.375000 452489600.000000 +5.687500 -41.500000 -12.187500 452589600.000000 +5.687500 -41.500000 -12.250000 452689600.000000 +5.750000 -41.500000 -12.062500 452789600.000000 +5.937500 -41.625000 -12.250000 452889600.000000 +6.062500 -41.687500 -12.750000 452989600.000000 +6.562500 -41.812500 -13.125000 453089600.000000 +6.875000 -42.125000 -13.750000 453189600.000000 +7.375000 -42.562500 -14.187500 453289600.000000 +7.437500 -42.187500 -14.250000 453389600.000000 +6.937500 -41.750000 -13.812500 453489600.000000 +6.812500 -41.625000 -13.875000 453589600.000000 +6.500000 -41.500000 -13.875000 453689600.000000 +6.125000 -41.250000 -13.250000 453789600.000000 +6.125000 -41.250000 -13.062500 453889600.000000 +6.187500 -41.187500 -12.750000 453989600.000000 +6.062500 -41.000000 -12.687500 454089600.000000 +6.062500 -41.187500 -12.812500 454189600.000000 +6.687500 -41.500000 -13.187500 454289600.000000 +6.812500 -41.750000 -13.250000 454389600.000000 +6.937500 -41.750000 -13.187500 454489600.000000 +7.250000 -41.875000 -13.437500 454589600.000000 +7.312500 -41.687500 -13.750000 454689600.000000 +7.187500 -41.812500 -13.875000 454789600.000000 +7.000000 -41.875000 -13.750000 454889600.000000 +6.937500 -41.812500 -13.562500 454989600.000000 +6.937500 -41.875000 -13.687500 455089600.000000 +6.750000 -41.625000 -13.562500 455189600.000000 +6.875000 -41.562500 -13.625000 455289600.000000 +7.062500 -41.625000 -13.625000 455389600.000000 +7.125000 -41.687500 -13.437500 455489600.000000 +7.375000 -41.562500 -13.250000 455589600.000000 +7.500000 -41.562500 -13.125000 455689600.000000 +7.000000 -41.500000 -12.812500 455789600.000000 +6.187500 -41.250000 -12.437500 455889600.000000 +5.875000 -41.250000 -12.062500 455989600.000000 +5.500000 -41.187500 -11.562500 456089600.000000 +5.312500 -41.250000 -11.750000 456189600.000000 +5.250000 -41.437500 -11.750000 456289600.000000 +4.437500 -41.187500 -11.437500 456389600.000000 +4.125000 -40.875000 -11.437500 456489600.000000 +4.062500 -40.812500 -11.250000 456589600.000000 +4.375000 -40.875000 -11.125000 456689600.000000 +4.875000 -41.187500 -11.687500 456789600.000000 +5.250000 -41.375000 -12.000000 456889600.000000 +5.312500 -41.500000 -12.000000 456989600.000000 +5.250000 -41.187500 -12.125000 457089600.000000 +5.875000 -41.437500 -12.562500 457189600.000000 +6.000000 -41.687500 -12.625000 457289600.000000 +6.312500 -41.937500 -13.062500 457389600.000000 +6.500000 -42.125000 -13.375000 457489600.000000 +6.250000 -41.937500 -13.250000 457589600.000000 +5.937500 -41.812500 -13.000000 457689600.000000 +5.062500 -41.625000 -12.375000 457789600.000000 +4.375000 -41.375000 -11.437500 457889600.000000 +3.562500 -41.312500 -10.687500 457989600.000000 +3.062500 -40.937500 -10.187500 458089600.000000 +2.875000 -40.812500 -9.812500 458189600.000000 +2.562500 -40.562500 -9.500000 458289600.000000 +2.312500 -40.500000 -9.062500 458389600.000000 +2.375000 -40.312500 -9.125000 458489600.000000 +3.125000 -40.500000 -9.437500 458589600.000000 +3.875000 -40.812500 -10.187500 458689600.000000 +4.750000 -41.062500 -10.812500 458789600.000000 +5.375000 -41.500000 -11.687500 458889600.000000 +5.875000 -41.437500 -12.375000 458989600.000000 +6.375000 -41.625000 -12.875000 459089600.000000 +6.812500 -41.812500 -13.250000 459189600.000000 +7.187500 -41.750000 -13.187500 459289600.000000 +7.687500 -41.562500 -13.000000 459389600.000000 +7.437500 -41.437500 -12.062500 459489600.000000 +7.375000 -40.937500 -10.750000 459589600.000000 +7.500000 -40.500000 -8.562500 459689600.000000 +7.750000 -40.500000 -6.625000 459789600.000000 +8.375000 -40.687500 -4.875000 459889600.000000 +8.875000 -40.437500 -2.625000 459989600.000000 +8.375000 -40.125000 0.062500 460089600.000000 +7.250000 -40.000000 3.125000 460189600.000000 +6.562500 -40.312500 5.500000 460289600.000000 +5.250000 -40.625000 7.625000 460389600.000000 +3.125000 -40.750000 9.625000 460489600.000000 +0.625000 -40.312500 11.875000 460589600.000000 +-2.500000 -39.812500 14.250000 460689600.000000 +-5.437500 -39.687500 16.062500 460789600.000000 +-7.000000 -39.875000 16.750000 460889600.000000 +-8.562500 -39.562500 17.062500 460989600.000000 +-10.250000 -38.875000 17.562500 461089600.000000 +-11.250000 -38.437500 17.375000 461189600.000000 +-11.312500 -38.437500 16.937500 461289600.000000 +-10.875000 -38.750000 16.375000 461389600.000000 +-10.000000 -39.062500 15.562500 461489600.000000 +-9.562500 -39.125000 14.375000 461589600.000000 +-9.812500 -39.437500 13.125000 461689600.000000 +-10.125000 -39.750000 11.312500 461789600.000000 +-10.062500 -40.062500 8.562500 461889600.000000 +-10.687500 -40.562500 5.937500 461989600.000000 +-10.937500 -40.500000 3.125000 462089600.000000 +-11.875000 -40.375000 0.687500 462189600.000000 +-12.750000 -40.187500 -1.812500 462289600.000000 +-12.437500 -40.312500 -4.937500 462389600.000000 +-11.250000 -39.937500 -7.250000 462489600.000000 +-8.812500 -40.062500 -8.562500 462589600.000000 +-6.562500 -40.125000 -9.562500 462689600.000000 +-4.187500 -39.875000 -10.312500 462789600.000000 +-2.312500 -39.937500 -11.062500 462889600.000000 +-0.562500 -40.187500 -12.000000 462989600.000000 +1.500000 -40.312500 -12.687500 463089600.000000 +2.750000 -40.187500 -12.625000 463189600.000000 +3.250000 -40.500000 -12.562500 463289600.000000 +2.812500 -40.437500 -12.625000 463389600.000000 +2.937500 -40.562500 -12.500000 463489600.000000 +3.562500 -40.625000 -12.312500 463589600.000000 +3.750000 -40.750000 -12.437500 463689600.000000 +4.312500 -40.625000 -12.312500 463789600.000000 +4.562500 -40.812500 -12.375000 463889600.000000 +4.812500 -40.937500 -12.375000 463989600.000000 +5.062500 -41.000000 -12.625000 464089600.000000 +5.312500 -41.125000 -13.000000 464189600.000000 +5.062500 -40.937500 -12.875000 464289600.000000 +4.250000 -41.062500 -12.812500 464389600.000000 +4.187500 -41.187500 -12.687500 464489600.000000 +3.687500 -41.125000 -12.187500 464589600.000000 +3.812500 -41.062500 -12.250000 464689600.000000 +3.687500 -41.000000 -12.187500 464789600.000000 +3.812500 -40.937500 -12.312500 464889600.000000 +4.000000 -40.937500 -12.312500 464989600.000000 +4.000000 -41.000000 -12.562500 465089600.000000 +4.375000 -41.187500 -12.875000 465189600.000000 +4.687500 -41.187500 -12.937500 465289600.000000 +5.062500 -41.250000 -13.562500 465389600.000000 +4.875000 -41.312500 -13.500000 465489600.000000 +4.750000 -41.437500 -13.375000 465589600.000000 +4.375000 -41.437500 -13.187500 465689600.000000 +3.500000 -41.437500 -12.375000 465789600.000000 +2.875000 -41.125000 -11.812500 465889600.000000 +2.250000 -40.750000 -11.187500 465989600.000000 +1.312500 -40.375000 -10.375000 466089600.000000 +0.750000 -40.312500 -9.687500 466189600.000000 +0.125000 -39.937500 -9.312500 466289600.000000 +-0.250000 -39.437500 -8.812500 466389600.000000 +0.000000 -39.375000 -8.812500 466489600.000000 +0.812500 -39.312500 -9.312500 466589600.000000 +1.437500 -39.687500 -9.687500 466689600.000000 +2.062500 -39.875000 -10.187500 466789600.000000 +2.875000 -40.125000 -11.000000 466889600.000000 +3.625000 -40.312500 -11.625000 466989600.000000 +4.562500 -40.750000 -12.000000 467089600.000000 +5.187500 -41.250000 -12.562500 467189600.000000 +5.562500 -41.500000 -12.625000 467289600.000000 +4.812500 -41.562500 -12.500000 467389600.000000 +4.375000 -41.250000 -11.875000 467489600.000000 +4.500000 -41.250000 -11.812500 467589600.000000 +5.187500 -41.250000 -11.375000 467689600.000000 +5.562500 -40.875000 -9.937500 467789600.000000 +5.750000 -40.625000 -8.000000 467889600.000000 +5.562500 -40.375000 -5.812500 467989600.000000 +5.625000 -40.062500 -3.437500 468089600.000000 +6.562500 -40.000000 -1.187500 468189600.000000 +6.625000 -40.062500 1.125000 468289600.000000 +6.000000 -39.937500 4.375000 468389600.000000 +4.562500 -39.812500 7.062500 468489600.000000 +3.125000 -40.000000 9.062500 468589600.000000 +1.062500 -39.937500 10.375000 468689600.000000 +-0.375000 -39.812500 11.687500 468789600.000000 +-2.687500 -39.750000 13.000000 468889600.000000 +-4.687500 -39.625000 13.937500 468989600.000000 +-5.687500 -39.500000 13.937500 469089600.000000 +-6.812500 -39.375000 14.062500 469189600.000000 +-8.375000 -39.250000 14.500000 469289600.000000 +-9.750000 -39.125000 14.312500 469389600.000000 +-10.250000 -39.125000 13.250000 469489600.000000 +-11.000000 -39.500000 11.375000 469589600.000000 +-11.187500 -39.625000 8.937500 469689600.000000 +-11.562500 -39.812500 5.937500 469789600.000000 +-11.875000 -39.937500 3.500000 469889600.000000 +-11.437500 -40.125000 0.000000 469989600.000000 +-10.375000 -40.000000 -3.062500 470089600.000000 +-8.625000 -39.937500 -6.125000 470189600.000000 +-7.125000 -39.687500 -7.875000 470289600.000000 +-5.250000 -39.625000 -9.625000 470389600.000000 +-3.562500 -39.750000 -11.000000 470489600.000000 +-1.625000 -39.937500 -11.500000 470589600.000000 +0.000000 -40.062500 -12.000000 470689600.000000 +1.062500 -40.125000 -12.187500 470789600.000000 +2.375000 -40.562500 -12.562500 470889600.000000 +2.562500 -40.625000 -12.312500 470989600.000000 +2.562500 -40.937500 -12.187500 471089600.000000 +2.312500 -40.687500 -11.625000 471189600.000000 +2.250000 -40.500000 -11.312500 471289600.000000 +2.375000 -40.375000 -11.500000 471389600.000000 +2.437500 -40.250000 -11.687500 471489600.000000 +2.187500 -40.250000 -11.312500 471589600.000000 +1.875000 -40.187500 -11.312500 471689600.000000 +1.937500 -40.312500 -11.500000 471789600.000000 +2.250000 -40.500000 -12.250000 471889600.000000 +2.625000 -40.750000 -12.500000 471989600.000000 +2.875000 -40.625000 -12.437500 472089600.000000 +2.562500 -40.562500 -12.062500 472189600.000000 +2.250000 -40.687500 -11.875000 472289600.000000 +1.562500 -40.500000 -11.187500 472389600.000000 +1.125000 -40.250000 -10.750000 472489600.000000 +1.062500 -40.125000 -10.437500 472589600.000000 +0.625000 -39.937500 -9.625000 472689600.000000 +0.250000 -39.625000 -9.250000 472789600.000000 +0.250000 -39.500000 -9.375000 472889600.000000 +0.000000 -39.250000 -9.437500 472989600.000000 +0.187500 -39.187500 -9.562500 473089600.000000 +1.125000 -39.375000 -10.500000 473189600.000000 +1.750000 -39.687500 -11.250000 473289600.000000 +2.250000 -40.062500 -11.750000 473389600.000000 +3.062500 -40.312500 -12.125000 473489600.000000 +3.750000 -40.562500 -12.375000 473589600.000000 +4.125000 -40.625000 -11.437500 473689600.000000 +5.062500 -40.875000 -10.250000 473789600.000000 +6.000000 -40.875000 -8.000000 473889600.000000 +6.062500 -40.812500 -4.937500 473989600.000000 +6.000000 -40.375000 -1.437500 474089600.000000 +4.750000 -39.750000 2.687500 474189600.000000 +3.250000 -39.187500 6.187500 474289600.000000 +1.875000 -39.062500 9.312500 474389600.000000 +-0.062500 -39.125000 11.875000 474489600.000000 +-2.312500 -38.937500 13.937500 474589600.000000 +-4.750000 -38.687500 15.125000 474689600.000000 +-6.500000 -38.750000 15.187500 474789600.000000 +-7.875000 -38.750000 15.062500 474889600.000000 +-7.875000 -39.187500 13.937500 474989600.000000 +-8.375000 -39.375000 13.875000 475089600.000000 +-8.937500 -39.312500 14.125000 475189600.000000 +-9.000000 -39.312500 14.000000 475289600.000000 +-8.750000 -39.250000 14.062500 475389600.000000 +-8.437500 -39.312500 14.187500 475489600.000000 +-9.187500 -39.125000 14.250000 475589600.000000 +-10.000000 -39.312500 12.875000 475689600.000000 +-11.000000 -39.375000 11.000000 475789600.000000 +-11.062500 -39.687500 8.187500 475889600.000000 +-11.250000 -40.000000 5.562500 475989600.000000 +-11.125000 -40.312500 2.937500 476089600.000000 +-10.187500 -40.500000 -0.687500 476189600.000000 +-9.187500 -40.625000 -4.250000 476289600.000000 +-7.062500 -41.000000 -7.562500 476389600.000000 +-4.687500 -41.250000 -9.437500 476489600.000000 +-2.562500 -41.437500 -10.625000 476589600.000000 +-0.812500 -41.500000 -11.625000 476689600.000000 +1.062500 -41.375000 -12.687500 476789600.000000 +2.937500 -41.437500 -13.875000 476889600.000000 +3.375000 -41.750000 -13.875000 476989600.000000 +3.812500 -41.875000 -13.937500 477089600.000000 +4.125000 -41.687500 -13.812500 477189600.000000 +4.000000 -41.750000 -13.750000 477289600.000000 +3.875000 -41.312500 -13.562500 477389600.000000 +3.437500 -40.937500 -13.000000 477489600.000000 +3.500000 -41.187500 -12.625000 477589600.000000 +3.187500 -41.125000 -12.375000 477689600.000000 +3.187500 -41.125000 -12.250000 477789600.000000 +3.062500 -41.250000 -12.187500 477889600.000000 +3.000000 -41.375000 -12.250000 477989600.000000 +3.000000 -41.375000 -12.375000 478089600.000000 +3.062500 -41.625000 -12.375000 478189600.000000 +3.000000 -41.812500 -12.437500 478289600.000000 +2.812500 -41.562500 -12.625000 478389600.000000 +2.937500 -41.687500 -12.562500 478489600.000000 +2.625000 -41.375000 -12.500000 478589600.000000 +2.375000 -41.187500 -12.562500 478689600.000000 +2.125000 -41.125000 -12.375000 478789600.000000 +1.750000 -41.000000 -12.062500 478889600.000000 +1.687500 -40.875000 -12.250000 478989600.000000 +1.875000 -40.750000 -12.187500 479089600.000000 +2.187500 -40.937500 -12.312500 479189600.000000 +2.062500 -40.875000 -12.312500 479289600.000000 +2.562500 -41.062500 -12.437500 479389600.000000 +2.937500 -41.375000 -12.437500 479489600.000000 +3.312500 -41.500000 -12.625000 479589600.000000 +3.750000 -41.500000 -13.062500 479689600.000000 +4.062500 -41.750000 -13.187500 479789600.000000 +4.500000 -41.937500 -13.562500 479889600.000000 +4.375000 -41.750000 -13.562500 479989600.000000 +4.437500 -41.750000 -13.750000 480089600.000000 +4.625000 -41.750000 -13.937500 480189600.000000 +4.500000 -41.687500 -14.000000 480289600.000000 +4.250000 -41.562500 -13.875000 480389600.000000 +4.312500 -41.750000 -13.812500 480489600.000000 +3.937500 -41.812500 -13.687500 480589600.000000 +4.000000 -41.750000 -13.750000 480689600.000000 +4.000000 -41.937500 -13.750000 480789600.000000 +4.000000 -41.750000 -13.875000 480889600.000000 +3.125000 -41.687500 -13.875000 480989600.000000 +2.562500 -41.750000 -14.000000 481089600.000000 +1.937500 -41.750000 -14.312500 481189600.000000 +1.000000 -41.437500 -14.312500 481289600.000000 +-0.312500 -41.187500 -14.125000 481389600.000000 +-2.000000 -41.187500 -13.562500 481489600.000000 +-3.625000 -41.062500 -12.687500 481589600.000000 +-5.375000 -40.937500 -11.187500 481689600.000000 +-6.937500 -40.875000 -9.187500 481789600.000000 +-8.125000 -40.437500 -6.625000 481889600.000000 +-9.562500 -40.312500 -4.000000 481989600.000000 +-10.625000 -40.437500 -1.312500 482089600.000000 +-10.937500 -40.250000 1.125000 482189600.000000 +-10.500000 -40.125000 3.875000 482289600.000000 +-10.125000 -40.000000 6.187500 482389600.000000 +-9.687500 -40.062500 8.187500 482489600.000000 +-8.562500 -40.187500 9.312500 482589600.000000 +-7.687500 -40.437500 10.125000 482689600.000000 +-6.812500 -40.312500 10.562500 482789600.000000 +-5.812500 -40.437500 10.812500 482889600.000000 +-5.187500 -40.625000 11.312500 482989600.000000 +-5.125000 -40.562500 11.062500 483089600.000000 +-5.000000 -40.812500 11.062500 483189600.000000 +-4.875000 -40.937500 11.125000 483289600.000000 +-4.562500 -41.000000 11.125000 483389600.000000 +-4.687500 -40.750000 11.062500 483489600.000000 +-5.562500 -40.750000 11.062500 483589600.000000 +-6.562500 -40.250000 11.437500 483689600.000000 +-7.187500 -40.187500 11.125000 483789600.000000 +-7.500000 -40.375000 11.375000 483889600.000000 +-7.187500 -40.375000 10.937500 483989600.000000 +-7.125000 -40.312500 10.750000 484089600.000000 +-7.187500 -40.125000 10.812500 484189600.000000 +-6.937500 -40.312500 11.125000 484289600.000000 +-5.312500 -40.312500 11.312500 484389600.000000 +-3.687500 -40.625000 11.312500 484489600.000000 +-1.750000 -40.500000 11.375000 484589600.000000 +0.250000 -40.250000 10.687500 484689600.000000 +2.062500 -40.250000 9.812500 484789600.000000 +4.000000 -40.062500 8.437500 484889600.000000 +5.125000 -39.937500 6.500000 484989600.000000 +7.125000 -39.937500 3.625000 485089600.000000 +7.562500 -39.937500 0.000000 485189600.000000 +8.375000 -40.062500 -3.312500 485289600.000000 +8.750000 -40.187500 -6.250000 485389600.000000 +8.562500 -40.500000 -8.937500 485489600.000000 +8.312500 -40.625000 -10.875000 485589600.000000 +7.750000 -40.812500 -12.625000 485689600.000000 +7.937500 -41.250000 -14.062500 485789600.000000 +7.312500 -41.562500 -14.562500 485889600.000000 +7.375000 -41.625000 -14.062500 485989600.000000 +7.125000 -41.562500 -13.812500 486089600.000000 +6.375000 -41.625000 -13.687500 486189600.000000 +5.625000 -41.125000 -13.250000 486289600.000000 +5.000000 -41.062500 -12.875000 486389600.000000 +4.937500 -41.000000 -12.812500 486489600.000000 +4.375000 -40.562500 -12.312500 486589600.000000 +3.687500 -40.187500 -12.000000 486689600.000000 +3.375000 -40.187500 -11.687500 486789600.000000 +2.937500 -40.000000 -11.375000 486889600.000000 +3.375000 -40.062500 -11.687500 486989600.000000 +4.187500 -40.500000 -12.125000 487089600.000000 +4.187500 -40.625000 -12.625000 487189600.000000 +4.125000 -40.875000 -12.562500 487289600.000000 +4.312500 -41.125000 -13.000000 487389600.000000 +4.812500 -41.375000 -13.500000 487489600.000000 +5.125000 -41.250000 -13.750000 487589600.000000 +5.062500 -41.625000 -14.312500 487689600.000000 +4.250000 -41.750000 -14.187500 487789600.000000 +2.875000 -41.687500 -14.187500 487889600.000000 +1.937500 -41.625000 -14.000000 487989600.000000 +0.750000 -41.625000 -13.750000 488089600.000000 +-0.812500 -41.625000 -13.187500 488189600.000000 +-2.812500 -41.562500 -12.000000 488289600.000000 +-4.750000 -41.500000 -10.062500 488389600.000000 +-6.000000 -41.375000 -7.437500 488489600.000000 +-6.437500 -41.187500 -4.437500 488589600.000000 +-6.937500 -41.000000 -1.312500 488689600.000000 +-6.812500 -40.750000 1.625000 488789600.000000 +-6.375000 -40.250000 4.625000 488889600.000000 +-5.687500 -40.312500 7.250000 488989600.000000 +-4.500000 -40.250000 9.375000 489089600.000000 +-3.375000 -40.437500 10.250000 489189600.000000 +-2.250000 -40.437500 10.750000 489289600.000000 +-1.937500 -40.437500 10.875000 489389600.000000 +-1.312500 -40.500000 10.812500 489489600.000000 +-0.937500 -40.687500 10.812500 489589600.000000 +-0.937500 -40.875000 10.437500 489689600.000000 +-0.562500 -40.812500 10.500000 489789600.000000 +0.000000 -40.750000 10.437500 489889600.000000 +1.062500 -40.687500 10.562500 489989600.000000 +1.625000 -40.562500 10.562500 490089600.000000 +2.625000 -40.500000 10.500000 490189600.000000 +4.000000 -40.562500 10.062500 490289600.000000 +5.375000 -40.625000 9.375000 490389600.000000 +7.000000 -40.750000 8.500000 490489600.000000 +8.375000 -40.875000 6.312500 490589600.000000 +9.312500 -41.125000 3.750000 490689600.000000 +9.812500 -41.437500 1.062500 490789600.000000 +10.375000 -41.687500 -1.875000 490889600.000000 +10.125000 -41.812500 -5.062500 490989600.000000 +9.625000 -42.000000 -7.687500 491089600.000000 +9.000000 -42.312500 -10.187500 491189600.000000 +8.250000 -42.375000 -12.375000 491289600.000000 +7.500000 -42.375000 -13.500000 491389600.000000 +6.812500 -42.375000 -14.125000 491489600.000000 +6.000000 -42.375000 -14.562500 491589600.000000 +5.687500 -42.187500 -14.687500 491689600.000000 +5.750000 -42.187500 -14.625000 491789600.000000 +5.875000 -42.125000 -14.750000 491889600.000000 +5.500000 -41.875000 -14.562500 491989600.000000 +4.812500 -41.687500 -14.000000 492089600.000000 +4.500000 -41.687500 -13.625000 492189600.000000 +4.000000 -41.687500 -13.375000 492289600.000000 +3.937500 -41.562500 -13.125000 492389600.000000 +3.562500 -41.687500 -13.250000 492489600.000000 +3.250000 -41.687500 -12.937500 492589600.000000 +2.687500 -41.437500 -12.437500 492689600.000000 +2.562500 -41.375000 -12.187500 492789600.000000 +2.750000 -41.375000 -12.500000 492889600.000000 +2.687500 -41.250000 -12.375000 492989600.000000 +2.625000 -40.875000 -12.250000 493089600.000000 +2.312500 -40.625000 -12.000000 493189600.000000 +2.375000 -40.562500 -11.562500 493289600.000000 +2.375000 -40.562500 -11.625000 493389600.000000 +2.437500 -40.625000 -11.750000 493489600.000000 +2.187500 -40.687500 -11.812500 493589600.000000 +2.375000 -40.812500 -11.625000 493689600.000000 +2.812500 -41.062500 -12.062500 493789600.000000 +3.250000 -41.375000 -12.375000 493889600.000000 +3.875000 -41.875000 -12.937500 493989600.000000 +3.812500 -42.062500 -13.312500 494089600.000000 +4.062500 -42.125000 -13.437500 494189600.000000 +4.500000 -42.375000 -13.812500 494289600.000000 +4.687500 -42.500000 -14.187500 494389600.000000 +4.000000 -42.500000 -14.562500 494489600.000000 +2.750000 -42.375000 -14.187500 494589600.000000 +1.562500 -42.500000 -13.937500 494689600.000000 +0.312500 -42.187500 -13.812500 494789600.000000 +-0.937500 -42.062500 -13.375000 494889600.000000 +-2.312500 -42.000000 -13.062500 494989600.000000 +-4.062500 -41.937500 -11.875000 495089600.000000 +-5.625000 -41.625000 -10.437500 495189600.000000 +-6.500000 -41.375000 -8.062500 495289600.000000 +-7.062500 -41.250000 -5.750000 495389600.000000 +-7.062500 -41.000000 -3.250000 495489600.000000 +-7.437500 -40.875000 -0.750000 495589600.000000 +-7.250000 -40.750000 2.000000 495689600.000000 +-6.812500 -40.375000 4.750000 495789600.000000 +-6.125000 -40.187500 6.875000 495889600.000000 +-5.125000 -40.375000 8.750000 495989600.000000 +-4.312500 -40.500000 9.500000 496089600.000000 +-3.500000 -40.250000 9.937500 496189600.000000 +-3.375000 -40.250000 10.125000 496289600.000000 +-2.937500 -40.125000 10.750000 496389600.000000 +-2.500000 -40.125000 10.875000 496489600.000000 +-2.187500 -40.375000 10.750000 496589600.000000 +-1.437500 -40.437500 10.875000 496689600.000000 +-0.312500 -40.375000 10.625000 496789600.000000 +0.750000 -40.312500 10.500000 496889600.000000 +2.187500 -40.500000 10.312500 496989600.000000 +3.812500 -40.500000 10.062500 497089600.000000 +6.125000 -40.687500 9.000000 497189600.000000 +8.250000 -40.812500 7.312500 497289600.000000 +10.250000 -40.937500 5.375000 497389600.000000 +12.000000 -40.875000 2.750000 497489600.000000 +12.312500 -40.875000 -0.437500 497589600.000000 +13.312500 -40.875000 -3.375000 497689600.000000 +13.375000 -41.062500 -6.125000 497789600.000000 +13.187500 -41.312500 -8.875000 497889600.000000 +12.187500 -41.437500 -11.062500 497989600.000000 +10.812500 -41.750000 -12.375000 498089600.000000 +9.312500 -41.812500 -13.562500 498189600.000000 +7.750000 -41.812500 -14.312500 498289600.000000 +7.125000 -42.125000 -14.125000 498389600.000000 +5.812500 -42.375000 -14.000000 498489600.000000 +4.687500 -42.250000 -13.750000 498589600.000000 +3.625000 -41.875000 -13.312500 498689600.000000 +2.625000 -41.500000 -12.937500 498789600.000000 +2.312500 -41.250000 -12.750000 498889600.000000 +1.812500 -41.437500 -12.437500 498989600.000000 +1.437500 -41.625000 -11.937500 499089600.000000 +0.812500 -41.312500 -11.562500 499189600.000000 +0.375000 -41.062500 -11.437500 499289600.000000 +0.250000 -41.187500 -11.562500 499389600.000000 +0.562500 -41.500000 -11.625000 499489600.000000 +0.687500 -41.937500 -11.437500 499589600.000000 +0.875000 -41.750000 -11.250000 499689600.000000 +0.875000 -41.750000 -11.062500 499789600.000000 +0.687500 -41.500000 -11.062500 499889600.000000 +0.812500 -41.500000 -11.000000 499989600.000000 +0.625000 -41.750000 -10.875000 500089600.000000 +0.687500 -41.500000 -10.937500 500189600.000000 +0.812500 -41.375000 -10.937500 500289600.000000 +0.875000 -41.375000 -11.187500 500389600.000000 +0.500000 -41.375000 -11.250000 500489600.000000 +0.437500 -41.187500 -11.312500 500589600.000000 +0.375000 -41.312500 -11.312500 500689600.000000 +0.625000 -41.437500 -11.812500 500789600.000000 +1.437500 -41.375000 -12.250000 500889600.000000 +2.062500 -41.687500 -12.500000 500989600.000000 +2.312500 -41.750000 -12.875000 501089600.000000 +2.687500 -42.000000 -13.125000 501189600.000000 +3.250000 -42.187500 -13.500000 501289600.000000 +4.062500 -42.500000 -13.687500 501389600.000000 +4.687500 -42.750000 -14.312500 501489600.000000 +4.812500 -43.000000 -14.125000 501589600.000000 +5.125000 -43.125000 -14.250000 501689600.000000 +4.812500 -43.125000 -14.187500 501789600.000000 +4.750000 -43.125000 -14.250000 501889600.000000 +4.937500 -43.000000 -14.500000 501989600.000000 +4.625000 -43.062500 -14.937500 502089600.000000 +4.625000 -42.812500 -15.062500 502189600.000000 +4.687500 -42.750000 -14.937500 502289600.000000 +4.687500 -42.562500 -14.812500 502389600.000000 +4.437500 -42.437500 -14.875000 502489600.000000 +4.500000 -42.437500 -14.937500 502589600.000000 +4.500000 -42.437500 -15.000000 502689600.000000 +4.375000 -42.375000 -14.750000 502789600.000000 +4.625000 -42.437500 -14.312500 502889600.000000 +4.312500 -42.500000 -14.437500 502989600.000000 +4.250000 -42.500000 -14.437500 503089600.000000 +4.500000 -42.687500 -14.687500 503189600.000000 +4.437500 -42.625000 -14.437500 503289600.000000 +4.375000 -42.562500 -14.187500 503389600.000000 +4.500000 -42.562500 -13.875000 503489600.000000 +4.375000 -42.750000 -13.875000 503589600.000000 +4.125000 -42.437500 -13.812500 503689600.000000 +4.312500 -42.250000 -13.812500 503789600.000000 +4.375000 -42.375000 -13.812500 503889600.000000 +4.125000 -42.375000 -13.875000 503989600.000000 +4.437500 -42.375000 -13.875000 504089600.000000 +4.437500 -42.562500 -14.125000 504189600.000000 +4.625000 -42.625000 -14.375000 504289600.000000 +4.750000 -42.562500 -14.562500 504389600.000000 +5.187500 -42.687500 -14.750000 504489600.000000 +5.187500 -42.687500 -14.812500 504589600.000000 +4.875000 -42.687500 -14.625000 504689600.000000 +5.062500 -42.687500 -14.437500 504789600.000000 +4.812500 -42.812500 -14.437500 504889600.000000 +5.000000 -42.625000 -14.312500 504989600.000000 +4.875000 -42.750000 -14.312500 505089600.000000 +4.750000 -42.750000 -14.312500 505189600.000000 +4.625000 -43.000000 -14.250000 505289600.000000 +4.500000 -43.062500 -14.125000 505389600.000000 +4.625000 -42.812500 -14.312500 505489600.000000 +4.375000 -42.875000 -14.375000 505589600.000000 +4.437500 -43.000000 -14.437500 505689600.000000 +4.312500 -43.375000 -14.437500 505789600.000000 +4.312500 -43.312500 -14.375000 505889600.000000 +4.375000 -43.250000 -14.312500 505989600.000000 +4.250000 -43.000000 -14.562500 506089600.000000 +4.312500 -43.125000 -14.375000 506189600.000000 +4.375000 -43.312500 -14.500000 506289600.000000 +4.437500 -43.125000 -14.437500 506389600.000000 +4.562500 -42.937500 -14.437500 506489600.000000 +4.562500 -42.937500 -14.562500 506589600.000000 +4.687500 -42.937500 -14.500000 506689600.000000 +4.812500 -43.062500 -14.625000 506789600.000000 +4.937500 -43.250000 -14.562500 506889600.000000 +4.750000 -43.125000 -14.625000 506989600.000000 +4.312500 -43.062500 -14.062500 507089600.000000 +3.750000 -42.937500 -13.625000 507189600.000000 +2.937500 -42.812500 -13.187500 507289600.000000 +2.250000 -42.312500 -12.500000 507389600.000000 +2.312500 -42.250000 -12.687500 507489600.000000 +1.687500 -42.125000 -12.187500 507589600.000000 +1.125000 -41.937500 -11.562500 507689600.000000 +0.625000 -41.687500 -11.312500 507789600.000000 +0.500000 -41.562500 -11.375000 507889600.000000 +0.687500 -41.500000 -11.375000 507989600.000000 +0.687500 -41.562500 -10.937500 508089600.000000 +0.500000 -41.750000 -10.875000 508189600.000000 +-0.750000 -41.500000 -9.687500 508289600.000000 +-1.000000 -41.312500 -9.625000 508389600.000000 +-1.312500 -41.312500 -9.375000 508489600.000000 +-1.500000 -41.125000 -9.062500 508589600.000000 +-1.750000 -41.125000 -8.625000 508689600.000000 +-1.875000 -41.250000 -8.687500 508789600.000000 +-1.437500 -41.250000 -9.125000 508889600.000000 +-1.000000 -41.125000 -9.687500 508989600.000000 +-0.062500 -41.375000 -10.500000 509089600.000000 +0.625000 -41.562500 -10.750000 509189600.000000 +1.375000 -41.562500 -11.312500 509289600.000000 +2.125000 -42.000000 -11.875000 509389600.000000 +2.937500 -42.250000 -12.562500 509489600.000000 +3.500000 -42.500000 -13.000000 509589600.000000 +3.562500 -42.562500 -13.375000 509689600.000000 +3.937500 -42.812500 -13.500000 509789600.000000 +4.062500 -43.062500 -13.500000 509889600.000000 +4.250000 -42.937500 -13.812500 509989600.000000 +4.375000 -43.062500 -14.000000 510089600.000000 +4.375000 -42.937500 -14.187500 510189600.000000 +4.375000 -43.125000 -14.375000 510289600.000000 +4.375000 -43.125000 -14.250000 510389600.000000 +4.500000 -43.125000 -14.125000 510489600.000000 +4.687500 -43.125000 -14.125000 510589600.000000 +4.937500 -43.000000 -14.250000 510689600.000000 +4.812500 -43.125000 -14.187500 510789600.000000 +4.937500 -43.125000 -14.125000 510889600.000000 +4.875000 -43.250000 -14.125000 510989600.000000 +5.187500 -43.125000 -14.125000 511089600.000000 +5.062500 -43.062500 -14.125000 511189600.000000 +4.500000 -42.750000 -13.875000 511289600.000000 +3.687500 -42.625000 -13.437500 511389600.000000 +2.937500 -42.500000 -13.125000 511489600.000000 +2.687500 -42.437500 -12.937500 511589600.000000 +1.875000 -42.000000 -12.437500 511689600.000000 +1.375000 -41.687500 -12.062500 511789600.000000 +0.500000 -41.437500 -11.687500 511889600.000000 +0.250000 -41.125000 -11.312500 511989600.000000 +0.250000 -41.437500 -11.375000 512089600.000000 +0.625000 -41.375000 -11.812500 512189600.000000 +0.750000 -41.625000 -11.625000 512289600.000000 +0.375000 -41.562500 -11.437500 512389600.000000 +0.375000 -41.875000 -11.625000 512489600.000000 +0.375000 -41.750000 -11.437500 512589600.000000 +0.812500 -41.812500 -11.437500 512689600.000000 +0.687500 -41.812500 -11.312500 512789600.000000 +0.812500 -41.875000 -11.250000 512889600.000000 +0.687500 -41.937500 -10.812500 512989600.000000 +0.500000 -41.562500 -10.687500 513089600.000000 +0.562500 -41.250000 -10.687500 513189600.000000 +0.875000 -41.000000 -10.812500 513289600.000000 +1.000000 -41.187500 -10.812500 513389600.000000 +0.625000 -41.125000 -10.875000 513489600.000000 +0.562500 -41.000000 -11.000000 513589600.000000 +0.437500 -40.687500 -10.937500 513689600.000000 +0.437500 -40.625000 -10.937500 513789600.000000 +0.562500 -40.750000 -11.000000 513889600.000000 +0.562500 -40.937500 -10.937500 513989600.000000 +0.500000 -41.125000 -10.625000 514089600.000000 +0.312500 -41.062500 -11.125000 514189600.000000 +0.812500 -41.187500 -11.437500 514289600.000000 +1.375000 -41.437500 -11.812500 514389600.000000 +1.812500 -41.625000 -12.062500 514489600.000000 +2.125000 -41.812500 -12.562500 514589600.000000 +2.437500 -42.000000 -13.062500 514689600.000000 +3.062500 -42.125000 -13.562500 514789600.000000 +3.437500 -42.250000 -13.937500 514889600.000000 +4.000000 -42.437500 -14.125000 514989600.000000 +4.187500 -42.750000 -14.062500 515089600.000000 +4.062500 -43.000000 -13.937500 515189600.000000 +4.250000 -43.125000 -14.062500 515289600.000000 +4.375000 -42.812500 -14.062500 515389600.000000 +4.437500 -42.625000 -14.062500 515489600.000000 +4.500000 -42.687500 -14.062500 515589600.000000 +4.500000 -42.437500 -14.187500 515689600.000000 +4.500000 -42.500000 -13.937500 515789600.000000 +4.562500 -42.375000 -14.062500 515889600.000000 +4.625000 -42.312500 -14.250000 515989600.000000 +4.625000 -42.312500 -14.312500 516089600.000000 +4.437500 -42.562500 -14.437500 516189600.000000 +4.500000 -42.875000 -14.375000 516289600.000000 +4.437500 -42.750000 -14.437500 516389600.000000 +4.500000 -42.937500 -14.375000 516489600.000000 +4.500000 -43.000000 -14.562500 516589600.000000 +4.375000 -42.750000 -14.562500 516689600.000000 +4.250000 -42.625000 -14.625000 516789600.000000 +4.187500 -42.437500 -14.625000 516889600.000000 +4.312500 -42.375000 -14.625000 516989600.000000 +4.250000 -42.250000 -14.625000 517089600.000000 +4.312500 -42.437500 -14.500000 517189600.000000 +4.250000 -42.625000 -14.500000 517289600.000000 +4.187500 -42.812500 -14.375000 517389600.000000 +4.250000 -42.937500 -14.375000 517489600.000000 +4.437500 -43.187500 -14.312500 517589600.000000 +4.562500 -43.437500 -14.375000 517689600.000000 +4.625000 -43.250000 -14.312500 517789600.000000 +4.750000 -43.562500 -14.187500 517889600.000000 +4.812500 -43.562500 -14.062500 517989600.000000 +4.750000 -43.625000 -14.125000 518089600.000000 +4.875000 -43.437500 -14.062500 518189600.000000 +4.750000 -43.562500 -14.062500 518289600.000000 +4.750000 -43.562500 -14.312500 518389600.000000 +4.500000 -43.500000 -14.250000 518489600.000000 +4.437500 -43.625000 -14.312500 518589600.000000 +4.375000 -43.375000 -14.562500 518689600.000000 +4.312500 -43.500000 -14.812500 518789600.000000 diff --git a/src/sensor_fusion/design/data/100ms/roll/accel.txt b/src/sensor_fusion/design/data/100ms/roll/accel.txt new file mode 100755 index 0000000..9aceffd --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/roll/accel.txt @@ -0,0 +1,840 @@ +-0.015553 0.190229 10.169496 302050432.000000 +0.026321 0.202193 10.185050 302150464.000000 +0.011964 0.215354 10.141978 302250720.000000 +0.008375 0.241675 10.199407 302350528.000000 +-0.007178 0.175872 10.158729 302450720.000000 +-0.007178 0.211765 10.182656 302550432.000000 +0.014357 0.210568 10.180264 302650720.000000 +0.019143 0.227318 10.191031 302750432.000000 +-0.005982 0.221336 10.164711 302850688.000000 +0.025125 0.199801 10.174281 302950624.000000 +0.008375 0.212961 10.182656 303050720.000000 +-0.020339 0.223729 10.229317 303150560.000000 +0.108873 0.216550 9.948160 303250720.000000 +0.066999 0.217747 10.181459 303350528.000000 +0.098106 0.206979 10.167104 303450752.000000 +0.120838 0.209372 10.168301 303550464.000000 +0.137587 0.235693 10.149158 303650752.000000 +0.108873 0.233300 10.164711 303750528.000000 +0.102891 0.220140 10.189835 303850688.000000 +0.150748 0.204586 10.153944 303950464.000000 +0.116052 0.221336 10.176675 304050720.000000 +0.229711 0.149551 10.165908 304150528.000000 +0.133998 0.173480 10.173084 304250720.000000 +0.137587 0.171087 10.141978 304350432.000000 +0.025125 0.198604 10.158729 304450944.000000 +0.002393 0.296710 10.141978 304550432.000000 +0.022732 0.294317 10.114462 304650720.000000 +-0.390030 0.262014 10.016356 304750432.000000 +-0.094516 0.282353 10.152746 304850720.000000 +-0.037089 0.364905 10.252048 304950496.000000 +0.172283 0.429512 10.815558 305050720.000000 +-0.197408 0.862613 10.305886 305150464.000000 +-0.673580 0.990629 9.795020 305250752.000000 +-0.318245 1.100698 9.920642 305350464.000000 +-0.244068 1.056431 10.011569 305450720.000000 +-0.244068 1.092324 9.802197 305550432.000000 +-0.458226 1.491925 10.155140 305650752.000000 +0.014357 1.697708 9.735199 305750464.000000 +0.137587 1.999203 9.731609 305850720.000000 +0.250050 2.155933 9.725628 305950528.000000 +0.077767 2.165504 9.827322 306050784.000000 +0.080160 2.169094 10.230514 306150464.000000 +-0.149551 2.169094 10.427922 306250720.000000 +-0.909273 3.102295 10.613364 306350464.000000 +-0.508475 3.358327 9.345169 306450688.000000 +-0.458226 4.006782 8.971889 306550528.000000 +-0.306281 5.100301 8.926425 306650752.000000 +-0.769292 6.265606 9.092726 306750432.000000 +0.126820 6.867401 7.335197 306850752.000000 +-0.023928 8.141580 5.089533 306950464.000000 +-1.915455 9.105886 3.315256 307051296.000000 +0.218943 8.935996 2.203789 307150496.000000 +-0.027517 9.720841 0.890130 307250816.000000 +1.204786 9.193225 -0.451047 307350496.000000 +2.143969 8.962317 -2.907279 307450944.000000 +0.236889 8.277969 -4.747360 307550432.000000 +0.171087 8.182258 -4.459025 307650720.000000 +0.466600 6.827919 -6.472585 307750560.000000 +0.200997 6.565905 -8.221739 307850752.000000 +0.424726 6.144768 -7.683353 307950464.000000 +-0.495314 5.230711 -6.664011 308050720.000000 +-0.713061 3.783052 -9.511470 308150528.000000 +-0.460618 3.440879 -11.235498 308250688.000000 +0.911665 1.765903 -8.000402 308350432.000000 +0.574277 0.613759 -10.207782 308450720.000000 +-0.351745 0.214158 -7.764710 308550432.000000 +0.220140 -0.198604 -9.457631 308650752.000000 +-0.309871 0.003589 -10.756934 308750432.000000 +0.005982 -0.223729 -9.463614 308850752.000000 +0.027517 -0.165105 -9.463614 308950592.000000 +0.022732 -0.185444 -9.481560 309050720.000000 +0.039482 -0.198604 -9.494720 309150464.000000 +0.015553 -0.186640 -9.471989 309250720.000000 +0.026321 -0.177069 -9.462417 309350496.000000 +0.038285 -0.181855 -9.476774 309450688.000000 +0.033500 -0.202193 -9.469595 309550496.000000 +0.043071 -0.202193 -9.493524 309650720.000000 +0.002393 -0.186640 -9.426525 309750496.000000 +0.015553 -0.189033 -9.467202 309850752.000000 +-0.154337 -0.004786 -9.450454 309950496.000000 +-0.016750 -0.224925 -9.451650 310050720.000000 +-0.124427 -0.148355 -9.500702 310150432.000000 +-0.208176 -0.038285 -9.482756 310250720.000000 +-0.016750 -0.801596 -9.718449 310350496.000000 +0.434297 -2.395216 -9.139386 310450912.000000 +-0.226122 -3.753142 -8.644072 310550528.000000 +0.159123 -5.889933 -7.125826 310650720.000000 +-0.440279 -6.941578 -7.021738 310750432.000000 +0.576670 -8.155936 -4.809574 310850720.000000 +0.957129 -9.929017 -2.094916 310950432.000000 +0.731007 -9.239884 -2.638087 311050720.000000 +0.081356 -9.351151 -1.490728 311150528.000000 +1.043271 -9.547362 1.111466 311250688.000000 +0.283549 -9.633504 0.920040 311350464.000000 +0.214158 -8.012366 5.056034 311450688.000000 +0.973879 -6.189036 8.377272 311550432.000000 +0.914058 -4.055835 9.451650 311650688.000000 +-0.050249 -1.810170 10.046266 311750464.000000 +0.106481 0.454636 9.755538 311850752.000000 +-0.367298 -0.308674 16.752151 311950560.000000 +-0.711865 0.185444 10.173084 312050720.000000 +0.004786 0.241675 11.650653 312150432.000000 +-0.370888 0.254836 11.174481 312250784.000000 +-0.275175 0.211765 10.937593 312350496.000000 +0.770489 0.104088 10.010373 312450720.000000 +0.043071 0.206979 10.158729 312550432.000000 +0.083749 0.204586 9.560523 312650432.000000 +-0.009571 0.208176 10.115658 312750400.000000 +0.016750 0.242871 10.212566 312850816.000000 +0.053839 0.238086 10.067801 312950464.000000 +-0.027517 0.220140 10.254441 313050496.000000 +-0.007178 0.236889 10.222138 313150656.000000 +0.014357 0.223729 10.162319 313250496.000000 +0.004786 0.217747 10.164711 313350688.000000 +0.123230 0.205783 9.856036 313450720.000000 +0.032303 0.208176 10.074981 313550720.000000 +0.001196 0.211765 10.084551 313650560.000000 +0.022732 0.232104 10.149158 313750720.000000 +0.005982 0.210568 10.234102 313850464.000000 +0.017946 0.234497 10.237692 313950752.000000 +-0.122034 0.256032 10.431510 314050464.000000 +-0.256032 0.251246 10.207782 314150720.000000 +0.084945 0.212961 10.208978 314250528.000000 +0.058624 0.210568 10.199407 314350720.000000 +0.070588 0.210568 10.163515 314450496.000000 +-0.040678 0.229711 10.113264 314550720.000000 +0.492921 0.735793 10.735399 314650464.000000 +-0.052642 0.951147 10.984252 314750720.000000 +0.022732 2.386841 10.289137 314850464.000000 +-0.013161 2.995814 9.826126 314950912.000000 +-0.399601 4.071388 8.871389 315050464.000000 +0.130409 5.681757 8.285149 315150720.000000 +-0.464208 6.795617 7.085148 315250528.000000 +-0.515653 7.931011 5.263013 315350720.000000 +-1.228714 8.930015 4.135994 315450496.000000 +-1.298106 9.383453 2.681158 315550752.000000 +-0.727418 9.400204 1.546960 315650432.000000 +-0.333799 9.273384 -0.373280 315750720.000000 +0.053839 8.738588 -2.725425 315850560.000000 +-0.819542 8.544770 -4.133601 315950720.000000 +-0.297906 7.521838 -5.410172 316050464.000000 +0.061017 6.424729 -6.675975 316150720.000000 +-0.693919 5.402994 -7.673782 316250496.000000 +-0.625723 3.980460 -8.422735 316350720.000000 +-0.401994 3.280560 -10.138390 316450880.000000 +-0.727418 1.351945 -12.594622 316550496.000000 +0.385244 1.280160 -10.128819 316650688.000000 +1.244268 0.429512 -13.769498 316750528.000000 +1.337588 0.960718 -7.543374 316850688.000000 +0.362513 -0.719043 -8.225327 316950432.000000 +0.074178 -0.254836 -9.455239 317050656.000000 +0.065803 -0.258425 -9.438489 317150464.000000 +0.041874 -0.254836 -9.481560 317250560.000000 +0.100499 -0.262014 -9.491131 317350688.000000 +0.066999 -0.253639 -9.467202 317450528.000000 +0.080160 -0.257228 -9.495917 317550560.000000 +0.051446 -0.273978 -9.476774 317650656.000000 +0.070588 -0.305085 -9.454042 317750496.000000 +0.058624 -0.282353 -9.439686 317850688.000000 +0.076570 -0.278764 -9.455239 317950688.000000 +0.064606 -0.246461 -9.463614 318050720.000000 +0.065803 -0.273978 -9.482756 318150464.000000 +0.034696 -0.317049 -9.443274 318250656.000000 +0.062213 -0.453440 -9.421739 318350496.000000 +0.222532 -0.211765 -9.487542 318450688.000000 +0.009571 -1.018146 -9.653843 318550464.000000 +0.364905 -1.763510 -9.256634 318650656.000000 +0.023928 -3.243471 -9.069994 318750560.000000 +0.151944 -5.454439 -7.525427 318850720.000000 +0.522832 -6.671190 -6.107680 318950464.000000 +0.683151 -7.986045 -5.142176 319050688.000000 +0.057428 -8.822337 -3.092723 319150592.000000 +0.021535 -9.401401 -1.064806 319250752.000000 +-0.028714 -9.714860 0.356531 319350496.000000 +-0.193819 -9.619147 2.194218 319450912.000000 +0.168694 -8.998209 4.137190 319550496.000000 +0.277567 -8.098508 5.586044 319650688.000000 +0.314656 -7.477571 6.607780 319750496.000000 +0.601795 -6.652047 7.755138 319850688.000000 +0.601795 -5.662615 8.328219 319950464.000000 +0.117248 -5.629115 8.274381 320050688.000000 +-0.232104 -5.056034 8.522038 320150496.000000 +-0.215354 -3.600002 9.314062 320250688.000000 +-0.267996 -3.248257 9.046066 320350496.000000 +0.289532 -2.744568 9.556933 320450720.000000 +-0.428315 -2.428715 10.510474 320550496.000000 +0.081356 -1.302892 9.842876 320650688.000000 +-0.248854 -0.789631 9.718449 320750496.000000 +-0.117248 -0.501296 10.269995 320850720.000000 +-0.307478 0.738186 10.060623 320950688.000000 +-0.302692 0.132802 10.120443 321050720.000000 +-0.074178 -0.417548 10.267602 321150528.000000 +-0.104088 -0.021535 10.237692 321250656.000000 +0.149551 0.652044 10.258030 321350496.000000 +0.064606 0.267996 10.155140 321450688.000000 +0.049053 0.291924 10.164711 321550496.000000 +0.040678 0.300299 10.152746 321650656.000000 +0.062213 0.295514 10.187442 321750496.000000 +0.058624 0.282353 10.235298 321850752.000000 +0.142373 0.270389 10.061819 321950496.000000 +0.159123 0.290728 10.207782 322050656.000000 +0.173480 0.300299 10.195816 322150368.000000 +0.190229 0.275175 10.152746 322250432.000000 +0.155533 0.294317 10.177871 322350496.000000 +0.144766 0.273978 10.171888 322450592.000000 +0.135194 0.281157 10.179067 322550592.000000 +0.174676 0.282353 10.157533 322650592.000000 +0.191426 0.234497 10.132407 322750528.000000 +0.173480 0.387637 10.101300 322850624.000000 +0.197408 0.283549 10.143176 322950336.000000 +0.222532 0.326620 10.156336 323050400.000000 +0.218943 0.288335 10.161121 323150400.000000 +0.217747 0.263210 10.150353 323250432.000000 +0.199801 0.278764 10.169496 323350368.000000 +0.245264 0.259621 10.161121 323450400.000000 +0.235693 0.345763 10.153944 323550400.000000 +0.275175 0.299103 10.220942 323650368.000000 +0.239282 0.267996 10.164711 323750336.000000 +0.254836 0.284746 10.177871 323850368.000000 +0.253639 0.278764 10.170692 323950944.000000 +0.241675 0.294317 10.213763 324050464.000000 +0.222532 0.299103 10.194620 324150624.000000 +0.226122 0.264407 10.186246 324250656.000000 +0.235693 0.295514 10.179067 324350720.000000 +0.240479 0.240479 10.146765 324450656.000000 +0.258425 0.281157 10.162319 324550528.000000 +0.246461 0.259621 10.165908 324650752.000000 +0.228515 0.267996 10.181459 324750528.000000 +0.227318 0.272782 10.213763 324850688.000000 +0.187837 0.239282 10.199407 324950400.000000 +0.183051 0.634098 10.364511 325050656.000000 +0.325424 0.046660 10.262815 325150560.000000 +0.159123 0.486939 10.262815 325250720.000000 +-0.114855 0.099302 10.131211 325350592.000000 +0.083749 0.221336 10.616954 325450912.000000 +0.658026 0.216550 10.259227 325550528.000000 +0.184247 0.284746 10.181459 325650720.000000 +0.205783 0.282353 10.210175 325750496.000000 +0.137587 0.245264 10.181459 325850720.000000 +0.149551 0.287139 10.250853 325950464.000000 +0.242871 0.287139 10.112068 326050592.000000 +-0.205783 0.324227 10.126426 326150496.000000 +0.196211 0.287139 10.163515 326250688.000000 +0.171087 0.300299 10.214959 326350432.000000 +0.157926 0.275175 10.143176 326450720.000000 +0.043071 0.325424 10.115658 326550528.000000 +0.230907 0.287139 10.222138 326650720.000000 +0.189033 0.287139 10.199407 326750464.000000 +0.156730 0.296710 10.060623 326850688.000000 +0.135194 0.277567 10.156336 326950688.000000 +0.100499 0.245264 10.182656 327050688.000000 +0.099302 0.276371 10.163515 327150464.000000 +0.110070 0.277567 10.181459 327250656.000000 +0.185444 0.248854 10.234102 327350496.000000 +0.181855 0.293121 10.180264 327450752.000000 +0.220140 0.294317 10.187442 327550496.000000 +0.178265 0.282353 10.153944 327650752.000000 +0.056231 0.334995 10.175477 327750528.000000 +0.187837 0.289532 10.216157 327850688.000000 +0.206979 0.299103 10.207782 327950496.000000 +0.262014 0.277567 10.121639 328050688.000000 +0.151944 0.284746 10.126426 328150496.000000 +0.267996 0.308674 10.134801 328250688.000000 +0.064606 0.423530 10.340584 328350496.000000 +0.594616 0.378066 10.937593 328450944.000000 +0.891326 1.647458 10.413565 328550560.000000 +0.616152 1.700100 10.255639 328650720.000000 +0.283549 3.139383 9.960124 328750560.000000 +1.152144 4.712664 8.886944 328850688.000000 +-0.502493 5.545367 7.660622 328950464.000000 +1.494318 6.595816 7.695317 329050688.000000 +0.776471 7.794620 6.334998 329150528.000000 +0.943969 8.772088 4.951947 329250720.000000 +0.522832 8.487342 3.701697 329350496.000000 +0.133998 8.919247 2.368894 329450656.000000 +-0.046660 9.736395 2.280360 329550496.000000 +0.029910 9.908678 1.799403 329650592.000000 +0.349352 10.097712 1.476372 329750336.000000 +0.471386 9.571291 -0.281157 329850592.000000 +0.684347 8.712267 -1.149751 329950656.000000 +-0.556331 8.593822 -2.427519 330050688.000000 +-1.959722 7.234699 -6.167500 330150528.000000 +-1.182054 5.380262 -5.654240 330250720.000000 +0.698704 4.122833 -8.904889 330350528.000000 +2.067399 2.902494 -10.978271 330450688.000000 +-0.641276 1.873580 -7.977671 330550496.000000 +0.782453 0.538385 -8.682357 330650656.000000 +1.082752 -0.278764 -7.788638 330750464.000000 +0.126820 0.704686 -9.714860 330850624.000000 +0.278764 0.119641 -9.294919 330950528.000000 +-0.137587 -0.544367 -9.064013 331050688.000000 +0.061017 -0.241675 -9.469595 331150432.000000 +0.078963 -0.257228 -9.464810 331250752.000000 +0.071785 -0.285942 -9.391829 331350496.000000 +0.072981 -0.276371 -9.430114 331450848.000000 +0.064606 -0.251246 -9.468399 331551136.000000 +-0.290728 -1.130609 -9.341579 331650688.000000 +-0.026321 -0.497707 -9.406186 331750528.000000 +0.479761 -2.280360 -9.595219 331850688.000000 +-0.512064 -2.872583 -9.393025 331950496.000000 +0.419940 -5.315656 -7.667800 332050688.000000 +0.798006 -7.208378 -6.143572 332150432.000000 +0.707079 -8.231310 -3.376273 332250720.000000 +-0.579063 -9.007781 -2.225325 332350496.000000 +0.034696 -9.640682 0.557528 332450656.000000 +-0.167498 -8.528020 4.384847 332550592.000000 +0.143569 -6.782455 7.137790 332650496.000000 +-0.494118 -5.332406 8.616554 332750720.000000 +-0.742971 -3.449254 9.632307 332850496.000000 +0.263210 -2.001596 10.161121 332950848.000000 +-0.051446 0.210568 10.285547 333050528.000000 +-0.299103 0.107677 9.830912 333150656.000000 +0.660419 0.317049 9.645468 333250560.000000 +-0.153141 0.378066 10.333405 333350720.000000 +0.139980 0.296710 10.216157 333450592.000000 +0.002393 0.311067 10.187442 333550720.000000 +0.080160 0.295514 10.202995 333650496.000000 +0.070588 0.299103 10.223334 333750688.000000 +0.160319 0.299103 9.876375 333850368.000000 +0.104088 0.321835 10.173084 333950432.000000 +0.105284 0.315853 10.195816 334050400.000000 +0.108873 0.314656 10.157533 334150464.000000 +0.046660 0.314656 10.201799 334250528.000000 +0.074178 0.306281 10.173084 334350464.000000 +0.055035 0.303888 10.153944 334450784.000000 +0.063410 0.303888 10.169496 334550464.000000 +0.065803 0.321835 10.180264 334650464.000000 +0.069392 0.318245 10.189835 334750592.000000 +0.025125 0.318245 10.216157 334850720.000000 +0.050249 0.323031 10.168301 334950528.000000 +0.076570 0.330210 10.185050 335050560.000000 +0.072981 0.297906 10.214959 335150784.000000 +0.049053 0.305085 10.163515 335250464.000000 +0.074178 0.300299 10.202995 335350688.000000 +0.044267 0.317049 10.133603 335450464.000000 +0.059821 0.300299 10.192227 335550656.000000 +0.070588 0.309871 10.169496 335650496.000000 +0.055035 0.323031 10.177871 335750688.000000 +0.098106 0.317049 10.159925 335850496.000000 +0.044267 0.300299 10.232906 335950848.000000 +0.023928 0.300299 10.156336 336050496.000000 +0.064606 0.270389 10.183852 336150624.000000 +0.039482 0.306281 10.171888 336250624.000000 +0.023928 0.326620 10.159925 336350656.000000 +0.052642 0.282353 10.191031 336450496.000000 +0.114855 0.256032 10.195816 336550720.000000 +0.111266 0.199801 10.132407 336650496.000000 +0.052642 0.193819 10.177871 336750720.000000 +0.049053 0.296710 10.170692 336850560.000000 +0.056231 0.223729 10.163515 336950720.000000 +0.044267 0.313460 10.171888 337050528.000000 +-0.044267 0.312263 10.180264 337150720.000000 +0.092124 0.295514 10.181459 337250496.000000 +0.070588 0.294317 10.169496 337350720.000000 +0.061017 0.307478 10.169496 337450688.000000 +0.090927 0.320638 10.180264 337550688.000000 +0.072981 0.302692 10.191031 337650560.000000 +0.076570 0.314656 10.180264 337750720.000000 +0.065803 0.295514 10.159925 337850560.000000 +0.088534 0.289532 10.189835 337950720.000000 +0.114855 0.306281 10.171888 338050400.000000 +0.077767 0.297906 10.167104 338150400.000000 +0.064606 0.302692 10.165908 338250464.000000 +0.068195 0.323031 10.173084 338350496.000000 +0.051446 0.320638 10.222138 338450496.000000 +0.075374 0.311067 10.173084 338550624.000000 +0.082552 0.313460 10.179067 338650400.000000 +0.031107 0.309871 10.225728 338750464.000000 +0.058624 0.320638 10.150353 338850432.000000 +0.071785 0.312263 10.173084 338950688.000000 +0.043071 0.329013 10.187442 339050432.000000 +0.106481 0.313460 10.134801 339150400.000000 +0.078963 0.305085 10.165908 339250496.000000 +0.061017 0.309871 10.152746 339350560.000000 +0.058624 0.307478 10.182656 339450560.000000 +0.074178 0.324227 10.206585 339550368.000000 +0.102891 0.311067 10.183852 339650432.000000 +0.056231 0.293121 10.170692 339750528.000000 +0.080160 0.324227 10.198210 339850560.000000 +0.072981 0.324227 10.237692 339950432.000000 +0.083749 0.305085 10.139585 340050400.000000 +0.064606 0.324227 10.177871 340150528.000000 +0.055035 0.285942 10.145569 340250560.000000 +0.070588 0.311067 10.151550 340350560.000000 +0.052642 0.314656 10.193424 340450496.000000 +0.037089 0.330210 10.161121 340550464.000000 +0.064606 0.315853 10.174281 340650464.000000 +0.046660 0.312263 10.134801 340750528.000000 +-0.130409 0.321835 10.738988 340850752.000000 +0.062213 0.306281 10.143176 340950400.000000 +0.038285 0.290728 10.194620 341050400.000000 +0.044267 0.329013 10.211370 341150720.000000 +0.116052 0.319442 9.979266 341250752.000000 +0.055035 0.326620 10.271191 341350464.000000 +0.065803 0.305085 10.168301 341450528.000000 +0.047856 0.294317 10.194620 341550976.000000 +0.043071 0.319442 10.204191 341652384.000000 +0.074178 0.312263 10.188639 341750464.000000 +0.072981 0.290728 10.204191 341850656.000000 +0.099302 0.291924 10.151550 341950656.000000 +0.104088 0.296710 10.206585 342050432.000000 +0.094516 0.283549 10.181459 342150464.000000 +0.011964 0.424726 10.275976 342250464.000000 +0.047856 0.399601 10.149158 342350912.000000 +0.001196 -0.364905 10.421940 342450432.000000 +0.046660 -1.112662 10.595419 342550592.000000 +0.260818 -3.297310 9.529416 342650816.000000 +-0.081356 -4.329813 9.121440 342750656.000000 +-0.071785 -5.989235 8.215756 342850720.000000 +0.105284 -7.441679 6.580262 342950464.000000 +-0.028714 -8.414361 4.813163 343050688.000000 +0.208176 -9.381061 2.316252 343150496.000000 +-0.780060 -9.603594 0.884148 343250720.000000 +-0.564706 -9.582059 -1.135394 343350464.000000 +-0.167498 -9.336794 -1.917847 343450880.000000 +-0.442672 -8.626125 -3.745964 343550528.000000 +-0.461815 -7.810174 -4.995017 343650688.000000 +-0.066999 -6.845865 -6.882955 343750528.000000 +0.179462 -4.290331 -8.303094 343850688.000000 +0.117248 -3.257828 -9.038888 343950400.000000 +-0.167498 -0.788435 -9.627522 344050624.000000 +0.325424 -0.376870 -11.083554 344150496.000000 +-0.017946 -0.355334 -9.485149 344250688.000000 +0.221336 -0.147159 -8.732606 344350560.000000 +0.014357 -0.228515 -9.432507 344450720.000000 +0.077767 -0.241675 -9.445667 344550496.000000 +0.074178 -0.273978 -9.437292 344650688.000000 +0.089731 -0.247657 -9.450454 344750592.000000 +0.045464 -0.245264 -9.395418 344850624.000000 +0.015553 -0.068195 -9.684950 344950560.000000 +-0.094516 0.014357 -9.397811 345050720.000000 +0.540778 -0.257228 -9.509077 345150496.000000 +1.950150 -0.362513 -9.553344 345250624.000000 +-0.035892 0.736989 -9.367901 345350496.000000 +0.240479 -0.072981 -9.565309 345450688.000000 +-2.373680 0.756132 -9.314062 345550464.000000 +0.129212 0.217747 -9.815358 345650656.000000 +0.350549 0.212961 -9.245867 345750464.000000 +2.085345 -0.181855 -11.727223 345850400.000000 +-0.559920 0.844666 -10.661221 345950592.000000 +-0.271585 2.270789 -11.026128 346050688.000000 +-0.526421 3.129812 -10.259227 346150528.000000 +0.625723 4.518846 -7.820941 346250720.000000 +-0.056231 5.815755 -6.759724 346350496.000000 +-0.113659 6.762117 -4.351348 346450848.000000 +-0.221336 7.771888 -1.325624 346550496.000000 +0.908076 8.993424 -0.424726 346650368.000000 +-0.620937 9.372685 0.989432 346750368.000000 +-1.289732 9.104690 2.437090 346850464.000000 +-1.850848 8.438289 5.113462 346950368.000000 +-1.852045 7.582855 6.628119 347050368.000000 +-1.706082 5.575277 7.600801 347150464.000000 +-0.508475 3.975675 8.318647 347250496.000000 +-0.284746 3.498307 9.836893 347350656.000000 +-0.467797 2.362912 10.390833 347450368.000000 +-0.520439 0.798006 9.661021 347550368.000000 +-0.870987 0.893719 10.234102 347651040.000000 +0.327817 0.876970 10.278370 347750368.000000 +0.173480 0.180658 9.943375 347850336.000000 +0.155533 0.117248 9.871590 347950464.000000 +0.084945 0.150748 10.262815 348050368.000000 +-0.333799 0.168694 10.992627 348150400.000000 +0.308674 0.151944 10.208978 348250432.000000 +0.111266 0.144766 10.168301 348350400.000000 +0.057428 0.137587 10.258030 348450368.000000 +-0.055035 0.165105 10.193424 348550336.000000 +0.046660 0.159123 10.225728 348650432.000000 +0.178265 0.136391 10.268798 348750496.000000 +0.013161 0.148355 10.441081 348850656.000000 +0.049053 0.132802 10.225728 348950528.000000 +0.026321 0.163908 10.193424 349050496.000000 +0.047856 0.177069 10.201799 349150464.000000 +0.039482 0.162712 10.116854 349250752.000000 +0.049053 0.144766 10.259227 349350528.000000 +0.035892 0.149551 10.098907 349450816.000000 +0.029910 0.151944 10.207782 349550464.000000 +0.041874 0.130409 10.162319 349650496.000000 +0.056231 0.130409 10.157533 349750720.000000 +0.044267 0.159123 10.208978 349850496.000000 +0.053839 0.163908 10.182656 349950688.000000 +0.016750 0.141177 10.198210 350050464.000000 +0.025125 0.128016 10.169496 350151872.000000 +0.098106 0.122034 9.972089 350250400.000000 +0.038285 0.142373 10.219746 350350560.000000 +0.021535 0.153141 10.199407 350450496.000000 +0.022732 0.166301 10.170692 350550688.000000 +0.022732 0.147159 10.194620 350650528.000000 +0.029910 0.150748 10.205389 350750688.000000 +0.026321 0.147159 10.156336 350850400.000000 +0.035892 0.168694 10.200603 350950528.000000 +0.035892 0.157926 10.179067 351050528.000000 +0.015553 0.149551 10.191031 351150336.000000 +0.019143 0.167498 10.210175 351250432.000000 +0.015553 0.168694 10.186246 351350624.000000 +0.065803 0.153141 10.161121 351450464.000000 +0.011964 0.148355 10.230514 351550560.000000 +0.033500 0.151944 10.279566 351650560.000000 +0.025125 0.159123 10.254441 351750560.000000 +-0.086142 0.148355 10.256834 351850464.000000 +-0.279960 0.032303 10.088140 351950528.000000 +-0.172283 -0.836291 10.450653 352050464.000000 +0.276371 -2.256432 9.769895 352150656.000000 +0.186640 -2.908476 9.608379 352250368.000000 +0.007178 -3.403790 9.370294 352350688.000000 +0.616152 -3.932604 9.474380 352450624.000000 +0.318245 -4.762914 9.260223 352550720.000000 +0.023928 -5.962914 8.370094 352650496.000000 +-0.111266 -6.735795 7.330412 352750688.000000 +-0.307478 -8.078169 5.712864 352850496.000000 +-0.563510 -8.641679 4.191029 352950720.000000 +-0.166301 -9.592826 2.411965 353051200.000000 +-0.082552 -9.519845 -0.489332 353150656.000000 +-0.809970 -8.902496 -2.922833 353250464.000000 +-0.099302 -7.618747 -5.285746 353350752.000000 +-1.113859 -6.022735 -7.002595 353450560.000000 +0.443869 -4.253242 -8.376076 353550848.000000 +0.617348 -2.189433 -8.008778 353650432.000000 +0.854238 -0.955933 -7.978867 353750432.000000 +-0.568295 -2.553142 -9.326026 353850368.000000 +-0.467797 -0.137587 -9.485149 353950432.000000 +-0.145962 0.178265 -9.451650 354050368.000000 +0.017946 0.303888 -9.481560 354150496.000000 +0.014357 0.046660 -9.445667 354250528.000000 +0.010768 0.027517 -9.412168 354350784.000000 +-0.007178 0.031107 -9.424131 354450560.000000 +0.002393 0.047856 -9.444471 354550656.000000 +-0.020339 0.008375 -9.489935 354650400.000000 +-0.211765 0.216550 -9.635897 354750688.000000 +-0.117248 0.284746 -9.589236 354850496.000000 +-0.587438 0.415155 -9.501899 354950720.000000 +-1.533799 0.746561 -11.224730 355050496.000000 +-0.350549 1.720440 -11.059627 355150720.000000 +0.655633 2.305485 -9.095119 355250528.000000 +-0.092124 4.264010 -8.356933 355350720.000000 +0.184247 5.566902 -7.178468 355450688.000000 +0.379262 6.491727 -5.071588 355550720.000000 +0.988236 8.463413 -3.862016 355650464.000000 +0.669990 8.428718 -3.934997 355750720.000000 +0.214158 9.086744 -1.884348 355850464.000000 +0.847059 9.567701 0.171087 355950688.000000 +-0.503689 9.208777 1.941776 356050528.000000 +-0.427119 8.361719 3.852444 356150656.000000 +0.597009 7.104291 5.949754 356250720.000000 +0.311067 5.357530 8.013563 356350528.000000 +-0.446261 3.108276 10.736595 356450720.000000 +-0.044267 2.074577 10.676775 356550528.000000 +0.130409 0.885344 9.509077 356650688.000000 +-0.394816 0.191426 10.357333 356750496.000000 +-0.119641 0.252443 11.081161 356850720.000000 +0.404387 0.133998 8.800802 356950720.000000 +-0.003589 0.215354 10.541580 357050720.000000 +-0.083749 0.142373 10.535598 357150528.000000 +0.307478 0.147159 9.661021 357250688.000000 +0.019143 0.151944 9.975677 357350528.000000 +-0.332602 0.165105 10.350154 357450528.000000 +-0.605384 0.195015 10.711470 357550400.000000 +-0.368495 0.189033 10.217353 357650528.000000 +-0.068195 0.139980 10.210175 357750464.000000 +-0.025125 0.166301 10.191031 357850560.000000 +-0.041874 0.144766 10.217353 357950368.000000 +0.039482 0.139980 10.122837 358050432.000000 +0.039482 0.165105 10.182656 358150464.000000 +-0.044267 0.148355 10.219746 358250560.000000 +-0.045464 0.157926 10.181459 358350560.000000 +-0.034696 0.160319 10.173084 358450816.000000 +-0.040678 0.138784 10.193424 358550560.000000 +-0.011964 0.153141 10.191031 358650752.000000 +0.216550 0.239282 10.213763 358750528.000000 +-0.013161 0.157926 10.225728 358850720.000000 +-0.013161 0.223729 10.200603 358950592.000000 +-0.047856 0.177069 10.198210 359050656.000000 +-0.015553 0.151944 10.216157 359150688.000000 +-0.039482 0.141177 10.144372 359250528.000000 +-0.035892 0.154337 10.181459 359350688.000000 +-0.011964 0.149551 10.187442 359450496.000000 +-0.002393 0.150748 10.206585 359550688.000000 +-0.070588 0.264407 10.171888 359650528.000000 +-0.159123 -0.558724 10.162319 359750720.000000 +0.684347 -0.259621 10.223334 359850432.000000 +-0.330210 -2.136791 9.914660 359950944.000000 +0.397209 -4.055835 9.738789 360050528.000000 +-0.514457 -5.015356 8.847462 360150720.000000 +0.388834 -6.291927 7.484749 360250496.000000 +-0.305085 -7.652246 6.094519 360350752.000000 +0.253639 -9.212367 3.556931 360450496.000000 +-0.552742 -9.688539 1.564906 360550720.000000 +-0.381655 -9.674182 0.780060 360650528.000000 +0.046660 -9.321240 -1.265803 360750720.000000 +-0.265603 -7.750352 -5.651847 360850496.000000 +0.550349 -6.375676 -6.885347 360950688.000000 +0.282353 -3.763910 -8.744570 361050464.000000 +1.582852 -1.909473 -9.361918 361150720.000000 +-0.495314 -3.025724 -6.847062 361250528.000000 +-0.253639 -0.876970 -9.863215 361350720.000000 +0.506082 -0.157926 -8.754142 361450688.000000 +0.193819 -0.191426 -9.426525 361550720.000000 +0.197408 -0.197408 -9.445667 361650496.000000 +0.197408 -0.211765 -9.434900 361750688.000000 +0.200997 -0.202193 -9.477970 361851168.000000 +1.009771 -0.748954 -9.626326 361950688.000000 +0.600598 -0.071785 -9.400204 362050432.000000 +0.262014 -0.232104 -9.467202 362150720.000000 +0.192622 -0.047856 -9.489935 362250496.000000 +0.610170 0.051446 -10.280763 362350720.000000 +0.451047 1.207179 -10.213763 362450528.000000 +0.703490 2.586641 -10.651650 362550656.000000 +-0.345763 2.364109 -9.501899 362650496.000000 +0.509671 4.323831 -7.567302 362750720.000000 +1.092324 5.560920 -6.106483 362850528.000000 +0.084945 7.469195 -4.177868 362950848.000000 +-0.307478 9.311669 -3.354738 363050432.000000 +0.004786 9.250652 -1.150948 363150720.000000 +0.204586 9.225528 2.346163 363250496.000000 +-0.236889 8.622537 4.329813 363350656.000000 +-0.665205 7.928618 5.816952 363450464.000000 +-0.551546 6.599405 7.477571 363550720.000000 +-0.139980 5.351548 8.682357 363650496.000000 +0.381655 4.132405 9.054441 363750720.000000 +0.870987 2.560320 10.423136 363850464.000000 +0.848256 1.356731 9.945767 363950624.000000 +0.790828 0.508475 10.534401 364050720.000000 +1.138984 0.543171 10.304690 364150496.000000 +0.132802 -0.071785 10.073784 364250656.000000 +1.201197 -0.002393 9.273384 364351136.000000 +0.021535 0.215354 10.214959 364450752.000000 +-0.081356 0.161516 10.414761 364550496.000000 +-0.011964 0.167498 10.189835 364650720.000000 +-0.017946 0.177069 10.217353 364750464.000000 +0.128016 0.191426 10.435099 364850432.000000 +0.349352 0.175872 9.176475 364950432.000000 +0.451047 0.157926 8.889337 365050560.000000 +0.568295 0.128016 9.662218 365150592.000000 +-0.210568 0.203390 10.762917 365250528.000000 +-0.034696 0.226122 10.862220 365350400.000000 +0.066999 0.235693 10.277173 365450528.000000 +-0.058624 0.160319 10.535598 365550592.000000 +0.138784 0.179462 9.744770 365650560.000000 +0.044267 0.199801 10.194620 365750432.000000 +0.090927 0.171087 9.841680 365850528.000000 +-0.029910 0.155533 10.303494 365950496.000000 +0.171087 0.242871 8.967103 366050560.000000 +0.150748 0.174676 9.696914 366150432.000000 +0.104088 0.163908 9.810574 366250464.000000 +0.040678 0.208176 9.999605 366350976.000000 +-0.003589 0.180658 10.258030 366450528.000000 +0.061017 0.148355 10.238889 366550400.000000 +-0.041874 0.165105 10.579866 366650496.000000 +0.175872 0.137587 9.603594 366750432.000000 +0.112463 0.166301 9.859627 366850400.000000 +0.056231 0.190229 10.097712 366950528.000000 +-0.005982 0.216550 10.421940 367050368.000000 +-0.041874 0.150748 10.408779 367151040.000000 +0.074178 0.151944 10.175477 367250464.000000 +0.022732 0.178265 10.229317 367350656.000000 +-0.189033 0.178265 10.868200 367450624.000000 +-0.013161 0.177069 10.435099 367550464.000000 +-0.001196 0.168694 10.273583 367650816.000000 +-0.004786 0.183051 10.192227 367750496.000000 +0.071785 0.154337 10.094121 367850368.000000 +-0.069392 0.179462 10.539186 367950528.000000 +0.055035 0.148355 10.023535 368050528.000000 +-0.005982 0.186640 10.234102 368150624.000000 +-0.001196 0.154337 10.181459 368250528.000000 +0.005982 0.177069 10.206585 368350688.000000 +0.010768 0.167498 10.187442 368450496.000000 +0.031107 0.185444 10.175477 368550688.000000 +0.027517 0.191426 10.183852 368650496.000000 +0.023928 0.157926 10.228121 368750720.000000 +0.013161 0.162712 10.186246 368850816.000000 +0.011964 0.193819 10.637293 368950496.000000 +0.317049 0.155533 9.123833 369050656.000000 +0.343370 0.165105 9.178867 369150560.000000 +-0.358923 0.171087 11.229517 369250528.000000 +-0.192622 0.241675 11.273784 369350368.000000 +0.306281 0.153141 9.251849 369450560.000000 +0.262014 0.161516 9.430114 369550624.000000 +-0.155533 0.098106 10.810772 369650560.000000 +-0.416351 0.174676 11.562119 369750432.000000 +-0.336192 0.075374 11.405389 369850816.000000 +0.206979 0.210568 9.603594 369950560.000000 +0.364905 0.181855 9.119047 370050624.000000 +-0.256032 0.167498 11.118251 370150432.000000 +0.191426 0.153141 9.597611 370250496.000000 +0.106481 0.180658 9.836893 370350528.000000 +0.020339 0.168694 10.143176 370450656.000000 +0.113659 0.131605 9.978070 370550400.000000 +-0.071785 0.145962 10.603793 370650496.000000 +0.043071 0.184247 10.071390 370750560.000000 +0.016750 0.154337 10.302298 370850432.000000 +0.308674 0.172283 9.661021 370950400.000000 +0.367298 0.148355 9.097511 371050528.000000 +0.422333 0.157926 9.013763 371150560.000000 +0.132802 0.203390 9.943375 371250624.000000 +-0.690329 0.105284 12.196217 371350432.000000 +-0.689133 0.220140 11.502297 371450528.000000 +-0.705883 0.192622 11.436496 371550528.000000 +-0.626920 0.196211 11.422139 371650560.000000 +-0.540778 0.156730 11.436496 371750400.000000 +0.257228 0.161516 9.460024 371850752.000000 +0.373280 0.179462 9.116654 371951552.000000 +0.366102 0.147159 9.253045 372050528.000000 +-0.635294 0.216550 11.321640 372150400.000000 +0.095713 0.098106 11.505888 372250432.000000 +-0.081356 0.141177 10.559525 372350496.000000 +-0.014357 0.178265 10.272388 372450528.000000 +0.051446 0.154337 10.152746 372550528.000000 +-0.334995 0.150748 11.278569 372650464.000000 +0.026321 0.253639 10.252048 372750464.000000 +0.191426 0.166301 9.699306 372850528.000000 +0.104088 0.163908 9.839286 372950496.000000 +0.005982 0.153141 10.329816 373050816.000000 +-0.053839 0.154337 10.340584 373150432.000000 +0.027517 0.142373 10.164711 373250528.000000 +0.015553 0.183051 10.213763 373350528.000000 +-0.001196 0.162712 10.170692 373450688.000000 +0.037089 0.195015 10.156336 373550912.000000 +-0.112463 0.161516 10.734202 373650400.000000 +-0.033500 0.160319 10.360922 373750464.000000 +0.014357 0.167498 10.145569 373850528.000000 +-0.297906 0.167498 10.841879 373950432.000000 +0.313460 0.177069 9.352347 374050400.000000 +-0.329013 0.174676 11.199607 374150912.000000 +0.148355 0.195015 9.686146 374251008.000000 +0.093320 0.162712 9.821341 374351040.000000 +0.190229 0.171087 9.577272 374450400.000000 +-0.278764 0.113659 11.273784 374550400.000000 +0.203390 0.161516 9.629914 374650464.000000 +-0.021535 0.161516 10.411172 374750528.000000 +-0.005982 0.144766 10.359726 374850400.000000 +-0.008375 0.179462 10.285547 374950464.000000 +0.015553 0.156730 10.185050 375050560.000000 +-0.019143 0.148355 10.218549 375150464.000000 +-0.002393 0.141177 10.207782 375250528.000000 +-0.214158 0.143569 11.084750 375350400.000000 +-0.589831 0.172283 11.472387 375450368.000000 +-0.549153 0.193819 11.481958 375550720.000000 +-0.470190 0.198604 11.368300 375650528.000000 +-0.038285 0.270389 10.716256 375750528.000000 +0.534796 0.160319 8.755339 375850368.000000 +0.056231 0.157926 10.016356 375950400.000000 +0.063410 0.156730 9.943375 376050496.000000 +0.022732 0.157926 10.131211 376150560.000000 +-0.017946 0.156730 10.207782 376250432.000000 +0.136391 0.177069 9.702895 376350400.000000 +0.065803 0.135194 9.968499 376450592.000000 +0.050249 0.135194 10.107283 376550560.000000 +0.020339 0.165105 10.202995 376650528.000000 +-0.023928 0.187837 10.250853 376750656.000000 +0.015553 0.150748 10.226924 376850528.000000 +0.004786 0.155533 10.244871 376950464.000000 +-0.007178 0.167498 10.228121 377050464.000000 +-0.009571 0.190229 10.261620 377150464.000000 +-0.009571 0.161516 10.183852 377250400.000000 +-0.013161 0.163908 10.214959 377350432.000000 +-0.009571 0.151944 10.168301 377450496.000000 +0.007178 0.175872 10.208978 377550880.000000 +0.017946 0.172283 10.255639 377650560.000000 +-0.020339 0.163908 10.230514 377750464.000000 +-0.025125 0.155533 10.208978 377850688.000000 +-0.008375 0.156730 10.188639 377950656.000000 +-0.014357 0.187837 10.229317 378050720.000000 +0.002393 0.159123 10.278370 378150496.000000 +-0.005982 0.166301 10.232906 378250688.000000 +-0.027517 0.166301 10.234102 378350496.000000 +-0.025125 0.165105 10.225728 378450688.000000 +-0.022732 0.179462 10.188639 378550496.000000 +0.005982 0.200997 10.242477 378650656.000000 +0.005982 0.166301 10.161121 378750496.000000 +-0.007178 0.157926 10.222138 378850688.000000 +-0.014357 0.167498 10.228121 378950464.000000 +-0.020339 0.165105 10.199407 379050688.000000 +0.002393 0.154337 10.238889 379150592.000000 +-0.013161 0.169890 10.217353 379250688.000000 +0.010768 0.179462 10.220942 379350528.000000 +0.004786 0.155533 10.195816 379450912.000000 +-0.021535 0.155533 10.188639 379550432.000000 +0.014357 0.165105 10.200603 379650752.000000 +0.016750 0.177069 10.236496 379750528.000000 +-0.035892 0.162712 10.279566 379850720.000000 +0.123230 0.256032 10.366903 379950496.000000 +0.276371 0.214158 10.128819 380050688.000000 +0.417548 0.174676 10.351351 380150496.000000 +0.473779 0.150748 10.095319 380250688.000000 +0.212961 0.373280 10.225728 380350496.000000 +0.606581 0.066999 10.223334 380450720.000000 +0.468993 0.165105 10.204191 380550496.000000 +0.484547 0.200997 10.195816 380650656.000000 +0.457029 0.153141 10.230514 380750560.000000 +0.454636 0.159123 10.183852 380850688.000000 +0.476172 0.174676 10.164711 380950592.000000 +0.466600 0.172283 10.228121 381050656.000000 +0.500100 0.173480 10.195816 381150496.000000 +0.478565 0.165105 10.180264 381250720.000000 +0.477368 0.181855 10.224532 381350560.000000 +0.477368 0.174676 10.183852 381450720.000000 +0.448654 0.128016 10.151550 381550464.000000 +0.472582 0.163908 10.213763 381650688.000000 +0.476172 0.187837 10.183852 381750560.000000 +0.478565 0.187837 10.206585 381850720.000000 +0.472582 0.168694 10.220942 381950464.000000 +0.443869 0.177069 10.181459 382050656.000000 +0.473779 0.189033 10.193424 382150560.000000 +0.454636 0.195015 10.188639 382250720.000000 +0.467797 0.162712 10.177871 382350464.000000 +0.474975 0.155533 10.229317 382450848.000000 +0.472582 0.160319 10.202995 382550656.000000 +0.447458 0.169890 10.173084 382650528.000000 +0.452243 0.173480 10.170692 382750656.000000 +0.466600 0.169890 10.188639 382850528.000000 +0.454636 0.178265 10.169496 382950720.000000 +0.466600 0.154337 10.192227 383050496.000000 +0.473779 0.180658 10.204191 383150688.000000 +0.483350 0.169890 10.225728 383250528.000000 +0.467797 0.160319 10.192227 383350656.000000 +0.465404 0.165105 10.192227 383450496.000000 +0.451047 0.151944 10.176675 383555776.000000 +0.455833 0.139980 10.189835 383655552.000000 +0.474975 0.151944 10.225728 383755328.000000 +0.458226 0.192622 10.191031 383855360.000000 +0.439083 0.156730 10.205389 383955424.000000 +0.470190 0.171087 10.240085 384055392.000000 +0.468993 0.137587 10.211370 384155520.000000 +0.476172 0.186640 10.150353 384255616.000000 +0.443869 0.145962 10.094121 384355584.000000 +0.445065 0.166301 10.220942 384455488.000000 +0.452243 0.174676 10.147961 384555680.000000 +0.494118 0.172283 10.170692 384655520.000000 +0.480957 0.141177 10.182656 384756064.000000 +0.452243 0.160319 10.219746 384855456.000000 +0.425922 0.167498 10.193424 384955712.000000 +0.447458 0.193819 10.188639 385055488.000000 +0.473779 0.151944 10.146765 385155648.000000 +0.468993 0.179462 10.186246 385255744.000000 +0.465404 0.168694 10.168301 385355680.000000 +0.478565 0.153141 10.230514 385555680.000000 +0.467797 0.169890 10.187442 385655488.000000 +0.478565 0.169890 10.217353 385755648.000000 +0.443869 0.174676 10.182656 385855808.000000 +0.439083 0.196211 10.231709 385955648.000000 +0.472582 0.166301 10.125229 386055744.000000 diff --git a/src/sensor_fusion/design/data/100ms/roll/gyro.txt b/src/sensor_fusion/design/data/100ms/roll/gyro.txt new file mode 100755 index 0000000..6ddf179 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/roll/gyro.txt @@ -0,0 +1,840 @@ +1.890000 0.472500 -0.472500 301970624.000000 +-8.557500 0.612500 -18.129999 302070784.000000 +-4.935000 0.297500 2.310000 302170592.000000 +-4.935000 0.332500 2.275000 302270816.000000 +-4.935000 0.297500 2.292500 302370464.000000 +-4.952500 0.262500 2.275000 302470784.000000 +-5.022500 0.227500 2.310000 302570496.000000 +-4.987500 0.227500 2.275000 302670784.000000 +-4.987500 0.262500 2.310000 302770496.000000 +-4.987500 0.227500 2.310000 302870752.000000 +-4.952500 0.262500 2.310000 302970464.000000 +-5.005000 -0.227500 2.327500 303070752.000000 +-4.952500 -2.852500 2.327500 303170496.000000 +-5.022500 -0.472500 2.117500 303270816.000000 +-4.987500 -0.647500 2.292500 303370496.000000 +-5.040000 -0.437500 2.310000 303471040.000000 +-5.075000 0.017500 2.310000 303570496.000000 +-5.127500 -0.297500 2.362500 303670816.000000 +-5.057500 -0.262500 2.327500 303770496.000000 +-5.005000 -0.052500 2.555000 303870848.000000 +-5.022500 -0.682500 2.677500 303970528.000000 +-5.057500 -0.017500 2.292500 304070784.000000 +-5.057500 0.402500 2.065000 304170464.000000 +-5.057500 0.717500 1.015000 304270784.000000 +-5.092500 0.787500 -1.487500 304370496.000000 +-4.690000 2.362500 -0.140000 304470784.000000 +-3.360000 3.027500 1.592500 304570496.000000 +-3.290000 2.852500 3.010000 304670752.000000 +-3.920000 1.592500 0.035000 304770496.000000 +-4.812500 0.787500 3.307500 304870752.000000 +-4.025000 1.417500 2.397500 304970560.000000 +-1.312500 6.107500 1.102500 305070784.000000 +17.955000 -0.157500 -1.260000 305170464.000000 +12.075000 1.522500 -0.980000 305270752.000000 +-3.955000 -5.442500 3.675000 305370496.000000 +3.972500 0.402500 3.325000 305470752.000000 +5.022500 8.627500 0.560000 305570464.000000 +3.342500 1.137500 -1.872500 305670752.000000 +22.452499 -1.977500 10.307500 305770496.000000 +17.202499 -3.587500 7.490000 305870784.000000 +3.150000 -7.192500 2.065000 305970496.000000 +-4.095000 -0.962500 0.997500 306070784.000000 +-8.820000 0.787500 1.312500 306170464.000000 +-4.095000 1.557500 2.362500 306270912.000000 +17.045000 9.502500 -1.382500 306370560.000000 +48.825001 7.192500 5.600000 306470848.000000 +53.567501 4.637500 7.682500 306570464.000000 +57.750000 -6.072500 4.637500 306670784.000000 +81.777504 5.932500 -3.482500 306770496.000000 +107.904999 -16.257500 0.630000 306870816.000000 +111.195000 -9.187500 -10.867500 306970528.000000 +108.709999 10.132500 -7.717500 307070816.000000 +110.985001 16.257500 -3.535000 307170496.000000 +102.445000 0.577500 -0.857500 307270752.000000 +114.887497 39.287498 8.242500 307370464.000000 +147.262497 22.032499 26.127501 307470784.000000 +101.044998 29.242500 5.950000 307570496.000000 +72.327499 12.652500 0.787500 307670784.000000 +75.092499 8.312500 -8.365000 307770496.000000 +60.287498 -1.557500 -0.840000 307870848.000000 +35.927502 -1.102500 10.867500 307970592.000000 +54.302502 -5.687500 9.450000 308070816.000000 +82.320000 -3.202500 9.345000 308170496.000000 +84.192497 7.577500 7.402500 308270752.000000 +47.180000 8.242500 13.125000 308370496.000000 +82.862503 5.967500 0.350000 308470752.000000 +39.392502 -23.432501 3.167500 308570496.000000 +23.502501 -4.532500 5.075000 308670784.000000 +-3.955000 -16.222500 3.955000 308770496.000000 +-5.775000 0.752500 7.210000 308870752.000000 +-4.847500 -0.192500 2.765000 308970496.000000 +-5.057500 0.192500 2.362500 309070752.000000 +-5.040000 0.227500 2.345000 309170496.000000 +-5.022500 0.227500 2.362500 309270784.000000 +-5.075000 0.227500 2.362500 309370496.000000 +-5.075000 0.262500 2.362500 309470976.000000 +-5.022500 0.262500 2.397500 309570496.000000 +-5.022500 0.262500 2.380000 309670880.000000 +-5.075000 0.227500 2.397500 309770496.000000 +-5.040000 0.192500 2.467500 309870912.000000 +-5.092500 -0.367500 -4.340000 309970528.000000 +-5.127500 -0.157500 3.920000 310070944.000000 +-3.920000 -0.787500 -0.262500 310171168.000000 +-1.767500 -1.207500 -4.322500 310270880.000000 +16.135000 -0.752500 0.157500 310370560.000000 +92.697502 -0.717500 12.775000 310470848.000000 +144.514999 1.347500 -5.267500 310570496.000000 +146.195007 17.097500 -15.540000 310670912.000000 +142.065002 -14.402500 -14.997500 310770496.000000 +105.139999 5.442500 16.240000 310870752.000000 +80.010002 -24.692499 -3.202500 310970592.000000 +77.367500 -8.522500 -0.822500 311070784.000000 +78.680000 15.662500 -4.935000 311170944.000000 +119.489998 -3.272500 1.907500 311270720.000000 +178.535004 10.622500 -8.470000 311370496.000000 +236.740005 46.287498 -39.060001 311470912.000000 +195.720001 36.487499 -27.492500 311570464.000000 +160.615005 17.692499 -21.822500 311670848.000000 +104.195000 -27.002501 -7.472500 311770496.000000 +41.072498 67.602501 3.062500 311870752.000000 +1.732500 -3.552500 21.787500 311970496.000000 +-1.732500 -49.717499 7.245000 312070752.000000 +-4.707500 17.097500 1.942500 312170496.000000 +-5.092500 -1.487500 1.015000 312270880.000000 +-5.075000 0.297500 6.335000 312370464.000000 +-5.057500 0.647500 4.602500 312471040.000000 +-4.952500 0.682500 0.070000 312570496.000000 +-4.987500 -0.262500 2.327500 312670496.000000 +-5.040000 0.472500 3.115000 312770400.000000 +-5.005000 -1.102500 2.310000 312871104.000000 +-5.022500 -0.612500 2.345000 312970528.000000 +-5.022500 1.522500 2.257500 313070528.000000 +-4.987500 0.157500 2.310000 313170752.000000 +-5.040000 0.227500 2.275000 313270496.000000 +-5.022500 0.052500 2.292500 313370784.000000 +-5.005000 -0.297500 2.292500 313470560.000000 +-5.057500 2.117500 2.222500 313570848.000000 +-5.057500 -0.997500 2.310000 313670560.000000 +-5.022500 0.227500 2.275000 313770880.000000 +-5.040000 0.052500 2.327500 313870496.000000 +-4.970000 2.257500 -0.070000 313970944.000000 +-5.005000 -2.817500 2.380000 314070496.000000 +-5.075000 -1.137500 6.667500 314170912.000000 +-5.057500 -0.297500 5.757500 314270464.000000 +-5.022500 -0.052500 2.310000 314370880.000000 +-5.005000 0.227500 2.310000 314470560.000000 +-4.987500 -2.327500 3.482500 314570752.000000 +0.350000 -4.392500 4.917500 314670496.000000 +34.702499 2.152500 2.450000 314770848.000000 +63.209999 6.107500 3.850000 314870496.000000 +86.379997 10.657500 5.775000 314970816.000000 +102.269997 9.922500 7.612500 315070496.000000 +108.184998 31.237499 11.305000 315170944.000000 +104.317497 13.142500 2.117500 315270496.000000 +104.562500 5.897500 3.850000 315370720.000000 +93.747498 18.742500 7.542500 315470656.000000 +91.787498 10.972500 10.202500 315570752.000000 +100.152504 2.782500 16.799999 315670496.000000 +116.270004 -4.952500 13.457500 315770944.000000 +127.032501 -10.062500 9.730000 315870496.000000 +122.430000 -14.612500 7.805000 315970784.000000 +115.657501 -10.167500 11.900000 316070496.000000 +103.512497 -24.097500 11.077500 316170912.000000 +99.925003 -27.632500 6.370000 316270432.000000 +94.535004 -24.867500 8.960000 316370560.000000 +102.882500 -19.337500 0.175000 316470880.000000 +78.137497 35.227501 8.995000 316570496.000000 +21.559999 35.612499 20.037500 316670848.000000 +40.215000 52.202499 1.627500 316770688.000000 +15.487500 -7.052500 3.972500 316870848.000000 +32.182499 -39.147499 4.847500 316970560.000000 +-4.707500 -0.332500 2.432500 317070688.000000 +-5.057500 0.227500 2.380000 317170752.000000 +-5.075000 0.192500 2.345000 317270560.000000 +-5.075000 0.262500 2.380000 317370848.000000 +-5.075000 0.227500 2.362500 317470528.000000 +-5.075000 0.227500 2.362500 317570368.000000 +-5.075000 0.227500 2.327500 317670688.000000 +-5.075000 0.262500 2.380000 317770496.000000 +-5.040000 0.227500 2.362500 317870720.000000 +-5.075000 0.262500 2.380000 317970496.000000 +-5.057500 0.227500 2.362500 318070816.000000 +-5.022500 0.227500 2.362500 318170496.000000 +-4.970000 0.192500 2.362500 318270784.000000 +-2.677500 0.192500 -1.330000 318370688.000000 +0.437500 0.507500 1.295000 318471040.000000 +21.629999 0.822500 4.707500 318570464.000000 +78.785004 3.132500 1.295000 318670688.000000 +103.722504 -9.502500 -14.682500 318770464.000000 +118.912498 8.802500 -22.522501 318870848.000000 +138.845001 23.712500 1.260000 318970464.000000 +131.722504 2.677500 -2.065000 319070976.000000 +134.137497 -9.362500 1.365000 319170496.000000 +127.487503 -10.062500 15.260000 319270816.000000 +110.355003 -18.322500 15.277500 319370496.000000 +109.812500 -0.402500 8.627500 319470848.000000 +105.489998 1.452500 -5.372500 319570752.000000 +95.690002 -1.837500 -5.250000 319670784.000000 +87.849998 -10.307500 3.062500 319770464.000000 +76.387497 -9.012500 23.397501 319870720.000000 +72.974998 -12.932500 20.615000 319970592.000000 +62.352501 -9.362500 26.477501 320070720.000000 +35.805000 11.252500 -4.445000 320170496.000000 +26.180000 -13.422500 8.925000 320270784.000000 +37.817501 1.872500 6.387500 320370496.000000 +37.572498 16.852501 -12.040000 320470848.000000 +36.487499 -20.457500 -6.895000 320570496.000000 +63.857502 -0.682500 0.420000 320670720.000000 +33.915001 11.987500 5.687500 320770464.000000 +20.212500 -13.317500 -11.602500 320870720.000000 +3.027500 17.237499 -15.085000 320970496.000000 +-5.635000 7.997500 23.100000 321070720.000000 +-6.107500 10.132500 25.847500 321170496.000000 +-5.512500 -2.817500 11.830000 321270688.000000 +-5.092500 -15.767500 -0.735000 321370464.000000 +-4.917500 0.297500 1.330000 321470976.000000 +-5.022500 -0.507500 2.065000 321570496.000000 +-5.005000 -0.962500 0.910000 321670880.000000 +-5.022500 -0.437500 2.275000 321770496.000000 +-5.040000 -1.837500 1.732500 321870784.000000 +-4.970000 -2.117500 1.242500 321970496.000000 +-5.005000 -1.102500 1.610000 322070848.000000 +-5.040000 2.222500 1.750000 322170432.000000 +-5.110000 -0.752500 1.960000 322270400.000000 +-5.022500 0.472500 2.135000 322370560.000000 +-5.005000 -0.087500 2.082500 322470560.000000 +-5.005000 -0.227500 1.942500 322570880.000000 +-5.040000 -0.192500 1.995000 322670688.000000 +-5.022500 -0.262500 1.855000 322770656.000000 +-4.970000 -1.697500 -1.487500 322870432.000000 +-5.022500 0.262500 1.942500 322970400.000000 +-5.040000 0.612500 1.750000 323070368.000000 +-5.022500 0.122500 -1.365000 323170368.000000 +-5.075000 0.997500 2.257500 323270368.000000 +-5.040000 0.437500 2.222500 323370368.000000 +-5.005000 -1.032500 -2.100000 323470368.000000 +-5.040000 -1.277500 -1.942500 323570368.000000 +-5.057500 0.262500 1.172500 323670336.000000 +-5.092500 0.367500 2.257500 323770368.000000 +-5.075000 0.402500 1.925000 323870368.000000 +-5.057500 0.017500 1.645000 323970336.000000 +-5.075000 0.262500 2.047500 324071552.000000 +-5.075000 0.297500 1.890000 324170624.000000 +-5.057500 0.192500 2.187500 324270784.000000 +-5.092500 -0.017500 1.592500 324370528.000000 +-5.092500 0.157500 2.222500 324470944.000000 +-5.092500 0.052500 1.750000 324570528.000000 +-5.092500 0.297500 1.942500 324670816.000000 +-5.092500 0.052500 1.890000 324770688.000000 +-5.162500 1.907500 2.642500 324870784.000000 +-5.127500 1.732500 4.130000 324970720.000000 +-5.197500 3.657500 6.055000 325070848.000000 +-5.250000 -2.642500 16.100000 325170496.000000 +-5.180000 2.292500 3.167500 325270880.000000 +-5.022500 -0.437500 1.837500 325370560.000000 +-5.040000 2.502500 3.307500 325470816.000000 +-5.092500 2.327500 1.505000 325570496.000000 +-4.987500 -4.182500 -1.102500 325670752.000000 +-5.092500 -0.507500 2.257500 325770496.000000 +-5.162500 4.952500 2.187500 325870784.000000 +-4.987500 -2.572500 1.662500 325970592.000000 +-5.127500 2.712500 3.220000 326070720.000000 +-5.022500 -3.027500 2.660000 326170464.000000 +-5.110000 0.262500 3.307500 326270752.000000 +-5.110000 0.297500 2.677500 326373152.000000 +-5.127500 1.067500 2.870000 326470784.000000 +-5.005000 0.052500 1.417500 326570496.000000 +-5.092500 -0.892500 0.647500 326670688.000000 +-5.110000 -0.157500 1.732500 326770496.000000 +-5.197500 2.712500 2.257500 326870752.000000 +-5.145000 2.817500 2.695000 326970496.000000 +-5.110000 1.767500 2.327500 327070720.000000 +-5.040000 0.927500 2.205000 327170496.000000 +-5.092500 -1.172500 2.257500 327270720.000000 +-5.092500 -0.472500 2.607500 327370496.000000 +-5.040000 -1.417500 2.292500 327470944.000000 +-4.987500 -2.992500 2.117500 327570560.000000 +-5.040000 0.157500 2.152500 327670784.000000 +-5.040000 0.962500 1.925000 327770464.000000 +-5.092500 -0.262500 1.890000 327870752.000000 +-5.127500 -0.892500 2.240000 327970496.000000 +-5.110000 -2.152500 2.310000 328070784.000000 +-5.197500 -0.402500 2.695000 328170464.000000 +-5.232500 -7.122500 0.595000 328270752.000000 +-5.320000 2.152500 2.887500 328370464.000000 +-2.817500 2.187500 -14.455000 328470944.000000 +9.187500 -25.847500 -16.799999 328570496.000000 +44.222500 -16.327499 -12.582500 328670880.000000 +74.584999 -7.542500 -2.275000 328770496.000000 +109.970001 -17.272501 -6.247500 328870912.000000 +123.672501 -13.597500 -41.702499 328970624.000000 +101.167503 23.187500 4.235000 329070912.000000 +92.330002 8.207500 -0.385000 329170528.000000 +95.987503 7.227500 -6.597500 329270752.000000 +71.872498 3.377500 -19.775000 329370464.000000 +18.112499 -11.322500 1.627500 329470560.000000 +21.927500 -14.542500 -1.540000 329570432.000000 +32.689999 -6.212500 3.500000 329670400.000000 +72.852501 -10.762500 -1.715000 329770336.000000 +76.754997 -0.577500 7.542500 329870720.000000 +105.787498 5.477500 -28.927500 329970496.000000 +168.332504 -11.532500 -13.160000 330070688.000000 +158.270004 15.592500 -5.250000 330170496.000000 +181.264999 -0.577500 17.097500 330270784.000000 +85.207497 37.362499 2.747500 330370496.000000 +75.162498 29.032499 -27.037500 330470848.000000 +97.614998 15.487500 -13.965000 330570496.000000 +20.545000 -6.702500 5.477500 330670752.000000 +-2.747500 -18.742500 -6.107500 330770464.000000 +-32.724998 -12.827500 7.945000 330870784.000000 +-0.682500 4.707500 3.447500 330970464.000000 +26.495001 0.052500 2.782500 331070880.000000 +-5.512500 0.472500 2.870000 331170464.000000 +-5.110000 0.262500 2.327500 331270848.000000 +-5.127500 0.262500 2.310000 331370784.000000 +-5.110000 0.262500 2.310000 331470816.000000 +-5.127500 0.227500 2.327500 331570368.000000 +-5.022500 0.192500 2.590000 331670784.000000 +-0.717500 -0.227500 -5.390000 331770496.000000 +16.940001 0.192500 -0.735000 331870784.000000 +108.902504 -5.092500 -10.395000 331970624.000000 +152.022507 -2.887500 -6.527500 332070752.000000 +183.994995 11.532500 -4.690000 332170464.000000 +217.997498 16.117500 -3.237500 332270752.000000 +206.744995 -14.157500 9.432500 332370528.000000 +141.627502 8.592500 26.477501 332470560.000000 +142.257507 0.997500 -1.855000 332570752.000000 +200.865005 29.662500 -0.367500 332670496.000000 +210.070007 14.017500 -10.430000 332770816.000000 +171.220001 4.532500 -23.957500 332870496.000000 +126.402504 7.227500 -5.600000 332970784.000000 +73.412498 -12.092500 8.802500 333070496.000000 +23.887501 12.407500 13.002500 333170848.000000 +13.072500 -43.207500 6.527500 333270496.000000 +-5.320000 13.282500 6.702500 333370912.000000 +-5.145000 1.452500 6.895000 333470624.000000 +-5.040000 0.192500 0.612500 333570944.000000 +-5.110000 0.402500 2.012500 333670496.000000 +-5.075000 1.102500 2.257500 333770848.000000 +-5.057500 0.157500 2.275000 333870624.000000 +-5.040000 0.822500 2.275000 333970464.000000 +-5.110000 0.612500 2.275000 334070400.000000 +-5.075000 -0.332500 1.995000 334170848.000000 +-5.022500 0.752500 2.240000 334270592.000000 +-5.075000 0.472500 2.222500 334370464.000000 +-5.075000 0.262500 2.275000 334470784.000000 +-5.075000 0.262500 2.240000 334570464.000000 +-5.075000 0.122500 2.257500 334670496.000000 +-5.075000 0.367500 2.345000 334770496.000000 +-5.075000 0.227500 2.327500 334870848.000000 +-5.075000 0.192500 2.257500 334970624.000000 +-5.075000 -0.262500 2.292500 335071232.000000 +-5.057500 0.297500 2.257500 335170720.000000 +-5.075000 0.857500 2.310000 335270496.000000 +-5.092500 -0.017500 2.292500 335370784.000000 +-5.075000 0.122500 2.257500 335470496.000000 +-5.110000 0.367500 2.257500 335570880.000000 +-5.092500 0.367500 2.257500 335670464.000000 +-5.092500 -0.017500 2.240000 335770848.000000 +-5.110000 0.297500 2.257500 335870496.000000 +-5.110000 1.872500 2.240000 335970752.000000 +-5.425000 0.647500 1.820000 336070496.000000 +-5.022500 0.717500 2.135000 336170496.000000 +-5.005000 -0.262500 1.802500 336270496.000000 +-5.110000 0.052500 1.715000 336370848.000000 +-6.282500 -0.752500 0.997500 336470592.000000 +-8.155000 -1.242500 -0.297500 336570880.000000 +-8.365000 -0.227500 2.590000 336670496.000000 +-4.025000 1.277500 2.782500 336770848.000000 +-2.625000 0.542500 1.645000 336870496.000000 +-2.677500 0.507500 2.432500 336970880.000000 +-3.342500 0.822500 1.470000 337070464.000000 +-4.970000 -0.122500 1.540000 337170880.000000 +-4.970000 -1.557500 1.522500 337270464.000000 +-5.057500 1.312500 2.275000 337370880.000000 +-5.092500 0.052500 2.275000 337470496.000000 +-5.075000 0.297500 2.240000 337570816.000000 +-5.092500 0.682500 2.275000 337670496.000000 +-5.057500 0.122500 2.257500 337770880.000000 +-5.075000 0.227500 2.257500 337870496.000000 +-5.092500 0.122500 2.257500 337971808.000000 +-5.092500 0.192500 2.292500 338070464.000000 +-5.110000 0.332500 2.257500 338170400.000000 +-5.092500 0.332500 2.292500 338272832.000000 +-5.057500 0.542500 2.275000 338370592.000000 +-5.092500 -0.402500 2.292500 338470688.000000 +-5.057500 0.542500 2.292500 338571168.000000 +-5.075000 0.437500 2.415000 338670528.000000 +-5.110000 -0.052500 2.257500 338770400.000000 +-5.110000 0.437500 2.257500 338870560.000000 +-5.092500 0.192500 2.275000 338970656.000000 +-5.092500 0.752500 2.310000 339070912.000000 +-5.145000 0.297500 2.292500 339170432.000000 +-5.110000 0.052500 2.257500 339270624.000000 +-5.110000 0.507500 2.257500 339370592.000000 +-5.092500 0.017500 2.222500 339471360.000000 +-5.110000 0.087500 2.275000 339570400.000000 +-5.092500 0.612500 2.257500 339670400.000000 +-5.110000 0.262500 2.240000 339770592.000000 +-5.110000 0.157500 2.222500 339870560.000000 +-5.127500 -0.087500 2.257500 339970912.000000 +-5.110000 0.752500 2.257500 340070400.000000 +-5.110000 0.262500 2.240000 340170656.000000 +-5.110000 0.402500 2.240000 340270752.000000 +-5.110000 0.297500 2.257500 340370624.000000 +-5.110000 0.472500 2.607500 340470944.000000 +-5.110000 0.402500 2.257500 340570432.000000 +-5.127500 0.052500 2.257500 340670624.000000 +-5.110000 0.612500 2.275000 340770624.000000 +-5.040000 1.102500 2.222500 340871008.000000 +-5.162500 -0.612500 2.555000 340970528.000000 +-5.127500 -0.297500 2.257500 341070464.000000 +-5.145000 0.717500 2.240000 341170848.000000 +-5.092500 1.802500 2.222500 341270464.000000 +-5.162500 -1.592500 2.257500 341370944.000000 +-5.145000 0.402500 2.222500 341471104.000000 +-5.110000 0.262500 2.257500 341570624.000000 +-5.127500 0.367500 2.240000 341672576.000000 +-5.110000 0.122500 2.257500 341770912.000000 +-5.145000 -0.262500 2.240000 341870720.000000 +-5.180000 -1.137500 2.257500 341970816.000000 +-5.110000 1.382500 2.240000 342070368.000000 +-5.162500 0.787500 2.240000 342170368.000000 +-5.320000 0.787500 2.397500 342270400.000000 +-12.302500 -3.027500 -2.975000 342370400.000000 +-43.557499 5.127500 -0.560000 342470656.000000 +-77.875000 14.892500 -4.655000 342570784.000000 +-104.370003 -7.542500 -5.075000 342671168.000000 +-115.797501 6.492500 -3.552500 342770592.000000 +-130.235001 -3.622500 0.525000 342870688.000000 +-138.425003 -5.407500 3.307500 342970496.000000 +-151.567505 -18.637501 8.032500 343070720.000000 +-158.654999 -26.267500 18.707500 343170496.000000 +-147.507507 -21.262501 13.737500 343270784.000000 +-87.605003 -15.417500 17.850000 343370464.000000 +-93.187500 5.932500 0.000000 343470752.000000 +-92.697502 8.382500 -0.822500 343570464.000000 +-147.157501 18.777500 -1.137500 343670720.000000 +-171.464996 -1.487500 1.767500 343770496.000000 +-141.522507 8.207500 6.142500 343870880.000000 +-127.120003 12.757500 14.700000 343970560.000000 +-114.152504 -1.312500 18.200001 344070880.000000 +-92.032501 -0.437500 19.757500 344170496.000000 +-19.844999 -0.367500 13.947500 344270880.000000 +-9.800000 3.167500 0.385000 344370496.000000 +-4.392500 -2.362500 2.555000 344470880.000000 +-5.267500 0.227500 2.362500 344570496.000000 +-5.215000 0.227500 2.380000 344670848.000000 +-5.215000 0.227500 2.345000 344770496.000000 +-5.197500 0.262500 2.310000 344870784.000000 +-5.582500 0.542500 1.155000 344970496.000000 +-8.172500 9.817500 4.987500 345070880.000000 +-8.610000 11.217500 4.935000 345170496.000000 +-7.332500 4.847500 0.787500 345270816.000000 +-0.630000 -10.307500 -3.465000 345370464.000000 +-8.645000 6.317500 0.192500 345470976.000000 +-7.840000 3.062500 4.532500 345570496.000000 +-6.720000 1.452500 5.425000 345670816.000000 +-14.332500 -1.662500 7.017500 345770464.000000 +-22.242500 3.692500 0.122500 345870400.000000 +-68.862503 -35.857502 -12.215000 345970432.000000 +-55.842499 12.477500 19.110001 346070912.000000 +-91.017502 17.552500 12.670000 346170528.000000 +-136.289993 -4.497500 1.995000 346270848.000000 +-149.642502 -21.332500 -0.595000 346370496.000000 +-153.895004 -4.987500 -2.485000 346470848.000000 +-149.274994 9.362500 -9.537500 346570400.000000 +-115.955002 12.687500 -16.799999 346670368.000000 +-131.652496 -24.202499 -16.292500 346770368.000000 +-145.110001 -21.087500 -15.487500 346870432.000000 +-136.604996 -30.117500 -12.810000 346970464.000000 +-125.754997 -9.957500 13.965000 347070400.000000 +-124.022499 -11.707500 16.240000 347170400.000000 +-139.352493 -16.362499 10.762500 347270400.000000 +-112.349998 -12.232500 7.385000 347370752.000000 +-76.754997 -5.687500 14.315001 347470592.000000 +-62.562500 -14.822500 11.882500 347570624.000000 +-12.197500 17.482500 13.825000 347670432.000000 +-5.145000 -0.682500 2.607500 347770368.000000 +-5.057500 -1.837500 2.292500 347870560.000000 +-5.180000 1.837500 2.240000 347970368.000000 +-5.110000 -0.297500 2.257500 348070368.000000 +-5.092500 8.662500 1.750000 348170400.000000 +-4.987500 -10.587500 3.657500 348270400.000000 +-5.285000 2.502500 2.362500 348370336.000000 +-5.180000 1.942500 2.205000 348470432.000000 +-5.162500 0.997500 2.572500 348570336.000000 +-5.162500 1.242500 3.010000 348670368.000000 +-5.145000 1.627500 2.625000 348770464.000000 +-5.162500 1.102500 2.292500 348870400.000000 +-5.145000 -0.472500 2.327500 348970784.000000 +-5.145000 -0.367500 2.397500 349070624.000000 +-5.162500 0.927500 2.205000 349170496.000000 +-5.110000 0.297500 2.222500 349270688.000000 +-5.145000 -0.472500 2.625000 349370400.000000 +-5.197500 1.312500 2.222500 349470400.000000 +-5.145000 0.332500 2.240000 349571552.000000 +-5.127500 -0.472500 2.380000 349670560.000000 +-5.180000 0.682500 2.240000 349770688.000000 +-5.197500 0.402500 2.205000 349870528.000000 +-5.180000 0.402500 2.205000 349970944.000000 +-5.145000 0.262500 2.187500 350070496.000000 +-5.162500 0.192500 2.240000 350170400.000000 +-5.127500 -0.472500 2.222500 350270368.000000 +-5.180000 0.997500 2.205000 350370528.000000 +-5.127500 -0.507500 2.537500 350470496.000000 +-5.180000 0.472500 2.555000 350570752.000000 +-5.180000 1.067500 2.205000 350670464.000000 +-5.180000 0.402500 2.222500 350772800.000000 +-5.110000 0.787500 2.205000 350870432.000000 +-5.180000 0.052500 2.222500 350973920.000000 +-5.127500 0.297500 2.205000 351070400.000000 +-5.145000 0.122500 2.222500 351170336.000000 +-5.145000 0.157500 2.170000 351270496.000000 +-5.145000 -0.157500 2.345000 351370368.000000 +-5.197500 0.052500 2.240000 351470624.000000 +-5.162500 0.542500 2.187500 351570528.000000 +-5.180000 0.437500 2.222500 351670496.000000 +-5.145000 -1.347500 2.257500 351770816.000000 +-6.090000 2.187500 0.052500 351870528.000000 +-12.320000 -1.697500 9.292500 351970432.000000 +-38.727501 6.177500 10.640000 352070464.000000 +-108.937500 -2.642500 7.962500 352170944.000000 +-78.785004 -0.087500 3.902500 352270464.000000 +-44.607502 0.157500 1.977500 352370688.000000 +-46.480000 3.832500 4.970000 352470528.000000 +-42.017502 2.397500 4.462500 352570784.000000 +-66.307503 -0.682500 -0.052500 352670560.000000 +-107.870003 -2.817500 6.475000 352770944.000000 +-140.367508 -9.187500 19.687500 352870496.000000 +-176.137497 -16.852501 24.500000 352971072.000000 +-179.305008 -19.757500 23.887501 353070528.000000 +-147.122498 -8.137500 -1.330000 353170720.000000 +-135.660004 -6.282500 0.087500 353270496.000000 +-147.384995 10.937500 -9.607500 353371040.000000 +-185.027496 23.222500 -28.770000 353470656.000000 +-178.027496 10.867500 -0.367500 353570944.000000 +-152.687500 9.327500 16.695000 353670400.000000 +-104.842499 -18.147501 12.652500 353770368.000000 +-78.050003 -22.837500 2.432500 353870368.000000 +-4.357500 0.052500 -4.235000 353970368.000000 +-12.687500 -0.367500 -1.312500 354070368.000000 +-11.060000 0.192500 6.492500 354170528.000000 +-5.022500 0.262500 3.097500 354270560.000000 +-5.250000 0.297500 2.292500 354370528.000000 +-5.232500 0.262500 2.292500 354470752.000000 +-5.197500 0.297500 2.275000 354570816.000000 +-5.232500 0.262500 2.275000 354670496.000000 +-4.970000 0.297500 6.790000 354770688.000000 +-8.767500 0.157500 5.285000 354870464.000000 +-14.595000 -8.522500 13.107500 354971008.000000 +-69.107498 -8.557500 20.475000 355070688.000000 +-129.867508 59.517502 20.264999 355170912.000000 +-111.457504 -8.907500 2.310000 355270496.000000 +-122.167503 21.927500 10.955000 355370912.000000 +-135.975006 -9.082500 5.022500 355470624.000000 +-130.602493 -10.237500 -7.560000 355570848.000000 +-130.585007 -5.057500 -11.585000 355670496.000000 +-139.335007 6.247500 -24.465000 355771072.000000 +-123.129997 -0.647500 -9.800000 355870464.000000 +-117.389999 -5.757500 -11.987500 355971040.000000 +-138.880005 2.152500 -3.167500 356070592.000000 +-148.242508 -3.237500 -3.150000 356170496.000000 +-148.610001 -23.747499 -10.290000 356270912.000000 +-158.690002 -16.782499 -3.465000 356370496.000000 +-153.335007 -10.587500 25.322500 356470944.000000 +-106.697502 -10.692500 36.365002 356570496.000000 +-60.567501 -11.812500 28.980000 356670848.000000 +-23.450001 12.057500 16.030001 356770496.000000 +-5.197500 10.622500 7.262500 356870880.000000 +-5.250000 -10.832500 2.485000 356970592.000000 +-5.215000 0.857500 2.292500 357070784.000000 +-5.127500 6.527500 2.135000 357170560.000000 +-5.215000 -7.647500 2.275000 357270880.000000 +-5.180000 7.892500 0.700000 357370656.000000 +-4.970000 17.027500 1.960000 357470752.000000 +-5.355000 -11.392500 1.732500 357570368.000000 +-5.180000 -3.342500 0.525000 357670752.000000 +-5.197500 -0.437500 1.802500 357770496.000000 +-5.197500 -0.122500 2.485000 357870528.000000 +-5.127500 0.682500 2.257500 357970368.000000 +-5.267500 -1.697500 2.397500 358070400.000000 +-5.162500 0.297500 2.275000 358170816.000000 +-5.197500 -0.017500 2.275000 358270624.000000 +-5.162500 0.437500 2.415000 358370528.000000 +-5.162500 0.577500 2.222500 358470688.000000 +-5.162500 0.752500 2.222500 358570528.000000 +-5.215000 -0.052500 2.222500 358670784.000000 +-5.197500 0.437500 2.240000 358770496.000000 +-5.267500 0.402500 4.812500 358870912.000000 +-5.232500 0.682500 2.345000 358970784.000000 +-5.180000 -0.437500 2.327500 359070496.000000 +-5.145000 0.227500 2.450000 359170848.000000 +-5.162500 0.367500 2.222500 359270560.000000 +-5.180000 0.052500 2.257500 359370784.000000 +-5.162500 0.332500 2.240000 359470496.000000 +-5.162500 -0.017500 2.257500 359570784.000000 +-5.250000 0.017500 1.120000 359670464.000000 +-6.317500 0.717500 -1.715000 359770784.000000 +-16.555000 -4.987500 -6.545000 359870496.000000 +-73.675003 15.907500 -17.797501 359970784.000000 +-120.557503 11.077500 -4.217500 360070496.000000 +-176.907501 -11.147500 -30.817501 360170784.000000 +-197.994995 -4.742500 -9.712500 360270464.000000 +-168.139999 6.002500 -4.602500 360370784.000000 +-137.427505 12.022500 10.482500 360470624.000000 +-103.074997 -2.677500 18.830000 360570912.000000 +-83.824997 -14.997500 17.639999 360670496.000000 +-136.972504 -30.187500 -11.077500 360770880.000000 +-183.820007 -39.287498 -20.282499 360870496.000000 +-251.895004 0.367500 -10.045000 360970784.000000 +-227.062500 -6.422500 10.482500 361070496.000000 +-154.157501 -3.202500 22.557501 361170912.000000 +-102.637497 7.682500 -1.400000 361270464.000000 +-5.040000 -0.892500 -1.312500 361370752.000000 +-5.477500 8.837500 -13.842500 361470464.000000 +-5.477500 1.172500 2.485000 361570752.000000 +-5.215000 0.332500 2.327500 361670464.000000 +-5.232500 0.332500 2.310000 361770848.000000 +-5.197500 0.332500 2.310000 361870400.000000 +-5.162500 0.577500 -0.840000 361971136.000000 +-5.442500 1.662500 -28.455000 362070496.000000 +-11.025000 -2.117500 15.067500 362170784.000000 +-12.950000 -0.577500 12.250000 362270464.000000 +-18.812500 13.842500 17.167500 362370880.000000 +-43.924999 -4.042500 13.772500 362470496.000000 +-74.445000 -7.822500 16.957500 362570848.000000 +-108.972504 4.077500 6.720000 362670496.000000 +-138.354996 16.782499 2.415000 362770816.000000 +-165.217499 9.257500 4.112500 362870496.000000 +-151.445007 6.982500 -6.020000 362970720.000000 +-140.210007 9.467500 -3.220000 363070464.000000 +-153.125000 5.582500 1.102500 363170784.000000 +-158.952499 -1.522500 2.905000 363270464.000000 +-152.774994 0.612500 4.480000 363370752.000000 +-141.330002 -9.152500 8.767500 363470592.000000 +-124.285004 4.042500 11.865000 363570944.000000 +-104.842499 -2.152500 10.237500 363670496.000000 +-94.622498 5.582500 1.312500 363770880.000000 +-84.122498 4.077500 -3.500000 363870464.000000 +-74.970001 -0.262500 -6.772500 363970496.000000 +-52.185001 -20.177500 -5.512500 364070784.000000 +-17.780001 66.097504 5.722500 364170464.000000 +-5.285000 -20.142500 13.755000 364270720.000000 +-5.197500 4.532500 2.467500 364370400.000000 +-5.180000 3.517500 2.222500 364470784.000000 +-5.127500 0.367500 2.275000 364570464.000000 +-5.127500 -0.227500 2.292500 364670816.000000 +-5.075000 1.977500 2.257500 364770400.000000 +-5.040000 -11.077500 2.485000 364870432.000000 +-5.180000 5.407500 2.222500 364970464.000000 +-5.145000 -2.502500 2.222500 365070560.000000 +-5.110000 1.872500 2.100000 365170560.000000 +-5.057500 8.522500 -7.805000 365270368.000000 +-5.162500 -6.597500 2.362500 365370400.000000 +-5.180000 6.492500 2.170000 365471168.000000 +-5.180000 -3.517500 2.327500 365571008.000000 +-5.145000 0.017500 2.257500 365670880.000000 +-5.127500 -0.472500 2.275000 365770400.000000 +-5.162500 1.312500 2.257500 365870656.000000 +-5.180000 1.137500 2.240000 365970464.000000 +-5.180000 0.402500 2.257500 366070464.000000 +-4.987500 -2.782500 2.397500 366170432.000000 +-5.215000 3.237500 2.205000 366270560.000000 +-5.145000 -0.087500 2.257500 366370784.000000 +-5.180000 0.717500 2.240000 366470624.000000 +-5.127500 -0.647500 2.257500 366570400.000000 +-5.215000 -0.787500 2.257500 366670784.000000 +-5.197500 0.857500 2.275000 366770432.000000 +-5.180000 1.347500 2.240000 366870368.000000 +-5.110000 0.997500 2.240000 366970400.000000 +-5.197500 -1.347500 2.292500 367070368.000000 +-5.197500 1.102500 2.257500 367170368.000000 +-5.180000 0.332500 2.257500 367270528.000000 +-5.180000 0.192500 2.257500 367370432.000000 +-5.110000 0.612500 2.310000 367470624.000000 +-5.197500 -0.647500 2.257500 367570528.000000 +-5.197500 0.927500 2.222500 367670528.000000 +-5.197500 -0.122500 2.240000 367770592.000000 +-5.215000 0.367500 2.257500 367870528.000000 +-5.180000 1.802500 2.222500 367970560.000000 +-5.197500 -0.962500 2.275000 368070848.000000 +-5.197500 0.087500 2.240000 368172896.000000 +-5.197500 0.262500 2.257500 368270528.000000 +-5.250000 0.262500 2.240000 368370688.000000 +-5.250000 0.227500 2.257500 368470496.000000 +-5.267500 0.262500 2.222500 368570784.000000 +-5.232500 0.297500 2.240000 368670528.000000 +-5.250000 0.227500 2.240000 368770848.000000 +-5.215000 0.262500 2.240000 368870400.000000 +-5.110000 -3.727500 2.450000 368970368.000000 +-5.232500 -0.717500 2.257500 369070464.000000 +-5.127500 -3.167500 2.345000 369170656.000000 +-5.355000 12.547500 2.047500 369270720.000000 +-4.882500 3.622500 2.240000 369370656.000000 +-5.390000 -9.922500 2.520000 369470432.000000 +-5.180000 -3.167500 2.310000 369570624.000000 +-5.302500 10.797500 2.100000 369670624.000000 +-4.882500 0.297500 2.520000 369770368.000000 +-5.267500 5.442500 2.205000 369870496.000000 +-5.267500 -8.732500 2.415000 369970560.000000 +-5.127500 -8.207500 2.415000 370070784.000000 +-5.337500 9.222500 2.065000 370170400.000000 +-5.180000 -3.062500 2.327500 370270496.000000 +-5.250000 2.537500 2.222500 370370528.000000 +-5.215000 -0.017500 2.240000 370470432.000000 +-5.180000 -0.367500 2.292500 370570368.000000 +-5.232500 2.467500 2.205000 370670496.000000 +-5.215000 -0.752500 2.257500 370770496.000000 +-5.215000 0.192500 2.257500 370870528.000000 +-5.022500 -7.927500 2.537500 370970464.000000 +-5.110000 -3.902500 2.345000 371071072.000000 +-5.285000 4.847500 2.170000 371170560.000000 +-5.057500 16.957500 2.065000 371270432.000000 +-4.987500 11.287500 2.502500 371370400.000000 +-5.215000 -3.832500 2.310000 371470528.000000 +-5.250000 -5.232500 2.327500 371570560.000000 +-5.215000 -2.047500 2.240000 371670592.000000 +-5.250000 -24.657499 2.852500 371770496.000000 +-5.250000 -1.417500 2.240000 371870784.000000 +-5.302500 2.537500 2.187500 371970464.000000 +-5.722500 21.437500 2.170000 372071552.000000 +-5.600000 -6.422500 5.582500 372170528.000000 +-5.320000 1.347500 2.310000 372270400.000000 +-5.250000 0.647500 2.205000 372370528.000000 +-5.250000 -0.122500 2.222500 372470688.000000 +-5.250000 0.402500 2.240000 372570688.000000 +-5.232500 -0.157500 2.222500 372670400.000000 +-5.232500 3.027500 2.222500 372770496.000000 +-5.197500 -6.387500 2.345000 372870528.000000 +-5.250000 4.007500 2.170000 372970496.000000 +-5.180000 0.087500 2.257500 373070560.000000 +-5.320000 1.347500 2.222500 373170400.000000 +-5.250000 -0.192500 2.240000 373270560.000000 +-5.267500 0.367500 2.222500 373370560.000000 +-5.232500 0.332500 2.240000 373470528.000000 +-5.215000 -1.732500 2.275000 373570496.000000 +-5.285000 2.502500 2.205000 373670432.000000 +-5.232500 0.507500 2.240000 373770912.000000 +-5.250000 -0.157500 2.257500 373871808.000000 +-5.302500 8.907500 2.170000 373971040.000000 +-5.285000 -16.187500 2.835000 374070400.000000 +-5.425000 10.062500 2.065000 374170528.000000 +-5.250000 -4.497500 2.362500 374272864.000000 +-5.302500 2.502500 2.222500 374370880.000000 +-5.162500 -0.612500 2.450000 374470432.000000 +-5.302500 6.142500 2.467500 374570560.000000 +-5.232500 -7.997500 2.380000 374671168.000000 +-5.355000 5.897500 2.117500 374770944.000000 +-5.267500 -0.507500 2.222500 374870400.000000 +-5.285000 -0.227500 2.257500 374970400.000000 +-5.267500 0.087500 2.240000 375070496.000000 +-5.285000 0.367500 2.240000 375170720.000000 +-5.285000 0.262500 2.222500 375270496.000000 +-5.162500 1.417500 2.327500 375370368.000000 +-5.302500 8.452500 2.222500 375470432.000000 +-5.250000 -0.402500 2.275000 375570560.000000 +-5.215000 0.822500 2.257500 375670560.000000 +-5.320000 -4.707500 2.310000 375770400.000000 +-5.092500 -20.037500 2.957500 375870368.000000 +-5.495000 13.247500 2.065000 375970368.000000 +-5.285000 1.592500 2.257500 376070496.000000 +-5.302500 0.997500 2.187500 376170528.000000 +-5.267500 0.682500 2.257500 376270368.000000 +-5.250000 -2.047500 2.310000 376370368.000000 +-5.337500 2.677500 2.187500 376470496.000000 +-5.267500 0.192500 2.222500 376570528.000000 +-5.285000 0.437500 2.222500 376670560.000000 +-5.267500 0.472500 2.257500 376770784.000000 +-5.267500 0.297500 2.205000 376870496.000000 +-5.250000 0.297500 2.222500 376970432.000000 +-5.215000 0.332500 2.222500 377070336.000000 +-5.250000 0.297500 2.222500 377170336.000000 +-5.250000 0.332500 2.222500 377270368.000000 +-5.267500 0.297500 2.222500 377370432.000000 +-5.232500 0.297500 2.222500 377470528.000000 +-5.267500 0.297500 2.222500 377570784.000000 +-5.302500 0.297500 2.240000 377670528.000000 +-5.285000 0.297500 2.257500 377770464.000000 +-5.302500 0.262500 2.222500 377870752.000000 +-5.250000 0.297500 2.205000 377970592.000000 +-5.302500 0.297500 2.222500 378070880.000000 +-5.267500 0.262500 2.257500 378170528.000000 +-5.267500 0.297500 2.205000 378270944.000000 +-5.250000 0.297500 2.240000 378370496.000000 +-5.285000 0.297500 2.222500 378470944.000000 +-5.232500 0.297500 2.222500 378570496.000000 +-5.285000 0.297500 2.240000 378670784.000000 +-5.285000 0.262500 2.240000 378770496.000000 +-5.320000 0.262500 2.222500 378870752.000000 +-5.302500 0.262500 2.240000 378970496.000000 +-5.337500 0.227500 2.240000 379070784.000000 +-5.267500 0.297500 2.240000 379170464.000000 +-5.285000 0.297500 2.257500 379270720.000000 +-5.250000 0.297500 2.240000 379370464.000000 +-5.302500 0.332500 2.240000 379470880.000000 +-5.267500 0.227500 2.240000 379570464.000000 +-5.285000 0.122500 2.257500 379670752.000000 +-5.285000 0.087500 2.257500 379770496.000000 +-5.057500 -20.877501 -3.045000 379870752.000000 +-5.810000 -9.362500 -5.967500 379970592.000000 +-5.337500 2.082500 1.120000 380070752.000000 +-5.320000 -1.417500 2.240000 380170496.000000 +-5.372500 -0.227500 2.240000 380270848.000000 +-5.390000 0.402500 -1.102500 380370496.000000 +-5.372500 -0.052500 1.382500 380470848.000000 +-5.337500 0.367500 0.035000 380570496.000000 +-5.250000 0.227500 1.855000 380670816.000000 +-5.285000 0.227500 1.662500 380770496.000000 +-5.250000 0.262500 2.292500 380870912.000000 +-5.250000 0.332500 2.275000 380970496.000000 +-5.285000 0.227500 2.257500 381070880.000000 +-5.250000 0.367500 2.257500 381170496.000000 +-5.267500 0.157500 2.257500 381270816.000000 +-5.232500 0.367500 0.980000 381370496.000000 +-5.232500 0.332500 2.327500 381471072.000000 +-5.232500 0.227500 2.292500 381570464.000000 +-5.267500 0.332500 2.275000 381670816.000000 +-5.215000 0.332500 2.257500 381770496.000000 +-5.232500 0.297500 2.275000 381870880.000000 +-5.180000 0.402500 2.275000 381970496.000000 +-5.197500 0.542500 2.275000 382070816.000000 +-5.215000 0.577500 2.275000 382170496.000000 +-5.215000 0.227500 2.275000 382270912.000000 +-5.232500 0.227500 2.292500 382370496.000000 +-5.215000 0.087500 2.310000 382570880.000000 +-5.215000 0.227500 2.310000 382670496.000000 +-5.267500 0.262500 2.327500 382770848.000000 +-5.250000 0.262500 2.275000 382870496.000000 +-5.232500 0.297500 2.292500 382971104.000000 +-5.232500 0.332500 2.275000 383070496.000000 +-5.232500 0.332500 2.275000 383170880.000000 +-5.232500 0.297500 2.257500 383270496.000000 +-5.232500 0.157500 2.257500 383370688.000000 +-5.215000 0.192500 2.275000 383470464.000000 +-5.197500 0.332500 2.275000 383570848.000000 +-5.215000 0.297500 2.292500 383670368.000000 +-5.232500 0.192500 2.275000 383770368.000000 +-5.197500 0.227500 2.292500 383870368.000000 +-5.197500 0.367500 2.257500 383970432.000000 +-5.197500 0.297500 2.275000 384070432.000000 +-5.232500 0.192500 2.275000 384172736.000000 +-5.232500 0.367500 2.275000 384270528.000000 +-5.215000 0.437500 2.240000 384372768.000000 +-5.250000 0.542500 2.257500 384470592.000000 +-5.215000 0.122500 2.257500 384570752.000000 +-5.250000 0.297500 2.292500 384670592.000000 +-5.197500 0.507500 2.257500 384770720.000000 +-5.232500 0.192500 2.275000 384870592.000000 +-5.215000 0.402500 2.275000 384970784.000000 +-5.232500 0.087500 2.257500 385070880.000000 +-5.232500 0.262500 2.275000 385170848.000000 +-5.250000 0.227500 2.275000 385270560.000000 +-5.250000 0.087500 2.257500 385370976.000000 +-5.250000 0.227500 2.292500 385470464.000000 +-5.215000 0.367500 2.257500 385570752.000000 +-5.250000 0.227500 2.257500 385670720.000000 +-5.232500 0.437500 2.257500 385870592.000000 +-5.162500 0.332500 2.257500 385970976.000000 +-5.250000 0.087500 2.292500 386070656.000000 diff --git a/src/sensor_fusion/design/data/100ms/roll/magnetic.txt b/src/sensor_fusion/design/data/100ms/roll/magnetic.txt new file mode 100755 index 0000000..6e1376c --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/roll/magnetic.txt @@ -0,0 +1,842 @@ +4.250000 -44.375000 -12.062500 301971680.000000 +5.312500 -44.562500 -12.750000 302071680.000000 +5.937500 -44.125000 -13.375000 302171680.000000 +5.437500 -44.312500 -13.500000 302271680.000000 +6.062500 -44.562500 -13.562500 302371680.000000 +6.125000 -44.437500 -13.687500 302471680.000000 +6.125000 -44.812500 -13.562500 302571680.000000 +5.937500 -44.562500 -13.187500 302671680.000000 +6.062500 -44.687500 -13.375000 302771680.000000 +6.062500 -44.812500 -13.375000 302871680.000000 +6.062500 -44.937500 -13.250000 302971680.000000 +6.125000 -45.000000 -13.312500 303071680.000000 +5.937500 -45.062500 -13.625000 303171680.000000 +6.125000 -45.375000 -13.687500 303271680.000000 +6.437500 -45.312500 -13.625000 303371680.000000 +6.500000 -45.437500 -13.750000 303471680.000000 +6.562500 -45.500000 -13.875000 303571680.000000 +6.750000 -45.375000 -14.062500 303671680.000000 +6.937500 -45.437500 -14.187500 303771680.000000 +7.000000 -45.437500 -13.875000 303871680.000000 +7.125000 -45.312500 -13.625000 303971680.000000 +7.125000 -45.125000 -13.687500 304071680.000000 +6.812500 -45.062500 -13.687500 304171680.000000 +6.625000 -45.062500 -13.750000 304271680.000000 +6.500000 -44.875000 -13.812500 304371680.000000 +6.375000 -45.062500 -13.625000 304471680.000000 +6.437500 -44.937500 -13.562500 304571680.000000 +6.625000 -45.000000 -13.625000 304671680.000000 +6.625000 -44.937500 -13.625000 304771680.000000 +6.562500 -45.000000 -13.312500 304871680.000000 +6.687500 -45.312500 -13.250000 304971680.000000 +6.937500 -45.250000 -13.125000 305071680.000000 +7.250000 -45.375000 -12.312500 305171680.000000 +7.375000 -45.312500 -11.875000 305271680.000000 +7.250000 -45.437500 -11.250000 305371680.000000 +7.125000 -45.437500 -10.500000 305471680.000000 +7.250000 -45.625000 -9.687500 305571680.000000 +7.250000 -45.687500 -8.812500 305671680.000000 +7.312500 -45.625000 -7.875000 305771680.000000 +7.250000 -45.750000 -6.562500 305871680.000000 +7.000000 -45.750000 -5.937500 305971680.000000 +6.875000 -45.937500 -4.875000 306071680.000000 +7.062500 -45.875000 -4.062500 306171680.000000 +7.312500 -45.875000 -3.187500 306271680.000000 +7.125000 -45.625000 -2.187500 306371680.000000 +7.187500 -45.062500 -0.937500 306471680.000000 +7.312500 -44.500000 0.812500 306571680.000000 +7.375000 -43.562500 3.062500 306671680.000000 +7.875000 -42.125000 6.000000 306771680.000000 +8.500000 -39.875000 9.000000 306871680.000000 +8.625000 -37.250000 12.500000 306971680.000000 +8.750000 -34.125000 16.437500 307071680.000000 +8.937500 -30.625000 20.562500 307171680.000000 +9.062500 -26.687500 24.562500 307271680.000000 +8.812500 -21.562500 28.375000 307371680.000000 +8.375000 -15.937500 31.062500 307471680.000000 +7.500000 -10.250000 33.437500 307571680.000000 +6.437500 -4.687500 35.125000 307671680.000000 +5.562500 0.937500 35.812500 307771680.000000 +4.625000 6.187500 35.937500 307871680.000000 +3.937500 11.375000 35.625000 307971680.000000 +3.437500 16.062500 34.562500 308071680.000000 +3.312500 20.062500 32.625000 308171680.000000 +3.500000 23.312500 30.500000 308271680.000000 +3.625000 26.375000 27.812500 308371680.000000 +3.687500 29.125000 25.250000 308471680.000000 +3.875000 31.250000 22.750000 308571680.000000 +4.125000 33.187500 20.187500 308671680.000000 +4.437500 34.687500 17.750000 308771680.000000 +4.625000 36.000000 16.000000 308871680.000000 +4.750000 36.687500 14.500000 308971680.000000 +4.750000 37.125000 13.500000 309071680.000000 +4.875000 37.250000 12.812500 309171680.000000 +5.062500 37.062500 12.562500 309271680.000000 +5.250000 37.062500 12.625000 309371680.000000 +5.312500 37.250000 12.562500 309471680.000000 +5.312500 37.187500 12.625000 309571680.000000 +5.375000 37.187500 12.437500 309671680.000000 +5.437500 37.312500 12.250000 309771680.000000 +5.562500 37.250000 12.375000 309871680.000000 +5.437500 37.375000 12.625000 309971680.000000 +5.500000 37.562500 12.375000 310071680.000000 +5.500000 37.437500 12.312500 310171680.000000 +5.500000 37.187500 12.000000 310271680.000000 +5.500000 37.437500 10.812500 310371680.000000 +5.375000 37.500000 8.687500 310471680.000000 +4.937500 37.250000 5.625000 310571680.000000 +4.312500 36.562500 1.125000 310671680.000000 +3.937500 35.312500 -3.875000 310771680.000000 +3.375000 33.937500 -8.937500 310871680.000000 +2.812500 32.062500 -14.500000 310971680.000000 +2.062500 29.562500 -20.125000 311071680.000000 +1.375000 26.312500 -25.000000 311171680.000000 +0.437500 22.187500 -29.312500 311271680.000000 +-0.062500 16.812500 -32.312500 311371680.000000 +0.187500 10.562500 -33.750000 311471680.000000 +0.312500 3.937500 -34.062500 311571680.000000 +0.687500 -3.312500 -33.000000 311671680.000000 +1.062500 -10.312500 -31.312500 311771680.000000 +1.812500 -17.000000 -29.000000 311871680.000000 +2.375000 -22.937500 -26.625000 311971680.000000 +3.500000 -27.937500 -23.812500 312071680.000000 +4.062500 -31.375000 -21.062500 312171680.000000 +4.062500 -33.562500 -18.812500 312271680.000000 +4.250000 -34.875000 -17.125000 312371680.000000 +4.250000 -35.500000 -16.437500 312471680.000000 +4.250000 -35.812500 -16.312500 312571680.000000 +3.875000 -35.750000 -16.000000 312671680.000000 +3.125000 -35.625000 -15.437500 312771680.000000 +2.625000 -35.750000 -15.437500 312871680.000000 +2.500000 -35.687500 -15.312500 312971680.000000 +2.500000 -35.562500 -15.187500 313071680.000000 +2.312500 -35.562500 -15.187500 313171680.000000 +2.187500 -35.500000 -15.187500 313271680.000000 +2.250000 -35.437500 -15.250000 313371680.000000 +2.437500 -35.437500 -15.375000 313471680.000000 +3.125000 -35.687500 -15.937500 313571680.000000 +3.312500 -35.812500 -15.812500 313671680.000000 +3.625000 -36.000000 -16.125000 313771680.000000 +3.562500 -35.812500 -16.250000 313871680.000000 +3.812500 -35.875000 -16.437500 313971680.000000 +3.875000 -35.812500 -16.562500 314071680.000000 +3.875000 -35.625000 -16.437500 314171680.000000 +3.750000 -35.750000 -16.500000 314271680.000000 +3.750000 -35.625000 -16.750000 314371680.000000 +3.875000 -35.750000 -16.875000 314471680.000000 +3.875000 -35.875000 -16.687500 314571680.000000 +3.875000 -36.187500 -16.312500 314671680.000000 +3.937500 -36.437500 -15.437500 314771680.000000 +4.187500 -36.750000 -13.562500 314871680.000000 +4.187500 -37.062500 -10.937500 314971680.000000 +4.375000 -37.187500 -7.437500 315071680.000000 +4.562500 -37.000000 -2.875000 315171680.000000 +4.875000 -36.125000 2.375000 315271680.000000 +4.937500 -35.062500 8.062500 315371680.000000 +5.125000 -33.250000 13.937500 315471680.000000 +5.062500 -30.500000 19.625000 315571680.000000 +5.062500 -26.937500 24.875000 315671680.000000 +5.437500 -22.562500 29.312500 315771680.000000 +5.937500 -17.125000 32.750000 315871680.000000 +6.562500 -11.125000 35.125000 315971680.000000 +7.000000 -4.750000 36.437500 316071680.000000 +7.937500 1.562500 36.500000 316171680.000000 +9.062500 8.125000 35.750000 316271680.000000 +10.375000 14.187500 34.062500 316371680.000000 +11.625000 19.937500 31.250000 316471680.000000 +12.562500 24.750000 28.250000 316571680.000000 +13.312500 28.500000 25.437500 316671680.000000 +13.687500 31.375000 22.750000 316771680.000000 +14.187500 33.562500 19.500000 316871680.000000 +14.250000 35.562500 17.250000 316971680.000000 +14.250000 36.500000 15.375000 317071680.000000 +14.062500 37.125000 13.875000 317171680.000000 +13.937500 37.375000 13.000000 317271680.000000 +13.625000 37.562500 12.437500 317371680.000000 +13.687500 37.812500 11.625000 317471680.000000 +13.562500 37.937500 11.312500 317571680.000000 +13.625000 37.750000 11.312500 317671680.000000 +13.625000 37.562500 11.312500 317771680.000000 +13.812500 37.687500 11.312500 317871680.000000 +13.687500 37.812500 11.562500 317971680.000000 +13.750000 37.812500 11.687500 318071680.000000 +14.062500 37.812500 11.500000 318171680.000000 +14.000000 37.812500 11.625000 318271680.000000 +14.062500 37.875000 11.375000 318371680.000000 +13.875000 37.937500 11.187500 318471680.000000 +14.062500 38.187500 10.187500 318571680.000000 +13.875000 38.437500 8.312500 318671680.000000 +13.500000 38.375000 5.437500 318771680.000000 +13.062500 37.937500 1.687500 318871680.000000 +12.562500 37.250000 -2.625000 318971680.000000 +12.125000 35.312500 -7.937500 319071680.000000 +11.625000 32.625000 -13.750000 319171680.000000 +11.312500 29.062500 -20.062500 319271680.000000 +10.562500 24.375000 -25.625000 319371680.000000 +10.250000 18.937500 -30.500000 319471680.000000 +10.125000 13.125000 -34.062500 319571680.000000 +9.937500 6.812500 -36.687500 319671680.000000 +9.375000 0.375000 -38.250000 319771680.000000 +9.062500 -5.500000 -38.812500 319871680.000000 +8.312500 -11.062500 -38.312500 319971680.000000 +7.375000 -16.062500 -36.937500 320071680.000000 +6.937500 -20.250000 -35.250000 320171680.000000 +6.000000 -24.000000 -33.375000 320271680.000000 +5.250000 -27.187500 -31.625000 320371680.000000 +4.687500 -29.562500 -29.500000 320471680.000000 +4.312500 -31.500000 -27.437500 320571680.000000 +4.187500 -33.375000 -25.125000 320671680.000000 +4.250000 -34.687500 -22.875000 320771680.000000 +4.687500 -35.812500 -20.812500 320871680.000000 +4.812500 -36.687500 -18.625000 320971680.000000 +5.062500 -37.500000 -16.875000 321071680.000000 +5.000000 -38.250000 -15.187500 321171680.000000 +4.812500 -38.687500 -13.750000 321271680.000000 +4.937500 -39.250000 -12.875000 321371680.000000 +4.562500 -39.500000 -12.312500 321471680.000000 +4.375000 -39.750000 -12.187500 321571680.000000 +4.000000 -39.875000 -12.000000 321671680.000000 +3.375000 -40.125000 -12.187500 321771680.000000 +3.000000 -40.187500 -12.000000 321871680.000000 +3.000000 -40.312500 -12.000000 321971680.000000 +2.937500 -40.312500 -12.125000 322071680.000000 +2.250000 -40.000000 -11.812500 322171680.000000 +1.875000 -40.062500 -11.500000 322271680.000000 +1.437500 -39.687500 -11.187500 322371680.000000 +1.000000 -39.562500 -11.000000 322471680.000000 +0.812500 -39.562500 -10.625000 322571680.000000 +0.750000 -39.437500 -10.687500 322671680.000000 +0.750000 -39.250000 -10.875000 322771680.000000 +0.687500 -39.187500 -10.687500 322871680.000000 +0.562500 -39.500000 -10.375000 322971680.000000 +-0.187500 -39.312500 -9.750000 323071680.000000 +-0.625000 -39.500000 -9.437500 323171680.000000 +-1.250000 -39.187500 -8.875000 323271680.000000 +-1.750000 -38.937500 -8.687500 323371680.000000 +-2.375000 -38.687500 -8.000000 323471680.000000 +-3.062500 -38.625000 -7.250000 323571680.000000 +-3.812500 -38.562500 -6.625000 323671680.000000 +-4.000000 -38.312500 -6.437500 323771680.000000 +-3.562500 -38.312500 -6.437500 323871680.000000 +-3.187500 -38.125000 -6.375000 323971680.000000 +-2.500000 -38.312500 -6.750000 324071680.000000 +-2.000000 -38.500000 -6.812500 324171680.000000 +-1.437500 -38.687500 -7.125000 324271680.000000 +-0.437500 -38.625000 -7.500000 324371680.000000 +0.625000 -38.750000 -8.312500 324471680.000000 +1.562500 -38.875000 -9.187500 324571680.000000 +2.312500 -38.875000 -10.000000 324671680.000000 +3.000000 -39.000000 -10.562500 324771680.000000 +3.500000 -39.187500 -11.000000 324871680.000000 +4.250000 -39.250000 -11.500000 324971680.000000 +4.375000 -39.375000 -12.062500 325071680.000000 +4.125000 -39.500000 -12.375000 325171680.000000 +3.937500 -39.687500 -12.375000 325271680.000000 +4.000000 -40.000000 -12.375000 325371680.000000 +4.062500 -40.125000 -12.500000 325471680.000000 +4.062500 -40.125000 -12.437500 325571680.000000 +4.062500 -40.187500 -12.625000 325671680.000000 +3.687500 -40.125000 -12.625000 325771680.000000 +3.875000 -40.250000 -12.687500 325871680.000000 +3.812500 -40.250000 -12.562500 325971680.000000 +3.875000 -40.062500 -12.562500 326071680.000000 +3.687500 -39.812500 -12.375000 326171680.000000 +3.687500 -39.875000 -12.250000 326271680.000000 +3.500000 -40.125000 -12.125000 326371680.000000 +3.562500 -39.937500 -12.250000 326471680.000000 +3.562500 -40.062500 -12.062500 326571680.000000 +3.562500 -40.000000 -12.000000 326671680.000000 +3.750000 -40.187500 -11.937500 326771680.000000 +4.062500 -40.312500 -11.937500 326871680.000000 +4.125000 -40.437500 -12.250000 326971680.000000 +4.062500 -40.187500 -12.187500 327071680.000000 +4.125000 -40.000000 -12.437500 327171680.000000 +3.875000 -39.812500 -12.187500 327271680.000000 +3.687500 -39.812500 -12.312500 327371680.000000 +3.625000 -39.875000 -12.375000 327471680.000000 +3.312500 -39.625000 -12.125000 327571680.000000 +2.875000 -39.687500 -12.250000 327671680.000000 +2.875000 -39.750000 -12.062500 327771680.000000 +2.875000 -40.000000 -12.125000 327871680.000000 +2.875000 -40.000000 -12.187500 327971680.000000 +3.000000 -40.250000 -12.125000 328071680.000000 +3.187500 -40.312500 -12.375000 328171680.000000 +3.250000 -40.375000 -12.312500 328271680.000000 +3.500000 -40.437500 -12.250000 328371680.000000 +3.875000 -40.500000 -11.875000 328471680.000000 +4.000000 -40.437500 -11.562500 328571680.000000 +4.250000 -40.500000 -10.375000 328671680.000000 +4.687500 -40.500000 -7.937500 328771680.000000 +5.687500 -40.312500 -4.937500 328871680.000000 +6.500000 -39.562500 -0.625000 328971680.000000 +7.062500 -38.312500 4.125000 329071680.000000 +7.625000 -36.562500 9.312500 329171680.000000 +8.187500 -34.187500 14.750000 329271680.000000 +8.812500 -31.000000 20.437500 329371680.000000 +9.437500 -27.625000 25.500000 329471680.000000 +9.437500 -24.500000 29.750000 329571680.000000 +9.250000 -21.062500 33.000000 329671680.000000 +9.312500 -17.562500 35.375000 329771680.000000 +10.062500 -13.687500 37.250000 329871680.000000 +10.875000 -9.625000 38.125000 329971680.000000 +11.312500 -4.875000 38.250000 330071680.000000 +12.000000 0.062500 37.562500 330171680.000000 +12.375000 5.812500 35.812500 330271680.000000 +12.937500 11.812500 33.562500 330371680.000000 +12.812500 18.062500 30.750000 330471680.000000 +12.500000 23.687500 27.375000 330571680.000000 +11.750000 28.875000 23.687500 330671680.000000 +10.875000 32.875000 20.437500 330771680.000000 +10.312500 35.625000 17.812500 330871680.000000 +9.500000 37.500000 15.687500 330971680.000000 +9.062500 38.562500 13.937500 331071680.000000 +8.500000 39.187500 12.812500 331171680.000000 +8.625000 39.187500 12.125000 331271680.000000 +8.750000 39.125000 12.000000 331371680.000000 +8.750000 38.937500 12.000000 331471680.000000 +8.812500 38.937500 12.000000 331571680.000000 +8.562500 39.000000 11.562500 331671680.000000 +8.625000 39.062500 11.125000 331771680.000000 +8.250000 39.062500 10.625000 331871680.000000 +8.000000 39.375000 8.875000 331971680.000000 +7.250000 39.187500 5.687500 332071680.000000 +6.687500 38.500000 1.062500 332171680.000000 +5.812500 36.250000 -4.812500 332271680.000000 +5.187500 32.937500 -11.312500 332371680.000000 +4.562500 28.625000 -17.812500 332471680.000000 +4.187500 22.625000 -24.312500 332571680.000000 +3.875000 15.312500 -29.562500 332671680.000000 +3.625000 6.562500 -33.062500 332771680.000000 +3.812500 -2.375000 -34.312500 332871680.000000 +4.125000 -11.125000 -33.687500 332971680.000000 +4.187500 -18.312500 -31.312500 333071680.000000 +4.250000 -24.875000 -28.187500 333171680.000000 +4.250000 -30.500000 -25.062500 333271680.000000 +3.875000 -34.375000 -22.000000 333371680.000000 +3.625000 -36.875000 -19.500000 333471680.000000 +3.562500 -38.250000 -17.812500 333571680.000000 +3.125000 -39.062500 -16.812500 333671680.000000 +2.812500 -39.312500 -16.250000 333771680.000000 +2.562500 -39.562500 -16.125000 333871680.000000 +2.000000 -39.312500 -15.812500 333971680.000000 +1.625000 -38.875000 -15.687500 334071680.000000 +0.937500 -38.437500 -15.062500 334171680.000000 +0.625000 -38.000000 -14.625000 334271680.000000 +0.375000 -38.062500 -14.562500 334371680.000000 +0.375000 -37.750000 -14.500000 334471680.000000 +0.312500 -37.687500 -14.562500 334571680.000000 +0.562500 -37.625000 -14.687500 334671680.000000 +1.062500 -37.750000 -14.937500 334771680.000000 +1.562500 -38.312500 -15.062500 334871680.000000 +2.187500 -38.687500 -15.437500 334971680.000000 +2.312500 -39.062500 -15.875000 335071680.000000 +2.625000 -39.062500 -15.812500 335171680.000000 +2.625000 -39.312500 -16.000000 335271680.000000 +2.687500 -39.625000 -16.000000 335371680.000000 +2.500000 -39.750000 -15.937500 335471680.000000 +2.562500 -39.875000 -16.062500 335571680.000000 +2.375000 -39.875000 -16.125000 335671680.000000 +2.437500 -39.875000 -16.312500 335771680.000000 +2.500000 -40.000000 -16.312500 335871680.000000 +2.437500 -40.125000 -16.500000 335971680.000000 +2.500000 -40.187500 -16.312500 336071680.000000 +2.562500 -40.062500 -16.187500 336171680.000000 +2.562500 -39.875000 -16.062500 336271680.000000 +2.562500 -39.812500 -16.062500 336371680.000000 +2.437500 -39.937500 -15.875000 336471680.000000 +2.562500 -39.812500 -15.937500 336571680.000000 +2.500000 -39.875000 -16.000000 336671680.000000 +2.562500 -39.750000 -15.937500 336771680.000000 +2.625000 -39.687500 -16.000000 336871680.000000 +2.562500 -39.625000 -16.187500 336971680.000000 +2.500000 -39.812500 -16.312500 337071680.000000 +2.375000 -39.812500 -16.437500 337171680.000000 +2.625000 -39.562500 -16.500000 337271680.000000 +2.750000 -39.687500 -16.500000 337371680.000000 +3.062500 -39.625000 -16.500000 337471680.000000 +3.250000 -39.812500 -16.312500 337571680.000000 +3.187500 -39.812500 -16.312500 337671680.000000 +3.250000 -39.937500 -16.125000 337771680.000000 +3.437500 -39.812500 -16.187500 337871680.000000 +3.500000 -40.062500 -16.125000 337971680.000000 +2.750000 -39.875000 -15.812500 338071680.000000 +1.937500 -39.500000 -15.312500 338171680.000000 +1.250000 -39.437500 -15.250000 338271680.000000 +0.312500 -38.937500 -14.750000 338371680.000000 +0.000000 -38.687500 -14.687500 338471680.000000 +-0.125000 -38.562500 -14.750000 338571680.000000 +-0.500000 -38.375000 -14.437500 338671680.000000 +-1.187500 -37.812500 -14.062500 338771680.000000 +-1.187500 -37.625000 -14.187500 338871680.000000 +-0.812500 -37.875000 -14.375000 338971680.000000 +-0.500000 -37.812500 -14.375000 339071680.000000 +-0.312500 -37.562500 -14.437500 339171680.000000 +-0.500000 -37.750000 -14.125000 339271680.000000 +-0.812500 -37.875000 -13.812500 339371680.000000 +-0.375000 -38.000000 -13.750000 339471680.000000 +-0.187500 -38.125000 -13.562500 339571680.000000 +-0.062500 -38.375000 -13.375000 339671680.000000 +-0.250000 -38.062500 -13.000000 339771680.000000 +-0.500000 -38.000000 -12.562500 339871680.000000 +-0.125000 -38.437500 -12.812500 339971680.000000 +-0.500000 -38.125000 -12.500000 340071680.000000 +-0.562500 -37.875000 -12.437500 340171680.000000 +-1.250000 -37.562500 -12.250000 340271680.000000 +-1.250000 -37.500000 -12.375000 340371680.000000 +-1.125000 -37.375000 -12.375000 340471680.000000 +-1.562500 -37.562500 -12.312500 340571680.000000 +-1.687500 -37.437500 -12.562500 340671680.000000 +-2.125000 -37.000000 -12.250000 340771680.000000 +-1.312500 -37.187500 -12.812500 340871680.000000 +-1.312500 -37.187500 -12.750000 340971680.000000 +-1.250000 -37.500000 -12.750000 341071680.000000 +-1.125000 -37.625000 -12.750000 341171680.000000 +-1.312500 -37.750000 -12.625000 341271680.000000 +-0.750000 -37.750000 -13.187500 341371680.000000 +-0.812500 -37.812500 -12.812500 341471680.000000 +-0.750000 -38.062500 -12.937500 341571680.000000 +-1.250000 -37.875000 -12.687500 341671680.000000 +-0.875000 -38.000000 -13.062500 341771680.000000 +-0.375000 -38.000000 -13.625000 341871680.000000 +0.000000 -38.187500 -13.875000 341971680.000000 +0.062500 -38.500000 -14.000000 342071680.000000 +0.000000 -38.500000 -13.750000 342171680.000000 +0.312500 -38.750000 -14.125000 342271680.000000 +0.125000 -38.687500 -14.187500 342371680.000000 +0.437500 -38.500000 -14.750000 342471680.000000 +0.187500 -37.812500 -15.562500 342571680.000000 +0.125000 -36.375000 -16.562500 342671680.000000 +0.125000 -34.000000 -18.687500 342771680.000000 +1.187500 -31.062500 -21.687500 342871680.000000 +2.000000 -27.812500 -25.000000 342971680.000000 +2.562500 -23.125000 -28.375000 343071680.000000 +3.500000 -17.375000 -31.687500 343171680.000000 +3.687500 -11.250000 -34.500000 343271680.000000 +3.937500 -5.000000 -36.250000 343371680.000000 +4.062500 1.312500 -37.437500 343471680.000000 +4.312500 7.687500 -36.875000 343571680.000000 +4.125000 14.187500 -34.437500 343671680.000000 +3.937500 20.562500 -30.812500 343771680.000000 +4.125000 25.750000 -25.937500 343871680.000000 +4.375000 29.562500 -20.312500 343971680.000000 +5.000000 32.750000 -13.687500 344071680.000000 +5.812500 35.562500 -7.625000 344171680.000000 +6.437500 37.562500 -1.687500 344271680.000000 +7.062500 38.500000 3.500000 344371680.000000 +7.562500 38.937500 7.562500 344471680.000000 +8.000000 39.000000 10.625000 344571680.000000 +8.375000 39.000000 12.562500 344671680.000000 +8.562500 38.750000 13.437500 344771680.000000 +8.625000 38.437500 13.812500 344871680.000000 +8.500000 38.250000 14.000000 344971680.000000 +8.750000 38.312500 14.250000 345071680.000000 +8.562500 38.312500 14.125000 345171680.000000 +8.625000 38.375000 14.062500 345271680.000000 +8.500000 38.250000 14.062500 345371680.000000 +8.562500 38.000000 14.187500 345471680.000000 +8.437500 38.125000 14.312500 345571680.000000 +8.437500 38.250000 14.000000 345671680.000000 +8.312500 38.437500 14.312500 345771680.000000 +8.000000 38.187500 14.687500 345871680.000000 +8.500000 37.750000 15.375000 345971680.000000 +8.875000 36.937500 16.500000 346071680.000000 +9.562500 35.625000 18.437500 346171680.000000 +10.062500 33.562500 21.062500 346271680.000000 +10.750000 30.375000 23.875000 346371680.000000 +11.437500 26.000000 26.937500 346471680.000000 +11.812500 20.500000 29.875000 346571680.000000 +12.125000 14.437500 32.312500 346671680.000000 +12.187500 7.687500 34.062500 346771680.000000 +12.125000 0.437500 34.812500 346871680.000000 +12.187500 -6.812500 33.812500 346971680.000000 +12.187500 -13.437500 31.000000 347071680.000000 +12.062500 -19.687500 27.375000 347171680.000000 +12.125000 -24.875000 22.375000 347271680.000000 +12.125000 -28.750000 16.750000 347371680.000000 +11.812500 -31.812500 11.062500 347471680.000000 +10.875000 -33.812500 5.437500 347571680.000000 +9.937500 -34.812500 0.500000 347671680.000000 +9.250000 -35.437500 -3.687500 347771680.000000 +8.562500 -35.937500 -7.062500 347871680.000000 +7.875000 -35.812500 -9.500000 347971680.000000 +6.875000 -35.375000 -10.500000 348071680.000000 +6.750000 -35.187500 -11.312500 348171680.000000 +6.875000 -35.187500 -11.875000 348271680.000000 +7.062500 -35.312500 -11.937500 348371680.000000 +7.312500 -35.625000 -11.875000 348471680.000000 +7.250000 -35.812500 -12.000000 348571680.000000 +6.937500 -35.687500 -11.625000 348671680.000000 +6.687500 -35.437500 -11.562500 348771680.000000 +6.937500 -35.375000 -11.812500 348871680.000000 +6.875000 -35.562500 -12.125000 348971680.000000 +6.687500 -35.250000 -11.875000 349071680.000000 +7.125000 -35.000000 -12.250000 349171680.000000 +7.500000 -34.937500 -12.625000 349271680.000000 +7.500000 -34.375000 -12.250000 349371680.000000 +7.562500 -34.250000 -12.375000 349471680.000000 +8.062500 -34.375000 -12.562500 349571680.000000 +8.250000 -34.750000 -12.875000 349671680.000000 +8.437500 -34.625000 -12.687500 349771680.000000 +8.812500 -34.937500 -13.250000 349871680.000000 +9.187500 -35.187500 -13.125000 349971680.000000 +9.375000 -35.312500 -13.062500 350071680.000000 +9.812500 -35.500000 -13.250000 350171680.000000 +10.000000 -35.062500 -13.125000 350271680.000000 +9.875000 -35.000000 -13.062500 350371680.000000 +9.750000 -34.812500 -12.875000 350471680.000000 +9.812500 -35.000000 -12.875000 350571680.000000 +10.000000 -35.062500 -12.812500 350671680.000000 +9.687500 -35.000000 -13.000000 350771680.000000 +9.437500 -34.875000 -12.875000 350871680.000000 +8.875000 -35.000000 -12.750000 350971680.000000 +8.562500 -35.062500 -12.312500 351071680.000000 +8.312500 -34.937500 -12.125000 351171680.000000 +7.687500 -34.687500 -12.000000 351271680.000000 +7.250000 -34.500000 -11.625000 351371680.000000 +6.875000 -34.375000 -11.375000 351471680.000000 +6.750000 -34.312500 -11.187500 351571680.000000 +6.812500 -34.500000 -11.250000 351671680.000000 +7.312500 -34.750000 -11.875000 351771680.000000 +7.687500 -35.125000 -12.250000 351871680.000000 +8.062500 -35.125000 -12.812500 351971680.000000 +8.750000 -35.062500 -14.250000 352071680.000000 +9.062500 -34.562500 -15.875000 352171680.000000 +9.312500 -33.562500 -17.687500 352271680.000000 +9.437500 -32.437500 -19.750000 352371680.000000 +9.250000 -31.000000 -21.750000 352471680.000000 +9.125000 -29.125000 -23.687500 352571680.000000 +9.187500 -27.062500 -26.500000 352671680.000000 +8.812500 -24.187500 -29.000000 352771680.000000 +8.062500 -20.187500 -30.937500 352871680.000000 +7.187500 -15.562500 -32.687500 352971680.000000 +6.062500 -10.250000 -33.687500 353071680.000000 +4.812500 -4.312500 -33.812500 353171680.000000 +4.250000 2.250000 -33.125000 353271680.000000 +3.312500 9.000000 -31.250000 353371680.000000 +2.125000 15.687500 -27.937500 353471680.000000 +1.500000 21.562500 -23.375000 353571680.000000 +0.312500 26.375000 -17.125000 353671680.000000 +-0.687500 30.062500 -10.250000 353771680.000000 +-2.187500 32.625000 -3.750000 353871680.000000 +-3.562500 34.375000 2.250000 353971680.000000 +-5.062500 35.312500 7.625000 354071680.000000 +-6.375000 35.750000 11.625000 354171680.000000 +-7.312500 35.875000 14.687500 354271680.000000 +-8.375000 35.687500 16.687500 354371680.000000 +-8.875000 35.375000 17.437500 354471680.000000 +-8.437500 35.125000 17.000000 354571680.000000 +-7.687500 35.062500 16.500000 354671680.000000 +-6.625000 34.937500 16.000000 354771680.000000 +-5.750000 34.875000 15.562500 354871680.000000 +-4.562500 34.687500 15.250000 354971680.000000 +-2.937500 34.437500 15.187500 355071680.000000 +-1.000000 34.250000 15.437500 355171680.000000 +1.250000 33.500000 16.625000 355271680.000000 +2.937500 31.937500 18.937500 355371680.000000 +4.750000 29.562500 21.812500 355471680.000000 +6.562500 26.437500 24.875000 355571680.000000 +8.125000 22.125000 27.750000 355671680.000000 +9.375000 17.000000 30.937500 355771680.000000 +10.250000 11.062500 33.312500 355871680.000000 +10.500000 4.375000 35.125000 355971680.000000 +10.750000 -2.562500 35.062500 356071680.000000 +10.625000 -9.312500 33.437500 356171680.000000 +10.812500 -15.875000 30.187500 356271680.000000 +11.000000 -21.750000 25.687500 356371680.000000 +10.937500 -26.562500 20.125000 356471680.000000 +10.687500 -30.687500 13.437500 356571680.000000 +10.375000 -33.562500 7.125000 356671680.000000 +9.875000 -35.812500 1.000000 356771680.000000 +9.437500 -37.250000 -4.250000 356871680.000000 +9.125000 -37.687500 -8.312500 356971680.000000 +8.812500 -37.812500 -11.312500 357071680.000000 +8.062500 -37.812500 -13.312500 357171680.000000 +7.500000 -37.875000 -14.250000 357271680.000000 +7.187500 -37.250000 -14.187500 357371680.000000 +6.187500 -37.187500 -13.812500 357471680.000000 +6.062500 -36.875000 -13.687500 357571680.000000 +5.875000 -36.687500 -13.562500 357671680.000000 +5.375000 -36.750000 -13.312500 357771680.000000 +4.750000 -36.687500 -13.125000 357871680.000000 +4.312500 -36.375000 -13.000000 357971680.000000 +4.250000 -35.937500 -12.812500 358071680.000000 +4.250000 -36.250000 -12.687500 358171680.000000 +4.625000 -36.375000 -12.812500 358271680.000000 +4.437500 -36.562500 -12.500000 358371680.000000 +4.437500 -36.687500 -12.687500 358471680.000000 +5.062500 -36.875000 -13.000000 358571680.000000 +5.125000 -37.062500 -13.187500 358671680.000000 +5.437500 -37.437500 -13.500000 358771680.000000 +5.750000 -37.562500 -13.625000 358871680.000000 +6.000000 -37.437500 -13.812500 358971680.000000 +6.500000 -37.687500 -14.125000 359071680.000000 +6.875000 -37.937500 -14.500000 359171680.000000 +7.062500 -38.125000 -14.437500 359271680.000000 +6.937500 -38.312500 -14.375000 359371680.000000 +7.125000 -38.187500 -14.437500 359471680.000000 +7.187500 -38.250000 -14.437500 359571680.000000 +7.000000 -38.312500 -14.437500 359671680.000000 +7.000000 -38.562500 -14.375000 359771680.000000 +7.062500 -38.187500 -14.750000 359871680.000000 +7.500000 -37.500000 -15.687500 359971680.000000 +8.000000 -35.875000 -17.500000 360071680.000000 +8.500000 -33.062500 -20.375000 360171680.000000 +8.750000 -29.312500 -23.125000 360271680.000000 +9.062500 -24.375000 -26.000000 360371680.000000 +9.312500 -19.000000 -28.687500 360471680.000000 +9.562500 -13.000000 -31.375000 360571680.000000 +9.500000 -6.375000 -33.250000 360671680.000000 +9.062500 0.875000 -33.937500 360771680.000000 +8.250000 8.437500 -32.000000 360871680.000000 +7.125000 15.062500 -27.812500 360971680.000000 +6.375000 20.437500 -22.437500 361071680.000000 +5.500000 24.625000 -16.375000 361171680.000000 +4.500000 28.125000 -10.125000 361271680.000000 +3.375000 31.187500 -4.187500 361371680.000000 +2.312500 33.437500 1.437500 361471680.000000 +1.437500 34.687500 6.500000 361571680.000000 +0.750000 34.625000 9.812500 361671680.000000 +0.312500 34.437500 11.750000 361771680.000000 +-0.312500 34.312500 12.500000 361871680.000000 +-1.125000 34.062500 12.562500 361971680.000000 +-1.812500 34.000000 12.562500 362071680.000000 +-2.000000 33.937500 12.562500 362171680.000000 +-2.375000 33.875000 12.750000 362271680.000000 +-2.187500 33.937500 12.812500 362371680.000000 +-1.812500 33.750000 13.562500 362471680.000000 +-0.750000 33.312500 14.562500 362571680.000000 +0.500000 32.375000 16.687500 362671680.000000 +2.062500 30.750000 19.437500 362771680.000000 +3.625000 27.687500 22.625000 362871680.000000 +4.750000 23.625000 25.937500 362971680.000000 +5.937500 18.562500 28.937500 363071680.000000 +6.562500 11.750000 31.562500 363171680.000000 +6.812500 4.625000 32.937500 363271680.000000 +6.625000 -3.500000 33.000000 363371680.000000 +6.375000 -11.250000 30.937500 363471680.000000 +5.875000 -18.437500 27.500000 363571680.000000 +5.312500 -24.500000 22.750000 363671680.000000 +5.062500 -29.750000 17.687500 363771680.000000 +4.812500 -33.812500 11.937500 363871680.000000 +4.875000 -36.562500 6.125000 363971680.000000 +5.062500 -38.250000 0.812500 364071680.000000 +5.062500 -38.687500 -3.687500 364171680.000000 +5.250000 -39.062500 -7.062500 364271680.000000 +5.312500 -39.062500 -9.687500 364371680.000000 +5.625000 -38.875000 -11.687500 364471680.000000 +5.625000 -38.625000 -13.187500 364571680.000000 +5.625000 -38.500000 -14.000000 364671680.000000 +5.062500 -38.062500 -14.000000 364771680.000000 +4.562500 -37.812500 -13.750000 364871680.000000 +3.937500 -37.687500 -13.562500 364971680.000000 +3.187500 -37.312500 -13.125000 365071680.000000 +2.937500 -37.312500 -12.812500 365171680.000000 +2.562500 -37.250000 -12.437500 365271680.000000 +2.312500 -37.000000 -12.000000 365371680.000000 +1.875000 -36.625000 -11.562500 365471680.000000 +2.000000 -36.437500 -11.187500 365571680.000000 +1.937500 -36.437500 -11.437500 365671680.000000 +2.312500 -36.750000 -11.125000 365771680.000000 +2.250000 -37.000000 -11.187500 365871680.000000 +2.187500 -36.875000 -11.125000 365971680.000000 +2.187500 -36.562500 -11.062500 366071680.000000 +2.062500 -36.437500 -11.062500 366171680.000000 +2.000000 -36.562500 -11.125000 366271680.000000 +1.937500 -36.625000 -11.187500 366371680.000000 +1.937500 -36.812500 -10.875000 366471680.000000 +2.000000 -36.687500 -11.000000 366571680.000000 +2.125000 -36.500000 -11.125000 366671680.000000 +1.812500 -36.312500 -11.062500 366771680.000000 +1.750000 -36.500000 -11.062500 366871680.000000 +1.500000 -36.625000 -10.687500 366971680.000000 +1.187500 -36.625000 -10.687500 367071680.000000 +0.875000 -36.750000 -10.687500 367171680.000000 +1.312500 -36.500000 -10.687500 367271680.000000 +1.125000 -36.437500 -10.812500 367371680.000000 +0.875000 -36.375000 -10.437500 367471680.000000 +0.937500 -36.375000 -10.312500 367571680.000000 +1.187500 -36.375000 -10.625000 367671680.000000 +1.687500 -36.062500 -10.937500 367771680.000000 +1.937500 -36.000000 -10.937500 367871680.000000 +2.187500 -35.875000 -10.937500 367971680.000000 +2.250000 -36.187500 -11.312500 368071680.000000 +2.625000 -36.375000 -11.500000 368171680.000000 +3.250000 -36.375000 -11.812500 368271680.000000 +3.750000 -36.750000 -12.250000 368371680.000000 +3.687500 -36.875000 -12.187500 368471680.000000 +4.312500 -37.375000 -12.562500 368571680.000000 +4.812500 -37.562500 -12.937500 368671680.000000 +5.562500 -37.687500 -13.437500 368771680.000000 +5.437500 -37.437500 -13.250000 368871680.000000 +5.125000 -37.187500 -12.937500 368971680.000000 +4.875000 -37.312500 -13.000000 369071680.000000 +4.937500 -37.125000 -13.000000 369171680.000000 +4.687500 -36.937500 -12.812500 369271680.000000 +4.125000 -36.625000 -12.500000 369371680.000000 +3.875000 -36.562500 -12.312500 369471680.000000 +3.500000 -36.500000 -12.125000 369571680.000000 +3.250000 -36.437500 -11.875000 369671680.000000 +3.375000 -36.687500 -12.187500 369771680.000000 +3.187500 -36.375000 -11.937500 369871680.000000 +3.000000 -36.562500 -11.937500 369971680.000000 +3.250000 -36.375000 -11.875000 370071680.000000 +3.250000 -36.375000 -12.125000 370171680.000000 +2.937500 -36.312500 -11.875000 370271680.000000 +2.812500 -36.312500 -11.500000 370371680.000000 +2.750000 -36.250000 -11.375000 370471680.000000 +2.500000 -36.062500 -10.812500 370571680.000000 +2.375000 -36.062500 -10.937500 370671680.000000 +2.062500 -35.625000 -10.375000 370771680.000000 +2.000000 -35.750000 -10.625000 370871680.000000 +1.812500 -35.687500 -10.250000 370971680.000000 +1.937500 -35.812500 -10.500000 371071680.000000 +1.687500 -35.437500 -10.562500 371171680.000000 +1.500000 -35.812500 -10.562500 371271680.000000 +1.562500 -35.937500 -10.687500 371371680.000000 +1.750000 -36.250000 -10.687500 371471680.000000 +1.750000 -36.187500 -10.812500 371571680.000000 +1.625000 -36.125000 -10.375000 371671680.000000 +1.875000 -36.250000 -10.500000 371771680.000000 +2.062500 -36.125000 -10.312500 371871680.000000 +2.125000 -36.187500 -10.312500 371971680.000000 +2.375000 -35.937500 -10.312500 372071680.000000 +2.437500 -35.812500 -10.437500 372171680.000000 +2.312500 -35.437500 -10.312500 372271680.000000 +2.375000 -35.687500 -10.312500 372371680.000000 +2.250000 -35.375000 -10.375000 372471680.000000 +2.250000 -35.562500 -10.562500 372571680.000000 +2.187500 -35.687500 -10.812500 372671680.000000 +2.125000 -35.750000 -10.750000 372771680.000000 +2.000000 -35.812500 -10.687500 372871680.000000 +2.062500 -35.500000 -10.625000 372971680.000000 +1.937500 -35.687500 -10.812500 373071680.000000 +1.937500 -35.687500 -10.812500 373171680.000000 +2.125000 -35.875000 -10.812500 373271680.000000 +1.937500 -35.562500 -10.687500 373371680.000000 +2.187500 -35.750000 -10.875000 373471680.000000 +2.500000 -35.687500 -11.000000 373571680.000000 +2.375000 -35.687500 -11.000000 373671680.000000 +2.625000 -36.062500 -11.250000 373771680.000000 +3.000000 -36.000000 -11.437500 373871680.000000 +2.750000 -36.125000 -11.500000 373971680.000000 +2.500000 -36.125000 -11.312500 374071680.000000 +2.500000 -36.375000 -11.625000 374171680.000000 +2.437500 -36.125000 -11.562500 374271680.000000 +2.437500 -36.437500 -11.875000 374371680.000000 +2.625000 -36.250000 -11.687500 374471680.000000 +2.187500 -36.125000 -11.375000 374571680.000000 +2.312500 -36.187500 -11.437500 374671680.000000 +2.812500 -36.312500 -11.625000 374771680.000000 +2.937500 -36.375000 -11.750000 374871680.000000 +2.687500 -36.312500 -11.187500 374971680.000000 +2.500000 -36.250000 -11.187500 375071680.000000 +2.375000 -36.125000 -11.125000 375171680.000000 +2.875000 -36.625000 -11.687500 375271680.000000 +2.812500 -36.687500 -11.500000 375371680.000000 +2.562500 -36.750000 -11.250000 375471680.000000 +2.562500 -36.687500 -11.437500 375571680.000000 +2.625000 -36.562500 -11.437500 375671680.000000 +2.875000 -36.625000 -11.875000 375771680.000000 +2.812500 -36.500000 -11.875000 375871680.000000 +3.062500 -36.500000 -11.687500 375971680.000000 +2.812500 -36.250000 -11.625000 376071680.000000 +3.000000 -36.000000 -11.687500 376171680.000000 +3.250000 -36.187500 -11.937500 376271680.000000 +2.875000 -36.000000 -11.500000 376371680.000000 +2.687500 -36.250000 -11.562500 376471680.000000 +2.437500 -36.187500 -11.312500 376571680.000000 +2.562500 -36.437500 -11.187500 376671680.000000 +2.750000 -36.562500 -11.437500 376771680.000000 +2.875000 -36.500000 -11.625000 376871680.000000 +2.812500 -36.937500 -11.937500 376971680.000000 +2.500000 -36.937500 -12.062500 377071680.000000 +2.812500 -37.312500 -12.187500 377171680.000000 +2.625000 -37.187500 -12.187500 377271680.000000 +2.625000 -37.500000 -12.500000 377371680.000000 +2.437500 -37.312500 -12.437500 377471680.000000 +1.750000 -36.937500 -11.812500 377571680.000000 +1.375000 -36.812500 -11.250000 377671680.000000 +1.750000 -36.687500 -11.562500 377771680.000000 +2.125000 -36.750000 -11.875000 377871680.000000 +2.500000 -36.687500 -12.187500 377971680.000000 +3.375000 -36.812500 -12.625000 378071680.000000 +4.125000 -36.875000 -12.750000 378171680.000000 +4.687500 -37.187500 -13.312500 378271680.000000 +5.437500 -37.500000 -14.000000 378371680.000000 +6.000000 -38.000000 -14.625000 378471680.000000 +6.062500 -38.187500 -14.625000 378571680.000000 +6.000000 -38.125000 -14.375000 378671680.000000 +5.750000 -38.250000 -14.312500 378771680.000000 +5.687500 -38.312500 -14.187500 378871680.000000 +5.437500 -38.312500 -14.000000 378971680.000000 +5.437500 -38.375000 -13.937500 379071680.000000 +5.312500 -38.437500 -13.812500 379171680.000000 +5.250000 -38.000000 -13.687500 379271680.000000 +5.125000 -37.937500 -13.812500 379371680.000000 +5.375000 -37.812500 -13.875000 379471680.000000 +5.562500 -37.625000 -13.875000 379571680.000000 +5.812500 -37.687500 -14.000000 379671680.000000 +6.000000 -37.687500 -14.125000 379771680.000000 +5.875000 -37.500000 -14.187500 379871680.000000 +5.875000 -37.562500 -14.312500 379971680.000000 +5.937500 -37.750000 -14.500000 380071680.000000 +6.187500 -37.750000 -14.375000 380171680.000000 +6.062500 -37.875000 -14.250000 380271680.000000 +6.187500 -37.937500 -14.250000 380371680.000000 +6.125000 -37.875000 -14.250000 380471680.000000 +5.937500 -37.875000 -14.312500 380571680.000000 +6.062500 -37.937500 -14.125000 380671680.000000 +6.000000 -37.687500 -14.062500 380771680.000000 +6.125000 -37.687500 -14.000000 380871680.000000 +5.875000 -37.500000 -14.000000 380971680.000000 +6.062500 -37.437500 -14.250000 381071680.000000 +6.000000 -37.562500 -14.312500 381171680.000000 +5.875000 -37.562500 -14.437500 381271680.000000 +5.937500 -37.375000 -14.312500 381371680.000000 +5.937500 -37.500000 -14.375000 381471680.000000 +6.125000 -37.687500 -14.375000 381571680.000000 +6.062500 -37.812500 -14.375000 381671680.000000 +6.250000 -37.687500 -14.250000 381771680.000000 +6.187500 -37.625000 -14.312500 381871680.000000 +6.125000 -37.500000 -14.312500 381971680.000000 +6.187500 -37.500000 -14.375000 382071680.000000 +6.312500 -37.500000 -14.625000 382171680.000000 +6.500000 -37.437500 -14.687500 382271680.000000 +6.625000 -37.375000 -14.687500 382371680.000000 +6.562500 -37.500000 -14.687500 382471680.000000 +6.812500 -37.750000 -14.937500 382571680.000000 +6.750000 -37.875000 -14.687500 382671680.000000 +6.875000 -37.875000 -14.625000 382771680.000000 +6.875000 -37.937500 -14.500000 382871680.000000 +7.000000 -38.187500 -14.375000 382971680.000000 +6.875000 -38.187500 -14.187500 383071680.000000 +6.937500 -38.062500 -14.437500 383171680.000000 +7.062500 -37.937500 -14.562500 383271680.000000 +7.125000 -37.812500 -14.437500 383371680.000000 +6.875000 -37.937500 -14.437500 383471680.000000 +6.750000 -38.000000 -14.625000 383571680.000000 +6.312500 -37.875000 -14.375000 383671680.000000 +5.937500 -37.937500 -14.187500 383771680.000000 +5.500000 -37.937500 -14.000000 383871680.000000 +4.500000 -37.812500 -13.062500 383971680.000000 +3.750000 -37.687500 -12.625000 384071680.000000 +3.187500 -37.437500 -12.187500 384171680.000000 +2.812500 -37.000000 -11.875000 384271680.000000 +2.375000 -36.687500 -11.375000 384371680.000000 +2.687500 -36.812500 -11.562500 384471680.000000 +2.875000 -36.750000 -11.750000 384571680.000000 +3.187500 -36.687500 -12.125000 384671680.000000 +4.125000 -36.625000 -12.812500 384771680.000000 +4.750000 -36.812500 -13.000000 384871680.000000 +5.250000 -37.000000 -13.562500 384971680.000000 +5.937500 -37.312500 -13.875000 385071680.000000 +6.687500 -37.437500 -14.250000 385171680.000000 +6.687500 -37.562500 -14.312500 385271680.000000 +7.062500 -37.437500 -14.312500 385371680.000000 +6.937500 -37.437500 -14.625000 385471680.000000 +6.750000 -37.500000 -14.562500 385571680.000000 +6.875000 -37.562500 -14.687500 385671680.000000 +6.437500 -37.437500 -14.625000 385771680.000000 +6.500000 -37.500000 -14.562500 385871680.000000 +6.125000 -37.437500 -14.625000 385971680.000000 +6.312500 -37.312500 -14.625000 386071680.000000 diff --git a/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/accel.txt b/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/accel.txt new file mode 100755 index 0000000..04f8b9b --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/accel.txt @@ -0,0 +1,1095 @@ +-0.025125 0.198604 10.131211 263050464.000000 +-0.025125 0.198604 10.131211 263150512.000000 +-0.088534 0.239282 10.122837 263250512.000000 +-0.025125 0.191426 10.128819 263350464.000000 +-0.008375 0.192622 10.107283 263450448.000000 +-0.028714 0.200997 10.134801 263550480.000000 +0.021535 0.190229 10.110871 263650464.000000 +0.015553 0.229711 10.147961 263750496.000000 +-0.032303 0.174676 10.139585 263850480.000000 +-0.032303 0.211765 10.150353 263950464.000000 +-0.027517 0.208176 10.118051 264050624.000000 +-0.031107 0.210568 10.144372 264150560.000000 +-0.017946 0.214158 10.098907 264250528.000000 +-0.016750 0.234497 10.141978 264350496.000000 +-0.028714 0.210568 10.122837 264450672.000000 +-0.028714 0.223729 10.112068 264550496.000000 +-0.014357 0.199801 10.135997 264650496.000000 +0.122034 0.218943 10.086944 264750560.000000 +-0.022732 0.090927 10.040283 264850512.000000 +0.001196 0.015553 10.030712 264950512.000000 +-0.899701 -0.422333 10.798808 265050528.000000 +-0.125623 -1.414158 10.022337 265150512.000000 +-0.077767 -2.183451 9.698111 265250512.000000 +0.171087 -3.529413 9.395418 265350528.000000 +-0.294317 -4.150351 8.676375 265450528.000000 +0.178265 -4.265206 9.280562 265550512.000000 +0.600598 -4.272385 9.457631 265650544.000000 +0.897308 -3.960121 8.657232 265750496.000000 +1.054038 -3.656233 9.780663 265850528.000000 +1.123430 -3.491128 9.877571 265950720.000000 +1.481157 -3.506681 9.469595 266050480.000000 +1.554138 -4.705486 7.899903 266150512.000000 +1.859223 -7.366304 7.328020 266250480.000000 +-0.369691 -9.361918 5.157729 266350464.000000 +-0.128016 -9.924232 3.285345 266450448.000000 +-1.491925 -9.139386 1.015753 266550480.000000 +-1.472782 -9.540184 -2.166701 266650624.000000 +-1.569692 -8.035098 -4.094120 266750560.000000 +-2.041078 -7.684550 -6.116055 266850576.000000 +-1.886741 -5.199604 -7.933403 266950528.000000 +-2.922833 -3.391826 -9.370294 267050512.000000 +-3.231507 1.081556 -8.874979 267150528.000000 +-4.695914 1.741975 -9.018548 267250448.000000 +-3.347559 3.203990 -9.131011 267350464.000000 +-3.068795 4.934000 -7.850852 267450496.000000 +-2.736193 6.942775 -6.167500 267550384.000000 +-1.316052 8.045866 -6.248857 267650384.000000 +-0.629312 8.096116 -3.769892 267750384.000000 +0.313460 9.109475 -1.091127 267850384.000000 +1.249053 8.506484 1.850848 267950368.000000 +1.467997 7.749156 3.710072 268050528.000000 +0.671187 6.443871 6.923633 268150368.000000 +0.837488 6.483353 7.210771 268250368.000000 +1.074377 6.107680 8.401200 268350384.000000 +0.859023 4.822734 8.644072 268450432.000000 +0.760918 3.198008 8.730213 268550432.000000 +0.994218 2.630908 9.352347 268650432.000000 +0.455833 1.234696 9.458827 268750688.000000 +0.921237 1.018146 10.097712 268850464.000000 +0.964308 0.065803 10.171888 268950464.000000 +-0.520439 -0.385244 10.567901 269050336.000000 +-1.241875 -1.079163 9.215956 269150368.000000 +-1.031307 -4.859823 8.662018 269250368.000000 +-1.890330 -6.604190 5.938986 269350400.000000 +-2.658426 -8.420342 6.600601 269450688.000000 +-3.334399 -9.491131 1.106680 269550336.000000 +-2.615355 -9.480364 -2.323431 269650368.000000 +-2.907279 -9.058030 -4.277170 269750368.000000 +-2.708675 -6.106483 -7.045666 269850368.000000 +-1.335195 -2.112862 -10.666007 269950368.000000 +-3.756732 -0.885344 -14.238490 270050400.000000 +0.765703 0.463011 -12.352946 270150368.000000 +0.329013 1.300499 -8.660822 270250400.000000 +0.167498 5.286942 -4.384847 270350432.000000 +1.196411 7.920243 1.222732 270450464.000000 +0.019143 8.463413 3.122634 270550400.000000 +-0.161516 8.598608 4.218546 270650400.000000 +-0.508475 8.646464 5.858827 270750400.000000 +0.008375 8.355737 6.501299 270850368.000000 +0.421137 7.256234 7.607980 270950400.000000 +0.780060 6.786045 7.901100 271050368.000000 +0.814756 6.063413 7.354341 271150400.000000 +0.360120 5.490332 8.355737 271250464.000000 +0.180658 4.612165 8.760124 271350496.000000 +-0.039482 4.618148 9.747163 271450368.000000 +0.294317 3.920640 9.608379 271550400.000000 +0.191426 3.724428 9.424131 271650400.000000 +0.351745 3.150151 9.145369 271750464.000000 +-0.440279 2.176272 9.951750 271850496.000000 +-1.351945 0.008375 8.766105 271950496.000000 +-1.530210 -2.761317 10.518847 272050336.000000 +-2.489732 -3.515057 7.636694 272150400.000000 +-2.514857 -4.715057 7.954939 272250368.000000 +-3.236293 -7.057630 5.831308 272350368.000000 +-2.855834 -8.989835 3.509074 272450368.000000 +-3.109473 -9.337991 0.662812 272550464.000000 +-3.202793 -8.696713 -0.875773 272650368.000000 +-3.286542 -8.068598 -4.960321 272750368.000000 +-2.006382 -5.596812 -6.905686 272850400.000000 +-0.805185 -1.445265 -7.499106 272950432.000000 +-1.610370 0.896112 -11.547763 273050432.000000 +-0.318245 -0.218943 -11.465210 273150400.000000 +1.105484 1.140180 -9.477970 273250400.000000 +1.800599 2.026721 -10.036695 273350368.000000 +1.128216 3.476771 -8.848659 273450496.000000 +0.364905 6.344569 -7.835298 273550368.000000 +-1.789831 8.286345 -1.695315 273650400.000000 +-2.068595 7.415358 0.551546 273750432.000000 +-1.016950 5.891129 -0.041874 273850400.000000 +0.624527 5.045266 3.665804 273950432.000000 +1.095913 3.881158 6.294320 274050400.000000 +1.409373 2.197808 10.291530 274150464.000000 +0.699901 1.137787 11.035697 274250400.000000 +1.383051 0.652044 11.105090 274350400.000000 +0.981057 -0.340977 10.943574 274450400.000000 +1.049253 -0.017946 9.584452 274550400.000000 +1.244268 0.126820 9.945767 274650400.000000 +0.745364 -0.250050 9.846465 274750432.000000 +0.279960 -0.262014 10.237692 274850400.000000 +0.544367 0.022732 10.098907 274950496.000000 +0.330210 -0.245264 10.189835 275050400.000000 +0.329013 -0.266800 10.177871 275150400.000000 +0.284746 -0.321835 10.047462 275250368.000000 +0.183051 -0.452243 10.072588 275350400.000000 +0.263210 -0.437887 10.202995 275450400.000000 +-0.089731 -0.321835 9.958927 275550400.000000 +0.290728 -0.319442 10.218549 275650400.000000 +0.178265 -0.148355 10.197014 275750400.000000 +0.112463 -0.135194 10.291530 275850400.000000 +-0.257228 0.461815 11.603992 275950432.000000 +-0.078963 1.144966 9.201599 276050368.000000 +0.441476 2.379662 10.064213 276150400.000000 +-0.709472 3.442075 9.829715 276250432.000000 +0.610170 4.461418 7.540981 276350368.000000 +-0.281157 6.891330 3.997210 276450592.000000 +1.735993 7.702496 -0.680758 276550400.000000 +1.627119 6.741778 -4.553542 276650432.000000 +1.511067 6.835098 -8.057830 276750400.000000 +1.604388 5.687739 -5.880362 276850368.000000 +0.238086 2.944368 -8.248059 276950400.000000 +-0.531207 2.003989 -9.759127 277050432.000000 +-2.666801 -0.978664 -9.840484 277150400.000000 +-1.727618 -3.498307 -6.512067 277250368.000000 +-0.587438 -9.007781 -9.145369 277350368.000000 +-1.150948 -7.719246 -1.173679 277450432.000000 +-2.890530 -8.992228 -6.401997 277550400.000000 +-0.367298 -10.339387 4.875376 277650400.000000 +-2.155933 -8.282756 4.360919 277750400.000000 +-0.381655 -7.205985 5.230711 277850400.000000 +0.035892 -5.587241 7.414161 277951648.000000 +0.902094 -4.258028 8.181061 278050368.000000 +0.466600 -1.813759 9.488738 278150368.000000 +2.647658 -2.073381 8.696713 278252096.000000 +0.544367 -1.686940 12.904492 278350368.000000 +0.478565 0.396012 10.460224 278450368.000000 +0.960718 2.165504 9.450454 278550368.000000 +1.272982 2.234896 8.859426 278650368.000000 +0.729811 1.946561 9.328419 278750400.000000 +0.409173 3.223132 9.969695 278850464.000000 +0.537189 4.662415 9.286544 278950400.000000 +0.716650 5.249853 8.366505 279050368.000000 +0.947558 5.441278 8.908479 279150368.000000 +0.354138 7.197611 7.685746 279250368.000000 +-0.183051 8.372486 7.262216 279350400.000000 +-2.142773 8.439486 4.067799 279450464.000000 +0.393619 9.343972 -0.040678 279550400.000000 +0.020339 8.677571 -3.085545 279650432.000000 +-0.715454 8.116454 -4.949553 279750432.000000 +-1.695315 5.487939 -6.973882 279850400.000000 +-1.069592 4.821537 -7.902297 279950400.000000 +0.758525 2.608176 -8.366505 280050400.000000 +0.575474 0.790828 -9.016156 280150368.000000 +0.384048 0.235693 -11.479566 280250368.000000 +0.549153 -2.231307 -7.975278 280350400.000000 +0.631705 -4.246064 -8.301898 280450368.000000 +-0.020339 -6.401997 -8.855836 280550400.000000 +0.983450 -10.222138 -7.343572 280650368.000000 +0.227318 -9.659825 -1.970490 280750368.000000 +-0.068195 -9.856036 3.678965 280850400.000000 +2.116452 -9.939785 8.133204 280950688.000000 +0.900898 -8.202596 5.721239 281050624.000000 +0.888934 -6.258427 6.653243 281150368.000000 +0.648455 -4.078567 8.452646 281250592.000000 +1.123430 -2.787638 9.695717 281350400.000000 +0.695115 -0.951147 11.273784 281450400.000000 +0.543171 -0.308674 10.758131 281550336.000000 +0.476172 0.040678 9.189635 281650848.000000 +1.238286 1.933401 10.467402 281750560.000000 +-0.319442 0.618545 9.586843 281850400.000000 +-0.731007 0.997807 11.933006 281950400.000000 +-0.558724 1.854438 9.830912 282050400.000000 +-1.366302 3.804588 9.523434 282150400.000000 +-1.262214 4.783253 8.778069 282250432.000000 +-0.965504 5.631508 8.737391 282350432.000000 +-2.003989 7.581659 3.406183 282450496.000000 +-1.473979 7.518249 -2.066202 282550496.000000 +1.581656 8.446664 -4.904090 282650400.000000 +1.051646 7.584052 -3.661019 282750400.000000 +1.325624 5.642276 -4.460221 282850400.000000 +0.512064 1.726421 -10.021141 282950432.000000 +0.393619 0.634098 -9.298509 283050624.000000 +0.290728 0.509671 -7.962118 283150368.000000 +-0.260818 -5.830112 -5.327620 283250368.000000 +-0.437887 -10.624132 -4.664808 283350368.000000 +-0.467797 -11.753544 -3.110669 283450368.000000 +-1.592424 -10.213763 -2.734996 283550368.000000 +-1.278964 -9.382257 -0.544367 283650368.000000 +0.074178 -7.482357 5.770292 283750400.000000 +0.795613 -5.261817 6.981060 283850528.000000 +-0.727418 -3.582055 9.032906 283950464.000000 +-0.707079 -2.511267 9.862019 284050400.000000 +-1.345963 -1.155733 11.714063 284150400.000000 +-1.226322 -0.641276 9.121440 284250368.000000 +-1.714458 0.557528 9.994821 284350336.000000 +-0.447458 0.762114 10.240085 284450400.000000 +-1.191626 0.559920 9.268599 284550464.000000 +-1.196411 1.247857 10.028319 284650464.000000 +-0.681954 1.178465 9.655040 284750496.000000 +-0.130409 1.219143 10.354939 284850496.000000 +0.282353 1.045663 10.389636 284950496.000000 +0.248854 0.765703 10.155140 285050400.000000 +0.581456 0.780060 9.771091 285150400.000000 +0.429512 0.457029 10.222138 285250400.000000 +0.211765 0.467797 10.816754 285350432.000000 +0.555135 0.792024 9.738789 285450496.000000 +0.212961 0.514457 10.347760 285550432.000000 +0.072981 0.363709 10.518847 285650400.000000 +0.156730 0.497707 10.408779 285750432.000000 +0.122034 0.553938 10.498510 285850400.000000 +0.210568 0.695115 10.061819 285950400.000000 +0.423530 0.610170 9.681360 286050368.000000 +0.582652 1.274178 9.899107 286150400.000000 +0.696311 1.016950 9.841680 286250400.000000 +0.510868 0.675972 10.186246 286350400.000000 +0.506082 1.344766 9.899107 286450368.000000 +0.447458 1.389034 9.797412 286550400.000000 +0.832702 1.010968 9.804591 286650464.000000 +0.713061 1.220340 9.810574 286750464.000000 +0.848256 1.032503 9.985250 286850400.000000 +0.608973 1.148555 10.003194 286950496.000000 +0.589831 1.274178 9.413363 287050368.000000 +0.535992 1.211965 10.169496 287150368.000000 +0.500100 1.235893 10.409975 287250400.000000 +0.701097 1.201197 9.870394 287350432.000000 +0.659223 0.958325 10.018748 287450496.000000 +0.757328 1.256232 10.399208 287550400.000000 +1.091127 1.100698 10.247264 287650368.000000 +1.323231 0.920040 10.259227 287750400.000000 +0.899701 1.097109 9.956534 287850400.000000 +0.937986 0.941576 9.961320 287950400.000000 +0.814756 1.159323 10.037891 288050432.000000 +0.800399 0.973879 9.897911 288150560.000000 +0.776471 1.121037 9.990034 288250400.000000 +1.033699 1.031307 9.996017 288350400.000000 +0.924826 1.333999 10.637293 288450464.000000 +0.714258 0.878166 10.243673 288550400.000000 +0.227318 1.798206 9.738789 288650400.000000 +0.524028 1.203590 10.265208 288750464.000000 +0.415155 1.064806 10.058230 288850368.000000 +0.489332 1.101895 10.042676 288950368.000000 +0.253639 1.060020 10.636096 289050368.000000 +0.508475 0.886541 10.259227 289150368.000000 +0.757328 0.799203 9.652647 289250336.000000 +0.392423 1.074377 10.043874 289350432.000000 +0.906880 0.734596 9.696914 289450464.000000 +0.558724 1.106680 10.033106 289550464.000000 +0.501296 1.140180 9.853643 289650432.000000 +0.532403 1.256232 9.677772 289750432.000000 +0.346959 1.031307 10.147961 289850400.000000 +0.477368 1.189233 11.280963 289950528.000000 +-0.122034 1.259821 10.839487 290050400.000000 +-0.147159 1.220340 9.981659 290150784.000000 +-0.942772 1.696511 11.200804 290250528.000000 +-1.238286 1.546960 10.286745 290350528.000000 +-1.387837 1.609173 10.677971 290450464.000000 +-0.981057 1.893919 10.833504 290550464.000000 +-0.144766 1.284946 10.256834 290650496.000000 +-0.483350 0.497707 9.023334 290750368.000000 +-2.209772 1.392623 10.935200 290850400.000000 +-1.814956 1.506282 10.073784 290951296.000000 +-1.615155 1.067199 10.115658 291050496.000000 +-1.301696 0.786042 9.783055 291150560.000000 +-1.062413 0.856631 10.049855 291251104.000000 +-0.969093 0.765703 10.061819 291350656.000000 +-0.898505 0.729811 10.058230 291451200.000000 +-0.799203 0.715454 10.070194 291550528.000000 +-0.474975 0.563510 9.966106 291650464.000000 +-0.471386 0.363709 10.011569 291750560.000000 +-0.405583 0.503689 10.089336 291850368.000000 +-0.442672 0.602991 10.137194 291950496.000000 +-0.331406 0.447458 10.092925 292050368.000000 +-0.553938 0.502493 10.156336 292150368.000000 +-0.448654 0.530010 10.083356 292250528.000000 +-0.415155 0.591027 10.246067 292350528.000000 +-0.418744 0.592224 10.214959 292450592.000000 +-0.343370 0.533599 10.017551 292550560.000000 +-0.300299 0.467797 10.144372 292650528.000000 +-0.228515 0.546760 10.121639 292750656.000000 +-0.295514 0.546760 10.224532 292850656.000000 +-0.320638 0.500100 10.131211 292951552.000000 +-0.283549 0.530010 10.122837 293050976.000000 +-0.186640 0.576670 10.272388 293150464.000000 +-0.345763 0.533599 10.054641 293250464.000000 +-0.391227 0.614955 10.421940 293350496.000000 +-0.279960 0.545564 10.329816 293450624.000000 +-0.171087 0.498904 10.164711 293551072.000000 +-0.270389 0.592224 10.156336 293650688.000000 +-0.212961 0.606581 10.139585 293750560.000000 +-0.166301 0.565903 10.152746 293850592.000000 +-0.208176 0.546760 10.201799 293950624.000000 +-0.178265 0.571885 10.223334 294050496.000000 +-0.198604 0.534796 10.258030 294150592.000000 +-0.165105 0.553938 10.204191 294250592.000000 +-0.083749 0.540778 10.121639 294350528.000000 +-0.066999 0.571885 10.201799 294450560.000000 +-0.089731 0.588634 10.206585 294550464.000000 +-0.108873 0.577867 10.214959 294650496.000000 +-0.247657 0.672383 10.283154 294750656.000000 +-0.049053 0.512064 10.102496 294851104.000000 +-0.107677 0.561117 10.199407 294950688.000000 +-0.064606 0.581456 10.039087 295051136.000000 +-0.173480 0.593420 10.110871 295150752.000000 +-0.175872 0.611366 10.301102 295250624.000000 +-0.063410 0.583849 10.214959 295350816.000000 +-0.111266 0.538385 10.104890 295450720.000000 +-0.193819 0.575474 10.225728 295550816.000000 +-0.110070 0.698704 10.322637 295650688.000000 +-0.217747 0.600598 10.165908 295750848.000000 +-0.391227 0.813560 10.204191 295850720.000000 +-1.240679 0.711865 10.179067 295951008.000000 +-0.581456 0.360120 10.110871 296050752.000000 +-1.129412 1.014557 9.801002 296150656.000000 +-1.147358 0.563510 9.151351 296250816.000000 +-1.143769 0.592224 10.350154 296350464.000000 +-1.363909 0.793221 10.115658 296450592.000000 +-1.605584 0.807578 9.626326 296550688.000000 +-1.185644 0.849452 10.246067 296650432.000000 +-1.239482 0.567099 10.479367 296750528.000000 +-1.704886 0.837488 9.736395 296850528.000000 +-2.870191 0.775275 9.623933 296950624.000000 +-3.890730 0.382852 8.102098 297050816.000000 +-6.021538 0.978664 8.663215 297150720.000000 +-6.997809 0.198604 6.226124 297250816.000000 +-10.249657 0.594616 6.226124 297350432.000000 +-9.576077 0.646062 -1.871187 297450432.000000 +-8.446664 1.235893 -2.382055 297550400.000000 +-7.301698 0.354138 -2.389233 297650496.000000 +-7.581659 0.041874 -5.718846 297750464.000000 +-6.550352 0.474975 -7.911868 297850400.000000 +-5.666204 1.752743 -8.139186 297950400.000000 +-4.412365 1.479961 -7.940581 298050368.000000 +-4.108476 1.842474 -7.739585 298150400.000000 +-2.622534 1.777867 -9.470792 298250400.000000 +-1.958525 1.680958 -9.436096 298350400.000000 +1.852045 1.947758 -8.195417 298450336.000000 +4.596612 2.042274 -8.073383 298550496.000000 +8.768498 1.996810 -4.474578 298650560.000000 +12.338590 1.990828 -3.730411 298750528.000000 +9.528220 0.936790 4.651647 298850720.000000 +8.581859 1.337588 5.285746 298950624.000000 +6.618547 0.491725 8.787642 299050336.000000 +4.773681 0.366102 8.635696 299150336.000000 +4.077370 0.014357 9.763913 299250368.000000 +3.073581 1.423729 11.595619 299350496.000000 +0.792024 1.460818 9.694521 299450528.000000 +0.585045 1.994418 10.674382 299550592.000000 +-0.479761 1.767099 10.019944 299650336.000000 +-0.701097 1.293321 10.656436 299750528.000000 +-0.646062 1.422533 10.180264 299850528.000000 +-1.051646 0.984646 9.609575 299950528.000000 +-2.097309 0.904487 8.912067 300050752.000000 +-2.225325 1.061217 8.425128 300150496.000000 +-5.060820 1.489532 8.878569 300250624.000000 +-6.586244 1.475175 7.268199 300350464.000000 +-8.070991 1.564906 5.483152 300450912.000000 +-8.901299 1.686940 3.505485 300550368.000000 +-8.781659 1.801795 1.854438 300650368.000000 +-9.195618 1.621137 0.173480 300750400.000000 +-9.448060 1.549353 -2.080559 300850432.000000 +-8.537591 2.099702 -3.718446 300950496.000000 +-7.228717 1.904687 -5.095516 301050560.000000 +-7.432107 2.225325 -6.195018 301150464.000000 +-6.020342 1.404587 -6.382854 301250624.000000 +-5.155336 1.631905 -8.193025 301350400.000000 +-5.076373 1.569692 -7.545766 301450400.000000 +-5.544170 1.575674 -7.555337 301550400.000000 +-4.955536 1.621137 -7.503892 301650400.000000 +-3.346362 1.808974 -8.065009 301751360.000000 +-2.158326 2.513660 -9.103494 301850432.000000 +-0.857827 2.848655 -9.810574 301950464.000000 +3.407379 2.461018 -8.994620 302050464.000000 +5.850451 1.841277 -6.294320 302150528.000000 +8.639286 0.812363 -2.828316 302250528.000000 +9.367901 1.526621 1.269392 302350688.000000 +8.981460 0.731007 3.584448 302450496.000000 +8.072187 1.131805 5.113462 302550720.000000 +8.236095 1.087538 6.970293 302650560.000000 +5.906683 1.010968 8.021938 302750752.000000 +5.469993 1.842474 8.457432 302850560.000000 +3.657429 1.825724 9.227921 302950752.000000 +2.883351 1.531406 9.675378 303050560.000000 +1.278964 1.641476 9.401401 303150720.000000 +0.364905 1.356731 9.793823 303250496.000000 +0.110070 1.221536 10.058230 303350688.000000 +0.500100 1.304088 9.707682 303450624.000000 +0.059821 2.388037 11.194820 303550688.000000 +-0.619741 1.727618 10.202995 303650496.000000 +-1.277767 1.445265 9.623933 303750784.000000 +-1.652244 1.479961 10.063015 303850496.000000 +-1.493121 1.411765 10.078569 303950752.000000 +-2.682354 1.560120 9.583255 304050496.000000 +-4.118048 1.153341 7.807780 304150784.000000 +-4.015156 1.237089 9.098708 304250592.000000 +-5.944968 1.611566 6.556334 304350720.000000 +-7.591230 1.580459 6.202196 304450496.000000 +-10.470992 1.464408 3.707679 304550720.000000 +-10.284351 1.002593 -0.001196 304650496.000000 +-9.166903 3.213561 -2.772085 304750752.000000 +-8.199007 1.657030 -4.939982 304850784.000000 +-6.953543 1.491925 -4.837091 304950432.000000 +-7.322037 1.390230 -5.516653 305050400.000000 +-7.272985 1.030110 -7.167700 305150368.000000 +-6.223732 1.362713 -6.837491 305250624.000000 +-5.185246 0.892523 -9.454042 305350432.000000 +-3.156133 1.319642 -9.762716 305450400.000000 +-1.435694 2.681158 -9.695717 305550400.000000 +1.659423 1.360320 -10.086944 305650368.000000 +4.368098 1.429712 -8.707481 305750720.000000 +6.731010 1.952543 -4.570292 305850528.000000 +8.176274 1.983650 0.145962 305950720.000000 +9.018548 1.822134 0.446261 306050464.000000 +9.275777 1.732404 2.646462 306150720.000000 +7.479963 1.454836 3.687340 306250464.000000 +7.177271 1.600798 6.302694 306350720.000000 +5.809773 1.306481 7.807780 306450592.000000 +5.004589 1.676172 8.312666 306550720.000000 +3.609573 1.992025 9.132208 306650432.000000 +2.126023 2.293520 10.250853 306750720.000000 +0.826720 2.038685 10.439885 306850464.000000 +0.074178 1.996810 10.711470 306950720.000000 +0.285942 1.670190 10.254441 307050464.000000 +0.228515 1.624727 10.534401 307150784.000000 +0.516850 1.706082 9.924232 307250528.000000 +0.403191 1.515853 10.161121 307350688.000000 +0.166301 0.987039 9.960124 307450464.000000 +0.198604 0.885344 10.176675 307550752.000000 +0.032303 0.777667 10.357333 307650528.000000 +-0.084945 0.673580 10.398011 307750784.000000 +-0.228515 0.503689 10.256834 307850496.000000 +-0.343370 0.538385 10.250853 307950976.000000 +-0.171087 0.592224 9.805787 308051264.000000 +-0.567099 0.391227 10.159925 308150496.000000 +-0.397209 0.442672 10.104890 308250560.000000 +-0.392423 0.528814 10.161121 308350720.000000 +-0.385244 0.464208 10.063015 308450496.000000 +-0.492921 0.482154 10.267602 308550688.000000 +-0.376870 0.491725 10.153944 308650496.000000 +-0.308674 0.522832 9.970891 308750752.000000 +-0.281157 0.508475 10.029516 308850496.000000 +-0.370888 0.500100 10.301102 308950688.000000 +-0.013161 0.717847 10.624132 309050528.000000 +-0.070588 1.033699 9.987641 309150752.000000 +0.453440 0.835095 9.763913 309250496.000000 +1.178465 0.777667 9.979266 309350752.000000 +3.351148 1.088734 8.422735 309450688.000000 +5.155336 0.265603 7.342376 309550720.000000 +6.604190 0.230907 8.239685 309650528.000000 +8.885747 0.585045 6.201000 309750720.000000 +8.447861 -0.599402 6.491727 309850592.000000 +9.026923 -0.830309 2.228914 309950688.000000 +9.424131 -0.585045 -0.634098 310050464.000000 +9.815358 -0.494118 -2.877369 310150752.000000 +7.613962 -0.267996 -8.650054 310250496.000000 +3.877569 -0.404387 -9.126225 310350720.000000 +0.692722 0.088534 -8.912067 310450464.000000 +-2.999403 -0.519243 -8.295916 310550784.000000 +-5.769095 -0.021535 -8.432307 310650528.000000 +-8.090133 0.226122 -6.086144 310750400.000000 +-9.407382 -0.366102 -4.278367 310850528.000000 +-9.707682 1.647458 0.573081 310950560.000000 +-10.202995 0.344566 1.251446 311050432.000000 +-8.355737 1.219143 3.281756 311150464.000000 +-8.746964 2.730211 5.394619 311250464.000000 +-7.881958 2.976671 4.133601 311350528.000000 +-6.289535 1.479961 6.446264 311450624.000000 +-7.014560 1.347159 6.937990 311550464.000000 +-5.215157 1.921437 8.394022 311650688.000000 +-3.527020 2.800799 9.558130 311750528.000000 +-2.912065 0.856631 9.099905 311850656.000000 +0.111266 0.069392 9.984053 311950528.000000 +1.603191 -0.197408 8.804391 312050688.000000 +0.248854 0.222532 10.244871 312150464.000000 +1.462015 0.721436 9.692128 312250720.000000 +2.136791 0.611366 7.117451 312350496.000000 +2.279164 1.067199 8.986245 312450944.000000 +3.326023 1.776671 8.957531 312550560.000000 +5.578866 1.333999 8.226524 312650720.000000 +5.892326 0.859023 7.000203 312750528.000000 +7.524230 1.377069 6.248857 312850720.000000 +8.447861 1.727618 5.099105 312950464.000000 +8.977871 3.463611 3.523431 313050752.000000 +9.541381 2.556731 2.220540 313150432.000000 +9.250652 1.396212 1.162912 313250688.000000 +10.162319 1.532603 -0.841077 313350432.000000 +5.468796 2.006382 -7.680960 313450688.000000 +3.355934 0.887737 -8.562716 313550432.000000 +-1.538585 0.790828 -8.583055 313650400.000000 +-4.942375 0.416351 -7.086344 313750432.000000 +-7.244271 0.311067 -7.948956 313850432.000000 +-7.942975 0.016750 -6.362515 313950528.000000 +-7.881958 0.076570 -4.383651 314050400.000000 +-10.053445 -0.227318 -1.971686 314150464.000000 +-10.018748 -0.579063 -1.165305 314250400.000000 +-9.994821 -1.927419 1.125823 314350400.000000 +-5.314459 -2.038685 6.873383 314450624.000000 +-5.984450 -0.120838 9.209974 314550432.000000 +-3.196811 -0.031107 9.729217 314650400.000000 +-1.287339 -0.616152 11.571690 314750400.000000 +-0.129212 -0.899701 13.055241 314850624.000000 +2.644069 0.329013 7.706085 314950528.000000 +4.308277 1.324427 8.563912 315050752.000000 +6.065805 1.251446 8.606983 315150752.000000 +6.221339 -0.620937 8.185846 315250400.000000 +7.097112 -0.139980 7.424929 315350400.000000 +8.082954 0.291924 7.829315 315450464.000000 +8.642875 -0.137587 5.587241 315550432.000000 +8.851050 0.495314 3.882355 315650528.000000 +9.513863 0.183051 -0.174676 315750464.000000 +8.785248 0.692722 -4.286742 315850368.000000 +4.954339 1.501496 -10.609775 315950368.000000 +0.105284 0.903291 -10.567901 316050368.000000 +-4.067799 0.660419 -14.154741 316150400.000000 +-5.040481 0.291924 -8.116454 316250464.000000 +-5.984450 0.305085 -8.268399 316350400.000000 +-7.434500 0.300299 -6.319445 316450464.000000 +-8.939585 -0.929612 -5.691329 316550368.000000 +-9.775877 1.118645 -2.615355 316650400.000000 +-10.104890 0.099302 -1.439283 316750400.000000 +-8.653644 0.771685 0.741775 316850432.000000 +-9.444471 0.412762 2.012364 316950464.000000 +-8.200203 0.894916 3.156133 317050368.000000 +-9.233903 0.569492 4.596612 317150656.000000 +-6.520442 0.728615 5.800202 317250688.000000 +-6.104091 1.542174 8.624929 317350496.000000 +-3.174079 1.457229 9.676575 317450688.000000 +-1.698904 1.557728 10.347760 317550752.000000 +1.184447 1.396212 10.521241 317650528.000000 +1.324427 1.318445 10.567901 317750688.000000 +1.452443 1.231107 10.159925 317850496.000000 +1.462015 0.890130 10.539186 317950720.000000 +1.383051 0.963111 10.323833 318050432.000000 +1.514657 0.831506 9.693325 318150688.000000 +1.162912 0.685544 9.771091 318250496.000000 +1.256232 0.837488 9.839286 318350688.000000 +1.265803 0.995414 10.007980 318450592.000000 +1.179662 1.025324 10.125229 318550752.000000 +1.089931 0.880559 9.972089 318650496.000000 +1.225125 0.970290 10.094121 318750752.000000 +1.104288 0.954736 10.071390 318850400.000000 +1.112662 0.975075 10.152746 318950720.000000 +1.097109 0.934397 10.037891 319050464.000000 +1.049253 0.976272 10.103694 319150720.000000 +1.077967 1.010968 10.109675 319250496.000000 +1.081556 0.941576 9.998409 319350720.000000 +1.040878 0.928415 9.984053 319450496.000000 +1.082752 0.954736 10.048658 319550720.000000 +1.063610 1.025324 10.108479 319650464.000000 +0.942772 0.976272 10.065409 319750784.000000 +1.039681 1.002593 9.933804 319850496.000000 +0.911665 0.833899 9.661021 319950752.000000 +0.800399 0.873380 9.706485 320050688.000000 +0.650848 0.837488 9.724431 320150464.000000 +0.836291 1.103091 10.079765 320250752.000000 +0.384048 1.434497 10.307084 320350528.000000 +1.272982 1.013360 10.912467 320450400.000000 +1.410569 0.290728 10.733006 320550368.000000 +1.663012 0.653241 11.764312 320650400.000000 +0.703490 -0.150748 10.095319 320750464.000000 +1.345963 0.197408 10.601401 320850496.000000 +2.043471 0.015553 11.602797 320950496.000000 +1.076770 -0.270389 9.724431 321050752.000000 +0.385244 -0.393619 9.755538 321150688.000000 +0.340977 -0.744168 9.751948 321250496.000000 +0.358923 -0.118445 10.342977 321350688.000000 +0.282353 0.033500 10.493724 321450560.000000 +0.376870 -0.171087 10.089336 321550688.000000 +0.293121 0.386441 10.197014 321650464.000000 +0.165105 0.230907 10.124033 321750752.000000 +-0.026321 0.191426 10.144372 321850496.000000 +0.813560 0.087338 10.240085 321950688.000000 +-0.049053 0.192622 10.420743 322050464.000000 +-0.122034 0.174676 10.597812 322150720.000000 +-0.031107 0.214158 10.188639 322250528.000000 +0.002393 0.216550 10.104890 322350720.000000 +-0.019143 0.179462 10.187442 322450560.000000 +-0.019143 0.227318 10.210175 322550752.000000 +-0.013161 0.203390 10.137194 322650528.000000 +-0.021535 0.204586 10.236496 322750752.000000 +-0.001196 0.179462 10.179067 322850560.000000 +0.004786 0.214158 10.177871 322950912.000000 +0.011964 0.209372 10.208978 323050496.000000 +-0.016750 0.198604 10.216157 323150720.000000 +-0.027517 0.224925 10.189835 323250496.000000 +0.002393 0.226122 10.139585 323350752.000000 +-0.011964 0.169890 10.168301 323450464.000000 +-0.016750 0.244068 10.195816 323550752.000000 +-0.014357 0.195015 10.161121 323650496.000000 +-0.002393 0.212961 10.135997 323750752.000000 +-0.002393 0.208176 10.186246 323850464.000000 +0.009571 0.250050 10.156336 323950688.000000 +-0.041874 0.199801 10.181459 324050464.000000 +1.304088 0.020339 10.121639 324150720.000000 +0.744168 0.263210 10.077373 324250528.000000 +1.036092 -0.070588 10.250853 324350688.000000 +3.451647 -0.288335 9.964910 324450624.000000 +0.611366 -0.446261 10.242477 324550688.000000 +-0.130409 -0.616152 10.258030 324650560.000000 +0.361316 0.514457 10.323833 324750688.000000 +1.013360 -0.445065 9.832108 324850464.000000 +-0.407976 -0.514457 10.268798 324950688.000000 +0.514457 0.345763 10.253245 325050464.000000 +0.995414 -0.244068 10.474581 325150688.000000 +0.110070 0.196211 10.268798 325250432.000000 +0.325424 -0.358923 9.653843 325350688.000000 +-1.913062 0.781257 11.015360 325450496.000000 +0.160319 -0.424726 10.055838 325550688.000000 +0.515653 1.594816 10.070194 325650432.000000 +-0.855434 0.687937 10.740184 325750784.000000 +1.252643 1.709672 11.042876 325850432.000000 +4.845466 -2.441875 11.167303 325950912.000000 +-2.250450 0.096909 10.126426 326050496.000000 +-1.920240 -0.015553 10.284351 326150720.000000 +0.072981 -0.007178 10.186246 326250496.000000 +0.009571 0.009571 10.201799 326350688.000000 +0.047856 -0.008375 10.193424 326450496.000000 +0.014357 0.023928 10.156336 326550720.000000 +0.175872 -0.001196 10.082158 326650464.000000 +0.082552 -0.260818 10.314261 326750720.000000 +0.525225 -0.538385 10.040283 326850560.000000 +0.701097 -0.625723 10.268798 326950752.000000 +-0.143569 -1.252643 10.340584 327050528.000000 +-0.581456 -0.820738 10.204191 327150720.000000 +-0.074178 -0.539581 10.424332 327250496.000000 +0.014357 -0.291924 9.802197 327350752.000000 +-0.311067 0.216550 10.342977 327450560.000000 +1.316052 -1.178465 9.962516 327550752.000000 +-1.617548 1.296910 10.432706 327650400.000000 +0.569492 0.205783 10.147961 327750432.000000 +0.575474 0.179462 10.156336 327850528.000000 +0.563510 0.209372 10.137194 327950528.000000 +0.571885 0.198604 10.120443 328050496.000000 +0.570688 0.187837 10.137194 328150656.000000 +0.571885 0.180658 10.155140 328250496.000000 +0.577867 0.208176 10.127622 328350560.000000 +0.568295 0.172283 10.153944 328450496.000000 +-0.508475 0.436690 10.210175 328550720.000000 +1.568495 0.162712 10.035499 328650592.000000 +1.593620 0.045464 10.147961 328750752.000000 +1.143769 -0.367298 10.191031 328850464.000000 +0.122034 -0.652044 10.018748 328950592.000000 +0.303888 -0.429512 9.955338 329050368.000000 +1.752743 -1.150948 9.914660 329150368.000000 +1.932204 -0.045464 9.986445 329250592.000000 +0.661615 -0.035892 9.938589 329350624.000000 +-1.209572 0.162712 10.046266 329450528.000000 +-0.924826 -0.168694 9.482756 329550592.000000 +1.092324 -0.025125 10.102496 329650688.000000 +-2.232504 0.587438 10.125229 329750528.000000 +0.037089 0.265603 10.186246 329850720.000000 +1.374677 0.951147 9.567701 329950496.000000 +-1.079163 -0.818345 10.118051 330050752.000000 +-1.929811 -1.152144 9.919446 330150592.000000 +-2.160719 0.664008 10.677971 330250752.000000 +1.928615 0.423530 10.536794 330350592.000000 +-0.415155 0.027517 10.144372 330450912.000000 +-0.911665 0.205783 10.134801 330550464.000000 +0.142373 0.369691 10.188639 330650720.000000 +1.432104 0.016750 10.061819 330750464.000000 +0.550349 0.267996 10.201799 330850720.000000 +0.569492 0.288335 10.182656 330950560.000000 +0.567099 0.300299 10.174281 331050720.000000 +1.402194 0.856631 10.023535 331150496.000000 +1.551746 0.604188 10.079765 331250720.000000 +1.545763 -0.648455 10.155140 331350496.000000 +0.522832 1.103091 10.187442 331450688.000000 +3.705286 0.958325 10.232906 331550432.000000 +0.658026 -1.360320 11.124231 331650688.000000 +2.901298 -0.366102 10.211370 331750528.000000 +2.187040 -1.561317 10.472188 331850720.000000 +0.745364 -0.654437 10.176675 331950624.000000 +-0.628116 0.008375 10.478169 332050688.000000 +0.784846 1.337588 10.085747 332150496.000000 +-0.599402 0.655633 10.235298 332250688.000000 +-0.668794 0.177069 10.109675 332350560.000000 +0.037089 -0.348156 10.079765 332450720.000000 +0.401994 -0.266800 10.132407 332550560.000000 +-0.801596 -0.821935 10.006784 332650752.000000 +0.589831 -0.789631 10.285547 332750464.000000 +-1.951347 0.088534 10.080962 332850784.000000 +-0.078963 -1.598405 9.501899 332950592.000000 +1.143769 -0.203390 10.364511 333050752.000000 +-1.910669 0.624527 10.070194 333150816.000000 +0.524028 0.057428 9.743573 333250368.000000 +0.406780 -0.019143 9.613165 333350624.000000 +0.250050 0.015553 9.969695 333450720.000000 +0.186640 -0.021535 10.177871 333550688.000000 +0.180658 0.004786 10.144372 333650496.000000 +0.161516 0.002393 10.202995 333750752.000000 +1.667797 -0.271585 11.005787 333850464.000000 +4.722236 -0.636491 9.826126 333950720.000000 +-0.935594 0.437887 10.348958 334050528.000000 +0.510868 -0.705883 9.877571 334150752.000000 +1.953740 -0.585045 9.933804 334250464.000000 +-0.397209 -0.751346 10.232906 334350784.000000 +-1.624727 0.500100 17.347965 334450496.000000 +-0.534796 -0.762114 9.795020 334550752.000000 +1.438086 -0.379262 9.722038 334650528.000000 +0.589831 -0.473779 10.137194 334750816.000000 +0.823131 -0.300299 10.180264 334850560.000000 +0.476172 -0.135194 12.108878 334951008.000000 +0.863809 0.892523 10.508080 335050496.000000 +0.184247 1.200001 9.153743 335150752.000000 +0.452243 -0.565903 14.194223 335250592.000000 +0.861416 -0.276371 10.242477 335350720.000000 +0.232104 -1.380659 10.328619 335450560.000000 +-0.617348 0.922433 10.650455 335550720.000000 +-1.069592 -0.128016 10.113264 335650464.000000 +0.215354 -0.052642 10.118051 335750752.000000 +0.291924 0.002393 10.220942 335850464.000000 +0.253639 -0.022732 10.164711 335950752.000000 +0.250050 -0.043071 10.162319 336050560.000000 +0.198604 -0.041874 10.135997 336150752.000000 +0.058624 0.074178 10.115658 336250496.000000 +0.039482 -0.999003 10.036695 336350720.000000 +2.585445 -1.738386 10.303494 336450560.000000 +0.157926 -0.199801 10.004392 336550720.000000 +-0.703490 -0.470190 10.286745 336650496.000000 +0.763310 -1.320838 10.185050 336750720.000000 +1.651048 -1.763510 10.218549 336850560.000000 +-1.277767 0.102891 9.574880 336950752.000000 +-0.179462 -0.558724 9.736395 337050464.000000 +-1.045663 -0.415155 9.933804 337150720.000000 +-1.055235 -0.997807 10.189835 337250464.000000 +-2.349752 -0.648455 10.413565 337350720.000000 +-0.768096 -0.459422 9.388239 337450496.000000 +0.454636 -1.079163 9.988838 337550720.000000 +1.217947 1.088734 10.170692 337650528.000000 +-0.423530 -0.133998 10.382458 337750752.000000 +-1.048056 0.095713 10.392029 337850464.000000 +-0.367298 0.050249 10.094121 337950912.000000 +0.434297 0.165105 10.158729 338050432.000000 +0.282353 0.233300 10.083356 338150720.000000 +0.284746 0.278764 9.686146 338250432.000000 +0.259621 0.210568 10.175477 338350688.000000 +-0.707079 0.358923 10.497313 338450496.000000 +0.421137 0.154337 10.152746 338550752.000000 +0.661615 0.192622 8.780463 338650432.000000 +0.637687 0.196211 8.654840 338750816.000000 +0.507278 0.185444 8.939585 338850464.000000 +0.351745 0.204586 9.281759 338950752.000000 +-0.095713 0.212961 11.072786 339050592.000000 +-0.156730 0.232104 10.789237 339150752.000000 +0.276371 0.220140 9.428917 339250592.000000 +-0.007178 0.196211 10.328619 339350688.000000 +-0.040678 0.208176 10.423136 339450624.000000 +0.099302 0.216550 10.025927 339550752.000000 +0.039482 0.191426 10.210175 339650560.000000 +0.035892 0.230907 10.159925 339750784.000000 +0.033500 0.208176 10.108479 339850528.000000 +0.050249 0.222532 10.186246 339950752.000000 +0.032303 0.229711 10.168301 340050464.000000 +0.044267 0.185444 10.159925 340150720.000000 +0.029910 0.203390 10.074981 340250496.000000 +-0.072981 0.214158 10.325029 340350688.000000 +0.047856 0.190229 10.147961 340450560.000000 +-0.045464 0.218943 10.182656 340550720.000000 +0.004786 0.214158 10.146765 340650496.000000 +-0.017946 0.204586 10.167104 340750784.000000 +0.037089 0.197408 10.176675 340850496.000000 +0.046660 0.223729 10.124033 340950976.000000 +-0.016750 0.200997 10.224532 341050432.000000 +0.020339 0.206979 10.278370 341150720.000000 +0.070588 0.210568 10.071390 341250528.000000 +-0.052642 0.222532 10.097712 341350752.000000 +0.014357 0.329013 10.220942 341450464.000000 +-1.534996 0.478565 9.993625 341550688.000000 +0.933201 -0.610170 9.860823 341650464.000000 +1.550549 -0.805185 10.234102 341750752.000000 +0.614955 -0.318245 10.320245 341850464.000000 +-1.883151 0.856631 10.095319 341950720.000000 +1.889133 -1.177269 9.487542 342050496.000000 +1.836491 0.130409 9.631111 342150720.000000 +0.223729 0.203390 9.432507 342250528.000000 +-0.250050 0.230907 10.887343 342350720.000000 +0.220140 0.230907 9.527023 342450624.000000 +-0.135194 0.235693 10.730613 342550720.000000 +-0.362513 0.209372 11.721242 342650496.000000 +-3.911068 -0.449851 9.884750 342750464.000000 +-2.520839 2.070988 9.957731 342850400.000000 +-4.135994 1.326820 9.929017 342950464.000000 +-0.421137 -0.783649 10.526026 343050848.000000 +-1.940579 1.398605 9.854840 343150784.000000 +-0.238086 0.105284 10.231709 343250624.000000 +-0.474975 -0.424726 10.080962 343350496.000000 +-1.278964 -1.573281 7.324430 343450720.000000 +1.380659 -0.915255 10.426724 343550528.000000 +-0.985843 -1.068395 9.639486 343650688.000000 +-2.908476 -1.013360 10.071390 343750464.000000 +-2.965904 1.048056 12.246466 343850688.000000 +2.545963 1.155733 19.601404 343950560.000000 +1.841277 -0.784846 10.255639 344050688.000000 +-0.232104 0.220140 10.134801 344150560.000000 +-0.189033 0.224925 10.135997 344250688.000000 +-0.202193 0.236889 10.176675 344350496.000000 +-0.202193 0.234497 10.128819 344450688.000000 +-2.176272 0.733400 10.017551 344550400.000000 +0.419940 -0.735793 10.168301 344650432.000000 +-1.456033 -0.459422 10.023535 344750464.000000 +0.386441 -0.744168 10.265208 344850816.000000 +-0.345763 0.094516 10.271191 344950464.000000 +-0.823131 0.934397 10.107283 345050656.000000 +0.142373 0.010768 8.876175 345150464.000000 +0.440279 -1.637887 10.322637 345250656.000000 +-0.089731 -1.365105 9.850054 345350464.000000 +2.104487 -1.806581 10.071390 345450848.000000 +-0.927219 0.238086 9.964910 345550496.000000 +-1.049253 0.230907 10.213763 345650688.000000 +2.494518 -1.070788 10.441081 345750528.000000 +-2.300699 0.530010 10.663614 345850688.000000 +1.494318 -0.020339 10.402797 345950496.000000 +-0.364905 0.100499 10.317852 346050752.000000 +-0.299103 0.059821 10.204191 346150432.000000 +-0.296710 0.059821 10.130014 346250752.000000 +-0.314656 0.066999 10.177871 346350432.000000 +-0.324227 0.081356 10.165908 346450688.000000 +0.514457 0.260818 8.664411 346551008.000000 +-2.309074 -0.387637 9.879964 346650400.000000 +0.368495 0.448654 10.128819 346750464.000000 +-0.934397 -0.369691 10.175477 346850528.000000 +-0.247657 0.089731 9.845268 346950816.000000 +2.298306 0.458226 11.186446 347050464.000000 +-3.457629 -0.039482 9.934999 347150720.000000 +-0.842274 0.649651 9.688539 347250464.000000 +-0.043071 0.535992 9.979266 347350688.000000 +-2.469393 0.687937 9.664611 347450464.000000 +1.509871 -3.064009 10.009177 347550752.000000 +-2.835495 1.540978 9.854840 347650528.000000 +-1.951347 -1.025324 10.045070 347750784.000000 +-3.396612 -0.077767 10.018748 347850528.000000 +-0.884148 -0.699901 8.374879 347950752.000000 +0.174676 0.344566 10.346564 348050560.000000 +2.694318 -0.137587 11.040483 348150752.000000 +0.955933 0.501296 7.849655 348250560.000000 +-0.137587 0.221336 10.055838 348350720.000000 +-0.095713 0.248854 10.183852 348450656.000000 +-0.129212 0.244068 10.176675 348550720.000000 +-2.143969 0.602991 9.868000 348650400.000000 +-0.598206 0.277567 9.656236 348750624.000000 +-0.634098 1.155733 9.879964 348850464.000000 +0.092124 0.640080 10.185050 348950432.000000 +-0.988236 0.413958 10.317852 349050496.000000 +-2.414358 0.660419 10.162319 349150496.000000 +-1.855634 0.874577 10.351351 349250496.000000 +-2.796013 2.157130 12.528819 349350624.000000 +-1.453640 -1.050449 8.165507 349450528.000000 +0.155533 0.885344 9.653843 349550688.000000 +-1.245464 0.407976 9.610772 349650496.000000 +-0.844666 0.350549 10.457830 349750752.000000 +0.859023 -0.762114 9.781858 349850496.000000 +-0.034696 0.248854 10.200603 349950944.000000 +0.474975 -0.312263 10.112068 350050528.000000 +0.725025 -0.447458 10.151550 350150720.000000 +0.964308 -0.284746 10.025927 350250528.000000 +1.160519 -0.631705 10.192227 350350720.000000 +0.331406 0.198604 10.284351 350450464.000000 +-0.784846 0.591027 10.004392 350550720.000000 +-0.470190 0.381655 10.145569 350650464.000000 +1.441676 -0.568295 10.041479 350750752.000000 +0.192622 0.025125 10.202995 350850528.000000 +-1.311267 -0.380459 10.201799 350950752.000000 +0.921237 -0.532403 9.883554 351050560.000000 +-0.984646 0.323031 10.054641 351150752.000000 +1.757528 -0.917647 10.212566 351250560.000000 +-2.888137 -0.062213 10.131211 351350752.000000 +0.751346 -0.238086 10.271191 351450528.000000 +0.996611 -1.456033 10.438687 351550720.000000 +-0.096909 -0.046660 10.149158 351650464.000000 +-0.076570 -0.052642 10.118051 351750720.000000 +-0.095713 -0.028714 10.175477 351850560.000000 +-0.096909 -0.061017 10.197014 351950720.000000 +-0.072981 -0.033500 10.157533 352050464.000000 +-0.714258 0.003589 10.286745 352150688.000000 +-0.678365 -0.155533 10.058230 352250432.000000 +0.334995 -0.166301 10.278370 352350720.000000 +-0.273978 -0.618545 9.960124 352450432.000000 +-0.818345 0.023928 10.133603 352550720.000000 +-0.068195 -0.392423 10.085747 352650464.000000 +1.435694 -0.704686 9.865608 352750720.000000 +-0.131605 -0.046660 10.224532 352850432.000000 +-0.117248 -0.038285 10.207782 352950912.000000 +-0.166301 -0.033500 10.176675 353050432.000000 +-0.289532 -0.139980 9.963714 353150752.000000 +-4.383651 0.999003 9.925428 353250464.000000 +1.914258 -0.014357 10.561919 353350496.000000 +-0.128016 -1.184447 10.363315 353450528.000000 +0.088534 -1.299303 9.863215 353550496.000000 +-1.670190 0.126820 11.261820 353650656.000000 +-1.063610 0.308674 9.615558 353750400.000000 +-1.192822 0.240479 9.399008 353850816.000000 +-2.221736 -0.687937 8.733803 353950464.000000 +-2.286342 -0.924826 10.077373 354050720.000000 +1.896312 0.132802 7.356733 354150464.000000 +1.813759 -0.476172 8.388040 354250720.000000 +0.702293 0.232104 8.572287 354350560.000000 +0.640080 0.229711 8.522038 354450912.000000 +0.537189 0.260818 8.773284 354550400.000000 +-0.885344 0.374477 8.398808 354650400.000000 +1.366302 0.082552 8.883354 354750400.000000 +0.390030 0.221336 9.140583 354850432.000000 +0.177069 0.203390 9.890733 354950432.000000 +0.392423 0.217747 9.108279 355050496.000000 +-0.697508 0.344566 10.675578 355150688.000000 +-0.017946 0.208176 10.352547 355250528.000000 +-0.533599 1.255035 10.130014 355350752.000000 +-2.798406 0.291924 10.068997 355450400.000000 +-2.673979 1.179662 8.712267 355550432.000000 +-1.007378 1.125823 10.250853 355650624.000000 +1.560120 0.184247 10.687543 355750496.000000 +2.112862 -0.078963 10.289137 355850688.000000 +-0.224925 -0.064606 10.549955 355950624.000000 +-0.112463 -1.149751 10.341780 356050752.000000 +-0.495314 -1.306481 9.729217 356150464.000000 +-0.786042 -3.865605 9.318848 356250720.000000 +-0.034696 -3.905087 8.409575 356350560.000000 +0.918844 -5.276174 10.003194 356450720.000000 +-0.430708 -5.352744 9.291330 356550432.000000 +0.502493 -5.974878 8.179864 356650752.000000 +1.361516 -5.943772 8.388040 356750464.000000 +3.211168 -3.421736 8.539984 356850720.000000 +-0.118445 -4.426722 9.098708 356950368.000000 +-2.605784 -2.921637 11.251052 357050752.000000 +-2.675175 -3.237489 9.451650 357150400.000000 +0.221336 -4.698307 10.329816 357250688.000000 +-3.046063 -2.652444 8.867801 357350496.000000 +-0.908076 -2.756532 15.212369 357450848.000000 +-3.284149 -0.935594 6.890133 357550464.000000 +-1.336391 -0.553938 9.298509 357650528.000000 +-0.427119 -0.167498 8.739785 357750432.000000 +0.920040 -0.088534 11.015360 357850528.000000 +0.838684 -0.993021 11.563314 357950432.000000 +0.149551 -1.518246 11.961720 358050336.000000 +2.032703 -0.762114 10.220942 358150368.000000 +1.377069 -1.338784 9.582059 358252896.000000 +1.201197 -0.105284 10.376474 358350368.000000 +0.838684 0.160319 10.091729 358450368.000000 +1.505085 -0.488136 10.124033 358550368.000000 +0.368495 0.026321 8.534002 358650368.000000 +0.056231 0.051446 9.705289 358760096.000000 +-0.016750 0.066999 10.197014 358880096.000000 +-0.013161 0.050249 10.207782 358995168.000000 +-0.020339 0.063410 10.144372 359099808.000000 +-0.051446 0.068195 10.214959 359215104.000000 +-0.040678 0.066999 10.183852 359315424.000000 +-0.041874 0.047856 10.244871 359415680.000000 +-0.044267 0.052642 10.174281 359534016.000000 +-0.022732 0.059821 10.199407 359630432.000000 +-0.016750 0.035892 10.193424 359732192.000000 +-0.043071 0.055035 10.176675 359830464.000000 +-0.026321 0.049053 10.200603 359945088.000000 +-0.016750 0.049053 10.150353 360045440.000000 +-0.043071 0.035892 10.191031 360145376.000000 +-0.040678 0.040678 10.206585 360245344.000000 +-0.034696 0.035892 10.197014 360345536.000000 +-0.026321 0.075374 10.173084 360445504.000000 +-0.027517 0.032303 10.191031 360545472.000000 +-0.013161 0.071785 10.180264 360645536.000000 +-0.063410 0.053839 10.179067 360745408.000000 +-0.045464 0.043071 10.169496 360845536.000000 +-0.026321 0.062213 10.188639 360945376.000000 +-0.049053 0.071785 10.163515 361045440.000000 +-0.044267 0.057428 10.175477 361145504.000000 +0.080160 0.046660 9.650253 361245408.000000 +-0.013161 0.044267 10.208978 361345472.000000 +-0.017946 0.080160 10.236496 361445440.000000 +-0.040678 0.068195 10.181459 361545504.000000 +-0.029910 0.061017 10.169496 361645440.000000 +-0.041874 0.034696 10.181459 361745344.000000 +-0.034696 0.029910 10.180264 361845504.000000 +-0.021535 0.009571 10.193424 361945376.000000 +-0.029910 0.059821 10.131211 362045568.000000 +-0.044267 0.020339 10.174281 362145408.000000 +-0.032303 0.051446 10.205389 362245632.000000 +-0.020339 0.044267 10.171888 362345472.000000 +-0.051446 0.057428 10.205389 362445344.000000 +-0.029910 0.019143 10.170692 362545504.000000 +-0.041874 0.032303 10.199407 362645376.000000 +-0.021535 0.070588 10.186246 362745536.000000 +-0.008375 0.040678 10.185050 362845344.000000 +-0.016750 0.058624 10.201799 362945504.000000 +-0.026321 0.058624 10.180264 363045408.000000 +-0.026321 0.078963 10.195816 363145568.000000 +-0.037089 0.080160 10.180264 363245376.000000 +-0.023928 0.053839 10.162319 363345504.000000 +-0.031107 0.031107 10.205389 363445376.000000 +-0.017946 0.034696 10.197014 363545696.000000 +-0.057428 0.026321 10.213763 363645344.000000 +-0.061017 0.065803 10.199407 363745504.000000 +-0.035892 0.071785 10.195816 363845376.000000 +-0.041874 0.063410 10.201799 363945504.000000 +-0.028714 0.056231 10.210175 364045344.000000 +-0.019143 0.039482 10.186246 364145472.000000 +-0.020339 0.045464 10.181459 364245376.000000 +-0.021535 0.049053 10.158729 364345536.000000 +-0.044267 0.061017 10.170692 364445376.000000 +-0.029910 0.062213 10.186246 364545504.000000 +-0.039482 0.031107 10.165908 364645504.000000 +-0.011964 0.056231 10.200603 364745408.000000 +-0.037089 0.043071 10.174281 364845472.000000 +0.005982 0.056231 10.173084 364945408.000000 +-0.050249 0.041874 10.188639 365045568.000000 +-0.047856 0.057428 10.163515 365145440.000000 +-0.028714 0.037089 10.183852 365245600.000000 +-0.038285 0.049053 10.175477 365345376.000000 +-0.032303 0.050249 10.217353 365445344.000000 +-0.038285 0.045464 10.155140 365545344.000000 +-0.023928 0.050249 10.193424 365645408.000000 +-0.052642 0.056231 10.194620 365745344.000000 +-0.009571 0.072981 10.187442 365845344.000000 +-0.013161 0.028714 10.168301 365945728.000000 +-0.015553 0.084945 10.171888 366050624.000000 +-0.009571 0.046660 10.200603 366150784.000000 +-0.043071 0.053839 10.161121 366256064.000000 +-0.033500 0.038285 10.167104 366355680.000000 +-0.014357 0.039482 10.191031 366455808.000000 +-0.053839 0.050249 10.197014 366555776.000000 +-0.016750 0.058624 10.162319 366655904.000000 +-0.009571 0.059821 10.175477 366756160.000000 +-0.005982 0.044267 10.168301 366856128.000000 +-0.039482 0.051446 10.183852 366956704.000000 +-0.038285 0.070588 10.182656 367055872.000000 +-0.014357 0.049053 10.188639 367156352.000000 +-0.045464 0.063410 10.206585 367261312.000000 +-0.045464 0.047856 10.180264 367361312.000000 +-0.021535 0.022732 10.213763 367461312.000000 +-0.034696 0.049053 10.202995 367561344.000000 +-0.023928 0.037089 10.191031 367660928.000000 +-0.043071 0.080160 10.205389 367761344.000000 +-0.037089 0.056231 10.194620 367861376.000000 +-0.034696 0.034696 10.181459 367961216.000000 +-0.029910 0.035892 10.200603 368061504.000000 +-0.053839 0.047856 10.195816 368160992.000000 +-0.043071 0.056231 10.168301 368260928.000000 +-0.017946 0.056231 10.167104 368361376.000000 +-0.065803 0.051446 10.197014 368460864.000000 +-0.055035 0.035892 10.179067 368560928.000000 +-0.086142 0.056231 10.218549 368660672.000000 +-0.015553 0.038285 10.187442 368760640.000000 +-0.043071 0.043071 10.186246 368860640.000000 +-0.025125 0.046660 10.204191 368960896.000000 +-0.025125 0.050249 10.198210 369060928.000000 +-0.019143 0.039482 10.211370 369160928.000000 +-0.027517 0.038285 10.195816 369260960.000000 +-0.040678 0.072981 10.188639 369360672.000000 +-0.040678 0.033500 10.222138 369460736.000000 +-0.033500 0.077767 10.174281 369561472.000000 +-0.031107 0.041874 10.177871 369661024.000000 +-0.015553 0.040678 10.182656 369760864.000000 +-0.028714 0.029910 10.186246 369860928.000000 +-0.037089 0.057428 10.177871 369960864.000000 +-0.032303 0.046660 10.195816 370060928.000000 +-0.020339 0.057428 10.210175 370160896.000000 +-0.022732 0.059821 10.212566 370260896.000000 +-0.057428 0.051446 10.194620 370361408.000000 +-0.034696 0.020339 10.168301 370460864.000000 +-0.040678 0.045464 10.193424 370561632.000000 +-0.035892 0.022732 10.225728 370660928.000000 +-0.040678 0.051446 10.193424 370760864.000000 +-0.029910 0.059821 10.193424 370860960.000000 +-0.019143 0.052642 10.206585 370960896.000000 +-0.034696 0.044267 10.197014 371060992.000000 +-0.051446 0.053839 10.211370 371160992.000000 +-0.027517 0.046660 10.200603 371260896.000000 +-0.019143 0.035892 10.230514 371360896.000000 +-0.051446 0.046660 10.220942 371460896.000000 +-0.063410 0.078963 10.232906 371560864.000000 +-0.028714 0.055035 10.213763 371660640.000000 +-0.045464 0.037089 10.216157 371770720.000000 +-0.026321 0.071785 10.187442 371871296.000000 +-0.029910 0.050249 10.200603 371971392.000000 +-0.001196 0.053839 10.193424 372071072.000000 +-0.025125 0.047856 10.205389 372171456.000000 +-0.038285 0.049053 10.200603 372271456.000000 +-0.028714 0.050249 10.220942 372371424.000000 +-0.041874 0.065803 10.223334 372475712.000000 +-0.029910 0.052642 10.180264 372575808.000000 diff --git a/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/gyro.txt b/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/gyro.txt new file mode 100755 index 0000000..0b134cc --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/gyro.txt @@ -0,0 +1,1095 @@ +1.890000 0.472500 -0.472500 263060416.000000 +-1.522500 0.682500 -33.250000 263160528.000000 +-4.620000 0.262500 2.502500 263260592.000000 +-4.602500 0.332500 2.257500 263360592.000000 +-4.655000 -0.192500 2.257500 263460576.000000 +-4.637500 -0.227500 2.275000 263560672.000000 +-4.620000 -0.052500 2.240000 263660544.000000 +-4.602500 0.087500 2.275000 263760576.000000 +-4.602500 0.577500 2.240000 263860656.000000 +-4.655000 0.402500 2.240000 263960560.000000 +-4.655000 0.332500 2.257500 264060528.000000 +-4.637500 0.227500 2.240000 264160608.000000 +-4.672500 0.052500 2.257500 264260528.000000 +-4.637500 -0.122500 2.257500 264360544.000000 +-4.655000 0.052500 2.275000 264460592.000000 +-4.637500 0.367500 2.257500 264560608.000000 +-4.655000 -0.017500 2.275000 264660512.000000 +-4.812500 -1.487500 0.315000 264760592.000000 +-7.840000 1.067500 1.837500 264860512.000000 +-11.445000 5.967500 0.315000 264960528.000000 +-38.500000 49.822498 -4.882500 265060608.000000 +-68.757500 -43.382500 13.772500 265160528.000000 +-64.102501 -15.557500 0.665000 265260512.000000 +-55.422501 -15.242500 -4.917500 265360592.000000 +-65.660004 -4.217500 -1.925000 265460528.000000 +-56.682499 -15.907500 1.680000 265560528.000000 +11.725000 -5.477500 3.220000 265660720.000000 +34.755001 -2.047500 -5.670000 265760592.000000 +10.797500 -0.262500 -6.440000 265860592.000000 +-4.462500 -10.237500 -9.765000 265960608.000000 +-15.207500 -22.067499 -5.827500 266060624.000000 +-55.720001 -28.612499 18.375000 266160512.000000 +-168.122498 -8.242500 56.577499 266260672.000000 +-182.384995 11.252500 42.070000 266360560.000000 +-197.645004 51.747501 83.667503 266460592.000000 +-184.397507 42.402500 45.692501 266567712.000000 +-152.722504 20.352501 18.077499 266665488.000000 +-149.134995 24.447500 35.857502 266765504.000000 +-140.682495 16.747499 38.132500 266865552.000000 +-180.214996 -3.517500 39.707500 266965504.000000 +-212.152496 -5.967500 18.952499 267065552.000000 +-193.199997 -14.892500 12.617500 267165840.000000 +-89.144997 5.267500 -7.857500 267265648.000000 +-104.842499 -18.077499 29.627501 267365712.000000 +-144.830002 9.782500 30.467501 267465600.000000 +-200.479996 39.462502 21.805000 267565568.000000 +-122.220001 22.557501 23.642500 267665376.000000 +-132.562500 47.897499 31.990000 267765584.000000 +-172.235001 2.712500 51.485001 267865392.000000 +-211.417496 14.927500 71.680000 267965376.000000 +-169.942505 1.032500 33.582500 268065408.000000 +-139.247498 -43.032501 2.835000 268165680.000000 +-104.772499 29.837500 7.472500 268265392.000000 +-99.312500 -2.397500 -3.185000 268365392.000000 +-96.092499 10.027500 -3.500000 268465408.000000 +-81.742500 5.127500 -9.940000 268565376.000000 +-74.830002 -8.172500 -0.210000 268665408.000000 +-74.567497 12.477500 11.655000 268765376.000000 +-74.305000 4.847500 16.012501 268865824.000000 +-68.215004 -2.677500 12.810000 268965408.000000 +-20.510000 73.832497 11.917500 269065408.000000 +-74.812500 37.117500 -5.810000 269165408.000000 +-149.292496 46.252499 12.215000 269265408.000000 +-184.677505 30.957500 -27.107500 269365728.000000 +-220.062500 58.152500 -21.647501 269465408.000000 +-216.422501 23.152500 13.737500 269565344.000000 +-235.479996 79.012497 48.509998 269665376.000000 +-231.822495 103.302498 25.725000 269765408.000000 +-268.607513 136.237503 20.737499 269865376.000000 +-229.722504 72.887497 30.257500 269965568.000000 +-129.430008 -32.777500 10.710000 270065408.000000 +-88.934998 118.772499 -18.252501 270165376.000000 +-230.947495 58.642502 -78.120003 270265408.000000 +-354.130005 91.472504 -77.525002 270366336.000000 +-303.135010 -25.077499 -49.840000 270465376.000000 +-234.692505 35.052502 -13.230000 270565472.000000 +-132.422501 29.942501 0.525000 270665376.000000 +-93.572502 5.372500 2.205000 270765408.000000 +-68.459999 12.022500 12.897500 270865376.000000 +-75.687500 4.042500 24.570000 270965408.000000 +-52.797501 -0.717500 24.080000 271065376.000000 +-36.522499 8.942500 7.385000 271165376.000000 +-48.877499 -7.752500 -6.177500 271265376.000000 +-49.490002 -3.727500 -5.390000 271365408.000000 +-53.252499 -5.792500 1.697500 271465376.000000 +-46.095001 13.037500 7.665000 271565504.000000 +-25.270000 0.927500 3.447500 271665376.000000 +-52.220001 -2.397500 13.387500 271765408.000000 +-74.760002 43.137501 22.434999 271866016.000000 +-96.687500 71.977501 35.472500 271965728.000000 +-170.292496 55.177502 32.095001 272065408.000000 +-115.815002 26.407499 -7.315000 272165376.000000 +-156.589996 3.272500 -8.557500 272265408.000000 +-169.330002 7.997500 12.232500 272365440.000000 +-219.012497 22.942499 19.565001 272465408.000000 +-213.867508 39.077499 17.377501 272565440.000000 +-192.937500 51.572498 19.932501 272665472.000000 +-207.217499 68.617500 2.992500 272765408.000000 +-245.000000 97.947502 3.360000 272865408.000000 +-233.467499 60.462502 6.545000 272965408.000000 +-132.422501 22.102501 -8.505000 273065408.000000 +-71.959999 28.612499 0.805000 273165408.000000 +-50.067501 66.202499 -37.974998 273265408.000000 +-61.180000 56.227501 -32.742500 273365344.000000 +-172.690002 -20.597500 -62.387501 273465408.000000 +-231.437500 -8.102500 -77.805000 273565472.000000 +-246.277496 -54.792500 -78.434998 273665376.000000 +-238.070007 -31.342501 -26.880001 273765408.000000 +-215.425003 -55.912498 62.580002 273865376.000000 +-205.747498 -10.097500 45.465000 273965376.000000 +-216.177505 -42.927502 45.867500 274065376.000000 +-121.992500 20.212500 29.610001 274165376.000000 +-69.212502 -8.837500 29.872499 274265376.000000 +-32.165001 -14.507500 2.432500 274365408.000000 +0.140000 12.232500 12.495000 274465376.000000 +-6.317500 7.017500 6.352500 274565376.000000 +-9.292500 8.942500 7.612500 274665376.000000 +-9.065000 12.337500 4.182500 274765376.000000 +-6.492500 7.122500 5.617500 274865408.000000 +-7.682500 -0.087500 4.305000 274965376.000000 +-7.560000 2.957500 5.582500 275065472.000000 +-5.670000 7.787500 5.197500 275165376.000000 +-7.735000 8.487500 4.112500 275265408.000000 +-5.880000 -4.287500 5.967500 275365376.000000 +-0.490000 2.292500 8.225000 275465376.000000 +-1.085000 -0.507500 8.767500 275565376.000000 +-4.445000 -4.532500 12.232500 275665376.000000 +-2.975000 3.727500 5.582500 275765376.000000 +-2.135000 2.362500 3.465000 275865408.000000 +11.865000 0.262500 3.517500 275965376.000000 +69.702499 8.137500 -16.975000 276065376.000000 +68.617500 2.432500 -4.235000 276165376.000000 +83.142502 20.212500 0.822500 276265408.000000 +141.627502 -12.512500 28.437500 276365408.000000 +219.257507 -2.607500 24.097500 276466048.000000 +276.447510 -42.647499 55.422501 276565504.000000 +280.665009 -21.892500 34.002499 276665408.000000 +245.122498 -64.417503 -6.352500 276765408.000000 +173.687500 9.887500 -37.485001 276865632.000000 +206.307495 -58.082500 -18.620001 276965408.000000 +112.840004 -54.512501 -22.067499 277066016.000000 +129.149994 -46.147499 -18.637501 277165408.000000 +197.977493 -19.687500 -8.347500 277265728.000000 +308.997498 -7.087500 -10.290000 277365824.000000 +86.379997 -29.802500 16.432501 277465504.000000 +239.767502 -36.172501 -65.677498 277565408.000000 +123.742500 -56.437500 5.617500 277665408.000000 +302.750000 -41.947498 -7.997500 277765408.000000 +152.669998 -44.222500 -44.502499 277865856.000000 +151.830002 -26.827499 -86.957497 277965568.000000 +118.754997 4.602500 -43.347500 278065472.000000 +84.227501 15.592500 -13.055000 278165344.000000 +42.787498 -57.347500 26.407499 278265632.000000 +94.535004 48.177502 0.857500 278365376.000000 +68.144997 -9.082500 -12.460000 278465408.000000 +54.145000 -2.502500 -30.450001 278565504.000000 +65.222504 -5.022500 -4.532500 278665440.000000 +39.759998 -0.892500 -7.892500 278765408.000000 +26.862499 -0.402500 -19.862499 278865408.000000 +39.970001 -8.312500 -21.245001 278965408.000000 +47.512501 -7.717500 -9.870000 279066176.000000 +34.737499 20.597500 7.070000 279165408.000000 +72.940002 17.692499 5.162500 279265408.000000 +167.807495 79.012497 4.672500 279365408.000000 +243.442505 -79.362503 -24.797501 279465408.000000 +163.362503 -50.172501 21.997499 279565472.000000 +194.529999 -74.812500 -33.285000 279665408.000000 +174.247498 23.187500 -54.267502 279765504.000000 +160.247498 22.207500 -56.805000 279865376.000000 +130.392502 53.567501 4.147500 279965376.000000 +150.657501 73.937500 7.227500 280065568.000000 +107.257500 37.152500 13.230000 280165408.000000 +72.169998 8.697500 15.365000 280265376.000000 +78.662498 -34.772499 18.760000 280365408.000000 +163.625000 43.347500 1.435000 280465408.000000 +175.402496 11.812500 21.700001 280565408.000000 +251.229996 -20.842501 52.412498 280665408.000000 +251.317505 -33.127499 2.345000 280765408.000000 +176.399994 -32.182499 7.735000 280865408.000000 +165.707504 -34.842499 0.280000 280965664.000000 +164.202499 -48.212502 -14.840000 281065472.000000 +132.912506 -33.547501 -4.410000 281165408.000000 +133.595001 -0.577500 -8.925000 281265408.000000 +114.449997 24.867500 -2.782500 281365408.000000 +90.037498 11.042500 -22.260000 281465376.000000 +84.087502 22.837500 -22.049999 281565344.000000 +14.752501 28.822500 -1.347500 281665408.000000 +7.122500 0.367500 -27.230000 281765376.000000 +17.132500 19.232500 -10.797500 281865376.000000 +15.715000 12.162500 -11.305000 281965408.000000 +63.560001 19.932501 -16.922501 282065440.000000 +92.294998 8.312500 -36.662498 282165376.000000 +126.279999 -7.507500 -16.555000 282265376.000000 +146.737503 -25.602501 7.787500 282365408.000000 +285.529999 8.347500 -35.787498 282465376.000000 +313.232513 105.402504 40.915001 282565504.000000 +217.822495 10.237500 101.167503 282665408.000000 +81.760002 46.462502 18.445000 282765440.000000 +143.815002 -48.107502 25.637501 282865568.000000 +203.157501 -49.402500 0.192500 282965984.000000 +146.282501 55.177502 -34.545002 283065408.000000 +182.297501 -24.237499 20.562500 283165408.000000 +254.257507 -29.172501 62.037498 283265472.000000 +288.225006 -47.267502 36.330002 283365408.000000 +257.512512 -70.962502 5.337500 283465376.000000 +256.252502 -55.072502 -39.917500 283565408.000000 +177.292496 -37.152500 -16.975000 283665408.000000 +162.330002 -22.032499 -8.715000 283765376.000000 +173.039993 13.422500 -17.132500 283865408.000000 +112.717499 28.752501 -9.100000 283965408.000000 +73.937500 24.412500 2.887500 284065504.000000 +59.237499 23.047501 -8.662500 284165408.000000 +91.612503 12.792500 -1.260000 284265408.000000 +34.807499 29.137501 14.210000 284365376.000000 +11.847500 -16.467501 15.435000 284465536.000000 +28.297501 -25.567499 -9.922500 284565376.000000 +2.957500 -20.982500 -5.162500 284665376.000000 +-5.250000 -16.677500 1.487500 284765408.000000 +-12.932500 -12.722500 7.157500 284865376.000000 +-8.435000 -17.097500 3.255000 284965376.000000 +-9.397500 -12.652500 -3.325000 285065376.000000 +-11.987500 -7.962500 4.655000 285165376.000000 +-12.897500 -1.137500 3.622500 285265376.000000 +5.075000 31.377501 6.632500 285365376.000000 +-4.515000 -13.002500 4.585000 285465376.000000 +-7.455000 3.517500 9.677500 285565472.000000 +-2.082500 -0.822500 5.705000 285665376.000000 +-3.920000 -4.462500 4.095000 285765376.000000 +5.075000 2.362500 4.672500 285865376.000000 +3.465000 -4.112500 8.995000 285965408.000000 +9.327500 -4.917500 7.455000 286065408.000000 +-8.995000 -16.887501 5.757500 286165376.000000 +1.575000 9.607500 4.585000 286265408.000000 +-2.502500 2.922500 3.255000 286365440.000000 +0.455000 0.647500 3.605000 286465376.000000 +-3.710000 -8.417500 4.252500 286565408.000000 +-4.462500 -1.697500 2.625000 286665376.000000 +-0.560000 -1.347500 3.430000 286765408.000000 +-4.252500 4.637500 -2.537500 286865408.000000 +-1.277500 0.297500 4.165000 286965792.000000 +-5.582500 -2.327500 3.902500 287065440.000000 +-16.379999 2.817500 1.627500 287165504.000000 +-5.530000 1.557500 5.320000 287265504.000000 +-3.150000 -2.957500 6.685000 287365376.000000 +-1.697500 0.227500 8.890000 287465376.000000 +-4.357500 -7.472500 3.062500 287567840.000000 +-4.690000 -21.962500 6.580000 287665376.000000 +-12.547500 -11.182500 4.550000 287765440.000000 +-1.715000 22.767500 -0.402500 287865440.000000 +-3.412500 5.127500 -0.052500 287965376.000000 +-5.810000 6.982500 1.960000 288065600.000000 +-5.092500 2.397500 1.767500 288165504.000000 +-6.352500 -0.577500 1.715000 288265408.000000 +-7.017500 -12.617500 2.100000 288365408.000000 +-3.902500 -0.017500 2.590000 288465728.000000 +-10.220000 11.497500 0.052500 288565472.000000 +13.282500 29.977501 -4.130000 288665376.000000 +-16.100000 -16.817499 7.700000 288765504.000000 +-1.855000 10.622500 3.902500 288865376.000000 +-10.237500 -4.602500 2.065000 288965536.000000 +-5.040000 7.157500 1.575000 289065408.000000 +-5.215000 -8.767500 3.185000 289165536.000000 +-11.812500 -13.142500 2.905000 289265408.000000 +-4.690000 19.337500 -1.487500 289365376.000000 +1.680000 -8.347500 9.467500 289465696.000000 +-8.102500 3.237500 1.750000 289565472.000000 +-3.815000 -2.117500 4.270000 289665536.000000 +-3.570000 1.802500 4.340000 289765536.000000 +-2.730000 12.547500 5.862500 289865440.000000 +9.100000 -1.977500 16.205000 289965408.000000 +-5.547500 -21.192499 17.202499 290065472.000000 +1.697500 47.022499 -6.965000 290165632.000000 +-6.825000 45.447498 -8.645000 290265632.000000 +3.185000 21.752501 -4.042500 290365696.000000 +-3.815000 2.502500 1.802500 290465664.000000 +1.382500 -9.677500 5.792500 290565728.000000 +-16.625000 -27.002501 6.737500 290665440.000000 +-43.330002 -18.707500 -7.385000 290765376.000000 +16.240000 134.837494 -41.142502 290865408.000000 +7.612500 -40.057499 8.750000 290967392.000000 +-15.627501 -5.127500 6.387500 291065472.000000 +-12.285000 -12.022500 3.867500 291165600.000000 +-15.715000 -16.327499 3.237500 291265792.000000 +-6.177500 -2.467500 0.752500 291365568.000000 +-9.257500 -18.007500 4.620000 291465888.000000 +-8.120000 -9.467500 3.220000 291565728.000000 +-8.522500 -5.512500 3.815000 291665792.000000 +-6.790000 -5.022500 3.605000 291765568.000000 +-6.667500 -5.057500 3.622500 291865376.000000 +-5.810000 -3.272500 3.937500 291965376.000000 +-4.340000 -0.192500 2.117500 292065376.000000 +-4.795000 -1.067500 2.275000 292165376.000000 +-4.007500 1.557500 1.785000 292265504.000000 +-4.795000 1.067500 2.065000 292365600.000000 +-4.935000 -1.522500 2.397500 292465568.000000 +-4.795000 -1.172500 2.730000 292565696.000000 +-5.495000 -0.612500 2.205000 292665632.000000 +-4.917500 -1.417500 2.800000 292765504.000000 +-5.530000 -1.872500 2.310000 292865792.000000 +-4.585000 0.262500 2.432500 292965856.000000 +-4.637500 0.787500 2.170000 293065728.000000 +-5.722500 -1.032500 2.117500 293165856.000000 +-4.690000 0.157500 1.750000 293265664.000000 +-5.687500 -0.087500 3.290000 293365632.000000 +-4.480000 -0.227500 3.027500 293465504.000000 +-3.902500 -0.192500 2.905000 293565888.000000 +-4.777500 -0.297500 2.607500 293665696.000000 +-3.867500 -0.052500 2.415000 293765600.000000 +-4.672500 -1.242500 3.202500 293865600.000000 +-4.935000 -0.927500 2.502500 293965568.000000 +-5.442500 -1.487500 2.905000 294065632.000000 +-4.602500 -0.017500 2.467500 294165568.000000 +-4.392500 0.227500 2.310000 294265664.000000 +-4.900000 -0.752500 2.170000 294365696.000000 +-4.550000 -0.192500 2.100000 294465504.000000 +-4.252500 0.402500 2.030000 294565888.000000 +-4.865000 -0.262500 1.802500 294665696.000000 +-5.267500 0.087500 2.257500 294765728.000000 +-5.530000 -0.402500 1.977500 294866016.000000 +-4.865000 -0.752500 1.767500 294965728.000000 +-2.975000 1.102500 1.925000 295065952.000000 +-5.320000 -0.437500 1.417500 295165568.000000 +-5.232500 0.332500 2.082500 295265696.000000 +-5.285000 -0.927500 2.275000 295365952.000000 +-5.250000 -0.647500 2.257500 295465600.000000 +-5.722500 -1.032500 2.170000 295565952.000000 +-2.835000 2.502500 2.537500 295665600.000000 +-2.170000 6.072500 2.800000 295765952.000000 +-6.457500 31.132500 6.615000 295865536.000000 +1.645000 21.577499 15.750000 295966048.000000 +-2.415000 9.187500 4.270000 296065824.000000 +1.102500 11.322500 2.240000 296165632.000000 +-14.700000 -13.597500 5.022500 296266080.000000 +-3.465000 9.642500 2.695000 296365600.000000 +-0.175000 4.042500 0.402500 296465600.000000 +-7.315000 -4.497500 0.735000 296565664.000000 +-8.557500 3.622500 2.432500 296665600.000000 +6.090000 25.882500 2.992500 296765568.000000 +-8.505000 60.042500 3.745000 296865568.000000 +-8.960000 98.822502 8.942500 296965728.000000 +-15.697500 139.107498 9.485000 297066016.000000 +-22.767500 197.347504 16.887501 297165632.000000 +-17.972500 169.592499 12.600000 297266080.000000 +-1.575000 144.532501 8.207500 297365536.000000 +-20.895000 150.657501 1.750000 297465376.000000 +-33.617500 134.977493 1.540000 297565472.000000 +-31.290001 153.247498 -8.750000 297665376.000000 +-13.247500 121.222504 -22.014999 297765376.000000 +-22.802500 103.967499 -0.770000 297865376.000000 +-3.990000 50.172501 26.127501 297965376.000000 +-29.365000 82.862503 22.155001 298065376.000000 +-7.385000 62.632500 17.867500 298165728.000000 +-10.290000 41.492500 19.460001 298265408.000000 +-6.755000 86.852501 13.107500 298365440.000000 +-23.817499 166.897507 20.125000 298465344.000000 +-20.492500 229.512497 22.365000 298565504.000000 +-18.585001 292.757507 24.885000 298665472.000000 +7.280000 280.577515 40.127499 298765856.000000 +-8.417500 303.432495 23.992500 298865536.000000 +-0.507500 226.677505 29.225000 298965344.000000 +-20.702499 163.327499 19.197500 299065408.000000 +-12.460000 136.762497 15.767500 299165440.000000 +-15.032500 82.617500 -10.867500 299265344.000000 +13.772500 129.412506 -21.402500 299365504.000000 +44.572498 84.577499 9.887500 299465536.000000 +10.237500 56.087502 -4.847500 299566464.000000 +-11.357500 34.247501 7.035000 299665376.000000 +-26.844999 18.217501 6.405000 299765568.000000 +-5.040000 -0.192500 15.225000 299865728.000000 +-0.630000 32.252499 4.690000 299965568.000000 +-5.600000 93.467499 5.687500 300065984.000000 +1.225000 154.892502 16.012501 300165536.000000 +-21.105000 131.897507 13.072500 300265696.000000 +-3.167500 90.912498 8.995000 300365664.000000 +-3.640000 134.067505 7.892500 300465696.000000 +-2.415000 152.232498 10.692500 300565440.000000 +-4.847500 157.482498 2.747500 300665376.000000 +13.142500 109.217499 2.572500 300765376.000000 +3.780000 88.742500 1.872500 300865536.000000 +-4.147500 144.042496 9.415000 300967872.000000 +-45.709999 162.102493 1.890000 301065920.000000 +-19.530001 50.487499 -19.809999 301165504.000000 +-0.420000 59.027500 -17.045000 301265824.000000 +14.280000 114.852501 -8.995000 301365408.000000 +4.060000 22.907499 -4.917500 301465376.000000 +-10.727500 -53.777500 -15.137500 301565408.000000 +-23.572500 37.782501 4.340000 301665408.000000 +-50.942501 104.807503 12.897500 301765536.000000 +-32.637501 80.412498 8.190000 301865408.000000 +-12.512500 99.487503 21.770000 301965408.000000 +11.830000 231.822495 41.930000 302065696.000000 +16.344999 330.662506 26.862499 302165632.000000 +-15.645000 335.912506 29.697500 302270496.000000 +-30.222500 205.047501 16.117500 302370880.000000 +5.740000 183.312500 27.195000 302470560.000000 +-10.430000 125.807503 14.140000 302570848.000000 +-8.155000 128.817505 6.562500 302670528.000000 +-5.460000 88.497498 -12.967500 302770720.000000 +28.350000 91.612503 -19.687500 302870528.000000 +4.392500 114.362503 10.535000 302971040.000000 +-15.540000 69.702499 4.007500 303070464.000000 +3.902500 77.682503 -17.972500 303170880.000000 +-13.265000 50.137501 18.760000 303270496.000000 +-11.795000 30.152500 -0.315000 303370784.000000 +-3.587500 25.392500 -7.857500 303470528.000000 +7.472500 35.192501 12.915000 303571168.000000 +6.632500 27.982500 -5.127500 303670528.000000 +-20.912500 33.407501 -2.065000 303771008.000000 +-17.027500 11.532500 -0.507500 303870528.000000 +-7.420000 29.452499 3.797500 303970976.000000 +0.490000 50.802502 5.022500 304070560.000000 +13.912500 98.017502 10.605000 304170784.000000 +-17.605000 108.097504 6.072500 304270560.000000 +3.325000 80.762497 11.375000 304370912.000000 +-4.147500 171.447495 -1.995000 304470528.000000 +-3.447500 142.957504 -23.415001 304570816.000000 +-4.270000 191.747498 31.850000 304670496.000000 +-74.654999 292.232513 27.230000 304770848.000000 +26.180000 105.157501 1.295000 304870400.000000 +29.995001 117.302498 -2.380000 304970400.000000 +23.677500 8.207500 -5.950000 305070496.000000 +14.472500 4.462500 -15.382500 305170400.000000 +-13.195000 105.507500 2.537500 305270944.000000 +-9.065000 87.342499 -11.077500 305370496.000000 +-43.259998 175.367508 22.645000 305470400.000000 +15.015000 158.847504 25.077499 305570400.000000 +9.852500 179.462494 15.592500 305670368.000000 +-18.620001 243.477509 7.350000 305770848.000000 +-8.382500 258.457489 -1.452500 305870496.000000 +-4.427500 204.837494 13.737500 305970720.000000 +-18.462500 156.222504 12.005000 306070496.000000 +-10.500000 117.652504 1.767500 306170816.000000 +-5.530000 139.212494 -1.557500 306270496.000000 +-11.672500 145.582504 -26.057501 306370848.000000 +-1.522500 77.962502 4.585000 306470496.000000 +12.722500 133.227493 6.317500 306571104.000000 +18.917500 116.042503 -0.192500 306670496.000000 +-12.915000 73.552498 16.100000 306770912.000000 +-23.100000 32.392502 4.865000 306870496.000000 +-13.230000 0.472500 -2.835000 306970688.000000 +-16.012501 7.682500 -3.727500 307070496.000000 +-8.557500 0.017500 -2.047500 307171264.000000 +-14.822500 -1.767500 1.365000 307270528.000000 +-21.840000 1.137500 2.642500 307370720.000000 +-18.445000 6.212500 1.872500 307470464.000000 +-15.732500 8.382500 0.560000 307570976.000000 +-14.472500 7.612500 0.175000 307670592.000000 +-13.142500 7.052500 1.907500 307770848.000000 +-8.837500 9.257500 3.605000 307870528.000000 +-8.015000 5.162500 4.585000 307971072.000000 +-5.197500 7.227500 7.752500 308070464.000000 +-10.482500 2.537500 3.517500 308170752.000000 +-4.830000 2.817500 2.747500 308270496.000000 +-4.427500 -0.087500 2.292500 308370976.000000 +-3.010000 -3.342500 1.207500 308470560.000000 +-5.390000 -0.682500 2.432500 308570848.000000 +-3.307500 -0.297500 2.240000 308670496.000000 +-4.795000 -0.052500 2.187500 308770880.000000 +-4.427500 -0.507500 2.257500 308870560.000000 +-3.097500 0.332500 2.922500 308970912.000000 +0.052500 2.327500 8.645000 309070496.000000 +5.530000 1.452500 12.075000 309170880.000000 +2.677500 -32.182499 5.582500 309270496.000000 +4.095000 -104.457497 -2.607500 309370976.000000 +4.252500 -157.657501 -1.050000 309470560.000000 +-15.435000 -157.307495 6.020000 309571072.000000 +-21.682501 -68.022499 31.377501 309670528.000000 +-11.042500 -98.087502 31.010000 309771168.000000 +-22.260000 -101.237503 15.645000 309870496.000000 +-8.032500 -196.472504 8.872500 309970720.000000 +-1.627500 -217.262497 0.840000 310070528.000000 +3.080000 -206.097504 1.645000 310170976.000000 +3.570000 -272.877502 -7.332500 310270496.000000 +-16.065001 -221.497498 -0.070000 310371136.000000 +-10.587500 -181.352493 -5.092500 310470496.000000 +-1.960000 -180.792496 -17.377501 310571136.000000 +-11.847500 -195.772507 -23.485001 310670560.000000 +-3.220000 -183.872498 -11.550000 310770368.000000 +-44.047501 -231.367508 -17.342501 310870496.000000 +-73.587502 -251.632507 -7.805000 310970464.000000 +-13.965000 -135.957504 28.157499 311070496.000000 +57.977501 -188.422501 40.250000 311170816.000000 +-13.230000 -70.752502 56.332500 311270592.000000 +-1.015000 -72.712502 8.890000 311370688.000000 +-28.070000 -13.737500 6.632500 311470688.000000 +27.247499 -113.487503 -13.265000 311570496.000000 +35.770000 -74.602501 -43.259998 311670848.000000 +-12.757500 -70.787498 -11.830000 311770496.000000 +-36.189999 -136.552505 -23.975000 311870688.000000 +-41.825001 -133.857498 -6.387500 311970464.000000 +-22.820000 -101.377502 -30.940001 312070848.000000 +-13.720000 -64.207497 -35.612499 312170496.000000 +1.890000 -14.717500 -3.482500 312270880.000000 +12.425000 -26.967501 -1.662500 312370496.000000 +0.070000 -32.147499 2.292500 312470816.000000 +15.627501 -52.692501 -4.725000 312570592.000000 +-17.150000 -121.222504 14.490000 312670912.000000 +-7.000000 -110.792503 22.487499 312770560.000000 +17.674999 -129.902496 -6.545000 312870720.000000 +-17.622499 -128.327499 -24.062500 312970496.000000 +3.832500 -72.117500 -32.497501 313070880.000000 +7.472500 -72.502502 -9.695000 313170496.000000 +20.247499 -115.482498 5.285000 313270752.000000 +14.962500 -200.392502 28.927500 313370464.000000 +20.632500 -286.842499 19.302500 313470784.000000 +18.707500 -293.912506 13.457500 313570368.000000 +2.852500 -314.352509 -3.990000 313670400.000000 +-0.472500 -235.952499 -5.950000 313770400.000000 +21.770000 -155.802505 -4.462500 313870400.000000 +9.905000 -142.747498 -3.290000 313970400.000000 +3.237500 -160.527496 -0.525000 314070464.000000 +-13.895000 -119.927498 -17.184999 314170400.000000 +-0.070000 -99.837502 -21.559999 314270432.000000 +-6.020000 -165.007507 -31.377501 314370368.000000 +-11.147500 -373.292511 22.277500 314470400.000000 +-11.655000 -189.157501 10.955000 314570368.000000 +-25.549999 -124.337502 -16.415001 314670368.000000 +41.772499 -156.852493 57.994999 314770400.000000 +59.237499 -125.667503 24.377501 314870816.000000 +6.370000 -177.432495 -34.755001 314970560.000000 +-12.250000 -109.322502 -69.702499 315070976.000000 +-76.597504 -73.552498 -62.527500 315170400.000000 +-89.949997 -73.167503 -11.567500 315270464.000000 +18.059999 -78.067497 -9.730000 315370496.000000 +40.320000 -51.467499 0.525000 315470400.000000 +3.325000 -103.022499 7.035000 315570848.000000 +-5.425000 -239.907501 15.225000 315670400.000000 +1.907500 -245.262497 -8.890000 315770944.000000 +-17.202499 -337.172516 -17.902500 315870400.000000 +-12.162500 -362.617493 -24.535000 315970368.000000 +6.895000 -324.712494 -31.500000 316070400.000000 +2.135000 -117.827499 -13.527500 316170400.000000 +6.877500 -98.822502 -10.342500 316270400.000000 +-10.762500 -125.562500 6.755000 316370368.000000 +-10.395000 -129.937500 5.267500 316470400.000000 +-65.537498 -149.152496 8.400000 316570368.000000 +32.637501 -98.612503 41.387501 316670368.000000 +-13.790000 -59.972500 -0.105000 316770464.000000 +2.642500 -77.507500 3.587500 316870464.000000 +11.340000 -79.957497 -15.680000 316971744.000000 +23.835001 -115.027504 -19.337500 317070464.000000 +14.997500 -171.237503 -8.890000 317170560.000000 +29.767500 -170.712494 -20.492500 317270880.000000 +-0.052500 -193.497498 20.212500 317370560.000000 +-12.442500 -141.802505 26.355000 317470560.000000 +-14.245000 -99.697502 22.592501 317570944.000000 +-7.087500 -59.307499 -2.502500 317670496.000000 +-7.577500 -11.777500 -1.855000 317770816.000000 +-16.450001 7.647500 -2.520000 317870464.000000 +-12.880000 -4.462500 0.665000 317970976.000000 +-10.045000 -4.462500 -3.552500 318070496.000000 +-2.642500 -16.012501 1.960000 318170848.000000 +-3.797500 6.912500 3.325000 318270560.000000 +-5.040000 13.457500 -1.452500 318370688.000000 +-1.890000 9.047500 -0.717500 318470528.000000 +-4.025000 0.262500 0.717500 318571200.000000 +-5.302500 -1.312500 2.817500 318670560.000000 +-6.037500 0.787500 1.137500 318770848.000000 +-3.797500 1.662500 3.237500 318870464.000000 +-6.265000 2.747500 1.050000 318970944.000000 +-3.377500 2.082500 2.467500 319070496.000000 +-4.445000 1.137500 2.030000 319170912.000000 +-5.442500 0.507500 1.750000 319270560.000000 +-4.690000 -0.472500 2.537500 319370720.000000 +-4.270000 -0.087500 2.520000 319470496.000000 +-4.935000 0.017500 2.870000 319570880.000000 +-4.550000 0.017500 1.925000 319670528.000000 +-5.337500 1.172500 1.977500 319771008.000000 +-5.512500 0.927500 4.287500 319870560.000000 +-4.235000 3.902500 4.585000 319970528.000000 +-2.257500 6.002500 3.150000 320071104.000000 +-5.092500 8.732500 4.077500 320170496.000000 +-6.125000 8.382500 4.812500 320271040.000000 +8.785000 0.787500 7.945000 320370624.000000 +-28.105000 -18.357500 9.380000 320470400.000000 +-14.385000 -8.732500 12.687500 320570368.000000 +-30.817501 16.572500 -5.880000 320670368.000000 +-14.175000 -5.057500 -8.155000 320770400.000000 +-7.280000 17.517500 -10.710000 320870400.000000 +-17.552500 2.047500 -7.472500 320970400.000000 +-22.469999 10.867500 -15.330000 321070496.000000 +-7.420000 0.647500 4.550000 321170752.000000 +3.692500 1.312500 13.597500 321270464.000000 +0.122500 -2.152500 1.890000 321370880.000000 +0.490000 13.142500 4.340000 321470624.000000 +2.520000 -8.732500 5.145000 321571136.000000 +3.552500 -6.177500 4.147500 321670464.000000 +-3.902500 11.217500 6.002500 321770880.000000 +-4.952500 12.127500 5.197500 321870560.000000 +-4.900000 8.102500 9.345000 321970688.000000 +-4.742500 6.737500 2.642500 322070496.000000 +-4.865000 -1.557500 2.257500 322170944.000000 +-4.812500 0.297500 2.275000 322270816.000000 +-4.830000 -0.507500 2.292500 322370816.000000 +-4.847500 0.507500 2.240000 322470496.000000 +-4.865000 0.017500 2.275000 322570752.000000 +-4.882500 0.192500 2.292500 322670496.000000 +-4.847500 0.157500 2.257500 322770944.000000 +-4.847500 0.157500 2.275000 322870528.000000 +-4.847500 0.157500 2.257500 322970976.000000 +-4.830000 0.157500 2.275000 323070624.000000 +-4.865000 0.192500 2.257500 323170944.000000 +-4.812500 0.192500 2.257500 323270496.000000 +-4.830000 0.192500 2.240000 323370784.000000 +-4.865000 0.192500 2.275000 323470528.000000 +-4.847500 0.157500 2.310000 323571008.000000 +-4.865000 0.122500 2.257500 323670528.000000 +-4.865000 0.157500 2.257500 323771040.000000 +-4.865000 0.157500 2.275000 323870528.000000 +-4.830000 0.157500 2.292500 323970752.000000 +-4.847500 1.242500 2.117500 324070496.000000 +-4.865000 -0.752500 0.770000 324170912.000000 +-4.550000 -0.507500 -14.945000 324270848.000000 +-4.287500 -4.182500 -49.525002 324370784.000000 +-3.482500 -2.432500 -107.029999 324470496.000000 +-3.202500 0.052500 -157.167496 324571136.000000 +-3.815000 -8.312500 -189.717499 324670560.000000 +-6.510000 -12.512500 -175.664993 324770752.000000 +-8.015000 -1.417500 -149.029999 324870464.000000 +-6.230000 3.972500 -190.259995 324970880.000000 +-5.530000 -3.727500 -113.084999 325070496.000000 +-5.792500 6.142500 -110.425003 325170880.000000 +-4.130000 9.607500 -91.507500 325270464.000000 +8.680000 17.692499 -79.922501 325370880.000000 +6.597500 -17.762501 -111.754997 325470496.000000 +-2.257500 -8.417500 -60.847500 325570912.000000 +3.027500 16.537500 -151.794998 325670496.000000 +-13.702500 -2.677500 -152.652496 325770880.000000 +-42.367500 -7.997500 -162.977493 325870464.000000 +-5.180000 2.607500 -257.005005 325970880.000000 +-3.797500 2.992500 -143.955002 326070592.000000 +-4.427500 0.297500 -44.029999 326170912.000000 +-4.830000 0.192500 2.327500 326270528.000000 +-4.847500 0.192500 2.292500 326370720.000000 +-4.847500 0.227500 2.257500 326470496.000000 +-4.900000 0.507500 3.447500 326570944.000000 +-4.672500 0.822500 -31.395000 326670464.000000 +-4.060000 2.747500 -104.580002 326770880.000000 +-2.887500 2.187500 -147.647507 326870528.000000 +-1.715000 3.482500 -226.012497 326970944.000000 +-1.645000 0.647500 -220.955002 327070528.000000 +-2.712500 1.067500 -199.692505 327170976.000000 +-4.252500 -10.762500 -154.524994 327270496.000000 +-7.315000 -14.612500 -120.137497 327370944.000000 +-13.545000 -3.657500 -115.482498 327470528.000000 +1.872500 -1.732500 -183.014999 327573408.000000 +-5.897500 5.197500 -46.707500 327670400.000000 +-4.917500 0.542500 -1.032500 327770624.000000 +-4.847500 0.262500 2.380000 327870560.000000 +-4.847500 0.192500 2.257500 327970528.000000 +-4.847500 0.192500 2.257500 328070496.000000 +-4.847500 0.192500 2.257500 328170688.000000 +-4.882500 0.192500 2.257500 328270560.000000 +-4.830000 0.192500 2.240000 328370752.000000 +-4.865000 0.192500 2.275000 328470528.000000 +-5.425000 0.017500 -11.007500 328570944.000000 +-6.107500 0.122500 -25.777500 328670688.000000 +-7.945000 0.087500 -70.437500 328770944.000000 +-7.595000 6.772500 -121.292503 328870400.000000 +-8.977500 -0.052500 -135.520004 328970368.000000 +-9.345000 -2.362500 -138.477493 329070432.000000 +-10.202500 -2.467500 -162.942505 329170368.000000 +-11.497500 -2.012500 -201.687500 329270496.000000 +-11.672500 -2.117500 -213.500000 329370720.000000 +-10.430000 7.087500 -197.242508 329474112.000000 +-3.430000 20.002501 -176.994995 329570528.000000 +-3.780000 0.297500 -66.622498 329670720.000000 +-3.605000 -0.962500 -73.465004 329770496.000000 +-4.497500 -1.032500 -19.162500 329870784.000000 +-4.707500 -7.927500 -6.282500 329970528.000000 +-3.920000 7.577500 -82.792503 330071200.000000 +6.230000 13.772500 -153.772507 330170560.000000 +-1.102500 -20.037500 -107.309998 330271136.000000 +-9.100000 -33.687500 -76.510002 330370560.000000 +-2.835000 2.117500 -0.857500 330470976.000000 +-8.400000 -5.197500 31.202499 330570624.000000 +-2.835000 0.717500 63.192501 330670976.000000 +-1.942500 1.172500 73.114998 330770496.000000 +-4.042500 0.367500 23.379999 330870976.000000 +-4.900000 0.192500 2.292500 330970656.000000 +-4.900000 0.192500 2.257500 331071040.000000 +-4.007500 2.012500 10.412500 331170528.000000 +-6.877500 -2.607500 -23.799999 331270784.000000 +-9.152500 -2.817500 -76.632500 331370464.000000 +-12.565000 -9.187500 -116.952499 331470880.000000 +1.872500 -4.532500 -82.582497 331570496.000000 +-22.785000 18.637501 -163.607498 331670880.000000 +-18.305000 22.417500 -52.552502 331770464.000000 +-15.260000 17.167500 -90.912498 331870912.000000 +0.630000 4.777500 -135.327499 331970720.000000 +2.362500 -3.692500 -177.712494 332071008.000000 +-0.210000 -3.237500 -165.077499 332170464.000000 +-1.697500 3.027500 -149.712494 332270816.000000 +-2.257500 0.297500 -118.982498 332370560.000000 +-3.570000 2.467500 -70.035004 332471008.000000 +-2.485000 -0.437500 -111.264999 332570528.000000 +-1.540000 1.452500 -203.875000 332670976.000000 +-3.062500 0.087500 -133.927505 332770496.000000 +-4.742500 -2.607500 -91.805000 332871072.000000 +-5.022500 -3.342500 -63.857502 332970848.000000 +-3.132500 7.892500 -104.790001 333071136.000000 +-3.325000 -1.907500 -126.052498 333170368.000000 +-3.570000 -21.367500 -10.342500 333270368.000000 +-6.072500 9.502500 -0.735000 333370944.000000 +-5.215000 5.827500 2.415000 333470528.000000 +-4.935000 1.312500 2.310000 333570848.000000 +-4.900000 0.472500 2.310000 333670464.000000 +-4.865000 0.227500 2.310000 333771008.000000 +-5.005000 -5.267500 -18.025000 333870464.000000 +-5.477500 -0.402500 -54.670002 333970880.000000 +-6.387500 11.392500 -130.410004 334070528.000000 +-4.340000 -2.677500 -153.282501 334170816.000000 +-4.900000 -7.157500 -172.934998 334270528.000000 +-7.385000 1.662500 -158.007507 334371136.000000 +-6.282500 -2.257500 -114.537498 334470560.000000 +-8.872500 6.947500 -100.625000 334570784.000000 +-6.230000 -1.347500 -110.705002 334670496.000000 +-6.930000 3.167500 -120.067497 334770816.000000 +-6.720000 5.407500 -103.635002 334870464.000000 +2.485000 11.532500 -99.959999 334970848.000000 +28.332500 -19.652500 -66.044998 335070592.000000 +-5.512500 -26.022501 -83.195000 335171104.000000 +-57.994999 24.622499 -69.317497 335270560.000000 +-4.760000 3.027500 -73.044998 335371008.000000 +-8.417500 11.917500 -109.497498 335470560.000000 +-3.430000 -1.802500 -135.467499 335571008.000000 +-0.122500 -16.257500 -91.927498 335670496.000000 +-9.537500 12.932500 11.445000 335770976.000000 +-4.900000 0.227500 2.415000 335870560.000000 +-4.322500 -1.207500 1.452500 335971264.000000 +-4.812500 -0.087500 2.152500 336070560.000000 +-4.287500 -1.522500 1.277500 336171008.000000 +-4.375000 -2.187500 -39.830002 336270496.000000 +-8.312500 6.562500 -87.535004 336370784.000000 +-7.350000 -3.727500 -176.820007 336470464.000000 +-10.395000 8.487500 -199.815002 336570976.000000 +-10.850000 10.447500 -175.350006 336670496.000000 +-10.430000 20.002501 -157.377502 336770880.000000 +-11.112500 26.547501 -171.762497 336870496.000000 +5.985000 21.332500 -145.145004 336971040.000000 +4.602500 11.392500 -162.645004 337070496.000000 +14.262500 9.642500 -99.925003 337170944.000000 +2.362500 -31.727501 -122.815002 337270528.000000 +2.800000 -21.122499 -110.652504 337370976.000000 +4.410000 -10.097500 -88.182503 337470528.000000 +5.530000 15.767500 -101.902504 337570880.000000 +-5.355000 9.782500 -73.989998 337670464.000000 +-4.445000 -1.277500 -35.297501 337770944.000000 +-4.585000 -3.062500 -1.645000 337870496.000000 +-4.812500 -1.452500 0.840000 337970944.000000 +-4.847500 -6.177500 -9.555000 338070624.000000 +-4.952500 3.307500 2.187500 338170880.000000 +-4.742500 -7.297500 2.590000 338270496.000000 +-4.777500 5.757500 7.735000 338370912.000000 +-4.742500 -0.752500 8.260000 338470464.000000 +-4.445000 -1.417500 35.314999 338570752.000000 +-5.057500 -9.537500 2.450000 338670528.000000 +-5.075000 8.907500 2.100000 338771168.000000 +-4.970000 4.777500 2.222500 338870528.000000 +-4.987500 4.217500 2.187500 338971040.000000 +-5.215000 8.452500 2.135000 339070560.000000 +-4.760000 7.052500 2.152500 339171136.000000 +-4.847500 -7.927500 2.415000 339270560.000000 +-4.900000 2.677500 2.222500 339371168.000000 +-4.882500 1.872500 2.205000 339470496.000000 +-4.795000 -2.047500 2.345000 339571328.000000 +-4.882500 0.017500 2.292500 339670496.000000 +-4.865000 0.542500 2.275000 339770784.000000 +-4.847500 -0.297500 2.292500 339870528.000000 +-4.847500 0.402500 2.292500 339970784.000000 +-4.830000 0.122500 2.257500 340070496.000000 +-4.865000 0.192500 2.275000 340171072.000000 +-4.865000 3.447500 2.205000 340270528.000000 +-4.830000 1.277500 2.257500 340370912.000000 +-4.847500 -0.122500 2.467500 340470528.000000 +-4.795000 1.067500 2.310000 340570976.000000 +-4.830000 -2.222500 3.412500 340670528.000000 +-4.900000 -0.017500 2.485000 340771008.000000 +-4.847500 -0.367500 2.240000 340870496.000000 +-4.865000 -0.087500 2.730000 340970720.000000 +-4.865000 1.207500 2.240000 341070624.000000 +-4.900000 -1.767500 2.275000 341170752.000000 +-4.830000 -1.102500 2.275000 341270528.000000 +-4.812500 -1.977500 2.747500 341370752.000000 +-5.005000 -1.452500 24.570000 341470496.000000 +-3.517500 -17.692499 83.125000 341570880.000000 +-1.452500 2.852500 160.002502 341670496.000000 +-0.647500 8.907500 207.235001 341771008.000000 +-4.235000 21.157499 226.607498 341870496.000000 +-10.360000 23.292500 198.800003 341970816.000000 +-15.645000 -15.837500 211.627502 342070528.000000 +-5.477500 -6.562500 83.632500 342170848.000000 +-4.847500 -0.367500 5.757500 342270464.000000 +-4.917500 9.047500 2.135000 342370784.000000 +-4.900000 -6.142500 2.362500 342470496.000000 +-4.882500 5.582500 2.187500 342571168.000000 +-4.812500 -5.827500 2.397500 342670368.000000 +-5.390000 15.382500 54.320000 342770432.000000 +-16.625000 34.002499 172.024994 342870432.000000 +-17.184999 -6.702500 177.992508 342970528.000000 +-11.462500 -24.902500 172.794998 343070560.000000 +-5.775000 -13.037500 120.050003 343170528.000000 +-5.127500 7.052500 164.482498 343270784.000000 +-7.192500 11.497500 169.294998 343370496.000000 +-13.265000 47.827499 240.345001 343470752.000000 +-28.577499 0.962500 226.537506 343570528.000000 +-17.097500 12.267500 90.282501 343670912.000000 +-27.195000 42.717499 130.095001 343770752.000000 +-37.485001 28.822500 169.242508 343870816.000000 +-10.342500 -85.172501 106.242500 343970496.000000 +-11.042500 -25.392500 98.227501 344071328.000000 +-5.372500 -1.032500 18.025000 344170496.000000 +-4.847500 0.157500 2.310000 344270912.000000 +-4.865000 0.192500 2.275000 344370496.000000 +-4.900000 0.227500 2.240000 344470848.000000 +-5.705000 3.762500 10.657500 344570368.000000 +-8.050000 -9.187500 140.402496 344670432.000000 +-9.502500 1.067500 179.865005 344772064.000000 +-11.672500 6.562500 153.912506 344871360.000000 +-11.060000 -1.277500 92.540001 344970496.000000 +-9.240000 4.007500 105.805000 345070784.000000 +-15.225000 -7.787500 182.839996 345170496.000000 +-10.220000 7.542500 215.862503 345270816.000000 +-12.932500 -9.222500 198.782501 345370528.000000 +-8.540000 11.847500 177.782501 345470816.000000 +-11.777500 5.337500 123.514999 345570560.000000 +-10.622500 -22.137501 116.077499 345670880.000000 +-8.067500 -1.452500 151.095001 345770464.000000 +-7.157500 23.082500 85.872498 345871008.000000 +-8.452500 -6.877500 83.790001 345970496.000000 +-5.652500 -1.452500 21.507500 346070816.000000 +-4.882500 1.347500 2.240000 346170496.000000 +-4.865000 0.332500 2.275000 346271008.000000 +-4.900000 0.262500 2.292500 346370464.000000 +-4.882500 0.192500 2.257500 346470848.000000 +-4.970000 -11.462500 2.345000 346570464.000000 +-6.947500 -8.347500 79.502502 346670400.000000 +-5.337500 0.332500 47.897499 346770560.000000 +-6.510000 -0.787500 83.492500 346870560.000000 +-5.075000 7.927500 189.647507 346970688.000000 +-12.092500 20.912500 198.222504 347070592.000000 +-14.245000 7.752500 220.167496 347170784.000000 +-19.355000 -9.677500 171.115005 347270496.000000 +-13.825000 -5.652500 168.384995 347371072.000000 +-16.082500 -6.632500 229.127502 347470528.000000 +-7.175000 21.507500 75.775002 347571040.000000 +-11.042500 6.702500 98.840004 347670496.000000 +-11.200000 -0.542500 93.257500 347771072.000000 +-9.660000 4.182500 171.762497 347870528.000000 +-20.422501 -27.702499 180.022507 347970976.000000 +-7.997500 13.387500 126.455002 348070528.000000 +-3.675000 -29.872499 5.845000 348170976.000000 +-5.355000 24.132500 -26.792500 348270528.000000 +-4.882500 -0.017500 2.275000 348371040.000000 +-4.865000 0.157500 2.257500 348470496.000000 +-4.900000 -2.292500 2.362500 348571264.000000 +-5.267500 -5.687500 7.997500 348670368.000000 +-5.320000 9.292500 23.625000 348770848.000000 +-5.285000 12.442500 21.647501 348870400.000000 +-6.895000 6.772500 39.654999 348970368.000000 +-7.087500 1.627500 40.477501 349070528.000000 +-7.892500 5.092500 45.727501 349170720.000000 +-7.070000 2.432500 78.032501 349270464.000000 +-3.482500 -23.922501 94.745003 349370720.000000 +-7.927500 17.727501 185.482498 349470560.000000 +-16.327499 -6.177500 40.950001 349570720.000000 +-37.432499 -30.572500 51.572498 349670784.000000 +-0.157500 7.787500 60.252499 349770720.000000 +-5.547500 -7.997500 55.982502 349870528.000000 +-3.342500 1.172500 37.485001 349970976.000000 +-6.772500 -17.552500 61.110001 350070656.000000 +-3.045000 -0.682500 39.462502 350170816.000000 +-3.867500 1.137500 13.597500 350270464.000000 +-4.200000 0.472500 9.275000 350370816.000000 +-5.897500 -8.067500 8.977500 350470496.000000 +-4.130000 -3.272500 22.960001 350570944.000000 +-2.555000 7.087500 24.062500 350670528.000000 +-1.995000 10.027500 11.917500 350771008.000000 +-2.432500 16.502501 -11.480000 350870528.000000 +-5.372500 10.377500 45.744999 350970816.000000 +-6.930000 -2.187500 88.217499 351070496.000000 +-5.005000 0.542500 8.505000 351171104.000000 +-8.085000 -1.312500 156.327499 351270528.000000 +-7.945000 -2.677500 135.869995 351370816.000000 +-9.660000 1.557500 209.072495 351470496.000000 +-8.400000 -6.982500 122.815002 351571328.000000 +-5.670000 1.067500 38.132500 351670528.000000 +-4.935000 0.192500 1.872500 351770880.000000 +-4.935000 0.157500 2.292500 351870496.000000 +-4.917500 0.192500 2.257500 351970752.000000 +-4.900000 0.192500 2.275000 352070464.000000 +-4.760000 3.657500 2.222500 352170816.000000 +-6.335000 -3.272500 52.430000 352270496.000000 +-7.192500 2.432500 98.507500 352370848.000000 +-7.472500 -3.307500 86.379997 352470464.000000 +-7.280000 -0.857500 91.997498 352570752.000000 +-7.857500 -3.132500 127.855003 352670496.000000 +-8.207500 -0.857500 138.669998 352770848.000000 +-5.950000 -0.262500 46.112499 352870496.000000 +-4.882500 0.437500 2.310000 352970848.000000 +-4.865000 0.087500 2.310000 353070624.000000 +-4.865000 -3.447500 6.335000 353170432.000000 +-7.682500 30.187500 80.272499 353270400.000000 +-17.482500 18.147501 176.294998 353370720.000000 +-10.062500 -27.457500 93.677498 353470560.000000 +-10.097500 42.857502 125.195000 353570496.000000 +-11.322500 -12.932500 123.270004 353671104.000000 +-8.802500 33.127499 129.990005 353770528.000000 +-26.635000 10.412500 160.072495 353870688.000000 +-27.947500 -2.082500 136.184998 353970528.000000 +-30.450001 -48.807499 164.552505 354070688.000000 +-13.020000 -46.777500 273.717499 354170528.000000 +-6.667500 -10.342500 146.089996 354270880.000000 +-4.760000 3.762500 5.127500 354370496.000000 +-4.882500 7.857500 2.065000 354471232.000000 +-4.917500 2.467500 2.187500 354570592.000000 +-5.267500 12.862500 3.850000 354670432.000000 +-5.582500 -8.312500 33.775002 354770368.000000 +-4.830000 0.962500 8.295000 354870464.000000 +-4.917500 2.047500 2.222500 354970752.000000 +-4.812500 -2.572500 2.310000 355070496.000000 +-5.092500 18.217501 9.467500 355170880.000000 +-5.180000 12.162500 20.545000 355270560.000000 +-10.482500 21.927500 63.927502 355370976.000000 +-9.240000 -4.777500 78.207497 355470400.000000 +-7.752500 -74.672501 117.547501 355570432.000000 +-1.225000 10.517500 45.342499 355670880.000000 +-3.430000 -0.192500 53.025002 355770496.000000 +2.852500 -1.662500 79.590004 355870944.000000 +0.000000 19.757500 18.672501 355970496.000000 +-61.424999 29.662500 -0.507500 356071360.000000 +-106.627502 -9.292500 13.300000 356170496.000000 +-79.169998 5.337500 28.087500 356270944.000000 +-34.790001 -7.437500 5.757500 356370528.000000 +-109.952499 -7.297500 20.177500 356470976.000000 +-95.742500 -32.567501 4.620000 356570592.000000 +-10.062500 -27.877501 2.485000 356670784.000000 +28.017500 16.607500 11.672500 356770496.000000 +66.114998 25.462500 10.640000 356871008.000000 +11.112500 31.202499 60.042500 356970368.000000 +40.232502 41.842499 90.614998 357070784.000000 +-35.612499 -1.137500 66.535004 357170368.000000 +14.192500 13.177500 -42.682499 357270848.000000 +-8.295000 7.297500 -16.170000 357370496.000000 +174.824997 -91.402504 -10.272500 357472992.000000 +42.209999 -0.367500 32.007500 357570496.000000 +27.755001 1.627500 61.145000 357670816.000000 +-15.662500 7.577500 59.727501 357770432.000000 +-10.167500 -8.452500 63.472500 357870496.000000 +3.657500 6.737500 67.847504 357970368.000000 +1.487500 -17.902500 56.665001 358070400.000000 +-44.974998 -25.357500 43.154999 358170368.000000 +-2.887500 -28.227501 13.860000 358295104.000000 +11.865000 -11.602500 1.680000 358395392.000000 +-1.137500 11.497500 24.867500 358495392.000000 +-5.512500 37.082500 3.867500 358595424.000000 +-5.180000 4.637500 2.047500 358695424.000000 +-4.900000 0.297500 2.275000 358795360.000000 +-4.917500 0.122500 2.240000 358913824.000000 +-4.935000 0.227500 2.257500 359010336.000000 +-4.917500 0.157500 2.240000 359110432.000000 +-4.952500 0.192500 2.240000 359216800.000000 +-4.917500 0.157500 2.222500 359315968.000000 +-4.935000 0.157500 2.222500 359416832.000000 +-4.952500 0.192500 2.240000 359535360.000000 +-4.935000 0.227500 2.257500 359635392.000000 +-4.917500 0.157500 2.222500 359735392.000000 +-4.935000 0.157500 2.222500 359836320.000000 +-4.935000 0.157500 2.222500 359946496.000000 +-4.970000 0.157500 2.205000 360046368.000000 +-5.005000 0.157500 2.222500 360145920.000000 +-4.987500 0.192500 2.222500 360245920.000000 +-4.987500 0.192500 2.205000 360346400.000000 +-4.987500 0.227500 2.222500 360446400.000000 +-4.970000 0.192500 2.222500 360546304.000000 +-4.987500 0.192500 2.205000 360646496.000000 +-4.987500 0.157500 2.222500 360746080.000000 +-4.970000 0.192500 2.240000 360846624.000000 +-4.970000 0.192500 2.292500 360946048.000000 +-4.970000 0.192500 2.275000 361047520.000000 +-4.987500 0.192500 2.205000 361146528.000000 +-4.987500 0.192500 2.257500 361246272.000000 +-4.795000 -0.612500 2.310000 361346112.000000 +-5.040000 0.892500 2.257500 361446080.000000 +-4.970000 0.192500 2.275000 361546464.000000 +-4.987500 0.192500 2.275000 361645952.000000 +-4.987500 0.192500 2.275000 361746016.000000 +-4.970000 0.227500 2.292500 361846464.000000 +-4.970000 0.192500 2.275000 361946016.000000 +-4.952500 0.192500 2.240000 362046688.000000 +-4.952500 0.192500 2.275000 362146144.000000 +-5.005000 0.192500 2.257500 362246368.000000 +-4.970000 0.227500 2.257500 362346400.000000 +-4.970000 0.157500 2.257500 362445824.000000 +-4.970000 0.227500 2.275000 362546176.000000 +-4.987500 0.227500 2.292500 362646464.000000 +-4.987500 0.192500 2.257500 362746272.000000 +-5.005000 0.192500 2.275000 362845824.000000 +-4.987500 0.192500 2.292500 362946208.000000 +-4.970000 0.227500 2.275000 363046528.000000 +-4.935000 0.192500 2.257500 363146336.000000 +-4.952500 0.227500 2.275000 363245856.000000 +-4.952500 0.192500 2.275000 363346176.000000 +-5.005000 0.192500 2.240000 363445856.000000 +-4.952500 0.227500 2.275000 363546432.000000 +-4.952500 0.227500 2.275000 363646400.000000 +-4.987500 0.192500 2.275000 363746144.000000 +-4.952500 0.192500 2.257500 363845856.000000 +-4.952500 0.192500 2.275000 363946240.000000 +-4.952500 0.192500 2.257500 364045824.000000 +-4.952500 0.227500 2.257500 364146112.000000 +-4.935000 0.192500 2.292500 364245888.000000 +-4.952500 0.192500 2.257500 364346272.000000 +-4.935000 0.192500 2.292500 364445824.000000 +-4.917500 0.192500 2.275000 364546176.000000 +-4.935000 0.192500 2.310000 364646208.000000 +-4.935000 0.192500 2.240000 364745984.000000 +-4.970000 0.192500 2.275000 364846176.000000 +-4.987500 0.192500 2.292500 364945920.000000 +-4.970000 0.192500 2.257500 365046272.000000 +-4.935000 0.192500 2.257500 365146016.000000 +-4.952500 0.157500 2.257500 365246336.000000 +-4.917500 0.192500 2.257500 365345792.000000 +-4.935000 0.192500 2.292500 365445728.000000 +-4.952500 0.192500 2.275000 365546048.000000 +-4.952500 0.192500 2.292500 365646016.000000 +-4.935000 0.227500 2.275000 365746080.000000 +-4.935000 0.157500 2.310000 365846080.000000 +-4.952500 0.192500 2.275000 365945376.000000 +-4.952500 0.192500 2.240000 366050336.000000 +-4.917500 0.192500 2.257500 366150336.000000 +-4.935000 0.157500 2.222500 366255680.000000 +-4.970000 0.157500 2.222500 366355360.000000 +-4.970000 0.157500 2.240000 366455424.000000 +-4.987500 0.227500 2.240000 366555392.000000 +-4.970000 0.192500 2.240000 366655488.000000 +-4.970000 0.192500 2.257500 366755360.000000 +-4.987500 0.192500 2.222500 366855392.000000 +-4.970000 0.192500 2.222500 366955424.000000 +-4.970000 0.192500 2.222500 367055456.000000 +-4.970000 0.157500 2.187500 367155424.000000 +-4.987500 0.192500 2.222500 367260352.000000 +-4.952500 0.192500 2.240000 367360352.000000 +-4.987500 0.192500 2.205000 367460352.000000 +-4.987500 0.192500 2.222500 367560352.000000 +-4.987500 0.192500 2.187500 367660448.000000 +-5.005000 0.192500 2.240000 367760352.000000 +-5.022500 0.192500 2.187500 367860416.000000 +-5.040000 0.192500 2.257500 367960352.000000 +-5.022500 0.157500 2.205000 368060352.000000 +-5.005000 0.192500 2.222500 368160480.000000 +-5.005000 0.192500 2.205000 368260416.000000 +-5.040000 0.192500 2.205000 368360352.000000 +-5.022500 0.192500 2.240000 368460352.000000 +-5.005000 0.157500 2.222500 368560416.000000 +-5.022500 0.192500 2.205000 368660352.000000 +-5.005000 0.227500 2.170000 368760352.000000 +-5.022500 0.192500 2.187500 368860320.000000 +-5.005000 0.192500 2.187500 368960352.000000 +-5.022500 0.192500 2.187500 369060416.000000 +-5.057500 0.192500 2.240000 369160416.000000 +-5.040000 0.227500 2.205000 369260416.000000 +-5.057500 0.192500 2.222500 369360352.000000 +-5.040000 0.192500 2.170000 369460416.000000 +-5.075000 0.227500 2.187500 369560416.000000 +-5.057500 0.192500 2.205000 369660512.000000 +-5.040000 0.192500 2.205000 369760352.000000 +-5.075000 0.227500 2.205000 369860416.000000 +-5.057500 0.227500 2.170000 369960384.000000 +-5.075000 0.262500 2.205000 370060352.000000 +-5.057500 0.262500 2.205000 370160384.000000 +-5.092500 0.192500 2.187500 370260384.000000 +-5.092500 0.192500 2.222500 370360352.000000 +-5.075000 0.227500 2.187500 370460384.000000 +-5.092500 0.262500 2.222500 370560352.000000 +-5.075000 0.227500 2.187500 370660416.000000 +-5.057500 0.192500 2.187500 370760352.000000 +-5.092500 0.227500 2.222500 370860416.000000 +-5.092500 0.262500 2.187500 370960384.000000 +-5.110000 0.227500 2.222500 371060384.000000 +-5.040000 0.192500 2.170000 371160480.000000 +-5.092500 0.227500 2.222500 371260384.000000 +-5.075000 0.192500 2.187500 371360384.000000 +-5.092500 0.227500 2.187500 371460384.000000 +-5.075000 0.227500 2.205000 371560352.000000 +-5.075000 0.192500 2.222500 371660320.000000 +-5.092500 0.192500 2.152500 371770400.000000 +-5.110000 0.227500 2.187500 371870336.000000 +-5.092500 0.227500 2.187500 371970432.000000 +-5.110000 0.227500 2.205000 372070432.000000 +-5.110000 0.227500 2.152500 372170432.000000 +-5.092500 0.192500 2.187500 372270432.000000 +-5.127500 0.227500 2.205000 372370432.000000 +-5.092500 0.227500 2.152500 372475392.000000 +-5.127500 0.227500 2.222500 372575392.000000 diff --git a/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/magnetic.txt b/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/magnetic.txt new file mode 100755 index 0000000..5121597 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/magnetic.txt @@ -0,0 +1,1096 @@ +1.687500 -52.562500 -16.625000 263063216.000000 +2.000000 -52.750000 -15.812500 263163216.000000 +3.000000 -53.000000 -16.375000 263263216.000000 +3.000000 -52.625000 -16.125000 263363216.000000 +3.562500 -52.500000 -16.125000 263463216.000000 +4.000000 -52.250000 -16.375000 263563216.000000 +3.625000 -52.062500 -16.312500 263663216.000000 +3.000000 -52.312500 -16.500000 263763216.000000 +3.250000 -52.250000 -16.437500 263863216.000000 +3.437500 -52.187500 -16.812500 263963216.000000 +3.375000 -52.000000 -16.562500 264063216.000000 +3.437500 -52.000000 -16.812500 264163216.000000 +3.312500 -51.937500 -16.687500 264263216.000000 +3.125000 -52.062500 -16.625000 264363216.000000 +3.375000 -52.125000 -16.437500 264463216.000000 +3.500000 -52.187500 -16.312500 264563216.000000 +3.375000 -52.312500 -16.312500 264663216.000000 +3.437500 -52.437500 -16.250000 264763216.000000 +3.437500 -52.437500 -16.500000 264863216.000000 +3.375000 -52.500000 -16.687500 264963216.000000 +3.687500 -52.187500 -17.562500 265063216.000000 +3.687500 -51.750000 -18.937500 265163216.000000 +3.562500 -51.062500 -20.687500 265263216.000000 +3.750000 -50.437500 -22.875000 265363216.000000 +3.812500 -49.000000 -25.187500 265463216.000000 +3.562500 -47.437500 -27.562500 265563216.000000 +3.562500 -46.062500 -29.812500 265663216.000000 +3.437500 -45.000000 -31.312500 265763216.000000 +3.250000 -43.937500 -32.125000 265863216.000000 +3.625000 -43.062500 -32.375000 265963216.000000 +3.937500 -42.187500 -32.437500 266063216.000000 +3.875000 -40.812500 -32.437500 266163216.000000 +3.812500 -38.437500 -33.250000 266263216.000000 +3.750000 -34.437500 -34.312500 266363216.000000 +4.375000 -28.750000 -35.437500 266463216.000000 +5.562500 -21.625000 -36.562500 266563216.000000 +6.625000 -13.625000 -37.437500 266663216.000000 +7.812500 -4.625000 -37.625000 266763216.000000 +9.625000 4.562500 -36.500000 266863216.000000 +11.812500 13.750000 -33.562500 266963216.000000 +14.062500 21.312500 -28.312500 267063216.000000 +16.562500 26.875000 -21.500000 267163216.000000 +18.125000 30.812500 -14.375000 267263216.000000 +19.562500 33.000000 -7.125000 267363216.000000 +20.687500 33.437500 1.000000 267463216.000000 +21.062500 31.937500 8.937500 267563216.000000 +20.750000 28.812500 16.000000 267663216.000000 +19.937500 24.312500 22.062500 267763216.000000 +19.437500 18.187500 26.375000 267863216.000000 +18.687500 11.000000 28.562500 267963216.000000 +17.875000 3.187500 29.875000 268063216.000000 +16.250000 -4.062500 29.875000 268163216.000000 +15.375000 -11.062500 27.937500 268263216.000000 +14.875000 -17.562500 24.750000 268363216.000000 +14.625000 -22.812500 20.812500 268463200.000000 +14.812500 -27.312500 15.812500 268563200.000000 +15.062500 -30.562500 11.062500 268663200.000000 +15.125000 -32.375000 6.875000 268763200.000000 +15.125000 -33.500000 2.875000 268863200.000000 +14.937500 -34.437500 -0.375000 268963200.000000 +14.562500 -34.812500 -3.000000 269063200.000000 +14.312500 -34.312500 -5.937500 269163200.000000 +14.625000 -33.250000 -9.562500 269263200.000000 +14.812500 -30.875000 -12.875000 269363200.000000 +15.000000 -26.812500 -16.375000 269463200.000000 +16.187500 -21.812500 -19.562500 269563200.000000 +18.562500 -15.375000 -21.750000 269663200.000000 +22.062500 -8.312500 -21.937500 269763200.000000 +25.687500 -1.312500 -20.812500 269863200.000000 +29.375000 4.937500 -18.312500 269963200.000000 +32.187500 10.375000 -13.750000 270063200.000000 +34.187500 14.625000 -7.562500 270163200.000000 +35.562500 16.000000 -0.125000 270263200.000000 +35.937500 15.062500 7.437500 270363200.000000 +35.500000 11.250000 13.750000 270463200.000000 +34.187500 6.000000 17.875000 270563200.000000 +32.625000 0.562500 20.187500 270663200.000000 +30.562500 -4.937500 22.062500 270763200.000000 +28.687500 -10.750000 22.500000 270863200.000000 +27.312500 -16.625000 21.437500 270963200.000000 +26.437500 -21.187500 19.250000 271063200.000000 +25.812500 -24.562500 16.875000 271163200.000000 +25.062500 -26.562500 14.937500 271263200.000000 +24.437500 -28.125000 12.750000 271363200.000000 +24.062500 -29.500000 10.562500 271463200.000000 +23.750000 -30.687500 8.500000 271563200.000000 +23.562500 -31.187500 6.625000 271663200.000000 +23.375000 -31.750000 4.812500 271763200.000000 +22.875000 -32.250000 2.812500 271863200.000000 +21.937500 -32.687500 0.187500 271963200.000000 +21.500000 -32.875000 -3.062500 272063200.000000 +21.125000 -32.250000 -6.812500 272163200.000000 +20.375000 -31.000000 -10.937500 272263200.000000 +20.187500 -28.187500 -16.000000 272363200.000000 +20.375000 -24.000000 -20.687500 272463200.000000 +21.187500 -18.375000 -24.500000 272563200.000000 +22.687500 -11.312500 -27.125000 272663200.000000 +25.062500 -3.625000 -26.937500 272763200.000000 +27.062500 4.125000 -24.875000 272863200.000000 +28.750000 11.125000 -20.750000 272963200.000000 +30.687500 17.687500 -15.500000 273063200.000000 +31.625000 22.375000 -8.750000 273163200.000000 +32.312500 25.687500 -1.687500 273263200.000000 +31.937500 27.250000 5.687500 273363200.000000 +31.062500 26.250000 12.812500 273463200.000000 +29.750000 23.562500 18.312500 273563200.000000 +28.687500 19.000000 22.125000 273663200.000000 +27.750000 13.375000 24.437500 273763200.000000 +26.687500 6.500000 25.437500 273863200.000000 +26.125000 -0.875000 24.625000 273963200.000000 +25.125000 -8.875000 22.250000 274063200.000000 +24.500000 -16.500000 18.562500 274163200.000000 +23.562500 -23.125000 13.750000 274263200.000000 +22.875000 -28.625000 8.687500 274363200.000000 +21.812500 -32.562500 3.687500 274463200.000000 +20.687500 -35.375000 -0.687500 274563200.000000 +19.500000 -37.062500 -4.000000 274663200.000000 +18.687500 -37.937500 -6.375000 274763200.000000 +17.937500 -38.187500 -7.687500 274863200.000000 +17.562500 -38.625000 -8.500000 274963200.000000 +17.375000 -38.812500 -8.812500 275063200.000000 +17.187500 -39.000000 -8.875000 275163200.000000 +17.125000 -38.812500 -8.937500 275263200.000000 +17.250000 -38.875000 -9.125000 275363200.000000 +17.312500 -39.000000 -9.375000 275463200.000000 +17.187500 -39.062500 -9.312500 275563200.000000 +17.187500 -39.312500 -9.312500 275663200.000000 +17.125000 -39.312500 -9.187500 275763200.000000 +17.000000 -39.312500 -9.062500 275863200.000000 +16.687500 -39.187500 -8.687500 275963200.000000 +16.437500 -39.250000 -7.562500 276063200.000000 +16.437500 -38.937500 -5.875000 276163200.000000 +16.500000 -38.375000 -3.687500 276263200.000000 +16.375000 -37.437500 -0.812500 276363200.000000 +16.500000 -35.500000 3.562500 276463200.000000 +16.312500 -31.937500 8.687500 276563200.000000 +16.812500 -26.625000 14.000000 276663200.000000 +17.500000 -19.937500 18.687500 276763200.000000 +17.937500 -12.000000 22.062500 276863200.000000 +18.250000 -3.500000 23.875000 276963200.000000 +18.687500 5.125000 24.437500 277063200.000000 +19.437500 13.937500 22.562500 277163200.000000 +19.250000 21.687500 18.187500 277263200.000000 +19.562500 27.187500 11.187500 277363200.000000 +19.187500 30.125000 3.000000 277463200.000000 +18.062500 30.062500 -5.937500 277563200.000000 +16.375000 26.500000 -14.812500 277663200.000000 +14.500000 20.687500 -22.187500 277763200.000000 +12.375000 13.562500 -28.187500 277863200.000000 +10.437500 5.062500 -31.312500 277963200.000000 +9.562500 -3.875000 -33.000000 278063200.000000 +8.687500 -12.312500 -32.187500 278163200.000000 +7.312500 -20.187500 -29.812500 278263200.000000 +6.937500 -26.875000 -26.062500 278363200.000000 +7.625000 -31.375000 -20.812500 278463200.000000 +8.625000 -34.187500 -15.750000 278563200.000000 +9.750000 -35.625000 -11.000000 278663200.000000 +10.562500 -36.437500 -7.250000 278763200.000000 +11.625000 -36.625000 -3.625000 278863200.000000 +12.562500 -36.437500 -0.375000 278963200.000000 +13.687500 -35.937500 2.500000 279063200.000000 +14.562500 -35.312500 5.375000 279163200.000000 +14.875000 -34.250000 8.187500 279263200.000000 +15.187500 -32.125000 11.750000 279363200.000000 +16.000000 -29.062500 15.187500 279463200.000000 +17.375000 -24.812500 18.687500 279563200.000000 +18.375000 -19.187500 21.937500 279663200.000000 +19.125000 -12.562500 24.312500 279763200.000000 +19.687500 -5.250000 26.250000 279863200.000000 +19.875000 2.687500 27.000000 279963200.000000 +19.937500 11.000000 26.625000 280063200.000000 +20.062500 18.125000 24.750000 280163200.000000 +19.500000 24.125000 22.125000 280263200.000000 +18.812500 29.187500 17.875000 280363200.000000 +18.062500 32.625000 12.500000 280463200.000000 +14.812500 33.500000 7.562500 280563200.000000 +14.875000 32.562500 -0.062500 280663200.000000 +13.625000 29.375000 -7.125000 280763200.000000 +13.687500 23.875000 -14.500000 280863200.000000 +13.000000 16.937500 -21.062500 280963200.000000 +10.562500 8.687500 -25.625000 281063200.000000 +9.312500 0.000000 -28.875000 281163200.000000 +8.375000 -9.062500 -30.125000 281263200.000000 +7.812500 -17.312500 -29.000000 281363200.000000 +7.187500 -24.187500 -25.500000 281463200.000000 +7.062500 -29.250000 -21.312500 281563200.000000 +7.125000 -32.875000 -16.750000 281663200.000000 +7.812500 -35.125000 -12.250000 281763200.000000 +8.937500 -36.625000 -8.250000 281863200.000000 +10.187500 -37.125000 -4.562500 281963200.000000 +12.062500 -36.750000 -1.250000 282063200.000000 +13.375000 -36.000000 1.812500 282163200.000000 +14.625000 -34.687500 4.937500 282263200.000000 +15.937500 -32.312500 9.000000 282363200.000000 +16.312500 -28.187500 13.875000 282463200.000000 +16.625000 -22.625000 18.625000 282563200.000000 +16.750000 -16.625000 23.125000 282663200.000000 +17.062500 -9.875000 26.687500 282763200.000000 +17.000000 -2.500000 28.812500 282863200.000000 +16.562500 5.375000 29.812500 282963200.000000 +16.062500 13.250000 28.562500 283063200.000000 +15.937500 19.937500 24.500000 283163200.000000 +16.375000 24.125000 17.312500 283263200.000000 +16.312500 25.250000 8.375000 283363200.000000 +15.875000 23.687500 -1.312500 283463200.000000 +14.812500 19.437500 -10.437500 283563200.000000 +13.437500 12.937500 -17.500000 283663200.000000 +12.500000 4.875000 -23.062500 283763200.000000 +11.562500 -3.812500 -26.500000 283863200.000000 +10.500000 -13.000000 -27.437500 283963200.000000 +9.500000 -21.187500 -25.625000 284063200.000000 +9.375000 -28.062500 -21.625000 284163200.000000 +9.687500 -32.375000 -16.500000 284263200.000000 +10.000000 -35.000000 -11.437500 284363200.000000 +10.875000 -36.187500 -7.500000 284463200.000000 +11.625000 -36.625000 -4.312500 284563200.000000 +12.062500 -36.812500 -2.312500 284663200.000000 +12.250000 -36.937500 -0.812500 284763200.000000 +12.312500 -36.687500 -0.062500 284863200.000000 +12.187500 -36.250000 0.062500 284963200.000000 +12.125000 -36.500000 -0.125000 285063200.000000 +12.250000 -36.750000 -0.500000 285163200.000000 +11.937500 -37.125000 -0.812500 285263200.000000 +11.750000 -37.437500 -1.062500 285363200.000000 +11.562500 -37.875000 -1.187500 285463200.000000 +11.437500 -38.062500 -1.375000 285563200.000000 +11.312500 -38.375000 -1.250000 285663200.000000 +11.250000 -38.750000 -1.250000 285763200.000000 +11.062500 -38.687500 -1.125000 285863200.000000 +10.937500 -38.437500 -0.875000 285963200.000000 +10.937500 -38.312500 -0.500000 286063200.000000 +10.562500 -38.125000 -0.125000 286163200.000000 +10.500000 -38.062500 0.125000 286263200.000000 +10.062500 -38.000000 0.625000 286363200.000000 +9.625000 -38.062500 0.937500 286463200.000000 +9.500000 -38.187500 1.000000 286563200.000000 +9.437500 -38.687500 1.312500 286663200.000000 +9.437500 -39.000000 1.500000 286763200.000000 +9.187500 -39.312500 1.437500 286863200.000000 +8.750000 -39.375000 1.812500 286963200.000000 +8.375000 -39.375000 2.312500 287063200.000000 +8.312500 -39.500000 2.562500 287163200.000000 +7.937500 -39.375000 3.062500 287263200.000000 +7.187500 -39.062500 3.812500 287363200.000000 +6.687500 -39.000000 4.250000 287463200.000000 +6.125000 -39.062500 4.812500 287563200.000000 +5.500000 -38.937500 5.437500 287663200.000000 +5.187500 -38.937500 5.312500 287763200.000000 +4.812500 -39.125000 5.250000 287863200.000000 +4.500000 -39.187500 5.250000 287963200.000000 +4.500000 -39.312500 5.125000 288063200.000000 +4.312500 -39.312500 5.062500 288163200.000000 +4.062500 -39.250000 4.812500 288263200.000000 +3.750000 -38.812500 4.625000 288363200.000000 +3.875000 -38.750000 4.625000 288463200.000000 +3.937500 -38.875000 4.812500 288563200.000000 +4.000000 -38.687500 4.875000 288663200.000000 +3.687500 -38.625000 5.187500 288763200.000000 +3.375000 -38.562500 5.437500 288863200.000000 +3.375000 -38.687500 5.562500 288963200.000000 +3.125000 -38.562500 6.187500 289063200.000000 +3.062500 -38.875000 6.500000 289163200.000000 +2.687500 -39.000000 6.750000 289263200.000000 +2.625000 -39.062500 6.687500 289363200.000000 +2.562500 -39.250000 6.812500 289463200.000000 +2.562500 -39.312500 6.500000 289563200.000000 +2.750000 -39.500000 6.437500 289663200.000000 +3.000000 -39.562500 6.312500 289763200.000000 +3.000000 -39.750000 6.062500 289863200.000000 +3.000000 -39.750000 5.937500 289963200.000000 +2.875000 -39.875000 5.687500 290063200.000000 +3.250000 -39.812500 5.437500 290163200.000000 +3.062500 -39.812500 5.375000 290263200.000000 +3.187500 -39.875000 5.812500 290363200.000000 +3.500000 -39.750000 5.625000 290463200.000000 +3.812500 -39.687500 5.687500 290563200.000000 +3.875000 -39.562500 5.562500 290663200.000000 +4.312500 -39.562500 5.625000 290763200.000000 +4.812500 -39.125000 6.125000 290863200.000000 +4.750000 -38.937500 6.687500 290963200.000000 +5.062500 -39.062500 6.875000 291063200.000000 +5.437500 -38.875000 6.562500 291163200.000000 +5.812500 -39.062500 6.312500 291263200.000000 +6.000000 -39.375000 5.875000 291363200.000000 +6.625000 -39.500000 5.500000 291463200.000000 +7.062500 -39.562500 4.875000 291563200.000000 +7.625000 -40.187500 3.562500 291663200.000000 +8.062500 -40.500000 2.562500 291763200.000000 +8.375000 -40.750000 1.812500 291863200.000000 +8.187500 -40.875000 1.500000 291963200.000000 +7.750000 -40.937500 1.437500 292063200.000000 +6.937500 -40.812500 1.750000 292163200.000000 +6.500000 -40.750000 2.125000 292263200.000000 +5.875000 -40.437500 2.375000 292363200.000000 +5.312500 -40.125000 2.875000 292463200.000000 +4.625000 -39.562500 3.437500 292563200.000000 +4.750000 -39.437500 3.312500 292663200.000000 +5.187500 -39.500000 2.937500 292763200.000000 +5.750000 -39.375000 2.625000 292863200.000000 +6.500000 -39.375000 2.000000 292963200.000000 +7.062500 -39.437500 1.250000 293063200.000000 +7.562500 -39.812500 0.812500 293163200.000000 +8.000000 -39.937500 0.375000 293263200.000000 +8.437500 -40.375000 0.000000 293363200.000000 +8.250000 -40.250000 -0.062500 293463200.000000 +8.187500 -40.312500 -0.125000 293563200.000000 +8.062500 -40.437500 -0.125000 293663200.000000 +8.125000 -40.687500 -0.375000 293763200.000000 +8.187500 -40.687500 0.125000 293863200.000000 +8.375000 -40.875000 0.000000 293963200.000000 +8.625000 -40.937500 0.125000 294063200.000000 +8.625000 -41.125000 0.000000 294163200.000000 +8.687500 -41.437500 0.062500 294263200.000000 +8.750000 -41.375000 0.000000 294363200.000000 +8.750000 -41.250000 -0.062500 294463200.000000 +8.937500 -41.187500 0.000000 294563200.000000 +9.125000 -41.250000 -0.437500 294663200.000000 +8.875000 -41.000000 -0.250000 294763200.000000 +8.812500 -40.875000 -0.437500 294863200.000000 +8.875000 -40.750000 -0.312500 294963200.000000 +9.312500 -40.750000 -0.437500 295063200.000000 +9.250000 -40.625000 -0.437500 295163200.000000 +9.187500 -40.750000 -0.437500 295263200.000000 +8.937500 -40.687500 -0.375000 295363200.000000 +8.687500 -40.625000 -0.125000 295463200.000000 +8.875000 -40.562500 -0.312500 295563200.000000 +8.812500 -40.812500 -0.062500 295663200.000000 +9.125000 -41.062500 -0.187500 295763200.000000 +8.687500 -41.000000 -0.062500 295863200.000000 +8.437500 -41.187500 0.000000 295963200.000000 +8.375000 -41.187500 0.125000 296063200.000000 +8.187500 -40.875000 0.562500 296163200.000000 +8.125000 -41.125000 0.625000 296263200.000000 +7.937500 -41.125000 0.937500 296363200.000000 +7.687500 -40.937500 0.875000 296463200.000000 +7.062500 -40.687500 0.812500 296563200.000000 +7.125000 -40.562500 0.750000 296663200.000000 +7.250000 -40.187500 0.937500 296763200.000000 +7.187500 -40.125000 1.125000 296863200.000000 +6.937500 -40.375000 0.937500 296963200.000000 +6.625000 -40.062500 1.000000 297063200.000000 +6.062500 -40.062500 1.062500 297163200.000000 +5.687500 -40.000000 1.250000 297263200.000000 +5.187500 -39.750000 1.750000 297363200.000000 +4.375000 -39.750000 1.875000 297463200.000000 +3.375000 -39.687500 2.187500 297563200.000000 +2.687500 -39.625000 1.875000 297663200.000000 +2.062500 -39.500000 2.000000 297763200.000000 +1.625000 -39.500000 1.812500 297863200.000000 +1.312500 -39.187500 1.562500 297963200.000000 +1.000000 -39.187500 1.437500 298063200.000000 +0.562500 -39.250000 1.000000 298163200.000000 +0.375000 -39.250000 0.750000 298263200.000000 +-0.062500 -39.187500 0.375000 298363200.000000 +-0.562500 -38.875000 0.375000 298463200.000000 +-0.937500 -38.750000 -0.312500 298563200.000000 +-1.437500 -38.500000 -1.125000 298663200.000000 +-1.750000 -38.500000 -1.750000 298763200.000000 +-2.062500 -38.125000 -2.125000 298863200.000000 +-2.312500 -38.000000 -2.312500 298963200.000000 +-2.937500 -37.375000 -1.937500 299063200.000000 +-3.000000 -37.375000 -1.875000 299163200.000000 +-2.687500 -37.375000 -1.687500 299263200.000000 +-2.062500 -37.312500 -0.687500 299363200.000000 +-1.750000 -37.250000 0.937500 299463200.000000 +-1.375000 -37.437500 2.312500 299563200.000000 +-1.312500 -37.750000 3.812500 299663200.000000 +-0.500000 -38.125000 4.437500 299763200.000000 +0.687500 -38.687500 4.562500 299863200.000000 +1.687500 -39.000000 4.812500 299963200.000000 +1.937500 -39.312500 5.250000 300063200.000000 +1.750000 -39.812500 5.125000 300163200.000000 +1.875000 -40.125000 4.562500 300263200.000000 +1.750000 -40.125000 3.875000 300363200.000000 +1.812500 -40.187500 3.000000 300463200.000000 +0.875000 -40.062500 2.875000 300563200.000000 +0.125000 -40.000000 2.812500 300663200.000000 +-0.437500 -40.000000 2.625000 300763200.000000 +-1.437500 -39.625000 2.812500 300863200.000000 +-2.187500 -39.000000 2.625000 300963200.000000 +-2.687500 -39.000000 2.125000 301063200.000000 +-2.812500 -39.125000 1.562500 301163200.000000 +-2.687500 -39.187500 0.875000 301263200.000000 +-2.000000 -39.187500 0.437500 301363200.000000 +-1.437500 -39.187500 -0.062500 301463200.000000 +-0.875000 -39.125000 -0.562500 301563200.000000 +0.250000 -39.500000 -1.687500 301663200.000000 +0.625000 -39.687500 -2.250000 301763200.000000 +0.812500 -39.625000 -2.250000 301863200.000000 +0.625000 -39.312500 -1.875000 301963200.000000 +0.562500 -39.000000 -1.250000 302063200.000000 +0.000000 -38.750000 -1.125000 302163200.000000 +-0.375000 -38.562500 -1.437500 302263200.000000 +-0.750000 -38.437500 -1.625000 302363200.000000 +-0.875000 -38.375000 -1.750000 302463200.000000 +-0.375000 -38.500000 -2.062500 302563200.000000 +0.312500 -38.562500 -2.375000 302663200.000000 +1.312500 -38.812500 -2.687500 302763200.000000 +1.687500 -39.000000 -2.750000 302863200.000000 +2.500000 -39.375000 -2.937500 302963200.000000 +3.125000 -39.500000 -2.187500 303063200.000000 +3.625000 -39.750000 -1.375000 303163200.000000 +3.937500 -40.000000 -0.812500 303263200.000000 +4.187500 -40.187500 -0.187500 303363200.000000 +4.125000 -40.375000 0.750000 303463200.000000 +3.812500 -40.375000 1.437500 303563200.000000 +4.000000 -40.562500 1.750000 303663200.000000 +4.062500 -40.687500 1.812500 303763200.000000 +3.812500 -40.875000 1.687500 303863200.000000 +3.812500 -41.000000 1.625000 303963200.000000 +3.625000 -40.875000 1.875000 304063200.000000 +3.250000 -40.875000 2.062500 304163200.000000 +3.000000 -40.750000 2.125000 304263200.000000 +2.562500 -40.625000 2.000000 304363200.000000 +2.000000 -40.625000 1.812500 304463200.000000 +1.062500 -40.687500 1.937500 304563200.000000 +0.500000 -40.937500 1.187500 304663200.000000 +-0.375000 -40.812500 0.437500 304763200.000000 +-0.750000 -40.937500 0.000000 304863200.000000 +-1.062500 -41.187500 0.000000 304963200.000000 +-1.062500 -41.250000 -0.312500 305063200.000000 +-1.062500 -41.625000 -0.437500 305163200.000000 +-0.875000 -41.687500 -0.625000 305263200.000000 +-0.500000 -41.625000 -1.312500 305363200.000000 +-0.250000 -41.500000 -1.312500 305463200.000000 +-0.125000 -41.312500 -1.250000 305563200.000000 +-0.062500 -40.937500 -1.562500 305663200.000000 +-0.062500 -40.500000 -2.437500 305763200.000000 +-0.125000 -40.312500 -3.187500 305863200.000000 +0.187500 -40.062500 -4.125000 305963200.000000 +0.437500 -39.687500 -5.000000 306063200.000000 +1.062500 -39.312500 -5.187500 306163200.000000 +2.187500 -39.187500 -5.312500 306263200.000000 +3.312500 -38.875000 -5.250000 306363200.000000 +4.312500 -39.000000 -5.187500 306463200.000000 +5.562500 -39.125000 -4.375000 306563200.000000 +6.687500 -39.312500 -3.312500 306663200.000000 +7.125000 -39.375000 -2.000000 306763200.000000 +7.625000 -39.750000 -0.687500 306863200.000000 +7.750000 -40.125000 0.562500 306963200.000000 +7.812500 -40.562500 1.562500 307063200.000000 +7.750000 -41.000000 2.250000 307163200.000000 +7.562500 -41.562500 2.812500 307263200.000000 +7.562500 -41.875000 2.937500 307363200.000000 +7.437500 -42.250000 2.562500 307463200.000000 +7.625000 -42.500000 2.125000 307563200.000000 +7.875000 -42.750000 1.750000 307663200.000000 +7.812500 -43.000000 1.000000 307763200.000000 +7.687500 -43.250000 0.437500 307863200.000000 +7.625000 -43.687500 -0.062500 307963200.000000 +7.812500 -43.875000 -0.500000 308063200.000000 +7.625000 -43.937500 -0.750000 308163200.000000 +7.375000 -44.000000 -0.937500 308263200.000000 +7.375000 -44.000000 -1.125000 308363200.000000 +7.062500 -43.937500 -1.375000 308463200.000000 +6.937500 -43.937500 -1.312500 308563200.000000 +6.812500 -44.000000 -1.375000 308663200.000000 +6.750000 -43.687500 -1.500000 308763200.000000 +6.625000 -43.625000 -1.375000 308863200.000000 +6.562500 -43.750000 -1.437500 308963200.000000 +6.625000 -43.750000 -1.250000 309063200.000000 +6.500000 -43.625000 -1.312500 309163200.000000 +6.250000 -43.437500 -1.125000 309263200.000000 +6.500000 -43.375000 -1.062500 309363200.000000 +6.500000 -43.125000 -1.000000 309463200.000000 +6.312500 -43.125000 -1.312500 309563200.000000 +5.937500 -42.812500 -1.937500 309663200.000000 +5.375000 -42.437500 -2.562500 309763200.000000 +4.375000 -42.125000 -3.437500 309863200.000000 +3.000000 -42.000000 -3.937500 309963200.000000 +1.500000 -41.875000 -4.250000 310063200.000000 +0.000000 -41.312500 -4.187500 310163200.000000 +-1.250000 -40.875000 -3.750000 310263200.000000 +-2.062500 -40.687500 -2.500000 310363200.000000 +-2.312500 -40.625000 -1.062500 310463200.000000 +-1.937500 -41.062500 0.125000 310563200.000000 +-0.625000 -41.187500 1.187500 310663200.000000 +1.062500 -41.312500 1.562500 310763200.000000 +2.937500 -41.375000 1.125000 310863200.000000 +3.687500 -41.500000 0.250000 310963200.000000 +3.750000 -41.750000 -0.812500 311063200.000000 +2.812500 -41.625000 -2.000000 311163200.000000 +1.375000 -41.437500 -3.125000 311263200.000000 +-0.437500 -41.250000 -4.562500 311363200.000000 +-2.562500 -41.000000 -5.562500 311463200.000000 +-4.500000 -41.062500 -5.375000 311563200.000000 +-6.125000 -41.250000 -4.500000 311663200.000000 +-6.750000 -41.875000 -3.750000 311763200.000000 +-6.625000 -42.250000 -3.000000 311863200.000000 +-5.812500 -43.062500 -2.812500 311963200.000000 +-4.187500 -44.000000 -2.500000 312063200.000000 +-2.750000 -44.500000 -1.750000 312163200.000000 +-1.250000 -45.250000 -1.187500 312263200.000000 +-0.062500 -45.500000 -1.250000 312363200.000000 +1.125000 -45.625000 -1.250000 312463200.000000 +2.062500 -45.250000 -1.000000 312563200.000000 +2.875000 -44.875000 -1.062500 312663200.000000 +3.375000 -44.125000 -0.875000 312763200.000000 +3.500000 -43.375000 -0.937500 312863200.000000 +3.812500 -42.750000 -1.250000 312963200.000000 +4.000000 -41.937500 -1.375000 313063200.000000 +4.062500 -41.250000 -1.375000 313163200.000000 +3.875000 -40.625000 -1.500000 313263200.000000 +3.500000 -40.375000 -1.625000 313363200.000000 +3.437500 -40.437500 -1.000000 313463200.000000 +3.187500 -40.312500 -0.250000 313563200.000000 +3.312500 -40.125000 0.437500 313663200.000000 +3.375000 -40.125000 1.312500 313763200.000000 +3.375000 -40.625000 2.125000 313863200.000000 +3.187500 -41.187500 2.437500 313963200.000000 +3.437500 -41.875000 2.312500 314063200.000000 +3.937500 -42.437500 2.062500 314163200.000000 +4.375000 -42.750000 1.125000 314263200.000000 +4.312500 -43.437500 -1.062500 314363200.000000 +3.062500 -44.062500 -2.812500 314463200.000000 +1.625000 -44.500000 -4.937500 314563200.000000 +-0.375000 -44.812500 -6.000000 314663200.000000 +-2.375000 -45.312500 -5.562500 314763200.000000 +-4.312500 -45.437500 -4.625000 314863200.000000 +-5.125000 -45.875000 -3.625000 314963200.000000 +-5.375000 -46.187500 -3.000000 315063200.000000 +-5.062500 -45.687500 -2.375000 315163200.000000 +-3.812500 -45.312500 -2.000000 315263200.000000 +-2.562500 -45.062500 -0.750000 315363200.000000 +-0.937500 -44.125000 -0.875000 315463200.000000 +0.375000 -43.062500 -1.812500 315563200.000000 +1.000000 -42.187500 -3.062500 315663200.000000 +0.687500 -41.125000 -4.187500 315763200.000000 +-0.375000 -40.312500 -4.437500 315863200.000000 +-0.875000 -40.375000 -3.750000 315963200.000000 +-1.000000 -40.437500 -2.812500 316063200.000000 +-1.062500 -40.750000 -2.187500 316163200.000000 +-0.437500 -41.375000 -1.562500 316263200.000000 +0.562500 -41.937500 -1.187500 316363200.000000 +1.875000 -42.500000 -0.812500 316463200.000000 +2.687500 -43.000000 -1.062500 316563200.000000 +3.375000 -43.312500 -1.312500 316663200.000000 +3.125000 -43.125000 -1.437500 316763200.000000 +2.625000 -42.812500 -1.500000 316863200.000000 +1.812500 -42.250000 -1.500000 316963200.000000 +1.312500 -41.875000 -1.437500 317063200.000000 +1.125000 -41.687500 -1.125000 317163200.000000 +1.125000 -41.625000 -0.312500 317263200.000000 +1.375000 -41.625000 0.812500 317363200.000000 +1.312500 -42.000000 1.812500 317463200.000000 +2.000000 -42.687500 2.187500 317563200.000000 +2.437500 -43.500000 2.312500 317663200.000000 +3.125000 -44.437500 2.562500 317763200.000000 +3.062500 -45.250000 2.937500 317863200.000000 +3.000000 -46.000000 2.750000 317963200.000000 +2.687500 -46.562500 2.250000 318063200.000000 +2.687500 -47.250000 2.000000 318163200.000000 +3.000000 -47.562500 1.500000 318263200.000000 +3.250000 -47.875000 1.312500 318363200.000000 +3.312500 -48.125000 1.375000 318463200.000000 +3.437500 -47.937500 1.125000 318563200.000000 +3.500000 -48.062500 0.937500 318663200.000000 +3.687500 -48.125000 1.062500 318763200.000000 +3.937500 -48.187500 0.937500 318863200.000000 +3.812500 -48.125000 0.875000 318963200.000000 +3.875000 -48.125000 1.000000 319063200.000000 +3.875000 -48.000000 1.062500 319163200.000000 +3.875000 -47.875000 1.125000 319263200.000000 +3.875000 -47.875000 1.187500 319363200.000000 +4.062500 -47.750000 1.187500 319463200.000000 +4.062500 -47.625000 1.000000 319563200.000000 +4.062500 -47.500000 1.000000 319663200.000000 +4.125000 -47.187500 1.000000 319763200.000000 +4.062500 -47.062500 0.937500 319863200.000000 +4.000000 -47.000000 0.875000 319963200.000000 +3.875000 -47.375000 0.625000 320063200.000000 +3.437500 -47.812500 0.625000 320163200.000000 +2.937500 -48.625000 0.625000 320263200.000000 +2.125000 -49.750000 0.687500 320363200.000000 +1.187500 -50.812500 0.125000 320463200.000000 +0.062500 -52.375000 -0.375000 320563200.000000 +-1.000000 -53.625000 -1.375000 320663200.000000 +-1.875000 -55.187500 -2.625000 320763200.000000 +-2.375000 -56.062500 -4.125000 320863200.000000 +-2.500000 -57.062500 -6.187500 320963200.000000 +-2.500000 -57.500000 -8.375000 321063200.000000 +-2.312500 -57.625000 -10.437500 321163200.000000 +-2.187500 -57.687500 -11.937500 321263200.000000 +-1.875000 -57.812500 -13.437500 321363200.000000 +-1.625000 -58.000000 -14.437500 321463200.000000 +-1.437500 -57.812500 -14.937500 321563200.000000 +-1.500000 -57.750000 -15.187500 321663200.000000 +-1.750000 -57.687500 -15.062500 321763200.000000 +-2.000000 -57.812500 -14.687500 321863200.000000 +-2.500000 -57.687500 -14.437500 321963200.000000 +-2.812500 -57.875000 -14.437500 322063200.000000 +-3.062500 -57.750000 -14.250000 322163200.000000 +-2.875000 -57.562500 -14.250000 322263200.000000 +-3.000000 -57.625000 -14.062500 322363200.000000 +-3.062500 -57.562500 -14.125000 322463200.000000 +-3.125000 -57.437500 -14.250000 322563200.000000 +-2.875000 -56.687500 -14.437500 322663200.000000 +-1.812500 -55.812500 -14.562500 322763200.000000 +-0.812500 -54.625000 -14.500000 322863200.000000 +0.312500 -53.187500 -14.250000 322963200.000000 +1.062500 -51.562500 -14.062500 323063200.000000 +2.000000 -50.000000 -14.000000 323163200.000000 +3.250000 -48.250000 -13.750000 323263200.000000 +4.125000 -46.812500 -13.500000 323363200.000000 +4.750000 -45.875000 -13.187500 323463200.000000 +4.875000 -45.125000 -12.812500 323563200.000000 +5.187500 -44.625000 -12.812500 323663200.000000 +5.500000 -44.562500 -12.812500 323763200.000000 +5.437500 -44.312500 -12.937500 323863200.000000 +5.437500 -44.187500 -13.125000 323963200.000000 +5.437500 -44.375000 -13.312500 324063200.000000 +5.687500 -44.250000 -13.125000 324163200.000000 +6.500000 -44.062500 -13.062500 324263200.000000 +8.062500 -43.750000 -13.250000 324363200.000000 +10.875000 -42.437500 -13.250000 324463200.000000 +14.562500 -39.812500 -13.250000 324563200.000000 +19.187500 -36.000000 -12.937500 324663200.000000 +23.687500 -30.687500 -12.750000 324763200.000000 +27.875000 -23.937500 -12.437500 324863200.000000 +32.000000 -16.812500 -12.812500 324963200.000000 +34.937500 -9.062500 -12.875000 325063200.000000 +36.875000 -1.062500 -12.875000 325163200.000000 +37.000000 6.500000 -12.625000 325263200.000000 +35.187500 13.187500 -12.500000 325363200.000000 +33.000000 19.000000 -11.937500 325463200.000000 +30.000000 23.750000 -12.250000 325563200.000000 +25.562500 26.875000 -12.687500 325663200.000000 +20.250000 29.750000 -12.875000 325763200.000000 +14.187500 31.437500 -12.875000 325863200.000000 +6.625000 31.375000 -13.062500 325963200.000000 +-0.937500 30.375000 -13.250000 326063200.000000 +-8.000000 28.687500 -13.500000 326163200.000000 +-15.125000 26.687500 -14.375000 326263200.000000 +-21.437500 24.437500 -14.375000 326363200.000000 +-26.187500 22.125000 -14.187500 326463200.000000 +-29.812500 19.687500 -13.937500 326563200.000000 +-32.312500 17.375000 -14.125000 326663200.000000 +-33.500000 15.500000 -14.312500 326763200.000000 +-34.375000 13.000000 -14.375000 326863200.000000 +-34.625000 9.125000 -14.562500 326963200.000000 +-34.500000 3.875000 -14.500000 327063200.000000 +-33.500000 -2.625000 -14.625000 327163200.000000 +-32.000000 -9.437500 -14.625000 327263200.000000 +-29.437500 -16.937500 -14.625000 327363200.000000 +-25.625000 -24.312500 -14.750000 327463200.000000 +-19.875000 -30.937500 -14.375000 327563200.000000 +-13.875000 -36.125000 -14.187500 327663200.000000 +-8.125000 -39.500000 -13.875000 327763200.000000 +-3.312500 -41.812500 -13.500000 327863200.000000 +0.437500 -42.687500 -12.812500 327963200.000000 +4.437500 -43.312500 -12.625000 328063200.000000 +7.437500 -43.437500 -12.562500 328163200.000000 +9.125000 -43.125000 -12.437500 328263200.000000 +9.312500 -43.000000 -12.375000 328363200.000000 +9.500000 -43.125000 -12.562500 328463200.000000 +9.750000 -43.375000 -12.812500 328563200.000000 +11.125000 -43.375000 -13.250000 328663200.000000 +13.312500 -43.250000 -13.687500 328763200.000000 +15.500000 -41.875000 -13.562500 328863200.000000 +18.312500 -39.375000 -13.250000 328963200.000000 +21.812500 -35.937500 -12.875000 329063200.000000 +25.125000 -30.625000 -12.375000 329163200.000000 +28.437500 -24.000000 -11.812500 329263200.000000 +31.000000 -15.750000 -11.375000 329363200.000000 +31.937500 -6.687500 -10.562500 329463200.000000 +31.375000 2.687500 -9.687500 329563200.000000 +30.312500 11.125000 -9.187500 329663200.000000 +27.312500 18.187500 -10.375000 329763200.000000 +23.875000 24.312500 -11.312500 329863200.000000 +20.312500 28.500000 -12.875000 329963200.000000 +15.750000 31.437500 -14.187500 330063200.000000 +11.312500 33.187500 -15.625000 330163200.000000 +7.125000 33.875000 -16.812500 330263200.000000 +3.250000 33.687500 -18.000000 330363200.000000 +-0.750000 33.687500 -18.875000 330463200.000000 +-2.937500 34.000000 -18.312500 330563200.000000 +-4.937500 34.437500 -17.812500 330663200.000000 +-6.187500 34.937500 -17.250000 330763200.000000 +-6.562500 35.687500 -16.562500 330863200.000000 +-6.437500 35.687500 -15.750000 330963200.000000 +-5.312500 35.937500 -15.687500 331063200.000000 +-3.875000 36.375000 -15.625000 331163200.000000 +-3.187500 36.437500 -15.750000 331263200.000000 +-3.687500 36.437500 -15.687500 331363200.000000 +-5.312500 35.937500 -15.625000 331463200.000000 +-8.062500 34.625000 -15.125000 331563200.000000 +-11.250000 32.875000 -14.875000 331663200.000000 +-14.812500 31.062500 -14.625000 331763200.000000 +-18.875000 28.312500 -14.375000 331863200.000000 +-23.437500 24.500000 -14.375000 331963200.000000 +-27.625000 19.562500 -14.250000 332063200.000000 +-31.250000 13.937500 -14.187500 332163200.000000 +-33.437500 7.375000 -14.250000 332263200.000000 +-34.625000 1.062500 -14.500000 332363200.000000 +-35.062500 -5.687500 -14.687500 332463200.000000 +-34.000000 -12.812500 -14.687500 332563200.000000 +-31.500000 -19.875000 -14.687500 332663200.000000 +-27.875000 -26.187500 -14.625000 332763200.000000 +-23.500000 -31.312500 -14.562500 332863200.000000 +-17.625000 -35.625000 -14.500000 332963200.000000 +-11.250000 -38.437500 -14.312500 333063200.000000 +-4.937500 -40.687500 -14.375000 333163200.000000 +1.000000 -42.125000 -14.250000 333263200.000000 +6.000000 -42.687500 -14.125000 333363200.000000 +9.750000 -42.500000 -14.062500 333463200.000000 +13.187500 -42.125000 -14.000000 333563200.000000 +15.687500 -41.687500 -13.937500 333663200.000000 +17.125000 -41.187500 -13.812500 333763200.000000 +17.812500 -40.625000 -13.937500 333863200.000000 +19.312500 -39.437500 -13.562500 333963200.000000 +21.812500 -37.500000 -13.562500 334063200.000000 +24.687500 -34.187500 -13.437500 334163200.000000 +27.875000 -29.500000 -13.312500 334263200.000000 +30.937500 -24.187500 -13.250000 334363200.000000 +33.812500 -17.875000 -13.062500 334463200.000000 +36.562500 -11.000000 -13.125000 334563200.000000 +38.125000 -3.750000 -13.000000 334663200.000000 +38.250000 3.312500 -13.250000 334763200.000000 +36.625000 10.000000 -13.125000 334863200.000000 +34.500000 15.500000 -12.937500 334963200.000000 +31.437500 19.937500 -13.187500 335063200.000000 +27.937500 24.125000 -13.000000 335163200.000000 +24.250000 27.500000 -12.875000 335263200.000000 +20.000000 30.437500 -12.687500 335363200.000000 +15.000000 32.437500 -12.687500 335463200.000000 +9.937500 33.625000 -12.500000 335563200.000000 +5.812500 34.625000 -12.562500 335663200.000000 +1.937500 35.437500 -12.750000 335763200.000000 +-1.500000 35.562500 -12.500000 335863200.000000 +-4.312500 35.562500 -12.625000 335963200.000000 +-6.875000 35.375000 -12.937500 336063200.000000 +-8.750000 35.312500 -13.000000 336163200.000000 +-9.625000 34.812500 -13.125000 336263200.000000 +-10.625000 34.625000 -13.187500 336363200.000000 +-12.937500 33.312500 -13.187500 336463200.000000 +-16.312500 30.562500 -13.125000 336563200.000000 +-19.750000 27.250000 -13.312500 336663200.000000 +-23.500000 22.500000 -13.250000 336763200.000000 +-27.125000 16.562500 -13.500000 336863200.000000 +-30.125000 9.437500 -14.125000 336963200.000000 +-32.062500 1.937500 -14.625000 337063200.000000 +-32.812500 -6.000000 -15.125000 337163200.000000 +-31.625000 -13.875000 -15.500000 337263200.000000 +-29.062500 -20.812500 -15.562500 337363200.000000 +-25.187500 -26.875000 -15.562500 337463200.000000 +-20.562500 -31.937500 -15.500000 337563200.000000 +-15.312500 -35.687500 -15.312500 337663200.000000 +-10.312500 -38.750000 -14.875000 337763200.000000 +-5.875000 -40.937500 -14.250000 337863200.000000 +-1.937500 -42.437500 -13.750000 337963200.000000 +1.187500 -43.062500 -13.500000 338063200.000000 +3.875000 -43.250000 -13.375000 338163200.000000 +5.437500 -43.562500 -13.125000 338263200.000000 +6.312500 -43.437500 -13.000000 338363200.000000 +6.500000 -43.437500 -13.125000 338463200.000000 +6.250000 -43.250000 -12.937500 338563200.000000 +5.750000 -43.187500 -12.750000 338663200.000000 +5.500000 -43.125000 -12.937500 338763200.000000 +5.062500 -43.250000 -12.875000 338863200.000000 +4.625000 -43.437500 -13.000000 338963200.000000 +4.375000 -43.312500 -13.187500 339063200.000000 +4.062500 -43.562500 -13.375000 339163200.000000 +4.000000 -43.750000 -13.312500 339263200.000000 +4.062500 -43.812500 -13.187500 339363200.000000 +4.187500 -44.000000 -13.500000 339463200.000000 +4.125000 -44.125000 -13.312500 339563200.000000 +4.125000 -44.250000 -13.437500 339663200.000000 +4.125000 -44.312500 -13.375000 339763200.000000 +4.062500 -44.312500 -13.375000 339863200.000000 +4.062500 -44.187500 -13.312500 339963200.000000 +4.125000 -44.062500 -13.312500 340063200.000000 +4.062500 -44.187500 -13.500000 340163200.000000 +3.937500 -44.125000 -13.500000 340263200.000000 +3.812500 -44.000000 -13.687500 340363200.000000 +3.937500 -44.062500 -13.687500 340463200.000000 +3.875000 -43.937500 -13.875000 340563200.000000 +3.812500 -44.062500 -13.687500 340663200.000000 +3.687500 -44.250000 -13.687500 340763200.000000 +3.750000 -44.437500 -13.750000 340863200.000000 +3.625000 -44.437500 -13.750000 340963200.000000 +3.687500 -44.375000 -13.687500 341063200.000000 +3.875000 -44.437500 -13.625000 341163200.000000 +3.750000 -44.250000 -13.625000 341263200.000000 +3.875000 -44.375000 -13.437500 341363200.000000 +3.375000 -44.437500 -13.625000 341463200.000000 +1.687500 -44.062500 -13.562500 341563200.000000 +-1.687500 -43.187500 -13.312500 341663200.000000 +-6.000000 -41.125000 -13.250000 341763200.000000 +-11.062500 -37.750000 -13.562500 341863200.000000 +-16.562500 -33.000000 -13.812500 341963200.000000 +-21.937500 -27.312500 -14.125000 342063200.000000 +-26.875000 -21.312500 -14.375000 342163200.000000 +-31.812500 -15.312500 -14.312500 342263200.000000 +-35.375000 -9.812500 -14.437500 342363200.000000 +-37.500000 -4.937500 -14.625000 342463200.000000 +-38.437500 -1.000000 -14.875000 342563200.000000 +-38.750000 1.562500 -14.875000 342663200.000000 +-38.812500 4.000000 -14.812500 342763200.000000 +-38.000000 6.750000 -14.375000 342863200.000000 +-36.875000 10.312500 -13.875000 342963200.000000 +-34.250000 14.562500 -13.250000 343063200.000000 +-30.875000 18.875000 -12.750000 343163200.000000 +-25.687500 23.312500 -12.750000 343263200.000000 +-19.062500 27.375000 -12.250000 343363200.000000 +-10.437500 30.187500 -11.687500 343463200.000000 +-1.500000 31.500000 -11.000000 343563200.000000 +7.312500 30.625000 -10.437500 343663200.000000 +15.812500 27.687500 -9.875000 343763200.000000 +23.437500 23.687500 -10.125000 343863200.000000 +30.062500 18.875000 -10.187500 343963200.000000 +34.937500 13.812500 -9.937500 344063200.000000 +38.250000 8.937500 -10.000000 344163200.000000 +39.625000 5.250000 -10.125000 344263200.000000 +40.875000 1.812500 -10.437500 344363200.000000 +41.375000 -0.625000 -10.875000 344463200.000000 +41.125000 -2.937500 -11.500000 344563200.000000 +40.250000 -5.687500 -11.500000 344663200.000000 +39.187500 -8.812500 -11.312500 344763200.000000 +37.187500 -12.187500 -11.000000 344863200.000000 +34.875000 -16.625000 -10.875000 344963200.000000 +31.125000 -21.937500 -11.125000 345063200.000000 +24.937500 -27.750000 -11.375000 345163200.000000 +16.875000 -32.562500 -11.687500 345263200.000000 +7.750000 -35.312500 -12.125000 345363200.000000 +-0.687500 -36.375000 -12.625000 345463200.000000 +-9.562500 -35.437500 -13.437500 345563200.000000 +-17.500000 -33.062500 -14.125000 345663200.000000 +-25.250000 -28.687500 -14.812500 345763200.000000 +-31.437500 -23.187500 -14.937500 345863200.000000 +-35.187500 -17.125000 -15.250000 345963200.000000 +-37.250000 -12.250000 -15.562500 346063200.000000 +-37.875000 -8.312500 -15.750000 346163200.000000 +-38.500000 -5.187500 -15.937500 346263200.000000 +-38.500000 -2.937500 -15.812500 346363200.000000 +-38.625000 -1.812500 -15.812500 346463200.000000 +-39.125000 -0.750000 -15.312500 346563200.000000 +-39.250000 0.125000 -15.312500 346663200.000000 +-39.562500 1.500000 -14.812500 346763200.000000 +-39.500000 3.375000 -14.125000 346863200.000000 +-38.250000 6.562500 -14.000000 346963200.000000 +-35.875000 10.500000 -13.625000 347063200.000000 +-32.125000 15.250000 -13.687500 347163200.000000 +-26.750000 19.937500 -13.500000 347263200.000000 +-19.562500 24.062500 -13.562500 347363200.000000 +-11.625000 27.375000 -13.250000 347463200.000000 +-3.062500 29.562500 -13.250000 347563200.000000 +6.000000 31.062500 -13.187500 347663200.000000 +13.875000 30.687500 -12.500000 347763200.000000 +21.562500 28.062500 -12.125000 347863200.000000 +27.625000 23.750000 -12.062500 347963200.000000 +32.375000 18.937500 -11.750000 348063200.000000 +35.812500 14.187500 -11.562500 348163200.000000 +38.000000 10.250000 -11.750000 348263200.000000 +39.625000 6.562500 -11.500000 348363200.000000 +40.500000 3.250000 -11.500000 348463200.000000 +41.375000 0.312500 -11.937500 348563200.000000 +41.500000 -1.187500 -12.062500 348663200.000000 +41.812500 -1.875000 -11.750000 348763200.000000 +41.250000 -2.312500 -11.625000 348863200.000000 +40.562500 -2.750000 -11.125000 348963200.000000 +40.062500 -3.562500 -10.312500 349063200.000000 +39.687500 -4.562500 -10.125000 349163200.000000 +39.312500 -6.437500 -10.062500 349263200.000000 +38.375000 -8.937500 -9.687500 349363200.000000 +36.937500 -12.125000 -9.937500 349463200.000000 +35.187500 -15.500000 -10.000000 349563200.000000 +33.500000 -19.000000 -10.562500 349663200.000000 +31.875000 -22.812500 -11.250000 349763200.000000 +29.562500 -26.812500 -12.125000 349863200.000000 +26.937500 -30.625000 -12.812500 349963200.000000 +23.750000 -33.750000 -13.375000 350063200.000000 +20.875000 -36.375000 -14.125000 350163200.000000 +18.187500 -38.312500 -14.125000 350263200.000000 +15.875000 -40.062500 -14.437500 350363200.000000 +13.500000 -41.500000 -14.375000 350463200.000000 +11.250000 -42.687500 -14.625000 350563200.000000 +9.437500 -43.500000 -14.812500 350663200.000000 +8.000000 -44.000000 -14.812500 350763200.000000 +7.000000 -44.375000 -14.625000 350863200.000000 +5.375000 -44.375000 -14.625000 350963200.000000 +3.625000 -44.562500 -14.750000 351063200.000000 +1.250000 -44.375000 -14.625000 351163200.000000 +-1.875000 -43.625000 -14.812500 351263200.000000 +-6.125000 -42.000000 -14.750000 351363200.000000 +-10.812500 -39.375000 -14.937500 351463200.000000 +-16.000000 -36.500000 -14.937500 351563200.000000 +-21.062500 -33.437500 -15.000000 351663200.000000 +-25.375000 -30.437500 -14.937500 351763200.000000 +-29.312500 -27.250000 -14.937500 351863200.000000 +-32.500000 -24.437500 -15.250000 351963200.000000 +-34.500000 -22.125000 -15.125000 352063200.000000 +-35.312500 -20.375000 -15.312500 352163200.000000 +-35.750000 -19.125000 -15.187500 352263200.000000 +-36.125000 -17.562500 -15.187500 352363200.000000 +-36.562500 -15.812500 -15.500000 352463200.000000 +-36.875000 -13.187500 -15.437500 352563200.000000 +-37.125000 -9.500000 -15.437500 352663200.000000 +-37.250000 -5.312500 -15.062500 352763200.000000 +-37.187500 -1.187500 -14.937500 352863200.000000 +-37.062500 2.875000 -14.687500 352963200.000000 +-36.625000 6.375000 -14.687500 353063200.000000 +-36.062500 9.625000 -14.687500 353163200.000000 +-35.125000 13.750000 -14.125000 353263200.000000 +-33.562500 17.250000 -13.562500 353363200.000000 +-31.437500 20.250000 -13.000000 353463200.000000 +-28.187500 22.937500 -13.062500 353563200.000000 +-23.750000 25.937500 -13.125000 353663200.000000 +-18.312500 28.875000 -13.000000 353763200.000000 +-12.062500 31.437500 -12.625000 353863200.000000 +-4.687500 32.937500 -12.437500 353963200.000000 +3.625000 32.125000 -12.437500 354063200.000000 +11.875000 29.875000 -12.687500 354163200.000000 +19.375000 27.187500 -13.000000 354263200.000000 +25.500000 24.187500 -12.687500 354363200.000000 +30.500000 21.187500 -12.312500 354463200.000000 +33.500000 18.062500 -11.625000 354563200.000000 +35.875000 15.250000 -11.187500 354663200.000000 +37.437500 13.125000 -10.687500 354763200.000000 +37.500000 12.000000 -10.500000 354863200.000000 +37.500000 11.750000 -10.500000 354963200.000000 +37.750000 11.187500 -10.437500 355063200.000000 +37.875000 10.812500 -10.500000 355163200.000000 +38.250000 9.875000 -10.312500 355263200.000000 +39.187500 8.312500 -10.625000 355363200.000000 +39.500000 6.250000 -11.562500 355463200.000000 +39.750000 3.750000 -12.312500 355563200.000000 +40.187500 0.750000 -12.687500 355663200.000000 +39.687500 -2.312500 -12.875000 355763200.000000 +39.250000 -5.437500 -13.125000 355863200.000000 +38.875000 -8.437500 -13.125000 355963200.000000 +38.125000 -10.625000 -13.812500 356063200.000000 +37.250000 -12.375000 -14.500000 356163200.000000 +36.937500 -13.375000 -14.687500 356263200.000000 +36.375000 -13.687500 -15.437500 356363200.000000 +35.750000 -13.125000 -16.875000 356463200.000000 +35.187500 -12.125000 -18.125000 356563200.000000 +34.437500 -11.187500 -19.562500 356663200.000000 +33.375000 -10.500000 -21.250000 356763200.000000 +33.000000 -10.875000 -22.187500 356863200.000000 +32.437500 -11.375000 -22.625000 356963200.000000 +31.187500 -12.562500 -22.000000 357063200.000000 +30.187500 -14.187500 -21.500000 357163200.000000 +29.562500 -16.250000 -20.625000 357263200.000000 +29.437500 -18.000000 -20.000000 357363200.000000 +28.812500 -20.187500 -18.562500 357463200.000000 +28.312500 -22.312500 -16.812500 357563200.000000 +27.125000 -24.187500 -15.375000 357663200.000000 +25.937500 -26.125000 -14.250000 357763200.000000 +25.062500 -28.062500 -14.000000 357863200.000000 +23.187500 -30.062500 -12.875000 357963200.000000 +20.687500 -32.312500 -12.187500 358063200.000000 +17.250000 -34.875000 -11.250000 358163200.000000 +14.375000 -37.000000 -11.062500 358263200.000000 +11.437500 -38.687500 -10.687500 358363200.000000 +8.500000 -40.125000 -10.687500 358463200.000000 +5.812500 -41.250000 -10.625000 358563200.000000 +3.687500 -41.812500 -10.437500 358663200.000000 +2.500000 -42.187500 -11.000000 358763200.000000 +1.750000 -42.375000 -11.062500 358863200.000000 +1.750000 -42.562500 -11.187500 358963200.000000 +1.687500 -42.312500 -11.000000 359063200.000000 +1.500000 -42.375000 -11.062500 359163200.000000 +1.625000 -42.500000 -11.125000 359263200.000000 +1.937500 -42.625000 -11.125000 359363200.000000 +1.750000 -42.750000 -11.312500 359463200.000000 +1.500000 -42.625000 -10.937500 359563200.000000 +1.500000 -42.625000 -10.812500 359663200.000000 +1.437500 -42.500000 -10.750000 359763200.000000 +1.250000 -42.562500 -10.500000 359863200.000000 +1.250000 -42.500000 -10.500000 359963200.000000 +1.562500 -42.375000 -10.625000 360063200.000000 +1.937500 -42.437500 -10.937500 360163200.000000 +2.562500 -42.562500 -11.187500 360263200.000000 +2.812500 -42.625000 -11.437500 360363200.000000 +3.000000 -42.875000 -11.625000 360463200.000000 +3.375000 -43.062500 -11.750000 360563200.000000 +3.875000 -43.250000 -12.312500 360663200.000000 +4.500000 -43.625000 -12.562500 360763200.000000 +4.812500 -43.687500 -12.875000 360863200.000000 +4.812500 -43.562500 -13.125000 360963200.000000 +4.812500 -43.375000 -13.187500 361063200.000000 +5.187500 -43.562500 -13.562500 361163200.000000 +5.125000 -43.187500 -13.937500 361263200.000000 +5.125000 -42.812500 -14.375000 361363200.000000 +5.062500 -42.687500 -14.625000 361463200.000000 +5.125000 -42.375000 -15.125000 361563200.000000 +5.000000 -42.062500 -15.312500 361663200.000000 +4.875000 -42.062500 -15.437500 361763200.000000 +4.875000 -42.187500 -15.812500 361863200.000000 +4.750000 -41.937500 -15.937500 361963200.000000 +5.062500 -41.937500 -16.062500 362063200.000000 +5.187500 -41.875000 -16.125000 362163200.000000 +5.187500 -41.750000 -16.062500 362263200.000000 +5.000000 -41.812500 -16.062500 362363200.000000 +5.250000 -41.750000 -15.875000 362463200.000000 +5.250000 -41.812500 -15.875000 362563200.000000 +5.437500 -41.875000 -15.937500 362663200.000000 +5.500000 -42.062500 -15.875000 362763200.000000 +5.750000 -42.125000 -15.812500 362863200.000000 +5.562500 -42.375000 -15.937500 362963200.000000 +5.500000 -42.437500 -15.875000 363063200.000000 +5.562500 -42.750000 -15.687500 363163200.000000 +5.437500 -43.000000 -15.687500 363263200.000000 +5.562500 -43.062500 -15.562500 363363200.000000 +5.562500 -43.187500 -15.375000 363463200.000000 +5.437500 -43.062500 -15.500000 363563200.000000 +5.187500 -43.062500 -15.437500 363663200.000000 +5.312500 -43.000000 -15.312500 363763200.000000 +5.312500 -43.125000 -15.437500 363863200.000000 +5.500000 -43.062500 -15.812500 363963200.000000 +5.687500 -43.125000 -16.125000 364063200.000000 +5.687500 -42.937500 -16.312500 364163200.000000 +5.625000 -42.750000 -16.437500 364263200.000000 +5.875000 -42.812500 -16.125000 364363200.000000 +5.687500 -42.812500 -16.250000 364463200.000000 +5.625000 -42.875000 -16.312500 364563200.000000 +5.625000 -42.875000 -16.187500 364663200.000000 +5.562500 -42.812500 -16.000000 364763200.000000 +5.625000 -42.937500 -15.687500 364863200.000000 +5.500000 -42.875000 -15.625000 364963200.000000 +5.437500 -42.937500 -15.562500 365063200.000000 +5.187500 -42.750000 -15.750000 365163200.000000 +5.187500 -42.687500 -15.562500 365263200.000000 +4.812500 -42.500000 -15.187500 365363200.000000 +4.562500 -42.312500 -15.187500 365463200.000000 +4.062500 -42.187500 -15.000000 365563200.000000 +3.625000 -41.812500 -15.000000 365663200.000000 +3.375000 -41.875000 -14.937500 365763200.000000 +3.250000 -41.625000 -14.812500 365863200.000000 +3.062500 -41.625000 -14.625000 365963200.000000 +2.937500 -41.812500 -14.500000 366063200.000000 +2.937500 -41.937500 -14.500000 366163200.000000 +2.437500 -41.812500 -13.937500 366263200.000000 +2.000000 -41.625000 -13.687500 366363200.000000 +1.562500 -41.500000 -13.250000 366463200.000000 +1.062500 -41.437500 -12.750000 366563200.000000 +0.625000 -41.500000 -12.562500 366663200.000000 +0.250000 -41.375000 -12.000000 366763200.000000 +0.062500 -41.250000 -11.875000 366863200.000000 +0.125000 -41.000000 -11.875000 366963200.000000 +0.562500 -41.062500 -12.000000 367063200.000000 +0.937500 -41.125000 -12.250000 367163200.000000 +1.000000 -41.125000 -12.250000 367263200.000000 +1.375000 -41.125000 -12.312500 367363200.000000 +1.437500 -41.000000 -12.062500 367463200.000000 +1.875000 -41.250000 -12.375000 367563200.000000 +1.875000 -41.250000 -12.437500 367663200.000000 +1.750000 -41.000000 -12.250000 367763200.000000 +1.625000 -40.937500 -12.125000 367863200.000000 +1.687500 -40.937500 -11.937500 367963200.000000 +1.812500 -41.000000 -12.250000 368063200.000000 +1.687500 -40.812500 -12.500000 368163200.000000 +1.750000 -40.875000 -12.687500 368263200.000000 +1.437500 -40.500000 -12.625000 368363200.000000 +1.312500 -40.437500 -12.500000 368463200.000000 +1.500000 -40.687500 -12.625000 368563200.000000 +1.562500 -40.625000 -12.687500 368663200.000000 +1.625000 -40.812500 -12.750000 368763200.000000 +1.562500 -40.687500 -12.687500 368863200.000000 +1.625000 -40.687500 -12.687500 368963200.000000 +1.562500 -40.687500 -12.562500 369063200.000000 +1.750000 -40.687500 -12.687500 369163200.000000 +2.062500 -40.812500 -12.875000 369263200.000000 +1.750000 -41.000000 -12.875000 369363200.000000 +1.625000 -41.125000 -12.937500 369463200.000000 +1.500000 -41.062500 -12.875000 369563200.000000 +1.375000 -41.250000 -12.625000 369663200.000000 +1.500000 -41.500000 -12.437500 369763200.000000 +1.625000 -41.812500 -12.500000 369863200.000000 +1.500000 -42.000000 -12.500000 369963200.000000 +1.312500 -41.875000 -12.312500 370063200.000000 +1.375000 -41.687500 -12.187500 370163200.000000 +1.312500 -41.562500 -12.062500 370263200.000000 +1.375000 -41.500000 -12.062500 370363200.000000 +1.375000 -41.375000 -12.062500 370463200.000000 +1.125000 -41.125000 -12.062500 370563200.000000 +1.125000 -40.750000 -12.125000 370663200.000000 +1.187500 -40.750000 -11.875000 370763200.000000 +1.000000 -40.875000 -11.875000 370863200.000000 +1.062500 -40.875000 -12.000000 370963200.000000 +1.125000 -40.937500 -12.062500 371063200.000000 +0.937500 -40.875000 -12.187500 371163200.000000 +1.062500 -41.000000 -12.250000 371263200.000000 +1.312500 -41.125000 -12.312500 371363200.000000 +1.312500 -41.312500 -12.125000 371463200.000000 +1.500000 -41.250000 -12.437500 371563200.000000 +1.625000 -41.062500 -12.500000 371663200.000000 +1.562500 -41.125000 -12.562500 371763200.000000 +1.750000 -41.062500 -12.625000 371863200.000000 +2.125000 -41.250000 -12.875000 371963200.000000 +2.250000 -41.312500 -12.937500 372063200.000000 +2.312500 -41.375000 -13.125000 372163200.000000 +2.562500 -41.375000 -13.437500 372263200.000000 +2.500000 -41.437500 -13.437500 372363200.000000 +2.875000 -41.500000 -13.625000 372463200.000000 +2.812500 -41.312500 -13.625000 372563200.000000 diff --git a/src/sensor_fusion/design/data/100ms/yaw/accel.txt b/src/sensor_fusion/design/data/100ms/yaw/accel.txt new file mode 100755 index 0000000..79c3bb5 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/yaw/accel.txt @@ -0,0 +1,664 @@ +-0.050249 0.208176 10.199407 603085696.000000 +0.005982 0.211765 10.181459 603185664.000000 +-0.002393 0.212961 10.185050 603285632.000000 +-0.001196 0.204586 10.191031 603385536.000000 +0.007178 0.205783 10.201799 603485504.000000 +-0.031107 0.206979 10.150353 603587456.000000 +-0.027517 0.186640 10.197014 603685696.000000 +-0.011964 0.216550 10.201799 603785536.000000 +-0.003589 0.200997 10.175477 603885632.000000 +-0.010768 0.212961 10.164711 603985472.000000 +-0.020339 0.217747 10.206585 604085504.000000 +-0.022732 0.206979 10.192227 604185664.000000 +-0.015553 0.206979 10.222138 604285504.000000 +-0.007178 0.215354 10.191031 604385536.000000 +-0.031107 0.233300 10.174281 604485504.000000 +-0.039482 0.209372 10.163515 604585664.000000 +-0.017946 0.202193 10.202995 604685696.000000 +-0.027517 0.239282 10.211370 604785664.000000 +-0.004786 0.211765 10.200603 604885504.000000 +-0.004786 0.214158 10.213763 604985536.000000 +0.002393 0.226122 10.214959 605085632.000000 +-0.022732 0.232104 10.193424 605185536.000000 +-0.038285 0.196211 10.200603 605285504.000000 +-0.026321 0.185444 10.219746 605385600.000000 +-0.020339 0.195015 10.240085 605485504.000000 +0.009571 0.185444 10.187442 605585664.000000 +-0.016750 0.206979 10.164711 605685504.000000 +-0.011964 0.191426 10.161121 605785664.000000 +0.023928 0.205783 10.179067 605885760.000000 +-0.014357 0.209372 10.173084 605985536.000000 +0.004786 0.203390 10.199407 606085632.000000 +-0.015553 0.214158 10.207782 606185792.000000 +-0.002393 0.209372 10.214959 606285504.000000 +-0.025125 0.217747 10.252048 606385472.000000 +0.074178 0.217747 9.955338 606485504.000000 +-0.065803 0.199801 10.439885 606585472.000000 +-0.065803 0.191426 10.259227 606685824.000000 +-0.019143 0.197408 10.180264 606785664.000000 +0.057428 0.209372 10.004392 606885376.000000 +0.080160 0.228515 10.009177 606985600.000000 +-0.075374 0.206979 10.438687 607085376.000000 +-0.034696 0.221336 10.170692 607185664.000000 +0.002393 0.224925 10.199407 607285440.000000 +-0.019143 0.212961 10.205389 607385408.000000 +0.046660 0.221336 9.960124 607486208.000000 +-0.037089 0.229711 10.295119 607585408.000000 +-0.023928 0.196211 10.150353 607685504.000000 +-0.027517 0.204586 10.197014 607785664.000000 +0.002393 0.209372 10.191031 607885376.000000 +-0.017946 0.220140 10.176675 607985472.000000 +-0.007178 0.193819 10.169496 608085504.000000 +-0.029910 0.208176 10.169496 608185472.000000 +-0.010768 0.221336 10.228121 608285376.000000 +-0.022732 0.229711 10.242477 608385408.000000 +-0.007178 0.217747 10.204191 608485376.000000 +1.318445 0.017946 10.309477 608585472.000000 +0.114855 0.229711 9.952947 608685440.000000 +-0.224925 0.290728 10.080962 608785536.000000 +1.676172 -0.025125 10.158729 608885376.000000 +0.667598 0.125623 10.333405 608985536.000000 +-0.320638 -0.306281 10.402797 609085696.000000 +-0.668794 -0.095713 10.248460 609185600.000000 +-0.228515 0.373280 9.714860 609285504.000000 +-1.377069 0.607777 10.162319 609385664.000000 +-1.243071 -0.129212 10.365707 609485760.000000 +-1.081556 0.672383 10.447062 609585536.000000 +-0.488136 -0.028714 10.353743 609685504.000000 +-0.947558 0.143569 10.079765 609785472.000000 +-0.715454 -0.331406 10.591830 609885568.000000 +0.251246 -0.021535 10.412368 609985472.000000 +0.279960 -0.016750 11.069198 610085504.000000 +-0.684347 0.781257 10.819147 610185536.000000 +0.431904 1.033699 9.598808 610285632.000000 +1.752743 0.434297 9.917053 610385728.000000 +-0.798006 1.204786 9.766305 610485504.000000 +1.268196 0.457029 10.077373 610585472.000000 +-0.293121 0.187837 10.463813 610685760.000000 +0.461815 -0.449851 10.309477 610785536.000000 +-2.106880 -0.461815 9.732806 610885696.000000 +0.398405 0.118445 10.168301 610985472.000000 +0.350549 0.179462 10.202995 611085504.000000 +0.370888 0.193819 10.220942 611185664.000000 +0.374477 0.172283 10.204191 611285760.000000 +0.367298 0.159123 10.155140 611385536.000000 +0.390030 0.173480 10.241282 611485504.000000 +0.352941 0.168694 10.186246 611585472.000000 +0.367298 0.061017 10.132407 611685568.000000 +0.605384 0.080160 10.153944 611785472.000000 +0.689133 0.289532 10.341780 611885504.000000 +0.100499 -0.044267 11.188839 611985536.000000 +1.329213 -0.345763 10.206585 612085632.000000 +2.100898 -0.563510 10.033106 612185792.000000 +1.004985 -0.538385 9.997212 612285568.000000 +-1.420140 0.088534 10.238889 612385600.000000 +-1.104288 0.228515 10.147961 612485504.000000 +-0.705883 -0.041874 10.194620 612585536.000000 +-0.065803 -0.437887 9.894321 612685504.000000 +-0.009571 -0.346959 10.108479 612785536.000000 +-1.560120 0.062213 10.198210 612885568.000000 +0.242871 0.046660 10.265208 612985600.000000 +-1.312463 0.552742 10.202995 613085760.000000 +-0.151944 0.250050 10.241282 613185536.000000 +-0.094516 -0.174676 10.213763 613285632.000000 +-0.059821 -0.068195 10.195816 613385792.000000 +-0.291924 -0.062213 10.198210 613485504.000000 +0.066999 -0.154337 10.121639 613585664.000000 +0.669990 -0.259621 10.188639 613685888.000000 +0.202193 -0.098106 10.176675 613785536.000000 +0.038285 0.045464 10.317852 613885632.000000 +1.459622 -0.485743 9.773483 613985536.000000 +-1.916651 0.056231 10.208978 614085504.000000 +0.058624 -0.014357 10.182656 614185472.000000 +0.089731 -0.043071 10.204191 614285504.000000 +0.066999 -0.019143 10.208978 614385536.000000 +0.064606 -0.043071 10.216157 614485696.000000 +0.089731 -0.043071 10.191031 614585472.000000 +0.071785 -0.044267 10.159925 614685504.000000 +0.096909 -0.022732 10.175477 614785472.000000 +0.074178 -0.027517 10.180264 614885504.000000 +0.050249 -0.028714 10.176675 614985536.000000 +0.089731 -0.043071 10.249657 615085632.000000 +0.078963 -0.041874 10.213763 615185792.000000 +0.047856 -0.041874 10.191031 615285504.000000 +-0.588634 0.117248 10.189835 615385664.000000 +0.106481 -0.058624 10.193424 615485760.000000 +1.258625 -0.423530 10.110871 615585600.000000 +-0.958325 -0.906880 10.242477 615685504.000000 +-1.009771 -0.653241 10.252048 615785664.000000 +2.349752 -0.650848 9.840484 615885440.000000 +0.459422 -0.003589 9.844072 615985536.000000 +-1.374677 -0.242871 10.469796 616085632.000000 +0.265603 -0.454636 9.926624 616185792.000000 +0.720240 -0.167498 10.286745 616285504.000000 +2.458625 -0.234497 9.842876 616385600.000000 +0.897308 -0.271585 10.214959 616485760.000000 +1.911865 -0.474975 10.366903 616585536.000000 +1.028914 0.195015 10.067801 616685760.000000 +0.961915 -0.524028 10.327423 616785536.000000 +-0.474975 2.072184 10.490135 616885504.000000 +1.356731 -0.047856 10.165908 616985472.000000 +1.587638 -0.044267 10.027123 617085696.000000 +1.719243 -0.017946 10.088140 617185536.000000 +0.991825 0.128016 10.114462 617285632.000000 +1.013360 0.145962 10.130014 617385536.000000 +0.972682 0.142373 10.176675 617485568.000000 +0.964308 0.102891 10.113264 617585408.000000 +0.996611 0.174676 10.135997 617685504.000000 +0.965504 0.142373 10.134801 617785536.000000 +1.000200 0.145962 10.145569 617885504.000000 +1.000200 0.167498 10.139585 617985408.000000 +0.978664 0.154337 10.189835 618085440.000000 +0.957129 0.159123 10.149158 618185536.000000 +1.539781 -0.013161 10.078569 618285632.000000 +2.392823 -0.759721 10.068997 618385536.000000 +2.306681 0.397209 9.351151 618485568.000000 +1.525424 -0.281157 9.479167 618585536.000000 +-0.412762 0.709472 8.770891 618685504.000000 +2.080559 0.072981 9.358330 618785600.000000 +-1.429712 -0.259621 10.378868 618885440.000000 +0.512064 -0.235693 10.213763 618985536.000000 +0.478565 -0.211765 10.182656 619085696.000000 +0.502493 -0.189033 10.218549 619185472.000000 +0.446261 -0.227318 10.185050 619285568.000000 +0.653241 0.241675 10.163515 619385664.000000 +1.081556 -0.026321 10.198210 619485504.000000 +0.585045 0.147159 10.327423 619585536.000000 +-0.139980 -1.228714 10.382458 619685632.000000 +3.312863 -1.835295 10.435099 619785536.000000 +0.870987 -0.617348 10.071390 619885504.000000 +-1.280160 0.076570 10.106087 619985664.000000 +0.551546 -0.167498 10.380065 620085632.000000 +-0.075374 0.195015 10.119246 620185536.000000 +0.372084 -0.348156 9.994821 620285504.000000 +0.449851 -0.321835 9.754342 620385664.000000 +0.203390 -0.187837 9.999605 620485568.000000 +0.384048 -0.175872 10.089336 620585664.000000 +1.764707 -0.068195 10.141978 620685760.000000 +1.439283 -0.043071 9.873982 620785600.000000 +0.934397 -0.058624 9.978070 620885568.000000 +0.964308 0.187837 9.911072 620985664.000000 +0.129212 0.017946 10.262815 621085504.000000 +1.207179 0.077767 10.258030 621185728.000000 +1.214357 0.092124 10.021141 621285568.000000 +1.211965 0.082552 10.156336 621385664.000000 +1.229911 0.058624 10.132407 621485504.000000 +1.246661 0.101695 10.127622 621585536.000000 +1.221536 0.093320 10.109675 621685632.000000 +1.213161 0.075374 10.112068 621785536.000000 +1.207179 0.082552 10.127622 621885632.000000 +1.227518 0.064606 10.113264 621985728.000000 +1.245464 0.081356 10.108479 622085504.000000 +1.209572 0.072981 10.246067 622185664.000000 +1.977668 0.192622 10.176675 622285760.000000 +2.133201 0.421137 10.100104 622385536.000000 +1.511067 -0.534796 9.842876 622485696.000000 +1.076770 -0.571885 10.097712 622585472.000000 +2.260021 -0.333799 10.494920 622685696.000000 +2.876173 -0.308674 9.834501 622785664.000000 +2.493321 -0.916451 10.226924 622885760.000000 +1.045663 -1.777867 10.016356 622985536.000000 +-0.014357 -0.715454 10.487741 623085696.000000 +2.362912 -0.062213 9.967302 623185536.000000 +0.543171 -0.155533 10.134801 623285568.000000 +1.538585 -0.312263 9.912268 623385664.000000 +0.681954 -0.215354 10.230514 623485504.000000 +0.143569 -0.187837 10.204191 623585536.000000 +1.592424 0.289532 10.068997 623685504.000000 +0.356531 -0.133998 10.198210 623785472.000000 +-0.435494 0.217747 10.248460 623885568.000000 +2.171487 0.769292 9.893126 623985472.000000 +0.334995 -0.135194 11.675778 624085504.000000 +0.447458 0.522832 10.128819 624185664.000000 +0.390030 0.386441 10.189835 624285568.000000 +0.472582 0.422333 10.187442 624385472.000000 +0.435494 0.412762 10.213763 624485504.000000 +0.437887 0.425922 10.218549 624585600.000000 +0.445065 0.451047 10.185050 624685504.000000 +0.431904 0.411566 10.197014 624785536.000000 +0.404387 0.427119 10.195816 624885632.000000 +0.442672 0.452243 10.192227 624985728.000000 +0.430708 0.356531 10.248460 625085504.000000 +0.393619 0.620937 10.248460 625185664.000000 +0.972682 0.323031 10.033106 625285568.000000 +1.597209 0.373280 10.371690 625385536.000000 +0.436690 0.356531 9.997212 625485632.000000 +0.224925 0.403191 10.127622 625585792.000000 +0.649651 -0.163908 9.942179 625685696.000000 +-0.095713 -1.121037 10.146765 625785536.000000 +0.411566 -0.836291 10.157533 625885632.000000 +-2.791228 -0.513260 10.171888 625985536.000000 +-0.276371 -0.185444 10.249657 626085632.000000 +-1.960918 0.824327 10.314261 626185792.000000 +2.121237 0.049053 10.240085 626285504.000000 +-0.898505 -0.552742 10.194620 626385600.000000 +2.018346 -0.479761 10.595419 626485440.000000 +-0.751346 0.250050 10.205389 626585536.000000 +1.241875 0.110070 10.103694 626685504.000000 +1.238286 -0.031107 10.091729 626785600.000000 +0.760918 -0.112463 10.103694 626885504.000000 +-0.089731 0.180658 10.101300 626985664.000000 +-0.293121 -0.110070 10.268798 627085504.000000 +0.842274 -0.327817 9.869196 627185728.000000 +-0.232104 0.248854 10.399208 627285568.000000 +0.629312 -0.332602 10.212566 627385664.000000 +1.156930 0.057428 10.295119 627485504.000000 +-1.021735 -0.211765 10.683953 627585664.000000 +-0.005982 -0.052642 10.165908 627685760.000000 +-0.093320 0.205783 10.265208 627785536.000000 +0.028714 0.190229 10.234102 627885632.000000 +0.022732 0.241675 10.303494 627985728.000000 +0.008375 0.186640 10.236496 628085504.000000 +0.087338 0.343370 10.220942 628185664.000000 +-0.166301 0.227318 10.717452 628285504.000000 +0.077767 0.230907 10.027123 628385536.000000 +0.094516 0.185444 10.051051 628485632.000000 +0.029910 0.217747 10.217353 628585728.000000 +0.026321 0.199801 10.262815 628685696.000000 +0.093320 0.226122 10.064213 628785408.000000 +-0.051446 0.227318 10.435099 628885440.000000 +0.129212 0.204586 9.850054 628985408.000000 +0.066999 0.203390 10.177871 629085440.000000 +0.013161 0.202193 10.291530 629185472.000000 +0.021535 0.227318 10.218549 629285504.000000 +0.162712 0.217747 9.755538 629385856.000000 +0.029910 0.193819 10.163515 629485440.000000 +0.032303 0.203390 10.189835 629585344.000000 +0.025125 0.222532 10.224532 629685376.000000 +0.028714 0.232104 10.199407 629785344.000000 +0.039482 0.185444 10.273583 629886592.000000 +0.061017 0.199801 10.173084 629985344.000000 +0.053839 0.196211 10.228121 630085376.000000 +0.057428 0.179462 10.210175 630185408.000000 +0.038285 0.228515 10.226924 630285440.000000 +0.128016 0.238086 9.973285 630385472.000000 +0.056231 0.205783 10.200603 630485504.000000 +0.033500 0.206979 10.212566 630585472.000000 +0.043071 0.220140 10.151550 630685504.000000 +0.289532 0.190229 9.564112 630786688.000000 +0.177069 0.229711 9.736395 630885504.000000 +0.169890 0.192622 9.690931 630985536.000000 +-0.093320 0.190229 10.620543 631085568.000000 +0.028714 0.224925 10.168301 631185600.000000 +0.230907 0.205783 9.554541 631285440.000000 +-0.063410 0.224925 10.656436 631385536.000000 +0.050249 0.203390 10.259227 631485440.000000 +0.123230 0.216550 9.897911 631585920.000000 +0.309871 0.185444 10.731809 631685440.000000 +0.143569 0.197408 10.089336 631785408.000000 +0.272782 0.203390 9.527023 631885632.000000 +0.364905 0.190229 9.237493 631985792.000000 +0.155533 0.214158 9.798609 632085952.000000 +-0.130409 0.205783 11.198411 632185472.000000 +-0.266800 0.181855 11.339586 632285568.000000 +0.205783 0.208176 9.780663 632385600.000000 +0.212961 0.226122 9.689735 632485568.000000 +0.008375 0.199801 10.325029 632586816.000000 +-0.112463 0.218943 10.680364 632685440.000000 +0.106481 0.197408 9.972089 632785664.000000 +0.063410 0.203390 10.133603 632885632.000000 +-0.009571 0.226122 10.356135 632985984.000000 +0.066999 0.220140 10.414761 633085504.000000 +0.252443 0.204586 9.517452 633185664.000000 +-0.061017 0.200997 10.642079 633285568.000000 +-0.040678 0.208176 10.543973 633386048.000000 +0.061017 0.204586 10.240085 633485440.000000 +0.069392 0.210568 10.161121 633585664.000000 +0.028714 0.214158 10.220942 633685440.000000 +0.016750 0.234497 10.243673 633785984.000000 +-0.034696 0.232104 10.338191 633885376.000000 +-0.052642 0.209372 10.597812 633985408.000000 +0.082552 0.181855 10.072588 634085376.000000 +0.027517 0.227318 10.214959 634185600.000000 +0.026321 0.200997 10.228121 634285696.000000 +0.063410 0.226122 10.162319 634385920.000000 +-0.106481 0.208176 10.819147 634485440.000000 +0.117248 0.196211 9.937392 634585408.000000 +0.138784 0.169890 9.838090 634685696.000000 +-0.055035 0.208176 10.485349 634786176.000000 +-0.111266 0.216550 10.717452 634885440.000000 +0.038285 0.199801 10.222138 634986048.000000 +0.066999 0.198604 10.191031 635085440.000000 +0.057428 0.191426 10.220942 635185536.000000 +0.028714 0.230907 10.210175 635286016.000000 +0.094516 0.234497 10.016356 635385536.000000 +0.005982 0.198604 10.325029 635485568.000000 +0.038285 0.192622 10.137194 635585600.000000 +0.041874 0.230907 10.237692 635685568.000000 +0.242871 0.209372 9.580862 635785920.000000 +0.110070 0.190229 10.110871 635885440.000000 +-0.116052 0.204586 10.615757 635985536.000000 +0.096909 0.212961 10.018748 636086080.000000 +0.045464 0.218943 10.243673 636185792.000000 +0.037089 0.220140 10.253245 636285952.000000 +0.063410 0.197408 10.150353 636385600.000000 +-1.473979 0.410369 10.012767 636485632.000000 +-0.559920 0.368495 10.108479 636585536.000000 +0.589831 -0.232104 10.192227 636686080.000000 +-0.611366 -0.460618 10.187442 636785920.000000 +-0.772882 0.181855 10.248460 636886656.000000 +1.362713 -1.332802 10.274779 636986624.000000 +0.154337 -0.868595 10.491331 637086848.000000 +1.716850 -0.046660 9.544970 637186880.000000 +-0.095713 0.216550 10.620543 637286784.000000 +0.096909 0.185444 9.845268 637386688.000000 +-0.168694 0.214158 10.673186 637487232.000000 +-0.119641 0.223729 10.537991 637586688.000000 +-0.068195 0.223729 10.371690 637686784.000000 +0.031107 0.208176 10.065409 637787008.000000 +-2.510071 1.054038 10.497313 637886208.000000 +-0.148355 -0.147159 9.791430 637987456.000000 +-2.343770 0.908076 10.476974 638085952.000000 +-1.422533 -0.801596 10.067801 638186176.000000 +3.561716 -1.276571 10.345367 638285952.000000 +-0.332602 -0.056231 10.127622 638385984.000000 +1.099502 -0.349352 10.186246 638485888.000000 +-0.277567 0.299103 10.244871 638585984.000000 +-0.597009 0.247657 10.317852 638686400.000000 +0.604188 0.296710 10.120443 638787904.000000 +-0.837488 0.271585 10.108479 638886336.000000 +-0.299103 0.826720 10.307084 638987072.000000 +-0.281157 0.230907 10.176675 639087296.000000 +0.043071 -0.172283 10.188639 639186496.000000 +-0.744168 0.904487 11.164910 639286400.000000 +-0.098106 0.699901 10.607382 639386304.000000 +1.265803 0.625723 9.908678 639486080.000000 +-0.604188 1.354338 10.461421 639586176.000000 +-0.009571 -0.226122 8.950353 639686784.000000 +-2.327020 0.138784 10.120443 639785984.000000 +1.290928 -1.396212 9.080762 639885952.000000 +-2.453840 0.388834 7.959724 639985920.000000 +-1.280160 -0.138784 19.601404 640086016.000000 +0.437887 -1.915455 10.118051 640185984.000000 +-0.637687 -0.427119 10.165908 640285952.000000 +-0.631705 -0.418744 10.212566 640385984.000000 +-0.653241 -0.449851 10.164711 640486400.000000 +-0.640080 -0.440279 10.165908 640586176.000000 +-2.069792 -0.279960 10.500903 640686080.000000 +0.114855 -0.928415 9.939785 640785920.000000 +1.112662 -1.081556 10.181459 640886016.000000 +0.007178 -1.174876 10.599008 640985984.000000 +-0.153141 0.083749 9.859627 641085888.000000 +-1.568495 0.059821 9.930215 641185984.000000 +2.206182 -1.475175 10.219746 641285952.000000 +2.646462 -1.064806 7.957332 641385984.000000 +1.150948 -0.252443 10.162319 641486016.000000 +1.143769 -0.247657 10.134801 641586112.000000 +1.136591 -0.277567 10.135997 641686080.000000 +1.113859 -0.269193 10.185050 641785984.000000 +1.131805 -0.260818 10.133603 641886080.000000 +1.125823 -0.256032 10.159925 641985920.000000 +1.127020 -0.279960 10.168301 642086080.000000 +1.140180 -0.264407 10.169496 642186048.000000 +1.124627 -0.256032 10.155140 642285888.000000 +1.122234 -0.289532 10.144372 642386176.000000 +1.088734 -0.283549 10.146765 642485760.000000 +1.092324 -0.242871 10.162319 642585728.000000 +1.104288 -0.279960 10.157533 642685760.000000 +1.111466 -0.267996 10.146765 642785728.000000 +1.089931 -0.270389 10.143176 642885632.000000 +1.129412 -0.246461 10.131211 642985664.000000 +1.131805 -0.293121 10.153944 643085824.000000 +1.113859 -0.279960 10.144372 643185984.000000 +1.137787 -0.282353 10.157533 643285952.000000 +-0.518046 0.185444 10.133603 643386240.000000 +-0.294317 -0.056231 10.560723 643489088.000000 +1.083949 -1.549353 9.728020 643587840.000000 +3.312863 -2.595016 9.395418 643686848.000000 +2.364109 -1.847259 11.590833 643788608.000000 +2.864209 -0.397209 11.260624 643886464.000000 +1.160519 -0.595813 7.003791 643986944.000000 +1.106680 -0.267996 10.145569 644088960.000000 +1.100698 -0.278764 10.161121 644186048.000000 +1.414158 -0.826720 11.042876 644286912.000000 +1.168894 0.959522 10.565508 644388032.000000 +1.158126 -0.329013 10.199407 644486656.000000 +-4.057031 0.120838 9.257831 644586240.000000 +-3.339184 1.542174 9.561719 644687744.000000 +-0.037089 -0.971486 12.837494 644786688.000000 +-0.189033 -1.185644 10.741381 644886848.000000 +-1.220340 -0.870987 10.662418 644987072.000000 +-0.581456 0.221336 10.734202 645086784.000000 +-2.285146 1.002593 9.139386 645187008.000000 +-3.458825 2.522035 11.277373 645286912.000000 +-6.123233 -0.058624 7.994420 645386688.000000 +-2.895315 0.988236 8.965906 645486848.000000 +0.750150 -0.680758 8.410772 645586880.000000 +-0.337388 -1.652244 4.139583 645686848.000000 +0.010768 -0.266800 4.986642 645786624.000000 +-0.981057 0.147159 10.532009 645886912.000000 +-1.062413 0.300299 10.128819 645987584.000000 +-1.087538 0.267996 10.139585 646087040.000000 +-1.085145 0.290728 10.134801 646186624.000000 +-1.081556 0.281157 10.133603 646286464.000000 +-2.130809 0.501296 9.958927 646387264.000000 +-2.940779 0.129212 9.616754 646485824.000000 +-2.743371 -0.478565 9.517452 646585472.000000 +1.817349 -1.762314 9.584452 646685632.000000 +-1.165305 -0.038285 10.168301 646785600.000000 +0.531207 0.212961 10.654043 646885632.000000 +-0.734596 -0.620937 10.351351 646985984.000000 +0.195015 -0.799203 10.001998 647085760.000000 +1.746760 -1.409373 9.899107 647185792.000000 +1.154537 -0.597009 8.477771 647285760.000000 +1.276571 0.972682 9.288938 647385472.000000 +1.027717 0.052642 10.636096 647485568.000000 +1.121037 -0.177069 10.140782 647585600.000000 +1.127020 -0.192622 10.156336 647685696.000000 +1.127020 -0.165105 10.155140 647785856.000000 +1.125823 -0.175872 10.177871 647885504.000000 +1.116252 -0.180658 10.153944 647985472.000000 +1.113859 -0.178265 10.261620 648085504.000000 +1.128216 -0.183051 10.150353 648185472.000000 +1.119841 -0.203390 10.177871 648285376.000000 +1.110270 -0.171087 10.171888 648385600.000000 +1.104288 -0.197408 10.157533 648485632.000000 +1.123430 -0.186640 10.165908 648585536.000000 +1.111466 -0.169890 10.132407 648685376.000000 +1.107877 -0.183051 10.181459 648785664.000000 +1.144966 -0.190229 10.118051 648885568.000000 +1.116252 -0.192622 10.176675 648985408.000000 +1.133002 -0.162712 10.153944 649085504.000000 +1.137787 -0.205783 10.162319 649185856.000000 +-0.160319 -0.203390 9.968499 649285824.000000 +1.253839 -0.078963 10.108479 649385408.000000 +0.732204 -1.040878 10.165908 649485376.000000 +1.036092 -0.451047 10.121639 649585408.000000 +0.982254 -0.695115 8.927622 649685824.000000 +1.398605 -2.927619 8.889337 649785408.000000 +2.149951 -3.367898 8.443074 649885440.000000 +1.018146 -2.403590 8.133204 649985536.000000 +1.703690 -0.868595 9.464810 650085504.000000 +3.317649 0.563510 19.601404 650185472.000000 +1.942972 -0.521635 12.447463 650285504.000000 +-0.303888 0.247657 11.751152 650385472.000000 +-0.102891 0.256032 11.637493 650485568.000000 +-0.212961 0.313460 11.400602 650585472.000000 +-0.483350 0.226122 11.400602 650685504.000000 +-0.482154 0.253639 11.294124 650785536.000000 +-6.016753 3.019742 9.841680 650885568.000000 +2.433501 -0.484547 10.390833 650985600.000000 +-2.484946 -1.846063 9.784252 651085568.000000 +-3.232704 -1.020539 9.525827 651185408.000000 +2.725425 -1.740778 10.543973 651285696.000000 +0.279960 -0.263210 9.899107 651386752.000000 +-0.069392 0.248854 10.181459 651485376.000000 +-0.037089 0.239282 10.248460 651585472.000000 +-0.068195 0.238086 10.205389 651685696.000000 +0.641276 0.619741 9.695717 651785408.000000 +-1.286142 0.403191 10.135997 651885568.000000 +-0.630509 2.001596 10.132407 651985664.000000 +-0.708275 -0.582652 10.189835 652085632.000000 +-1.211965 0.234497 9.558130 652185536.000000 +-1.076770 0.184247 10.557133 652285632.000000 +-2.623730 1.113859 10.875379 652385472.000000 +0.740579 0.094516 10.234102 652485504.000000 +2.732604 -0.881755 9.724431 652585728.000000 +2.569891 -1.329213 9.890733 652685632.000000 +1.497907 -1.386641 9.652647 652785728.000000 +2.665605 -2.421536 9.115458 652886080.000000 +1.339981 -0.888934 10.791630 652985792.000000 +0.413958 -0.256032 10.476974 653085568.000000 +-1.134198 0.411566 10.235298 653185472.000000 +0.235693 -0.198604 10.297512 653285504.000000 +0.442672 -0.179462 10.255639 653385536.000000 +0.777667 -0.155533 10.241282 653485504.000000 +0.969093 -0.161516 10.275976 653585472.000000 +1.037289 -0.163908 10.254441 653685504.000000 +1.085145 -0.142373 10.230514 653785472.000000 +1.081556 -0.137587 10.218549 653885376.000000 +0.458226 -0.195015 11.249856 653985408.000000 +0.917647 -0.234497 10.224532 654085376.000000 +0.829113 -0.160319 10.326227 654185728.000000 +0.961915 -0.144766 10.277173 654285632.000000 +1.038485 -0.175872 10.284351 654385600.000000 +1.165305 -0.137587 9.951750 654486080.000000 +1.119841 -0.125623 9.929017 654585472.000000 +0.784846 -0.123230 10.049855 654685440.000000 +0.009571 -0.192622 10.487741 654785408.000000 +1.846063 -0.171087 10.287941 654885632.000000 +0.637687 -0.190229 10.293922 654985408.000000 +0.764507 -0.161516 10.277173 655085376.000000 +1.013360 -0.203390 10.211370 655185408.000000 +1.021735 -0.183051 10.232906 655285376.000000 +1.118645 -0.124427 10.291530 655385408.000000 +1.087538 -0.142373 10.127622 655485568.000000 +1.122234 -0.135194 10.171888 655585600.000000 +1.122234 -0.151944 10.153944 655685440.000000 +1.100698 -0.119641 10.219746 655785536.000000 +1.130609 -0.141177 10.152746 655885376.000000 +1.075574 -0.153141 10.150353 655985472.000000 +1.093520 -0.135194 10.179067 656085504.000000 +1.116252 -0.104088 10.191031 656185536.000000 +1.070788 -0.116052 10.135997 656285568.000000 +1.131805 -0.180658 10.174281 656385664.000000 +1.135394 -0.113659 10.139585 656485760.000000 +1.097109 -0.149551 10.168301 656585664.000000 +1.104288 -0.138784 10.199407 656685824.000000 +1.435694 -0.732204 10.134801 656785728.000000 +0.996611 -0.216550 10.149158 656886592.000000 +1.109073 -0.089731 10.210175 656986560.000000 +0.905683 -0.033500 10.217353 657086464.000000 +1.080359 -0.309871 10.164711 657186624.000000 +1.221536 -0.072981 10.194620 657286592.000000 +0.865005 0.057428 10.242477 657386560.000000 +1.149751 -0.239282 10.173084 657486144.000000 +1.325624 -0.397209 9.962516 657586560.000000 +-0.138784 -0.873380 10.351351 657686592.000000 +1.091127 -0.218943 10.128819 657786496.000000 +1.009771 0.068195 11.473583 657886592.000000 +0.802792 0.092124 9.113065 657986560.000000 +-0.011964 0.216550 10.366903 658086400.000000 +-0.008375 0.224925 10.232906 658186560.000000 +0.038285 0.232104 10.121639 658286336.000000 +0.038285 0.217747 10.139585 658386496.000000 +-0.026321 0.220140 10.274779 658486848.000000 +-0.008375 0.185444 10.248460 658586496.000000 +0.013161 0.196211 10.236496 658686464.000000 +-0.004786 0.228515 10.216157 658786560.000000 +0.013161 0.196211 10.222138 658886784.000000 +0.013161 0.218943 10.234102 658986624.000000 +-0.955933 0.269193 11.392227 659085952.000000 +-0.118445 0.241675 11.040483 659186048.000000 +0.044267 0.211765 10.146765 659286400.000000 +-0.120838 0.215354 10.725827 659387264.000000 +0.046660 0.204586 10.061819 659486336.000000 +0.056231 0.214158 10.132407 659585984.000000 +0.108873 0.228515 9.823733 659686400.000000 +0.063410 0.212961 9.986445 659785920.000000 +-0.013161 0.210568 10.272388 659886080.000000 +0.404387 0.239282 8.986245 659985792.000000 +-0.260818 0.216550 11.094322 660086144.000000 +0.075374 0.214158 10.055838 660186048.000000 +0.110070 0.221336 9.824929 660286016.000000 +-0.107677 0.247657 11.114661 660385728.000000 +-0.643669 0.218943 11.389835 660486144.000000 +-0.585045 0.244068 11.423335 660585984.000000 +-0.477368 0.247657 11.401800 660686208.000000 +-0.241675 0.246461 11.471190 660786176.000000 +0.366102 0.138784 10.756934 660885824.000000 +-0.427119 0.262014 11.485549 660985728.000000 +-0.251246 0.279960 11.753544 661086912.000000 +-0.358923 0.227318 11.370694 661186624.000000 +-0.482154 0.218943 11.272588 661285824.000000 +-0.786042 0.228515 12.003594 661385920.000000 +-0.717847 0.253639 11.680564 661486080.000000 +-0.729811 0.253639 11.290534 661587200.000000 +-0.611366 0.241675 11.454442 661685888.000000 +-0.510868 0.223729 11.345569 661786560.000000 +-0.650848 0.247657 11.557333 661885824.000000 +-0.587438 0.238086 11.383853 661985920.000000 +-0.531207 0.230907 11.344372 662085632.000000 +-0.492921 0.192622 11.355140 662185664.000000 +0.071785 0.265603 10.189835 662285760.000000 +0.358923 0.206979 9.239884 662386112.000000 +0.071785 0.187837 10.064213 662486400.000000 +-0.171087 0.204586 10.858629 662586560.000000 +-0.082552 0.200997 10.523634 662686016.000000 +0.118445 0.212961 10.036695 662791488.000000 +0.025125 0.199801 10.114462 662890944.000000 +-0.033500 0.220140 10.399208 662991168.000000 +-0.014357 0.224925 10.255639 663091584.000000 +0.069392 0.186640 10.120443 663191168.000000 +-0.040678 0.211765 10.384850 663291584.000000 +-0.009571 0.215354 10.195816 663391936.000000 +0.096909 0.197408 9.468399 663491648.000000 +0.037089 0.221336 10.195816 663591168.000000 +0.053839 0.210568 10.157533 663691136.000000 +0.049053 0.185444 10.021141 663792192.000000 +-0.025125 0.184247 10.321441 663891328.000000 +0.070588 0.200997 10.028319 663990848.000000 +0.031107 0.187837 10.128819 664091200.000000 +0.023928 0.224925 10.171888 664191296.000000 +0.005982 0.223729 10.187442 664293248.000000 +-0.038285 0.180658 10.399208 664390720.000000 +0.111266 0.198604 9.994821 664490752.000000 +0.039482 0.228515 10.264012 664591168.000000 +0.053839 0.221336 10.066606 664691456.000000 +0.156730 0.198604 9.755538 664790656.000000 +0.117248 0.189033 10.028319 664892544.000000 +-0.106481 0.203390 10.624132 664990976.000000 +-0.047856 0.206979 10.407581 665092736.000000 +0.023928 0.198604 10.174281 665192448.000000 +0.033500 0.202193 10.281959 665290944.000000 +0.029910 0.217747 10.146765 665391424.000000 +-0.043071 0.199801 10.427922 665492928.000000 +0.010768 0.229711 10.156336 665591232.000000 +0.046660 0.222532 10.141978 665692608.000000 +0.098106 0.215354 10.035499 665791104.000000 +0.057428 0.222532 10.024731 665891392.000000 +-0.179462 0.200997 10.875379 665992640.000000 +0.099302 0.203390 9.844072 666091136.000000 +-0.013161 0.228515 10.335798 666191040.000000 +-0.119641 0.190229 10.735399 666292416.000000 +0.016750 0.192622 10.325029 666391872.000000 +-0.046660 0.218943 10.319048 666492992.000000 +0.014357 0.208176 10.161121 666592384.000000 +-0.005982 0.217747 10.213763 666691712.000000 +0.003589 0.183051 10.249657 666792576.000000 +0.007178 0.199801 10.255639 666892224.000000 +0.004786 0.234497 10.247264 666993984.000000 +0.015553 0.200997 10.264012 667092352.000000 +0.026321 0.200997 10.183852 667191872.000000 +-0.013161 0.220140 10.225728 667292288.000000 +-0.004786 0.203390 10.208978 667391744.000000 +0.011964 0.199801 10.222138 667491712.000000 +-0.016750 0.206979 10.280763 667591232.000000 +-0.004786 0.208176 10.275976 667693440.000000 +-0.004786 0.204586 10.262815 667791872.000000 +-0.003589 0.229711 10.236496 667891392.000000 +-0.015553 0.203390 10.271191 667992320.000000 +0.020339 0.212961 10.216157 668091968.000000 +0.001196 0.189033 10.229317 668191744.000000 +0.005982 0.215354 10.208978 668291904.000000 +0.005982 0.204586 10.260423 668391936.000000 +0.005982 0.222532 10.198210 668491584.000000 +0.033500 0.223729 10.206585 668592128.000000 +-0.027517 0.224925 10.231709 668692096.000000 +0.017946 0.209372 10.189835 668792000.000000 +0.004786 0.230907 10.202995 668891200.000000 +0.001196 0.208176 10.268798 668991680.000000 +-0.007178 0.236889 10.205389 669092160.000000 +-0.015553 0.202193 10.273583 669192320.000000 +0.015553 0.222532 10.212566 669292288.000000 +-0.035892 0.229711 10.259227 669391296.000000 diff --git a/src/sensor_fusion/design/data/100ms/yaw/gyro.txt b/src/sensor_fusion/design/data/100ms/yaw/gyro.txt new file mode 100755 index 0000000..7a02ad1 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/yaw/gyro.txt @@ -0,0 +1,664 @@ +1.890000 0.472500 -0.472500 603086592.000000 +-2.747500 0.962500 -14.805000 603186432.000000 +-5.145000 0.262500 2.257500 603286272.000000 +-5.127500 0.297500 2.240000 603386176.000000 +-5.162500 0.262500 2.257500 603486528.000000 +-5.197500 0.262500 2.240000 603588032.000000 +-5.162500 0.262500 2.257500 603686336.000000 +-5.197500 0.297500 2.275000 603786240.000000 +-5.215000 0.262500 2.240000 603886208.000000 +-5.180000 0.262500 2.257500 603986048.000000 +-5.145000 0.262500 2.257500 604086208.000000 +-5.215000 0.297500 2.257500 604186240.000000 +-5.215000 0.297500 2.257500 604286080.000000 +-5.215000 0.262500 2.275000 604386304.000000 +-5.180000 0.297500 2.292500 604486080.000000 +-5.197500 0.332500 2.257500 604586432.000000 +-5.180000 0.332500 2.275000 604686720.000000 +-5.197500 0.332500 2.275000 604786304.000000 +-5.215000 0.297500 2.292500 604886144.000000 +-5.232500 0.297500 2.275000 604986688.000000 +-5.215000 0.297500 2.275000 605086272.000000 +-5.215000 0.297500 2.240000 605186176.000000 +-5.232500 0.262500 2.310000 605286528.000000 +-5.215000 0.262500 2.275000 605386240.000000 +-5.215000 0.262500 2.275000 605486144.000000 +-5.215000 0.297500 2.292500 605586240.000000 +-5.232500 0.262500 2.257500 605686528.000000 +-5.232500 0.297500 2.275000 605786240.000000 +-5.232500 0.262500 2.257500 605886592.000000 +-5.215000 0.297500 2.310000 605987072.000000 +-5.215000 0.297500 2.257500 606086336.000000 +-5.232500 0.297500 2.292500 606186368.000000 +-5.197500 0.297500 2.257500 606286400.000000 +-5.197500 -0.367500 2.292500 606385984.000000 +-5.267500 -1.382500 2.310000 606485824.000000 +-5.250000 2.012500 2.275000 606585792.000000 +-5.250000 1.207500 2.257500 606686208.000000 +-5.232500 -0.087500 2.292500 606786240.000000 +-5.250000 0.437500 2.275000 606885760.000000 +-5.197500 -2.047500 2.327500 606986112.000000 +-5.267500 2.467500 2.222500 607085888.000000 +-5.232500 0.507500 2.257500 607186240.000000 +-5.250000 0.157500 2.275000 607285888.000000 +-5.232500 0.367500 2.257500 607386112.000000 +-5.250000 1.662500 2.275000 607486592.000000 +-5.232500 -0.472500 2.292500 607585920.000000 +-5.250000 -0.262500 2.310000 607685888.000000 +-5.267500 0.472500 2.257500 607786240.000000 +-5.285000 0.262500 2.257500 607886144.000000 +-5.250000 0.332500 2.257500 607986432.000000 +-5.320000 0.262500 2.257500 608086464.000000 +-5.285000 0.297500 2.222500 608186112.000000 +-5.285000 0.297500 2.275000 608286016.000000 +-5.250000 0.262500 2.240000 608385984.000000 +-5.250000 0.297500 2.257500 608485952.000000 +-5.215000 -2.292500 1.890000 608585984.000000 +-5.197500 -0.857500 -7.315000 608685952.000000 +-5.075000 -11.497500 -0.857500 608786048.000000 +-5.320000 5.372500 -4.410000 608885696.000000 +-5.162500 3.272500 -69.072502 608985920.000000 +-4.480000 0.052500 -118.720001 609086272.000000 +-4.497500 -5.827500 -139.125000 609186176.000000 +-5.582500 -6.772500 -150.115005 609286144.000000 +-5.670000 1.487500 -129.500000 609386240.000000 +-5.355000 0.577500 -96.285004 609486336.000000 +-5.582500 -0.647500 -95.077499 609586368.000000 +-5.162500 4.042500 -86.730003 609686080.000000 +-2.712500 7.157500 -120.942497 609786112.000000 +-4.165000 -6.562500 -117.004997 609886272.000000 +-0.420000 -0.682500 -111.492500 609986112.000000 +2.047500 -6.807500 -139.089996 610086080.000000 +14.367500 -16.327499 -78.574997 610186240.000000 +24.570000 4.042500 -48.195000 610286208.000000 +4.410000 4.602500 -56.279999 610386368.000000 +-16.432501 -18.777500 -129.255005 610486336.000000 +-36.470001 -17.762501 -55.930000 610586240.000000 +-5.337500 -11.077500 -91.472504 610686336.000000 +-16.764999 10.237500 -91.472504 610786368.000000 +-8.102500 -5.617500 -104.720001 610886272.000000 +-5.460000 -2.852500 -10.552500 610985984.000000 +-5.250000 0.157500 2.380000 611086208.000000 +-5.267500 0.227500 2.292500 611186240.000000 +-5.302500 0.262500 2.275000 611286336.000000 +-5.267500 0.297500 2.292500 611386368.000000 +-5.302500 0.262500 2.275000 611486080.000000 +-5.285000 0.262500 2.257500 611586048.000000 +-5.232500 0.297500 2.275000 611686272.000000 +-5.267500 0.717500 1.785000 611786112.000000 +-6.020000 0.927500 -41.650002 611886080.000000 +-7.927500 1.872500 -77.805000 611986624.000000 +-7.962500 2.397500 -90.667503 612086400.000000 +-10.622500 4.847500 -105.840004 612186432.000000 +-11.375000 16.467501 -163.869995 612286528.000000 +-2.170000 6.002500 -199.097504 612386240.000000 +-2.397500 3.797500 -156.677505 612486272.000000 +-3.290000 2.537500 -102.025002 612586560.000000 +-2.747500 2.712500 -120.889999 612686080.000000 +-2.152500 2.222500 -154.770004 612786112.000000 +-3.027500 10.342500 -152.582504 612886528.000000 +-1.312500 -6.527500 -92.504997 612986240.000000 +-3.360000 -0.402500 -87.132500 613086592.000000 +-4.357500 -1.767500 -40.005001 613186624.000000 +-4.620000 0.437500 -38.027500 613286208.000000 +-4.970000 1.242500 -28.892500 613386624.000000 +-4.970000 1.487500 -28.962500 613486656.000000 +-4.917500 0.017500 -14.525000 613586368.000000 +-4.935000 -0.262500 -17.955000 613686720.000000 +-4.690000 -2.152500 -35.980000 613786624.000000 +-5.110000 -0.157500 -23.817499 613886208.000000 +-5.022500 -1.417500 -37.939999 613985984.000000 +-4.637500 5.582500 -98.087502 614086528.000000 +-5.215000 0.367500 -5.355000 614186112.000000 +-5.250000 0.297500 2.275000 614286080.000000 +-5.232500 0.262500 2.292500 614386304.000000 +-5.302500 0.262500 2.292500 614486272.000000 +-5.250000 0.297500 2.292500 614586048.000000 +-5.267500 0.262500 2.292500 614686208.000000 +-5.250000 0.192500 2.292500 614786048.000000 +-5.232500 0.192500 2.327500 614886080.000000 +-5.285000 0.402500 2.292500 614986240.000000 +-5.250000 0.297500 2.292500 615086336.000000 +-5.267500 0.297500 2.327500 615186368.000000 +-5.285000 0.297500 2.275000 615286400.000000 +-5.267500 0.332500 2.380000 615386304.000000 +-5.232500 1.172500 -13.072500 615486400.000000 +-4.427500 2.047500 -89.162498 615586240.000000 +-3.587500 0.192500 -172.585007 615686336.000000 +-5.110000 -15.662500 -180.949997 615786240.000000 +-7.752500 -21.437500 -138.162506 615886016.000000 +-13.510000 8.207500 -155.259995 615986240.000000 +-12.040000 1.417500 -156.817505 616086208.000000 +-9.660000 -11.777500 -102.970001 616186432.000000 +-12.075000 -8.102500 -109.497498 616286336.000000 +-12.302500 -2.677500 -92.995003 616386240.000000 +-15.557500 0.612500 -127.557503 616486336.000000 +-14.857500 -0.927500 -117.162498 616586496.000000 +-17.815001 1.032500 -152.985001 616686336.000000 +-16.957500 2.047500 -152.634995 616786048.000000 +-16.362499 -1.767500 -149.292496 616886208.000000 +-8.907500 -3.552500 -22.504999 616986112.000000 +0.560000 0.157500 66.097504 617086272.000000 +1.382500 0.822500 85.102501 617186240.000000 +-2.905000 0.682500 32.742500 617286272.000000 +-5.302500 0.332500 2.310000 617386176.000000 +-5.267500 0.262500 2.310000 617486528.000000 +-5.285000 0.297500 2.292500 617585792.000000 +-5.232500 0.332500 2.310000 617685888.000000 +-5.250000 0.262500 2.327500 617785920.000000 +-5.285000 0.297500 2.310000 617886080.000000 +-5.285000 0.262500 2.310000 617986432.000000 +-5.285000 0.262500 2.345000 618085952.000000 +-5.250000 0.297500 2.327500 618186176.000000 +-5.320000 0.332500 2.117500 618286272.000000 +-18.917500 1.207500 -170.029999 618386176.000000 +-1.977500 -0.962500 -180.862503 618486400.000000 +-22.750000 6.597500 -194.634995 618587520.000000 +-12.267500 -5.547500 -113.102501 618686528.000000 +-49.314999 22.347500 -94.167503 618786176.000000 +-12.005000 2.642500 -106.732498 618886080.000000 +-5.687500 0.542500 -5.687500 618986240.000000 +-5.145000 -0.017500 1.522500 619086272.000000 +-5.320000 0.472500 2.992500 619186048.000000 +-5.250000 0.262500 2.590000 619286272.000000 +-5.040000 -0.262500 9.922500 619386304.000000 +-5.267500 -1.592500 4.060000 619486144.000000 +-7.805000 3.657500 -76.072502 619586752.000000 +-10.062500 3.412500 -133.227493 619686272.000000 +-13.370000 14.997500 -144.619995 619786176.000000 +-10.115000 4.392500 -158.112503 619886528.000000 +-8.207500 1.627500 -120.417503 619986240.000000 +-9.957500 7.612500 -93.467499 620086272.000000 +-10.185000 14.472500 -77.419998 620186560.000000 +-9.852500 22.522501 -64.154999 620286144.000000 +3.080000 -11.322500 -106.190002 620386304.000000 +2.765000 -28.052500 -97.264999 620486592.000000 +-4.427500 -13.632500 -59.605000 620586304.000000 +-5.617500 -5.022500 -30.362499 620686592.000000 +-8.382500 -5.792500 -65.957497 620786240.000000 +-12.407500 -0.892500 -86.029999 620886592.000000 +-9.730000 -2.817500 -64.732498 620986240.000000 +-13.475000 0.367500 -68.932503 621086464.000000 +-5.302500 -1.662500 0.927500 621186688.000000 +-4.935000 -0.192500 2.572500 621286144.000000 +-5.250000 0.262500 2.537500 621386496.000000 +-5.250000 0.227500 2.432500 621486656.000000 +-5.250000 0.262500 2.397500 621586112.000000 +-5.250000 0.262500 2.380000 621686400.000000 +-5.232500 0.262500 2.345000 621786624.000000 +-5.250000 0.262500 2.345000 621886272.000000 +-5.267500 0.262500 2.327500 621986688.000000 +-5.267500 0.262500 2.310000 622086656.000000 +-5.757500 0.717500 2.292500 622186240.000000 +-5.845000 0.822500 0.840000 622286592.000000 +-9.940000 2.187500 -29.032499 622386688.000000 +-19.320000 7.787500 -89.040001 622486272.000000 +-20.440001 2.152500 -154.664993 622586432.000000 +-21.385000 1.977500 -161.735001 622686720.000000 +-22.295000 2.117500 -167.335007 622786240.000000 +-26.985001 2.957500 -216.317505 622886592.000000 +-29.452499 2.887500 -246.837494 622987072.000000 +-26.267500 2.467500 -213.990005 623086272.000000 +-16.292500 1.837500 -122.342499 623186112.000000 +-19.635000 3.202500 -144.479996 623286592.000000 +-12.915000 5.022500 -126.349998 623386304.000000 +-11.672500 4.217500 -110.145004 623486144.000000 +-13.107500 4.112500 -97.422501 623586560.000000 +-10.937500 1.802500 -87.937500 623686080.000000 +-5.985000 2.362500 -68.862503 623786112.000000 +5.460000 18.217501 -73.150002 623886272.000000 +-4.305000 9.292500 -54.355000 623986112.000000 +-20.615000 1.942500 -104.527504 624086208.000000 +2.572500 -6.702500 6.895000 624186688.000000 +-5.985000 -0.787500 1.137500 624286144.000000 +-4.987500 0.542500 3.185000 624386368.000000 +-5.390000 0.227500 2.012500 624486528.000000 +-5.232500 0.367500 2.380000 624586240.000000 +-5.302500 0.297500 2.257500 624686336.000000 +-5.267500 0.297500 2.275000 624786560.000000 +-5.250000 0.332500 2.292500 624886208.000000 +-5.267500 0.297500 2.275000 624986624.000000 +-5.635000 0.647500 2.012500 625086656.000000 +-5.582500 -0.472500 6.107500 625186240.000000 +-6.825000 -1.487500 3.517500 625286336.000000 +-9.677500 -4.427500 -14.525000 625386560.000000 +-10.185000 5.267500 -38.727501 625486208.000000 +-9.327500 5.897500 -56.227501 625586752.000000 +-15.557500 10.202500 -64.925003 625686400.000000 +-13.562500 7.787500 -93.660004 625786112.000000 +-3.832500 1.977500 -151.252502 625886272.000000 +-4.690000 1.802500 -140.175003 625986368.000000 +-9.590000 12.687500 -52.674999 626086208.000000 +-7.787500 11.672500 -42.752499 626186432.000000 +-4.515000 2.572500 -30.135000 626286656.000000 +8.417500 -17.867500 -98.245003 626386240.000000 +-3.570000 -10.552500 -23.397501 626486272.000000 +-6.212500 -23.327499 -93.099998 626586560.000000 +-7.682500 -3.692500 -63.892502 626686080.000000 +-10.745000 0.052500 -88.847504 626786432.000000 +-10.692500 2.082500 -105.489998 626886656.000000 +-11.252500 1.592500 -114.345001 626986304.000000 +-9.397500 3.482500 -89.582497 627086208.000000 +-6.965000 0.542500 -37.974998 627186752.000000 +-8.190000 6.877500 -50.172501 627286336.000000 +-8.400000 2.957500 -29.557501 627386496.000000 +-8.190000 -1.172500 -26.827499 627486656.000000 +-3.832500 37.397499 -122.220001 627586240.000000 +2.800000 -3.132500 -6.107500 627686592.000000 +-5.145000 1.522500 -3.990000 627786688.000000 +-5.127500 1.137500 2.205000 627886208.000000 +-5.250000 -1.172500 2.292500 627986688.000000 +-5.110000 1.277500 -8.382500 628086656.000000 +-4.987500 0.822500 -17.762501 628186240.000000 +-5.232500 0.332500 -4.427500 628286336.000000 +-5.250000 -2.537500 2.345000 628386560.000000 +-5.250000 -1.312500 2.327500 628486272.000000 +-5.267500 1.277500 2.275000 628586688.000000 +-5.215000 0.892500 2.240000 628686848.000000 +-5.197500 0.227500 2.345000 628785920.000000 +-5.337500 2.642500 2.257500 628885824.000000 +-5.250000 -3.272500 2.345000 628985856.000000 +-5.232500 0.647500 2.292500 629086144.000000 +-5.285000 1.312500 2.222500 629185792.000000 +-5.232500 0.192500 2.240000 629285888.000000 +-5.180000 -2.817500 2.327500 629386368.000000 +-5.320000 2.852500 2.205000 629485824.000000 +-5.267500 0.577500 2.240000 629585728.000000 +-5.215000 0.367500 2.240000 629685696.000000 +-5.250000 0.297500 2.257500 629785664.000000 +-5.267500 0.472500 2.257500 629887488.000000 +-5.285000 -0.017500 2.240000 629985664.000000 +-5.285000 0.262500 2.257500 630085824.000000 +-5.267500 0.402500 2.240000 630185728.000000 +-5.267500 0.227500 2.257500 630285888.000000 +-5.285000 -0.647500 2.275000 630385920.000000 +-5.267500 0.752500 2.205000 630486144.000000 +-5.302500 0.962500 2.205000 630586112.000000 +-5.232500 -0.157500 2.257500 630686144.000000 +-5.145000 -2.012500 2.345000 630788416.000000 +-5.337500 2.362500 2.257500 630885824.000000 +-5.215000 -3.237500 2.327500 630986304.000000 +-5.355000 5.792500 2.152500 631086272.000000 +-5.285000 -0.612500 2.275000 631186368.000000 +-5.197500 -4.847500 2.362500 631285760.000000 +-5.407500 5.757500 2.152500 631386496.000000 +-5.302500 0.542500 2.222500 631485952.000000 +-5.267500 -2.397500 2.310000 631586368.000000 +-5.145000 -9.257500 3.465000 631685760.000000 +-5.495000 14.612500 2.030000 631785664.000000 +-5.285000 -4.182500 2.362500 631886080.000000 +-5.267500 -5.197500 2.345000 631986816.000000 +-5.390000 3.412500 2.240000 632087168.000000 +-5.320000 2.222500 2.205000 632185856.000000 +-5.337500 7.542500 2.117500 632286016.000000 +-5.302500 -6.107500 2.380000 632386048.000000 +-5.232500 -2.992500 2.292500 632485888.000000 +-5.320000 2.712500 2.222500 632587264.000000 +-5.372500 4.812500 2.170000 632686016.000000 +-5.320000 -2.607500 2.292500 632788352.000000 +-5.320000 -0.647500 2.240000 632886976.000000 +-5.337500 2.292500 2.170000 632986560.000000 +-5.250000 -4.812500 2.327500 633087040.000000 +-5.390000 2.117500 2.222500 633186880.000000 +-5.407500 6.492500 2.135000 633286848.000000 +-5.390000 3.097500 2.187500 633387136.000000 +-5.180000 -6.632500 2.432500 633486080.000000 +-5.407500 4.112500 2.170000 633586816.000000 +-5.337500 -0.087500 2.257500 633686080.000000 +-5.337500 0.787500 2.222500 633786688.000000 +-5.337500 4.427500 2.222500 633885888.000000 +-5.390000 -1.942500 2.380000 633985984.000000 +-5.320000 -1.627500 2.257500 634086272.000000 +-5.355000 -0.157500 2.222500 634186880.000000 +-5.355000 1.312500 2.222500 634286656.000000 +-5.320000 -0.472500 2.257500 634386944.000000 +-5.442500 1.312500 2.222500 634486144.000000 +-5.355000 0.122500 2.275000 634586304.000000 +-5.320000 -2.607500 2.292500 634686912.000000 +-5.425000 3.762500 2.170000 634787328.000000 +-5.302500 3.657500 2.187500 634886208.000000 +-5.355000 -4.042500 2.310000 634986688.000000 +-5.355000 0.122500 2.240000 635086080.000000 +-5.355000 0.367500 2.222500 635186496.000000 +-5.355000 0.332500 2.240000 635286976.000000 +-5.355000 -0.262500 2.257500 635386048.000000 +-5.372500 1.347500 2.187500 635486528.000000 +-5.355000 -0.192500 2.240000 635586304.000000 +-5.355000 0.577500 2.222500 635686016.000000 +-5.390000 -2.502500 2.327500 635786432.000000 +-5.390000 0.542500 2.240000 635885952.000000 +-5.460000 5.127500 2.170000 635986368.000000 +-5.337500 -2.222500 2.257500 636087232.000000 +-5.355000 0.332500 2.222500 636187712.000000 +-5.372500 1.102500 2.187500 636286912.000000 +-5.355000 -0.402500 2.222500 636386944.000000 +-5.425000 4.707500 4.970000 636486848.000000 +-6.090000 6.177500 43.610001 636586496.000000 +-7.735000 1.557500 92.382500 636687808.000000 +-7.997500 -4.777500 139.527496 636786304.000000 +-8.452500 3.762500 202.264999 636885504.000000 +-11.007500 17.027500 238.017502 636985664.000000 +-12.967500 -2.362500 183.242508 637085632.000000 +-7.000000 -12.967500 103.477501 637185536.000000 +-5.460000 2.572500 13.370000 637285632.000000 +-5.372500 0.787500 2.222500 637385536.000000 +-5.337500 2.432500 2.170000 637485568.000000 +-5.372500 -0.612500 2.275000 637585728.000000 +-5.337500 0.612500 2.240000 637685504.000000 +-5.372500 -0.297500 2.275000 637785536.000000 +-5.040000 10.307500 3.167500 637885376.000000 +-7.262500 -1.207500 55.562500 637985664.000000 +-7.437500 -6.772500 81.987503 638085376.000000 +-4.357500 -17.867500 145.740005 638185472.000000 +-2.065000 17.727501 291.707489 638285376.000000 +-7.315000 9.852500 158.287506 638385408.000000 +-7.437500 2.957500 115.937500 638485312.000000 +-6.545000 5.092500 71.172501 638585408.000000 +-7.087500 2.502500 64.837502 638685376.000000 +-7.700000 -2.467500 96.425003 638787072.000000 +-6.230000 2.222500 56.700001 638885376.000000 +-7.595000 7.437500 91.945000 638985536.000000 +-8.347500 1.452500 87.937500 639085696.000000 +-7.262500 -5.022500 77.367500 639185344.000000 +1.365000 16.292500 65.152504 639285696.000000 +11.497500 6.142500 83.702499 639385664.000000 +11.410000 -22.102501 53.025002 639485504.000000 +-5.512500 34.597500 46.287498 639585536.000000 +-24.885000 56.577499 97.457497 639685760.000000 +-44.257500 -8.312500 77.542503 639785536.000000 +-43.767502 -15.802500 149.625000 639885568.000000 +-5.547500 15.487500 98.419998 639985536.000000 +-64.750000 -33.897499 191.240005 640085568.000000 +-17.430000 -15.662500 158.917496 640185536.000000 +-3.395000 14.787500 9.817500 640285504.000000 +-5.302500 0.227500 2.257500 640385536.000000 +-5.320000 0.262500 2.257500 640485760.000000 +-5.320000 0.262500 2.257500 640585664.000000 +-5.197500 -0.122500 2.502500 640685504.000000 +-12.985000 -21.542500 130.970001 640785472.000000 +-17.045000 -16.327499 170.205002 640885504.000000 +-10.815000 -21.717501 100.817497 640985536.000000 +-5.792500 -36.347500 121.537498 641085504.000000 +-1.592500 -7.927500 123.882500 641185536.000000 +2.660000 -20.912500 156.764999 641285504.000000 +9.450000 -42.402500 41.545002 641385536.000000 +-3.990000 3.832500 19.652500 641485504.000000 +-5.355000 0.507500 2.310000 641585664.000000 +-5.355000 0.297500 2.292500 641685632.000000 +-5.355000 0.297500 2.310000 641785536.000000 +-5.337500 0.297500 2.292500 641885632.000000 +-5.337500 0.332500 2.275000 641985472.000000 +-5.355000 0.297500 2.275000 642085632.000000 +-5.355000 0.332500 2.292500 642185472.000000 +-5.355000 0.332500 2.275000 642285440.000000 +-5.092500 0.507500 2.117500 642385408.000000 +-5.512500 0.157500 2.345000 642485440.000000 +-5.390000 0.297500 2.275000 642585408.000000 +-5.372500 0.297500 2.275000 642685376.000000 +-5.355000 0.332500 2.257500 642785344.000000 +-5.355000 0.367500 2.257500 642885376.000000 +-5.355000 0.297500 2.257500 642985408.000000 +-5.372500 0.262500 2.275000 643085440.000000 +-5.372500 0.332500 2.222500 643185600.000000 +-5.302500 0.297500 2.257500 643285568.000000 +-3.605000 -0.402500 19.792500 643385600.000000 +4.480000 -3.552500 97.824997 643485568.000000 +14.122500 -13.807500 167.982498 643585728.000000 +21.332500 13.982500 291.672516 643685632.000000 +-4.042500 17.622499 224.612503 643786176.000000 +6.405000 -31.867500 87.902504 643885824.000000 +-5.512500 -11.812500 2.397500 643985536.000000 +-5.110000 -2.152500 1.837500 644085568.000000 +-5.355000 0.297500 2.222500 644185664.000000 +2.170000 -19.267500 9.047500 644285504.000000 +1.505000 6.632500 57.557499 644385792.000000 +3.745000 8.347500 111.772499 644485504.000000 +6.737500 9.432500 146.667496 644585664.000000 +-10.955000 66.377502 190.925003 644686464.000000 +-6.282500 -9.047500 149.467499 644785536.000000 +-11.130000 -2.502500 148.085007 644885632.000000 +5.565000 33.687500 114.309998 644985600.000000 +23.799999 41.982502 159.057495 645085568.000000 +55.107502 39.637501 186.812500 645185664.000000 +-48.125000 65.082497 170.397507 645285568.000000 +-2.572500 59.412498 228.305008 645385472.000000 +-62.055000 7.752500 212.029999 645485632.000000 +-108.762497 -12.757500 218.277496 645585536.000000 +-165.672501 -23.502501 157.482498 645685632.000000 +54.407501 51.852501 64.732498 645785472.000000 +-9.625000 -4.777500 2.152500 645885504.000000 +2.292500 7.752500 2.695000 645985664.000000 +-5.372500 0.227500 2.275000 646085632.000000 +-5.390000 0.262500 2.292500 646185536.000000 +-5.390000 0.262500 2.292500 646285504.000000 +-9.082500 0.157500 31.132500 646386752.000000 +-22.295000 1.347500 152.547501 646486656.000000 +-31.447500 -1.592500 197.872498 646586624.000000 +-58.397499 -71.452499 162.732498 646686656.000000 +-15.487500 -56.157501 134.750000 646786496.000000 +7.542500 -21.962500 153.615005 646886336.000000 +2.572500 -18.707500 80.832497 646987328.000000 +4.130000 -5.617500 32.672501 647086528.000000 +-13.177500 4.742500 1.260000 647187776.000000 +-15.557500 1.662500 -7.000000 647286400.000000 +29.382500 11.462500 18.480000 647386432.000000 +-2.975000 -11.567500 -0.840000 647486656.000000 +-5.285000 0.507500 2.397500 647586560.000000 +-5.320000 0.297500 2.257500 647686656.000000 +-5.320000 0.297500 2.257500 647787584.000000 +-5.320000 0.297500 2.257500 647886400.000000 +-5.337500 0.297500 2.257500 647986432.000000 +-5.337500 0.297500 2.275000 648086784.000000 +-5.285000 0.332500 2.187500 648186112.000000 +-5.355000 0.367500 2.292500 648286016.000000 +-5.337500 0.297500 2.257500 648386368.000000 +-5.337500 0.297500 2.240000 648486336.000000 +-5.372500 0.297500 2.275000 648587392.000000 +-5.250000 -0.157500 2.275000 648685888.000000 +-5.355000 0.332500 2.240000 648786176.000000 +-5.337500 0.297500 2.275000 648886016.000000 +-5.355000 0.297500 2.275000 648985984.000000 +-5.355000 0.297500 2.205000 649086208.000000 +-5.337500 0.262500 2.240000 649186560.000000 +-5.267500 1.032500 4.025000 649286720.000000 +-2.607500 -1.137500 31.500000 649385856.000000 +-5.547500 -3.097500 84.367500 649485760.000000 +-12.075000 -39.952499 178.395004 649585984.000000 +-39.602501 -66.517502 186.952499 649686144.000000 +-38.622501 -52.832500 186.287506 649785728.000000 +6.440000 -27.597500 187.809998 649885760.000000 +56.314999 -3.167500 160.212494 649986304.000000 +89.144997 -14.717500 122.692497 650086208.000000 +112.297501 29.312500 124.425003 650186176.000000 +-3.850000 35.717499 118.807503 650286912.000000 +-6.002500 1.732500 23.642500 650386048.000000 +-5.267500 -2.607500 2.275000 650486016.000000 +-5.320000 3.412500 2.187500 650586240.000000 +-5.530000 7.997500 2.117500 650686272.000000 +-5.320000 6.877500 2.082500 650786304.000000 +-8.137500 24.412500 52.185001 650886528.000000 +-23.712500 7.192500 253.767502 650985920.000000 +-18.742500 -2.397500 240.887497 651086592.000000 +-28.875000 3.062500 389.532501 651185792.000000 +-25.549999 -16.117500 432.827515 651286592.000000 +-6.632500 -9.642500 88.567497 651387264.000000 +-5.180000 10.727500 1.872500 651488384.000000 +-5.355000 0.227500 2.275000 651588736.000000 +-5.372500 0.297500 2.257500 651686464.000000 +-8.802500 30.887501 40.162498 651785792.000000 +-7.000000 -17.657499 41.037498 651886144.000000 +-6.615000 -12.582500 55.299999 651986240.000000 +-7.910000 -5.792500 166.477493 652086144.000000 +-4.917500 8.522500 126.385002 652186048.000000 +-2.817500 4.147500 193.637497 652286144.000000 +-0.647500 -2.117500 161.524994 652385984.000000 +-45.045002 -100.502502 218.960007 652486144.000000 +20.107500 -26.582500 134.365005 652586432.000000 +-21.174999 3.412500 91.735001 652686208.000000 +-53.042500 4.147500 87.482498 652786304.000000 +-0.035000 10.657500 67.007500 652886656.000000 +53.672501 54.477501 -68.459999 652986240.000000 +26.162500 27.877501 -48.930000 653086016.000000 +-3.342500 -3.447500 -28.052500 653185920.000000 +-6.177500 2.047500 4.217500 653285888.000000 +-4.480000 -12.057500 2.240000 653385920.000000 +-3.622500 -23.292500 2.152500 653485952.000000 +-4.060000 -16.257500 2.152500 653585920.000000 +-5.022500 -3.657500 2.012500 653685952.000000 +-5.320000 -0.647500 2.380000 653785920.000000 +-5.250000 -1.382500 2.257500 653885760.000000 +-7.385000 30.712500 1.680000 653985856.000000 +-3.570000 -22.942499 2.747500 654085824.000000 +-6.160000 10.377500 2.555000 654186176.000000 +-4.462500 -10.832500 2.275000 654286080.000000 +-5.145000 -3.272500 2.222500 654386048.000000 +-5.215000 -2.397500 2.257500 654486720.000000 +-5.372500 0.822500 2.187500 654585856.000000 +-6.702500 19.722500 1.977500 654685952.000000 +-9.450000 53.777500 3.185000 654785792.000000 +0.700000 -74.252502 1.575000 654886144.000000 +-7.735000 29.767500 2.450000 654985728.000000 +-4.987500 -4.952500 2.257500 655085696.000000 +-4.217500 -16.957500 2.240000 655185728.000000 +-5.425000 0.612500 2.450000 655285696.000000 +-5.285000 -0.577500 2.135000 655385728.000000 +-5.372500 0.437500 2.275000 655486208.000000 +-5.372500 0.122500 2.240000 655586496.000000 +-5.390000 0.332500 2.240000 655686080.000000 +-5.390000 0.367500 2.222500 655787712.000000 +-5.390000 0.437500 2.170000 655885824.000000 +-5.407500 0.367500 2.257500 655986176.000000 +-5.355000 0.402500 2.240000 656085952.000000 +-5.390000 0.402500 2.222500 656186048.000000 +-5.407500 0.297500 2.257500 656286400.000000 +-5.390000 0.297500 2.222500 656386176.000000 +-5.372500 0.367500 2.047500 656486464.000000 +-5.372500 0.332500 1.925000 656586624.000000 +-5.355000 0.332500 1.592500 656687552.000000 +-5.250000 0.297500 0.997500 656786112.000000 +-5.040000 1.662500 3.010000 656885696.000000 +-5.810000 3.237500 2.555000 656985536.000000 +-9.187500 -5.057500 4.882500 657085632.000000 +-5.407500 0.052500 2.362500 657185600.000000 +-4.952500 0.507500 2.642500 657285568.000000 +-5.197500 0.402500 2.957500 657385664.000000 +-5.722500 -0.297500 11.077500 657485760.000000 +-6.282500 -1.697500 12.372500 657585536.000000 +-3.762500 0.997500 9.240000 657685504.000000 +-3.115000 0.157500 4.812500 657785600.000000 +1.312500 -1.697500 -2.922500 657885568.000000 +12.355000 31.097500 3.167500 657985664.000000 +-0.472500 45.167500 1.050000 658085504.000000 +-5.390000 2.852500 2.205000 658185536.000000 +-5.390000 -0.857500 2.240000 658285504.000000 +-5.355000 0.822500 2.222500 658385664.000000 +-5.390000 0.367500 2.275000 658485568.000000 +-5.372500 0.192500 2.240000 658585664.000000 +-5.355000 0.262500 2.240000 658685504.000000 +-5.372500 0.332500 2.240000 658785536.000000 +-5.390000 0.332500 2.257500 658885696.000000 +-5.372500 0.332500 2.257500 658985728.000000 +-5.145000 27.842501 1.680000 659085440.000000 +-5.320000 -33.442501 2.957500 659185408.000000 +-5.477500 7.927500 2.117500 659285504.000000 +-5.390000 0.227500 2.257500 659385536.000000 +-5.390000 -0.367500 2.257500 659485376.000000 +-5.232500 -3.552500 2.345000 659585472.000000 +-5.442500 2.887500 2.222500 659685504.000000 +-5.372500 0.122500 2.257500 659785536.000000 +-5.390000 1.487500 2.222500 659885440.000000 +-5.145000 -10.342500 2.485000 659985408.000000 +-5.547500 9.747500 2.065000 660085760.000000 +-5.390000 2.257500 2.222500 660185536.000000 +-5.337500 -5.127500 2.310000 660285568.000000 +-5.337500 8.837500 2.275000 660385408.000000 +-5.495000 12.827500 2.030000 660485440.000000 +-5.390000 -2.222500 2.257500 660585536.000000 +-5.442500 -1.907500 2.275000 660685696.000000 +-5.267500 -4.602500 2.327500 660785664.000000 +-5.582500 0.892500 2.800000 660885440.000000 +-5.530000 -9.012500 3.045000 660985408.000000 +-5.425000 -2.817500 2.327500 661085632.000000 +-5.495000 3.482500 2.170000 661185664.000000 +-5.232500 7.682500 2.100000 661285376.000000 +-5.565000 15.977500 2.782500 661385408.000000 +-4.970000 2.642500 2.712500 661485440.000000 +-5.320000 -4.427500 2.345000 661586304.000000 +-5.442500 -9.012500 2.345000 661685440.000000 +-5.180000 -2.887500 2.292500 661785536.000000 +-5.495000 4.882500 2.152500 661885440.000000 +-5.512500 -0.297500 2.240000 661985408.000000 +-5.495000 0.087500 2.222500 662085376.000000 +-5.285000 1.172500 2.205000 662185344.000000 +-5.407500 -8.207500 2.397500 662285376.000000 +-5.285000 -8.522500 2.362500 662385600.000000 +-5.425000 5.302500 2.152500 662485568.000000 +-5.407500 0.717500 2.222500 662585600.000000 +-5.442500 -0.122500 2.205000 662685632.000000 +-5.355000 -3.272500 2.310000 662790656.000000 +-5.442500 2.747500 2.152500 662890624.000000 +-5.390000 1.662500 2.187500 662990784.000000 +-5.407500 -0.122500 2.240000 663091008.000000 +-5.442500 -1.067500 2.240000 663190400.000000 +-5.442500 2.082500 2.170000 663290624.000000 +-5.390000 -0.017500 2.257500 663391040.000000 +-5.425000 0.262500 2.222500 663490816.000000 +-5.390000 -0.297500 2.222500 663590656.000000 +-5.407500 -1.557500 2.240000 663690624.000000 +-5.442500 1.592500 2.205000 663791168.000000 +-5.460000 0.822500 2.187500 663890944.000000 +-5.460000 -0.962500 2.292500 663990464.000000 +-5.442500 0.892500 2.240000 664090816.000000 +-5.407500 1.627500 2.187500 664190848.000000 +-5.407500 0.402500 2.205000 664292736.000000 +-5.407500 -0.052500 2.240000 664390400.000000 +-5.460000 -0.437500 2.222500 664490432.000000 +-5.425000 -0.542500 2.222500 664590784.000000 +-5.425000 1.347500 2.205000 664690944.000000 +-5.320000 0.752500 2.187500 664790336.000000 +-5.407500 -4.217500 2.292500 664890496.000000 +-5.477500 4.497500 2.170000 664990656.000000 +-5.442500 0.822500 2.205000 665091840.000000 +-5.407500 0.472500 2.240000 665191040.000000 +-5.495000 -1.277500 2.257500 665290624.000000 +-5.442500 1.277500 2.205000 665390720.000000 +-5.460000 0.892500 2.222500 665490944.000000 +-5.425000 0.752500 2.222500 665590656.000000 +-5.442500 -0.262500 2.222500 665692160.000000 +-5.372500 -5.197500 2.327500 665790592.000000 +-5.477500 6.387500 2.082500 665890624.000000 +-5.425000 0.227500 2.240000 665990848.000000 +-5.442500 -1.347500 2.240000 666090688.000000 +-5.495000 2.922500 2.187500 666190400.000000 +-5.477500 -1.032500 2.257500 666290880.000000 +-5.460000 0.332500 2.205000 666390656.000000 +-5.442500 0.962500 2.205000 666490816.000000 +-5.460000 0.332500 2.205000 666590784.000000 +-5.477500 0.402500 2.240000 666690688.000000 +-5.425000 0.332500 2.240000 666790848.000000 +-5.460000 0.367500 2.222500 666891008.000000 +-5.460000 0.367500 2.205000 666991424.000000 +-5.442500 0.332500 2.222500 667090880.000000 +-5.442500 0.297500 2.240000 667190976.000000 +-5.460000 0.332500 2.222500 667291392.000000 +-5.442500 0.332500 2.240000 667390720.000000 +-5.442500 0.367500 2.222500 667490624.000000 +-5.425000 0.157500 2.222500 667590720.000000 +-5.425000 0.437500 2.240000 667690944.000000 +-5.460000 0.367500 2.240000 667790784.000000 +-5.442500 0.332500 2.240000 667890624.000000 +-5.460000 0.332500 2.205000 667990976.000000 +-5.477500 0.332500 2.222500 668090816.000000 +-5.460000 0.367500 2.222500 668190784.000000 +-5.442500 0.332500 2.257500 668290816.000000 +-5.442500 0.332500 2.240000 668390784.000000 +-5.442500 0.332500 2.257500 668490688.000000 +-5.442500 0.367500 2.240000 668590720.000000 +-5.442500 0.367500 2.257500 668690944.000000 +-5.407500 0.367500 2.257500 668790784.000000 +-5.390000 0.402500 2.222500 668890624.000000 +-5.425000 0.367500 2.240000 668990976.000000 +-5.425000 0.367500 2.222500 669090944.000000 +-5.442500 0.297500 2.240000 669190976.000000 +-5.442500 0.297500 2.240000 669291008.000000 +-5.460000 0.332500 2.257500 669390656.000000 diff --git a/src/sensor_fusion/design/data/100ms/yaw/magnetic.txt b/src/sensor_fusion/design/data/100ms/yaw/magnetic.txt new file mode 100755 index 0000000..c441a49 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/yaw/magnetic.txt @@ -0,0 +1,664 @@ +2.312500 -42.437500 -14.312500 603089536.000000 +3.375000 -42.437500 -14.312500 603189568.000000 +4.312500 -42.875000 -14.062500 603289536.000000 +3.437500 -42.437500 -14.312500 603389568.000000 +4.187500 -42.687500 -14.625000 603489536.000000 +4.062500 -42.750000 -14.250000 603589568.000000 +3.687500 -42.500000 -14.062500 603689536.000000 +3.687500 -42.562500 -14.250000 603789568.000000 +3.875000 -42.750000 -14.000000 603889536.000000 +3.687500 -42.812500 -13.875000 603989568.000000 +3.687500 -42.687500 -14.000000 604089536.000000 +3.875000 -42.875000 -13.937500 604189568.000000 +3.687500 -42.750000 -13.625000 604289536.000000 +3.625000 -42.750000 -13.875000 604389568.000000 +3.750000 -42.687500 -13.937500 604489536.000000 +3.937500 -42.812500 -13.687500 604589568.000000 +3.812500 -42.562500 -13.937500 604689536.000000 +3.937500 -42.562500 -13.875000 604789568.000000 +3.812500 -42.625000 -13.875000 604889536.000000 +3.750000 -42.687500 -13.875000 604989568.000000 +3.937500 -42.750000 -14.312500 605089536.000000 +3.875000 -42.687500 -14.187500 605189568.000000 +3.750000 -42.875000 -14.250000 605289536.000000 +3.562500 -42.812500 -14.375000 605389568.000000 +3.750000 -42.750000 -14.312500 605489536.000000 +3.687500 -42.625000 -14.437500 605589568.000000 +3.750000 -42.687500 -14.375000 605689536.000000 +3.687500 -42.750000 -14.250000 605789568.000000 +3.687500 -42.562500 -14.125000 605889536.000000 +4.000000 -42.625000 -14.062500 605989568.000000 +4.062500 -42.562500 -14.062500 606089536.000000 +4.062500 -42.312500 -14.125000 606189568.000000 +4.062500 -42.562500 -14.250000 606289536.000000 +3.875000 -42.500000 -14.000000 606389568.000000 +3.500000 -42.250000 -13.625000 606489536.000000 +3.000000 -41.812500 -13.187500 606589568.000000 +2.312500 -41.812500 -12.500000 606689536.000000 +2.187500 -41.750000 -12.687500 606789568.000000 +2.062500 -41.750000 -12.625000 606889536.000000 +1.562500 -41.562500 -12.062500 606989568.000000 +0.875000 -41.250000 -11.562500 607089536.000000 +0.562500 -41.187500 -11.312500 607189568.000000 +0.562500 -41.375000 -11.562500 607289536.000000 +0.875000 -41.625000 -11.875000 607389568.000000 +0.937500 -41.625000 -12.125000 607489536.000000 +0.250000 -41.375000 -11.625000 607589568.000000 +-0.187500 -41.250000 -11.187500 607689536.000000 +-0.062500 -41.437500 -11.500000 607789568.000000 +-0.187500 -41.375000 -11.500000 607889536.000000 +0.187500 -41.750000 -11.937500 607989568.000000 +0.687500 -41.625000 -12.187500 608089536.000000 +0.687500 -41.687500 -12.187500 608189568.000000 +1.062500 -41.875000 -12.500000 608289536.000000 +1.125000 -42.187500 -12.687500 608389568.000000 +1.312500 -42.250000 -12.687500 608489536.000000 +1.625000 -42.250000 -12.562500 608589568.000000 +1.937500 -42.375000 -12.250000 608689536.000000 +1.937500 -42.125000 -11.937500 608789568.000000 +1.875000 -41.625000 -11.312500 608889536.000000 +3.750000 -41.000000 -11.125000 608989568.000000 +6.625000 -39.750000 -11.000000 609089536.000000 +10.875000 -37.562500 -11.187500 609189568.000000 +15.500000 -34.687500 -11.562500 609289536.000000 +20.000000 -30.875000 -11.875000 609389568.000000 +24.937500 -26.687500 -12.437500 609489536.000000 +29.625000 -21.500000 -12.750000 609589568.000000 +34.125000 -15.750000 -13.125000 609689536.000000 +36.500000 -9.562500 -13.250000 609789568.000000 +37.750000 -3.312500 -13.375000 609889536.000000 +37.500000 2.875000 -13.437500 609989568.000000 +36.312500 8.437500 -13.562500 610089536.000000 +34.687500 13.437500 -13.812500 610189568.000000 +32.562500 17.875000 -14.250000 610289536.000000 +29.875000 22.062500 -14.375000 610389568.000000 +26.562500 25.375000 -14.812500 610489536.000000 +22.937500 28.312500 -15.000000 610589568.000000 +18.812500 30.812500 -15.062500 610689536.000000 +14.687500 32.437500 -15.000000 610789568.000000 +10.000000 33.687500 -15.187500 610889536.000000 +5.625000 34.562500 -14.875000 610989568.000000 +1.625000 35.375000 -14.687500 611089536.000000 +-1.625000 35.937500 -14.562500 611189568.000000 +-4.562500 36.062500 -14.125000 611289536.000000 +-6.687500 36.187500 -14.062500 611389568.000000 +-8.187500 35.875000 -14.250000 611489536.000000 +-9.000000 35.750000 -14.187500 611589568.000000 +-9.125000 35.687500 -13.875000 611689536.000000 +-9.250000 35.687500 -13.937500 611789568.000000 +-9.812500 35.562500 -14.000000 611889536.000000 +-11.125000 34.937500 -14.062500 611989568.000000 +-12.875000 34.187500 -14.125000 612089536.000000 +-15.125000 32.687500 -14.187500 612189568.000000 +-18.000000 30.187500 -14.187500 612289536.000000 +-21.875000 26.312500 -14.375000 612389568.000000 +-25.625000 21.625000 -14.562500 612489536.000000 +-29.062500 16.250000 -14.937500 612589568.000000 +-32.187500 10.000000 -15.125000 612689536.000000 +-33.937500 2.875000 -15.250000 612789568.000000 +-34.500000 -4.625000 -15.687500 612889536.000000 +-34.187500 -12.062500 -15.937500 612989568.000000 +-32.875000 -18.687500 -15.875000 613089536.000000 +-30.187500 -24.187500 -15.937500 613189568.000000 +-27.375000 -28.875000 -16.187500 613289536.000000 +-24.375000 -33.187500 -15.937500 613389568.000000 +-21.375000 -36.187500 -15.750000 613489536.000000 +-18.562500 -38.062500 -16.000000 613589568.000000 +-16.312500 -39.312500 -16.000000 613689536.000000 +-13.937500 -40.187500 -16.062500 613789568.000000 +-12.000000 -40.687500 -16.125000 613889536.000000 +-9.687500 -41.187500 -16.000000 613989568.000000 +-7.000000 -41.437500 -15.750000 614089536.000000 +-4.937500 -41.500000 -16.000000 614189568.000000 +-2.625000 -41.812500 -15.875000 614289536.000000 +-0.750000 -42.125000 -15.750000 614389568.000000 +1.000000 -42.500000 -15.437500 614489536.000000 +2.250000 -42.375000 -15.312500 614589568.000000 +3.625000 -42.312500 -15.375000 614689536.000000 +4.125000 -42.250000 -15.437500 614789568.000000 +4.187500 -42.187500 -15.562500 614889536.000000 +4.437500 -42.250000 -15.437500 614989568.000000 +4.375000 -42.312500 -15.437500 615089536.000000 +4.375000 -42.187500 -15.375000 615189568.000000 +4.562500 -42.187500 -15.500000 615289536.000000 +4.687500 -42.250000 -15.562500 615389568.000000 +5.437500 -42.250000 -15.375000 615489536.000000 +7.437500 -41.437500 -15.312500 615589568.000000 +10.500000 -39.562500 -15.375000 615689536.000000 +14.062500 -36.750000 -15.375000 615789568.000000 +18.250000 -33.000000 -15.375000 615889536.000000 +22.500000 -28.187500 -15.437500 615989568.000000 +26.625000 -22.437500 -15.500000 616089536.000000 +30.625000 -16.000000 -15.562500 616189568.000000 +33.750000 -9.250000 -15.875000 616289536.000000 +35.062500 -2.312500 -15.875000 616389568.000000 +36.187500 4.312500 -16.187500 616489536.000000 +34.937500 10.437500 -16.500000 616589568.000000 +32.000000 16.500000 -16.875000 616689536.000000 +27.750000 21.625000 -17.062500 616789568.000000 +23.500000 25.812500 -17.062500 616889536.000000 +19.875000 29.312500 -17.187500 616989568.000000 +16.937500 32.312500 -17.250000 617089536.000000 +14.937500 34.000000 -17.562500 617189568.000000 +11.687500 35.000000 -17.187500 617289536.000000 +10.687500 35.687500 -17.125000 617389568.000000 +10.750000 35.500000 -17.125000 617489536.000000 +11.750000 35.062500 -17.062500 617589568.000000 +12.500000 34.875000 -17.125000 617689536.000000 +13.000000 34.750000 -17.125000 617789568.000000 +13.187500 34.625000 -17.187500 617889536.000000 +12.812500 34.812500 -17.125000 617989568.000000 +12.875000 34.875000 -17.312500 618089536.000000 +12.687500 35.000000 -17.250000 618189568.000000 +11.937500 35.437500 -17.125000 618289536.000000 +10.250000 35.812500 -17.187500 618389568.000000 +7.312500 35.687500 -16.875000 618489536.000000 +3.062500 35.000000 -16.500000 618589568.000000 +-2.062500 33.812500 -16.125000 618689536.000000 +-7.437500 31.875000 -15.750000 618789568.000000 +-13.500000 29.437500 -15.125000 618889536.000000 +-19.500000 27.062500 -14.750000 618989568.000000 +-24.812500 24.625000 -14.312500 619089536.000000 +-29.000000 22.062500 -13.812500 619189568.000000 +-31.750000 20.062500 -13.562500 619289536.000000 +-33.187500 18.625000 -13.312500 619389568.000000 +-33.937500 17.437500 -13.125000 619489536.000000 +-34.687500 16.687500 -12.937500 619589568.000000 +-35.187500 15.187500 -13.125000 619689536.000000 +-35.937500 12.312500 -13.250000 619789568.000000 +-36.375000 8.312500 -13.500000 619889536.000000 +-36.500000 3.500000 -13.562500 619989568.000000 +-36.062500 -1.437500 -14.000000 620089536.000000 +-35.562500 -7.187500 -14.562500 620189568.000000 +-34.875000 -13.250000 -15.250000 620289536.000000 +-33.062500 -19.437500 -15.875000 620389568.000000 +-30.437500 -24.687500 -15.875000 620489536.000000 +-27.500000 -28.625000 -15.562500 620589568.000000 +-24.312500 -31.875000 -15.500000 620689536.000000 +-20.812500 -34.312500 -15.437500 620789568.000000 +-17.062500 -36.687500 -15.375000 620889536.000000 +-12.812500 -38.437500 -15.062500 620989568.000000 +-8.687500 -39.625000 -14.687500 621089536.000000 +-5.000000 -40.437500 -14.500000 621189568.000000 +-2.125000 -40.812500 -14.687500 621289536.000000 +0.562500 -41.000000 -15.062500 621389568.000000 +2.937500 -41.187500 -15.250000 621489536.000000 +4.562500 -41.437500 -15.375000 621589568.000000 +5.437500 -41.500000 -15.250000 621689536.000000 +5.687500 -41.562500 -15.562500 621789568.000000 +5.812500 -41.625000 -15.562500 621889536.000000 +5.687500 -41.375000 -15.562500 621989568.000000 +6.000000 -41.375000 -15.625000 622089536.000000 +5.687500 -41.750000 -15.687500 622189568.000000 +5.687500 -41.750000 -15.562500 622289536.000000 +6.437500 -41.500000 -15.687500 622389568.000000 +8.500000 -40.625000 -15.687500 622489536.000000 +11.437500 -38.687500 -15.812500 622589568.000000 +15.062500 -35.812500 -15.875000 622689536.000000 +19.000000 -31.562500 -16.062500 622789568.000000 +22.750000 -25.687500 -16.125000 622889536.000000 +26.500000 -18.062500 -16.250000 622989568.000000 +29.437500 -9.812500 -16.250000 623089536.000000 +30.687500 -1.125000 -16.125000 623189568.000000 +30.312500 7.312500 -15.875000 623289536.000000 +28.125000 15.000000 -16.125000 623389568.000000 +24.812500 22.062500 -16.687500 623489536.000000 +20.562500 27.562500 -17.187500 623589568.000000 +15.375000 31.250000 -17.312500 623689536.000000 +10.000000 33.437500 -17.250000 623789568.000000 +4.937500 34.812500 -17.500000 623889536.000000 +0.062500 35.125000 -17.625000 623989568.000000 +-4.375000 34.937500 -18.000000 624089536.000000 +-8.125000 34.562500 -17.687500 624189568.000000 +-11.625000 33.687500 -16.812500 624289536.000000 +-14.250000 32.875000 -16.187500 624389568.000000 +-15.750000 32.375000 -15.875000 624489536.000000 +-16.812500 31.937500 -15.750000 624589568.000000 +-17.625000 31.750000 -15.500000 624689536.000000 +-17.687500 31.750000 -15.375000 624789568.000000 +-17.812500 31.812500 -15.187500 624889536.000000 +-17.812500 31.812500 -15.125000 624989568.000000 +-17.625000 31.750000 -15.250000 625089536.000000 +-17.500000 31.687500 -15.000000 625189568.000000 +-17.750000 31.625000 -15.000000 625289536.000000 +-18.000000 31.312500 -14.875000 625389568.000000 +-18.812500 30.562500 -14.687500 625489536.000000 +-19.937500 29.687500 -14.562500 625589568.000000 +-21.562500 28.187500 -14.625000 625689536.000000 +-23.875000 25.937500 -14.500000 625789568.000000 +-26.437500 22.937500 -14.562500 625889536.000000 +-29.062500 18.812500 -14.687500 625989568.000000 +-31.687500 14.500000 -15.000000 626089536.000000 +-34.250000 10.000000 -15.312500 626189568.000000 +-36.062500 5.312500 -15.812500 626289536.000000 +-37.375000 0.562500 -16.125000 626389568.000000 +-38.187500 -4.000000 -16.125000 626489536.000000 +-38.000000 -8.375000 -15.937500 626589568.000000 +-37.250000 -12.250000 -15.687500 626689536.000000 +-36.187500 -15.625000 -15.500000 626789568.000000 +-34.125000 -19.500000 -14.875000 626889536.000000 +-31.500000 -23.437500 -14.625000 626989568.000000 +-28.437500 -27.250000 -14.250000 627089536.000000 +-25.187500 -30.937500 -14.062500 627189568.000000 +-21.500000 -34.062500 -14.062500 627289536.000000 +-17.937500 -36.875000 -14.437500 627389568.000000 +-14.062500 -39.125000 -14.750000 627489536.000000 +-9.875000 -40.875000 -14.937500 627589568.000000 +-6.562500 -42.125000 -15.062500 627689536.000000 +-3.500000 -42.750000 -14.937500 627789568.000000 +-1.062500 -43.187500 -14.812500 627889536.000000 +0.812500 -43.312500 -14.750000 627989568.000000 +2.625000 -43.500000 -14.812500 628089536.000000 +4.187500 -43.250000 -14.625000 628189568.000000 +5.312500 -43.312500 -14.375000 628289536.000000 +5.750000 -43.250000 -14.437500 628389568.000000 +6.375000 -43.125000 -14.562500 628489536.000000 +6.562500 -43.062500 -14.687500 628589568.000000 +6.937500 -43.000000 -14.812500 628689536.000000 +6.937500 -43.000000 -14.437500 628789568.000000 +6.312500 -42.812500 -13.875000 628889536.000000 +6.250000 -42.937500 -13.687500 628989568.000000 +6.187500 -42.687500 -13.625000 629089536.000000 +5.937500 -42.750000 -13.187500 629189568.000000 +5.750000 -42.750000 -13.062500 629289536.000000 +5.625000 -42.500000 -12.625000 629389568.000000 +5.312500 -42.375000 -12.312500 629489536.000000 +5.437500 -42.250000 -12.375000 629589568.000000 +5.500000 -42.062500 -12.437500 629689536.000000 +5.125000 -41.937500 -12.187500 629789568.000000 +4.500000 -41.875000 -11.562500 629889536.000000 +4.000000 -41.562500 -11.312500 629989568.000000 +3.562500 -41.312500 -11.000000 630089536.000000 +3.500000 -41.375000 -10.875000 630189568.000000 +3.187500 -41.062500 -10.625000 630289536.000000 +3.437500 -41.062500 -10.875000 630389568.000000 +4.062500 -41.500000 -11.187500 630489536.000000 +4.562500 -41.500000 -11.500000 630589568.000000 +5.250000 -41.687500 -12.062500 630689536.000000 +5.312500 -41.562500 -12.250000 630789568.000000 +5.062500 -41.437500 -11.937500 630889536.000000 +4.812500 -41.375000 -11.937500 630989568.000000 +4.937500 -41.562500 -12.000000 631089536.000000 +4.687500 -41.375000 -11.750000 631189568.000000 +4.125000 -41.125000 -11.562500 631289536.000000 +3.625000 -41.062500 -11.250000 631389568.000000 +2.812500 -41.062500 -10.687500 631489536.000000 +2.687500 -41.312500 -10.500000 631589568.000000 +2.687500 -41.437500 -10.312500 631689536.000000 +2.375000 -41.375000 -9.937500 631789568.000000 +2.500000 -41.312500 -10.062500 631889536.000000 +2.125000 -41.312500 -10.062500 631989568.000000 +2.250000 -41.125000 -9.937500 632089536.000000 +2.375000 -41.125000 -9.875000 632189568.000000 +2.500000 -41.125000 -10.125000 632289536.000000 +3.000000 -40.875000 -10.437500 632389568.000000 +3.187500 -41.000000 -10.687500 632489536.000000 +3.250000 -40.937500 -11.000000 632589568.000000 +2.750000 -41.000000 -11.000000 632689536.000000 +2.937500 -41.250000 -10.625000 632789568.000000 +3.000000 -41.312500 -10.437500 632889536.000000 +3.062500 -41.437500 -10.500000 632989568.000000 +3.062500 -41.375000 -10.250000 633089536.000000 +3.312500 -41.625000 -10.437500 633189568.000000 +3.875000 -41.687500 -10.812500 633289536.000000 +4.500000 -42.000000 -11.312500 633389568.000000 +4.750000 -41.875000 -11.312500 633489536.000000 +4.500000 -41.562500 -11.375000 633589568.000000 +4.875000 -41.625000 -11.812500 633689536.000000 +5.062500 -41.562500 -12.125000 633789568.000000 +5.062500 -41.500000 -11.875000 633889536.000000 +4.687500 -41.312500 -11.625000 633989568.000000 +4.187500 -40.937500 -11.312500 634089536.000000 +4.125000 -40.937500 -11.250000 634189568.000000 +4.437500 -41.125000 -11.500000 634289536.000000 +5.062500 -41.500000 -11.875000 634389568.000000 +4.562500 -41.500000 -11.687500 634489536.000000 +4.250000 -41.312500 -11.312500 634589568.000000 +4.687500 -41.625000 -11.875000 634689536.000000 +5.000000 -41.687500 -12.000000 634789568.000000 +5.375000 -42.125000 -12.125000 634889536.000000 +5.312500 -41.937500 -11.875000 634989568.000000 +5.000000 -42.062500 -11.625000 635089536.000000 +4.937500 -41.937500 -11.562500 635189568.000000 +5.187500 -42.125000 -11.750000 635289536.000000 +5.000000 -42.437500 -12.062500 635389568.000000 +4.750000 -42.437500 -11.937500 635489536.000000 +4.437500 -42.562500 -11.875000 635589568.000000 +4.312500 -42.500000 -12.062500 635689536.000000 +4.187500 -42.562500 -12.125000 635789568.000000 +4.000000 -42.500000 -11.875000 635889536.000000 +3.750000 -42.437500 -12.000000 635989568.000000 +3.500000 -42.187500 -11.875000 636089536.000000 +4.000000 -41.937500 -12.062500 636189568.000000 +4.437500 -41.875000 -12.437500 636289536.000000 +4.750000 -42.000000 -12.625000 636389568.000000 +4.312500 -41.750000 -12.625000 636489536.000000 +3.875000 -42.187500 -12.937500 636589568.000000 +2.562500 -42.312500 -13.812500 636689536.000000 +-0.750000 -41.750000 -14.000000 636789568.000000 +-4.937500 -40.312500 -14.375000 636889536.000000 +-10.437500 -37.437500 -14.875000 636989568.000000 +-16.250000 -33.375000 -15.187500 637089536.000000 +-22.062500 -29.187500 -15.500000 637189568.000000 +-27.187500 -25.500000 -15.875000 637289536.000000 +-32.312500 -20.812500 -15.812500 637389568.000000 +-36.125000 -16.562500 -15.687500 637489536.000000 +-38.250000 -13.062500 -15.687500 637589568.000000 +-39.375000 -10.750000 -15.625000 637689536.000000 +-39.812500 -9.812500 -15.500000 637789568.000000 +-39.875000 -9.375000 -15.437500 637889536.000000 +-40.375000 -8.125000 -14.812500 637989568.000000 +-41.000000 -5.562500 -13.875000 638089536.000000 +-41.187500 -1.812500 -13.125000 638189568.000000 +-40.062500 3.000000 -12.625000 638289536.000000 +-38.562500 8.312500 -11.937500 638389568.000000 +-36.000000 13.812500 -11.625000 638489536.000000 +-32.937500 19.562500 -10.750000 638589568.000000 +-29.687500 25.250000 -9.750000 638689536.000000 +-25.500000 30.000000 -9.437500 638789568.000000 +-19.937500 33.562500 -10.000000 638889536.000000 +-13.812500 35.250000 -10.625000 638989568.000000 +-8.500000 36.125000 -10.937500 639089536.000000 +-3.250000 36.562500 -11.312500 639189568.000000 +1.562500 36.375000 -11.750000 639289536.000000 +6.625000 35.812500 -12.375000 639389568.000000 +11.625000 34.562500 -13.250000 639489536.000000 +16.875000 32.937500 -13.687500 639589568.000000 +21.000000 31.062500 -13.125000 639689536.000000 +24.812500 28.625000 -12.812500 639789568.000000 +28.062500 25.375000 -12.187500 639889536.000000 +31.312500 20.937500 -12.187500 639989568.000000 +34.062500 16.125000 -11.750000 640089536.000000 +36.062500 11.562500 -11.187500 640189568.000000 +37.875000 7.187500 -10.750000 640289536.000000 +39.125000 3.187500 -10.687500 640389568.000000 +40.000000 -0.562500 -10.937500 640489536.000000 +40.250000 -3.437500 -11.000000 640589568.000000 +40.437500 -5.500000 -11.375000 640689536.000000 +40.062500 -7.375000 -11.125000 640789568.000000 +39.125000 -9.687500 -11.437500 640889536.000000 +37.750000 -12.625000 -12.125000 640989568.000000 +35.500000 -15.937500 -12.687500 641089536.000000 +32.312500 -19.937500 -13.437500 641189568.000000 +27.875000 -24.500000 -14.312500 641289536.000000 +23.062500 -29.312500 -15.000000 641389568.000000 +18.000000 -34.062500 -15.625000 641489536.000000 +13.437500 -37.750000 -16.187500 641589568.000000 +9.187500 -40.187500 -16.500000 641689536.000000 +5.625000 -42.062500 -16.687500 641789568.000000 +3.062500 -43.562500 -16.750000 641889536.000000 +1.187500 -44.125000 -16.687500 641989568.000000 +1.000000 -44.312500 -16.312500 642089536.000000 +1.000000 -44.437500 -16.312500 642189568.000000 +1.062500 -44.312500 -16.437500 642289536.000000 +0.937500 -44.375000 -16.500000 642389568.000000 +0.750000 -44.312500 -16.375000 642489536.000000 +0.062500 -44.125000 -15.937500 642589568.000000 +-1.125000 -44.000000 -15.187500 642689536.000000 +-1.500000 -43.687500 -14.625000 642789568.000000 +-2.312500 -43.187500 -14.562500 642889536.000000 +-2.812500 -43.125000 -14.062500 642989568.000000 +-3.437500 -43.062500 -13.625000 643089536.000000 +-3.750000 -43.062500 -13.375000 643189568.000000 +-4.000000 -42.937500 -12.875000 643289536.000000 +-4.375000 -42.937500 -12.937500 643389568.000000 +-5.875000 -42.687500 -13.000000 643489536.000000 +-9.437500 -41.687500 -12.750000 643589568.000000 +-13.625000 -39.000000 -13.000000 643689536.000000 +-18.125000 -35.187500 -12.812500 643789568.000000 +-22.562500 -31.125000 -12.625000 643889536.000000 +-27.375000 -27.187500 -12.250000 643989568.000000 +-31.937500 -23.312500 -12.312500 644089536.000000 +-36.125000 -19.437500 -12.062500 644189568.000000 +-39.000000 -15.500000 -11.875000 644289536.000000 +-40.000000 -11.812500 -12.062500 644389568.000000 +-40.437500 -8.875000 -11.562500 644489536.000000 +-40.000000 -5.000000 -12.062500 644589568.000000 +-38.687500 -1.000000 -12.312500 644689536.000000 +-36.625000 4.250000 -12.500000 644789568.000000 +-33.937500 9.875000 -12.687500 644889536.000000 +-29.750000 15.812500 -13.250000 644989568.000000 +-24.125000 21.250000 -14.625000 645089536.000000 +-17.500000 26.187500 -15.312500 645189568.000000 +-8.812500 29.062500 -15.750000 645289536.000000 +-0.312500 29.437500 -15.562500 645389568.000000 +8.375000 28.125000 -15.375000 645489536.000000 +16.312500 25.187500 -15.437500 645589568.000000 +23.687500 21.187500 -14.875000 645689536.000000 +29.562500 16.687500 -14.187500 645789568.000000 +34.375000 12.562500 -12.750000 645889536.000000 +37.687500 8.062500 -12.000000 645989568.000000 +39.500000 4.750000 -11.125000 646089536.000000 +40.625000 1.937500 -10.750000 646189568.000000 +40.812500 0.250000 -10.312500 646289536.000000 +40.562500 -1.625000 -9.500000 646389568.000000 +39.750000 -3.875000 -9.125000 646489536.000000 +38.500000 -7.312500 -9.625000 646589568.000000 +35.937500 -11.687500 -10.687500 646689536.000000 +32.500000 -16.562500 -11.500000 646789568.000000 +28.125000 -21.875000 -12.437500 646889536.000000 +23.437500 -26.875000 -13.500000 646989568.000000 +18.812500 -31.812500 -14.812500 647089536.000000 +14.750000 -36.000000 -16.250000 647189568.000000 +10.812500 -39.375000 -17.750000 647289536.000000 +7.375000 -41.375000 -17.875000 647389568.000000 +5.312500 -42.625000 -17.500000 647489536.000000 +3.937500 -43.125000 -17.187500 647589568.000000 +3.375000 -43.187500 -17.000000 647689536.000000 +3.312500 -43.312500 -16.500000 647789568.000000 +3.125000 -43.250000 -16.250000 647889536.000000 +3.000000 -43.437500 -16.062500 647989568.000000 +3.250000 -43.500000 -15.937500 648089536.000000 +2.812500 -43.187500 -15.437500 648189568.000000 +2.062500 -42.750000 -15.125000 648289536.000000 +1.625000 -42.250000 -14.875000 648389568.000000 +1.437500 -42.375000 -14.687500 648489536.000000 +1.250000 -42.562500 -14.875000 648589568.000000 +0.875000 -42.375000 -14.312500 648689536.000000 +0.312500 -42.187500 -13.937500 648789568.000000 +-0.250000 -41.937500 -13.437500 648889536.000000 +0.000000 -42.187500 -13.750000 648989568.000000 +0.687500 -42.562500 -14.187500 649089536.000000 +1.062500 -43.312500 -14.437500 649189568.000000 +1.062500 -43.125000 -14.562500 649289536.000000 +0.250000 -43.062500 -14.125000 649389568.000000 +-1.625000 -43.312500 -14.062500 649489536.000000 +-4.562500 -42.687500 -13.937500 649589568.000000 +-9.437500 -40.812500 -13.562500 649689536.000000 +-15.187500 -37.312500 -12.812500 649789568.000000 +-21.562500 -32.500000 -11.875000 649889536.000000 +-27.812500 -26.750000 -10.937500 649989568.000000 +-33.187500 -20.812500 -10.437500 650089536.000000 +-37.375000 -13.937500 -10.687500 650189568.000000 +-40.250000 -6.187500 -10.625000 650289536.000000 +-42.000000 0.812500 -10.687500 650389568.000000 +-42.062500 6.437500 -10.875000 650489536.000000 +-40.875000 10.250000 -11.687500 650589568.000000 +-39.375000 12.812500 -12.437500 650689536.000000 +-37.625000 14.750000 -13.750000 650789568.000000 +-36.375000 17.437500 -13.937500 650889536.000000 +-34.687500 20.250000 -13.500000 650989568.000000 +-30.000000 22.875000 -12.937500 651089536.000000 +-22.250000 24.500000 -12.750000 651189568.000000 +-13.125000 24.562500 -12.812500 651289536.000000 +-4.812500 25.250000 -12.125000 651389568.000000 +3.125000 25.750000 -11.250000 651489536.000000 +10.875000 26.375000 -9.937500 651589568.000000 +18.750000 25.562500 -9.187500 651689536.000000 +25.750000 23.250000 -8.875000 651789568.000000 +30.687500 20.062500 -9.562500 651889536.000000 +32.562500 16.812500 -9.937500 651989568.000000 +33.250000 14.500000 -10.000000 652089536.000000 +33.937500 10.375000 -10.312500 652189568.000000 +34.562500 5.500000 -10.500000 652289536.000000 +33.750000 -0.812500 -11.687500 652389568.000000 +31.750000 -7.375000 -13.062500 652489536.000000 +29.000000 -14.312500 -14.187500 652589568.000000 +25.062500 -20.812500 -15.187500 652689536.000000 +20.312500 -26.250000 -15.937500 652789568.000000 +16.125000 -31.375000 -16.875000 652889536.000000 +13.125000 -34.875000 -17.187500 652989568.000000 +10.562500 -37.562500 -18.187500 653089536.000000 +9.250000 -39.062500 -18.187500 653189568.000000 +8.875000 -40.125000 -17.937500 653289536.000000 +9.187500 -40.375000 -17.687500 653389568.000000 +9.937500 -40.687500 -17.187500 653489536.000000 +11.312500 -40.875000 -16.687500 653589568.000000 +12.062500 -40.812500 -16.250000 653689536.000000 +12.062500 -40.812500 -16.500000 653789568.000000 +11.937500 -40.562500 -16.187500 653889536.000000 +11.500000 -40.437500 -15.812500 653989568.000000 +11.000000 -39.937500 -15.312500 654089536.000000 +10.687500 -39.750000 -15.312500 654189568.000000 +10.312500 -39.750000 -15.125000 654289536.000000 +10.250000 -39.687500 -15.187500 654389568.000000 +10.125000 -39.812500 -15.125000 654489536.000000 +10.062500 -39.687500 -14.812500 654589568.000000 +10.125000 -39.687500 -14.812500 654689536.000000 +10.125000 -39.500000 -14.812500 654789568.000000 +9.750000 -39.687500 -14.687500 654889536.000000 +8.937500 -39.625000 -14.000000 654989568.000000 +8.500000 -39.375000 -13.312500 655089536.000000 +8.062500 -39.250000 -12.875000 655189568.000000 +7.437500 -38.937500 -12.375000 655289536.000000 +6.875000 -38.937500 -12.000000 655389568.000000 +6.375000 -39.000000 -11.812500 655489536.000000 +6.375000 -39.312500 -11.937500 655589568.000000 +6.812500 -39.500000 -12.187500 655689536.000000 +7.250000 -39.625000 -12.375000 655789568.000000 +7.937500 -39.937500 -12.875000 655889536.000000 +8.500000 -40.125000 -13.250000 655989568.000000 +9.125000 -40.187500 -14.000000 656089536.000000 +9.625000 -40.375000 -14.375000 656189568.000000 +10.125000 -40.562500 -14.875000 656289536.000000 +10.562500 -40.437500 -15.187500 656389568.000000 +10.937500 -40.437500 -15.562500 656489536.000000 +11.312500 -40.437500 -15.875000 656589568.000000 +11.562500 -40.375000 -16.125000 656689536.000000 +11.562500 -40.187500 -16.250000 656789568.000000 +11.500000 -40.312500 -16.125000 656889536.000000 +11.625000 -40.312500 -16.312500 656989568.000000 +11.562500 -40.187500 -16.187500 657089536.000000 +11.437500 -40.312500 -16.187500 657189568.000000 +11.562500 -40.312500 -16.312500 657289536.000000 +11.562500 -40.375000 -16.625000 657389568.000000 +11.000000 -40.500000 -16.750000 657489536.000000 +10.937500 -40.687500 -17.000000 657589568.000000 +10.625000 -40.812500 -16.875000 657689536.000000 +10.312500 -40.812500 -16.875000 657789568.000000 +10.250000 -40.937500 -16.750000 657889536.000000 +10.187500 -41.125000 -16.437500 657989568.000000 +10.125000 -41.125000 -16.062500 658089536.000000 +10.312500 -41.375000 -15.625000 658189568.000000 +10.687500 -41.500000 -15.187500 658289536.000000 +10.750000 -41.500000 -14.562500 658389568.000000 +11.000000 -41.500000 -14.250000 658489536.000000 +11.250000 -41.562500 -14.000000 658589568.000000 +11.562500 -41.562500 -13.750000 658689536.000000 +11.562500 -41.625000 -13.750000 658789568.000000 +11.562500 -41.687500 -13.750000 658889536.000000 +11.375000 -41.437500 -13.687500 658989568.000000 +10.625000 -41.375000 -13.375000 659089536.000000 +10.437500 -41.187500 -13.250000 659189568.000000 +10.062500 -41.125000 -13.312500 659289536.000000 +9.875000 -41.250000 -13.125000 659389568.000000 +9.437500 -41.125000 -12.875000 659489536.000000 +9.312500 -40.937500 -12.812500 659589568.000000 +8.937500 -40.812500 -12.625000 659689536.000000 +8.937500 -40.812500 -12.437500 659789568.000000 +9.187500 -40.500000 -12.375000 659889536.000000 +9.000000 -40.500000 -12.437500 659989568.000000 +9.000000 -40.312500 -11.875000 660089536.000000 +9.062500 -40.062500 -11.875000 660189568.000000 +9.125000 -40.000000 -11.875000 660289536.000000 +8.937500 -40.000000 -11.562500 660389568.000000 +9.062500 -40.125000 -11.500000 660489536.000000 +8.875000 -40.187500 -11.562500 660589568.000000 +8.937500 -40.437500 -11.750000 660689536.000000 +9.187500 -40.687500 -11.687500 660789568.000000 +9.375000 -40.937500 -11.937500 660889536.000000 +9.187500 -40.750000 -11.687500 660989568.000000 +8.937500 -41.062500 -11.687500 661089536.000000 +8.875000 -41.312500 -11.875000 661189568.000000 +8.875000 -41.250000 -11.812500 661289536.000000 +8.937500 -41.062500 -11.750000 661389568.000000 +8.812500 -41.125000 -11.375000 661489536.000000 +8.562500 -40.875000 -10.812500 661589568.000000 +8.375000 -40.812500 -11.000000 661689536.000000 +8.625000 -41.125000 -11.125000 661789568.000000 +8.437500 -40.812500 -11.062500 661889536.000000 +7.937500 -40.437500 -10.437500 661989568.000000 +7.500000 -40.500000 -10.250000 662089536.000000 +6.687500 -40.625000 -10.125000 662189568.000000 +6.250000 -40.562500 -10.062500 662289536.000000 +5.812500 -40.437500 -10.437500 662389568.000000 +5.937500 -40.375000 -10.125000 662489536.000000 +5.812500 -40.250000 -10.125000 662589568.000000 +6.062500 -40.437500 -10.125000 662689536.000000 +6.500000 -40.437500 -10.312500 662789568.000000 +6.625000 -40.250000 -10.500000 662889536.000000 +7.062500 -40.250000 -10.500000 662989568.000000 +7.562500 -40.125000 -10.500000 663089536.000000 +8.062500 -40.375000 -10.625000 663189568.000000 +7.812500 -40.500000 -10.687500 663289536.000000 +7.562500 -40.312500 -10.312500 663389568.000000 +7.625000 -40.125000 -10.437500 663489536.000000 +7.750000 -40.312500 -10.812500 663589568.000000 +7.750000 -40.312500 -10.500000 663689536.000000 +7.937500 -40.437500 -10.437500 663789568.000000 +7.875000 -40.437500 -10.625000 663889536.000000 +7.437500 -40.437500 -10.187500 663989568.000000 +7.812500 -40.437500 -10.125000 664089536.000000 +8.187500 -40.375000 -10.437500 664189568.000000 +8.187500 -40.562500 -10.562500 664289536.000000 +8.312500 -40.687500 -10.875000 664389568.000000 +8.312500 -40.437500 -11.062500 664489536.000000 +8.437500 -40.250000 -11.437500 664589568.000000 +8.625000 -40.312500 -11.625000 664689536.000000 +8.500000 -40.125000 -11.687500 664789568.000000 +8.062500 -40.062500 -11.750000 664889536.000000 +7.812500 -40.062500 -11.312500 664989568.000000 +7.875000 -40.125000 -11.375000 665089536.000000 +7.312500 -39.937500 -10.562500 665189568.000000 +7.375000 -40.125000 -10.562500 665289536.000000 +7.437500 -40.062500 -10.500000 665389568.000000 +7.437500 -40.187500 -10.500000 665489536.000000 +7.687500 -40.187500 -10.625000 665589568.000000 +8.062500 -40.000000 -10.625000 665689536.000000 +8.062500 -40.187500 -11.000000 665789568.000000 +8.125000 -40.125000 -10.875000 665889536.000000 +8.562500 -40.312500 -11.687500 665989568.000000 +8.750000 -40.500000 -11.812500 666089536.000000 +8.437500 -40.687500 -11.937500 666189568.000000 +8.375000 -40.750000 -11.375000 666289536.000000 +8.500000 -41.062500 -11.812500 666389568.000000 +8.875000 -41.500000 -12.062500 666489536.000000 +9.312500 -41.625000 -12.062500 666589568.000000 +9.375000 -41.625000 -12.187500 666689536.000000 +9.625000 -41.625000 -12.187500 666789568.000000 +9.937500 -41.687500 -12.437500 666889536.000000 +10.437500 -41.625000 -12.500000 666989568.000000 +10.875000 -41.625000 -13.000000 667089536.000000 +11.125000 -41.625000 -13.125000 667189568.000000 +10.875000 -41.500000 -13.250000 667289536.000000 +10.812500 -41.625000 -13.500000 667389568.000000 +10.687500 -41.812500 -13.562500 667489536.000000 +10.500000 -41.625000 -13.687500 667589568.000000 +10.312500 -41.750000 -13.375000 667689536.000000 +10.187500 -41.937500 -13.312500 667789568.000000 +9.937500 -41.937500 -13.187500 667889536.000000 +10.312500 -41.875000 -13.062500 667989568.000000 +10.500000 -41.875000 -13.062500 668089536.000000 +10.500000 -41.687500 -13.187500 668189568.000000 +10.562500 -41.687500 -13.125000 668289536.000000 +10.812500 -41.937500 -13.187500 668389568.000000 +10.687500 -41.875000 -13.375000 668489536.000000 +10.875000 -41.937500 -13.625000 668589568.000000 +10.937500 -42.000000 -13.625000 668689536.000000 +10.562500 -41.937500 -13.687500 668789568.000000 +10.500000 -41.812500 -13.625000 668889536.000000 +10.437500 -42.187500 -13.562500 668989568.000000 +10.500000 -42.125000 -13.750000 669089536.000000 +10.437500 -42.000000 -13.625000 669189568.000000 +10.562500 -42.000000 -13.687500 669289536.000000 +10.562500 -41.750000 -13.312500 669389568.000000 diff --git a/src/sensor_fusion/design/lib/quat2euler.m b/src/sensor_fusion/design/lib/quat2euler.m new file mode 100755 index 0000000..9cba0e1 --- /dev/null +++ b/src/sensor_fusion/design/lib/quat2euler.m @@ -0,0 +1,32 @@ +function euler = quat2euler(q) +% Quat2Euler +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Converts a quaternion orientation to ZYX Euler angles where phi is a +% rotation around X, theta around Y and psi around Z. + + R(1,1,:) = 2.*q(:,1).^2-1+2.*q(:,2).^2; + R(2,1,:) = 2.*(q(:,2).*q(:,3)-q(:,1).*q(:,4)); + R(3,1,:) = 2.*(q(:,2).*q(:,4)+q(:,1).*q(:,3)); + R(3,2,:) = 2.*(q(:,3).*q(:,4)-q(:,1).*q(:,2)); + R(3,3,:) = 2.*q(:,1).^2-1+2.*q(:,4).^2; + + phi = atan2(R(3,2,:), R(3,3,:) ); + theta = -atan(R(3,1,:) ./ sqrt(1-R(3,1,:).^2) ); + psi = atan2(R(2,1,:), R(1,1,:) ); + + euler = [phi(1,:)' theta(1,:)' psi(1,:)']; +end \ No newline at end of file diff --git a/src/sensor_fusion/design/lib/quat2rot_mat.m b/src/sensor_fusion/design/lib/quat2rot_mat.m new file mode 100755 index 0000000..6e795fc --- /dev/null +++ b/src/sensor_fusion/design/lib/quat2rot_mat.m @@ -0,0 +1,30 @@ +function R = quat2rot_mat(q) +% Quat2RotMat +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Converts a quaternion orientation to a rotation matrix. + + R(1,1,:) = 2.*q(:,1).^2-1+2.*q(:,2).^2; + R(1,2,:) = 2.*(q(:,2).*q(:,3)+q(:,1).*q(:,4)); + R(1,3,:) = 2.*(q(:,2).*q(:,4)-q(:,1).*q(:,3)); + R(2,1,:) = 2.*(q(:,2).*q(:,3)-q(:,1).*q(:,4)); + R(2,2,:) = 2.*q(:,1).^2-1+2.*q(:,3).^2; + R(2,3,:) = 2.*(q(:,3).*q(:,4)+q(:,1).*q(:,2)); + R(3,1,:) = 2.*(q(:,2).*q(:,4)+q(:,1).*q(:,3)); + R(3,2,:) = 2.*(q(:,3).*q(:,4)-q(:,1).*q(:,2)); + R(3,3,:) = 2.*q(:,1).^2-1+2.*q(:,4).^2; +end + diff --git a/src/sensor_fusion/design/lib/quat_prod.m b/src/sensor_fusion/design/lib/quat_prod.m new file mode 100755 index 0000000..3ca9acf --- /dev/null +++ b/src/sensor_fusion/design/lib/quat_prod.m @@ -0,0 +1,25 @@ +function ab = quat_prod(a, b) +% QuatProd +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Calculates the quaternion product of quaternion a and b. + + ab(:,1) = a(:,1).*b(:,1)-a(:,2).*b(:,2)-a(:,3).*b(:,3)-a(:,4).*b(:,4); + ab(:,2) = a(:,1).*b(:,2)+a(:,2).*b(:,1)+a(:,3).*b(:,4)-a(:,4).*b(:,3); + ab(:,3) = a(:,1).*b(:,3)-a(:,2).*b(:,4)+a(:,3).*b(:,1)+a(:,4).*b(:,2); + ab(:,4) = a(:,1).*b(:,4)+a(:,2).*b(:,3)-a(:,3).*b(:,2)+a(:,4).*b(:,1); +end + diff --git a/src/sensor_fusion/design/lib/rot_mat2quat.m b/src/sensor_fusion/design/lib/rot_mat2quat.m new file mode 100755 index 0000000..133068c --- /dev/null +++ b/src/sensor_fusion/design/lib/rot_mat2quat.m @@ -0,0 +1,44 @@ +function q = rot_mat2quat(R) +% RotMat2Quat +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Converts a rotation matrix orientation to a quaternion. + + [row col numR] = size(R); + q = zeros(numR, 4); + K = zeros(4,4); + for i = 1:numR + K(1,1) = (1/3) * (R(1,1,i) - R(2,2,i) - R(3,3,i)); + K(1,2) = (1/3) * (R(2,1,i) + R(1,2,i)); + K(1,3) = (1/3) * (R(3,1,i) + R(1,3,i)); + K(1,4) = (1/3) * (R(2,3,i) - R(3,2,i)); + K(2,1) = (1/3) * (R(2,1,i) + R(1,2,i)); + K(2,2) = (1/3) * (R(2,2,i) - R(1,1,i) - R(3,3,i)); + K(2,3) = (1/3) * (R(3,2,i) + R(2,3,i)); + K(2,4) = (1/3) * (R(3,1,i) - R(1,3,i)); + K(3,1) = (1/3) * (R(3,1,i) + R(1,3,i)); + K(3,2) = (1/3) * (R(3,2,i) + R(2,3,i)); + K(3,3) = (1/3) * (R(3,3,i) - R(1,1,i) - R(2,2,i)); + K(3,4) = (1/3) * (R(1,2,i) - R(2,1,i)); + K(4,1) = (1/3) * (R(2,3,i) - R(3,2,i)); + K(4,2) = (1/3) * (R(3,1,i) - R(1,3,i)); + K(4,3) = (1/3) * (R(1,2,i) - R(2,1,i)); + K(4,4) = (1/3) * (R(1,1,i) + R(2,2,i) + R(3,3,i)); + [V,D] = eig(K); + q(i,:) = V(:,4)'; + q(i,:) = [q(i,4) q(i,1) q(i,2) q(i,3)]; + end +end \ No newline at end of file diff --git a/src/sensor_fusion/design/sf_orien.m b/src/sensor_fusion/design/sf_orien.m new file mode 100755 index 0000000..eebc2c0 --- /dev/null +++ b/src/sensor_fusion/design/sf_orien.m @@ -0,0 +1,491 @@ +% SF_Orien +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Sensor Fusion Implementation - Orientation Estimation +% +% - Orientation Estimation using Gyroscope as the driving system and Accelerometer+Geo-Magnetic Sensors as Aiding System. +% - Quaternion based approach +% - Estimation and correction of Euler errors and bias errors for gyroscope using Kalman filter + +addpath('lib'); +clear +clc + +LOW_PASS_FILTERING_ON = 1; + +Max_Range_Accel = 39.203407; Min_Range_Accel = -39.204006; Res_Accel = 0.000598; +Max_Range_Gyro = 1146.862549; Min_Range_Gyro = -1146.880005; Res_Gyro = 0.017500; +Max_Range_Magnetic = 1200; Min_Range_Magnetic = -1200; Res_Magnetic = 1; + +PI = 3.141593; +GRAVITY = 9.80665; +NON_ZERO_VAL = 0.1; + +Bias_Ax = 0.098586; +Bias_Ay = 0.18385; +Bias_Az = 10.084 - GRAVITY; + +Bias_Gx = -5.3539; +Bias_Gy = 0.24325; +Bias_Gz = 2.3391; + +BUFFER_SIZE = 1095; +MOVING_AVERAGE_WINDOW_LENGTH = 20; +RAD2DEG = 57.2957795; +DEG2RAD = 0.0174532925; +US2S = 1.0 / 1000000.0; + +% Gyro Types +% Systron-donner "Horizon" +ZigmaW = 0.05 * DEG2RAD; %deg/s +TauW = 1000; %secs +% Crossbow DMU-6X +%ZigmaW = 0.05 * DEG2RAD; %deg/s +%TauW = 300; %secs +%FOGs (KVH Autogyro and Crossbow DMU-FOG) +%ZigmaW = 0; %deg/s + +% get accel x,y,z axis data from stored file +Ax = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,1))') - Bias_Ax)(1:BUFFER_SIZE); +Ay = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,2))') - Bias_Ay)(1:BUFFER_SIZE); +Az = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,3))') - Bias_Az)(1:BUFFER_SIZE); +ATime = ((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,4))'); + +% get gyro x,y,z axis data from stored file +Gx = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,1))') - Bias_Gx)(1:BUFFER_SIZE); +Gy = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,2))') - Bias_Gy)(1:BUFFER_SIZE); +Gz = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,3))') - Bias_Gz)(1:BUFFER_SIZE); +GTime = ((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,4))'); + +scale_Gyro = 575; +Gx = Gx/scale_Gyro; +Gy = Gy/scale_Gyro; +Gz = Gz/scale_Gyro; + +% get magnetometer x,y,z axis data from stored file +Mx = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,1))'))(1:BUFFER_SIZE); +My = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,2))'))(1:BUFFER_SIZE); +Mz = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,3))'))(1:BUFFER_SIZE); +MTime = ((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,4))'); + +% Gyroscope Bias Variables +Bx = 0; By = 0; Bz = 0; + +% 1st order smoothening filter +b = [0.98 0 ]; +a = [1.0000000 0.02 ]; + +% initialize filter output variables to zero +filt_Ax = zeros(1,BUFFER_SIZE); +filt_Ay = zeros(1,BUFFER_SIZE); +filt_Az = zeros(1,BUFFER_SIZE); +filt_Gx = zeros(1,BUFFER_SIZE); +filt_Gy = zeros(1,BUFFER_SIZE); +filt_Gz = zeros(1,BUFFER_SIZE); +filt_Mx = zeros(1,BUFFER_SIZE); +filt_My = zeros(1,BUFFER_SIZE); +filt_Mz = zeros(1,BUFFER_SIZE); + +acc_x = zeros(1,BUFFER_SIZE); +acc_y = zeros(1,BUFFER_SIZE); +acc_z = zeros(1,BUFFER_SIZE); +gyr_x = zeros(1,BUFFER_SIZE); +gyr_y = zeros(1,BUFFER_SIZE); +gyr_z = zeros(1,BUFFER_SIZE); +mag_x = zeros(1,BUFFER_SIZE); +mag_y = zeros(1,BUFFER_SIZE); +mag_z = zeros(1,BUFFER_SIZE); + +% User Acceleration mean and Variance +A_T = zeros(1,BUFFER_SIZE); +G_T = zeros(1,BUFFER_SIZE); +M_T = zeros(1,BUFFER_SIZE); +var_roll = zeros(1,BUFFER_SIZE); +var_pitch = zeros(1,BUFFER_SIZE); +var_yaw = zeros(1,BUFFER_SIZE); +var_Gx = zeros(1,BUFFER_SIZE); +var_Gy = zeros(1,BUFFER_SIZE); +var_Gz = zeros(1,BUFFER_SIZE); + +roll = zeros(1,BUFFER_SIZE); +pitch = zeros(1,BUFFER_SIZE); +yaw = zeros(1,BUFFER_SIZE); +quat_driv = zeros(BUFFER_SIZE,4); +quat_aid = zeros(BUFFER_SIZE,4); +quat_error = zeros(BUFFER_SIZE,4); +euler = zeros(BUFFER_SIZE,3); +Ro = zeros(3, 3, BUFFER_SIZE); + +% system covariance matrix +Q = zeros(6,6); + +% measurement covariance matrix +R = zeros(6,6); + +A_T(1) = 100000; +G_T(1) = 100000; +M_T(1) = 100000; + +acc_e = [0.0;0.0;1.0]; % gravity vector in earth frame +mag_e = [0.0;1.0;0.0]; % magnetic field vector in earth frame + +H = [eye(3) zeros(3,3); zeros(3,6)]; +x = zeros(6,BUFFER_SIZE); +e = zeros(1,6); +P = 1 * eye(6);% state covariance matrix + +quat_driv(1,:) = [1 0 0 0]; + +% first order filtering +for i = 1:BUFFER_SIZE + if LOW_PASS_FILTERING_ON == 1 + if i < 2 + filt_Ax(i) = Ax(i); + filt_Ay(i) = Ay(i); + filt_Az(i) = Az(i); + filt_Gx(i) = Gx(i); + filt_Gy(i) = Gy(i); + filt_Gz(i) = Gz(i); + filt_Mx(i) = Mx(i); + filt_My(i) = My(i); + filt_Mz(i) = Mz(i); + elseif i >= 2 + filt_Ax(i) = -a(2)*filt_Ax(i-1)+b(1)*Ax(i); + filt_Ay(i) = -a(2)*filt_Ay(i-1)+b(1)*Ay(i); + filt_Az(i) = -a(2)*filt_Az(i-1)+b(1)*Az(i); + filt_Gx(i) = -a(2)*filt_Gx(i-1)+b(1)*Gx(i); + filt_Gy(i) = -a(2)*filt_Gy(i-1)+b(1)*Gy(i); + filt_Gz(i) = -a(2)*filt_Gz(i-1)+b(1)*Gz(i); + filt_Mx(i) = -a(2)*filt_Mx(i-1)+b(1)*Mx(i); + filt_My(i) = -a(2)*filt_My(i-1)+b(1)*My(i); + filt_Mz(i) = -a(2)*filt_Mz(i-1)+b(1)*Mz(i); + end + else + filt_Ax(i) = Ax(i); + filt_Ay(i) = Ay(i); + filt_Az(i) = Az(i); + filt_Gx(i) = Gx(i); + filt_Gy(i) = Gy(i); + filt_Gz(i) = Gz(i); + filt_Mx(i) = Mx(i); + filt_My(i) = My(i); + filt_Mz(i) = Mz(i); + end + + % normalize accelerometer measurements + norm_acc = 1/sqrt(filt_Ax(i)^2 + filt_Ay(i)^2 + filt_Az(i)^2); + acc_x(i) = norm_acc * filt_Ax(i); + acc_y(i) = norm_acc * filt_Ay(i); + acc_z(i) = norm_acc * filt_Az(i); + + % normalize magnetometer measurements + norm_mag = 1/sqrt(filt_Mx(i)^2 + filt_My(i)^2 + filt_Mz(i)^2); + mag_x(i) = norm_mag * filt_Mx(i); + mag_y(i) = norm_mag * filt_My(i); + mag_z(i) = norm_mag * filt_Mz(i); + + gyr_x(i) = filt_Gx(i) * PI; + gyr_y(i) = filt_Gy(i) * PI; + gyr_z(i) = filt_Gz(i) * PI; + + UA(i) = sqrt(acc_x(i)^2 + acc_y(i)^2 + acc_z(i)^2) - GRAVITY; + + gyr_x(i) = gyr_x(i) - Bx; + gyr_y(i) = gyr_y(i) - By; + gyr_z(i) = gyr_z(i) - Bz; + + % Aiding System (Accelerometer + Geomagnetic) quaternion generation + % gravity vector in body frame + acc_b =[acc_x(i);acc_y(i);acc_z(i)]; + % magnetic field vector in body frame + mag_b =[mag_x(i);mag_y(i);mag_z(i)]; + + % compute measurement quaternion with TRIAD algorithm + acc_b_x_mag_b = cross(acc_b,mag_b); + acc_e_x_mag_e = cross(acc_e,mag_e); + M_b = [acc_b acc_b_x_mag_b cross(acc_b_x_mag_b,acc_b)]; + M_e = [acc_e acc_e_x_mag_e cross(acc_e_x_mag_e,acc_e)]; + Rot_m = M_e * M_b'; + quat_aid(i,:) = rot_mat2quat(Rot_m); + + euler = quat2euler(quat_aid(i,:)); + roll(i) = euler(1); + pitch(i) = euler(2); + yaw(i) = euler(3); + + if i <= MOVING_AVERAGE_WINDOW_LENGTH + var_Gx(i) = NON_ZERO_VAL; + var_Gy(i) = NON_ZERO_VAL; + var_Gz(i) = NON_ZERO_VAL; + var_roll(i) = NON_ZERO_VAL; + var_pitch(i) = NON_ZERO_VAL; + var_yaw(i) = NON_ZERO_VAL; + else + var_Gx(i) = var(gyr_x((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_Gy(i) = var(gyr_y((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_Gz(i) = var(gyr_z((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_roll(i) = var(roll((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_pitch(i) = var(pitch((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_yaw(i) = var(yaw((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + end + if i > 1 + A_T(i) = ATime(i) - ATime(i-1); + G_T(i) = GTime(i) - GTime(i-1); + M_T(i) = MTime(i) - MTime(i-1); + end + + dt = G_T(i) * US2S; + + Qwn = [var_Gx(i) 0 0;0 var_Gy(i) 0;0 0 var_Gz(i);]; + Qwb = (2 * (ZigmaW^2) / TauW) * eye(3); + + % Process Noise Covariance + Q = [Qwn zeros(3,3);zeros(3,3) Qwb]; + + % Measurement Noise Covariance + R = [[var_roll(i) 0 0;0 var_pitch(i) 0;0 0 var_yaw(i)] zeros(3,3); zeros(3,3) zeros(3,3)]; + + % initialization for q + if i == 1 + q = quat_aid(i,:); + end + + q_t = [q(2) q(3) q(4)]'; + Rtan = (q(1)^2 - q_t'*q_t)*eye(3) + 2*q_t*q_t' - 2*q(1)*[0 -q(4) q(3);q(4) 0 -q(2);-q(3) q(2) 0]; + F = [[0 gyr_z(i) -gyr_y(i);-gyr_z(i) 0 gyr_x(i);gyr_y(i) -gyr_x(i) 0] Rtan; zeros(3,3) (-(1/TauW) * eye(3))]; + + % Time Update + if i > 1 + x(:,i) = F * x(:,i-1); + end + + % compute covariance of prediction + P = (F * P * F') + Q; + + % Driving System (Gyroscope) quaternion generation + % convert scaled gyro data to rad/s + qDot = 0.5 * quat_prod(q, [0 gyr_x(i) gyr_y(i) gyr_z(i)]); + + % Integrate to yield quaternion + q = q + qDot * dt * PI; + + % normalise quaternion + quat_driv(i,:) = q / norm(q); + + % Kalman Filtering + quat_error(i,:) = quat_prod(quat_aid(i,:), quat_driv(i,:)); + + euler_e = quat2euler(quat_error(i,:)); + x1 = euler_e(1)'/PI; + x2 = euler_e(2)'/PI; + x3 = euler_e(3)'/PI; + + q = quat_prod(quat_driv(i,:), [1 x1 x2 x3]) * PI; + q = q / norm(q); + + Bx = Bx + x(4,i); + By = By + x(5,i); + Bz = Bz + x(6,i); + + if i > 1 + e = [x1 x2 x3 x(4,i) x(5,i) x(6,i)]; + end + + for j =1:6 + % compute Kalman gain + K(:,j) = P(j ,:)./(P(j,j)+R(j,j)); + % update state vector + x(:,i) = x(:,i) + K(:,j) * e(j); + % update covariance matrix + P = (eye(6) - (K(:,j) * H(j,:))) * P; + end +end + + +roll = roll * RAD2DEG; +pitch = pitch * RAD2DEG; +yaw = yaw * RAD2DEG; + +euler = quat2euler(quat_driv); +phi = euler(:,1)' * RAD2DEG; +theta = euler(:,2)' * RAD2DEG; +psi = -euler(:,3)' * RAD2DEG; + +euler = quat2euler(quat_error); +roll_e = euler(:,1)' * RAD2DEG; +pitch_e = euler(:,2)' * RAD2DEG; +yaw_e = euler(:,3)' * RAD2DEG; + +% Plot results +close all + +% Rotation Plot Results +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +subplot(3,1,1) +UA = pitch; +p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +hold on; +grid on; +UA = theta; +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = pitch_e; +p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); +title(['Pitch']); +legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); +subplot(3,1,2) +UA = roll; +p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +hold on; +grid on; +UA = phi; +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = roll_e; +p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); +title(['Roll']); +legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); +subplot(3,1,3) +UA = yaw; +p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +hold on; +grid on; +UA = psi; +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = yaw_e; +p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); +title(['Yaw']); +legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); + +% Accelerometer/Gyroscope/Magnetometer scaled Plot results +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +subplot(3,1,1) +p1 = plot(1:BUFFER_SIZE,acc_x(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,gyr_x(1,1:BUFFER_SIZE),'b'); +hold on; +grid on; +p3 = plot(1:BUFFER_SIZE,mag_x(1,1:BUFFER_SIZE),'k'); +title(['Accelerometer/Gyroscope/Magnetometer X-Axis Plot']); +legend([p1 p2 p3],'Acc_X', 'Gyr_X', 'Mag_X'); +subplot(3,1,2) +p1 = plot(1:BUFFER_SIZE,acc_y(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,gyr_y(1,1:BUFFER_SIZE),'b'); +hold on; +grid on; +p3 = plot(1:BUFFER_SIZE,mag_y(1,1:BUFFER_SIZE),'k'); +title(['Accelerometer/Gyroscope/Magnetometer Y-Axis Plot']); +legend([p1 p2 p3],'Acc_Y', 'Gyr_Y', 'Mag_Y'); +subplot(3,1,3) +p1 = plot(1:BUFFER_SIZE,acc_z(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,gyr_z(1,1:BUFFER_SIZE),'b'); +hold on; +grid on; +p3 = plot(1:BUFFER_SIZE,mag_z(1,1:BUFFER_SIZE),'k'); +title(['Accelerometer/Gyroscope/Magnetometer Z-Axis Plot']); +legend([p1 p2 p3],'Acc_Z', 'Gyr_Z', 'Mag_Z'); + +% Accelerometer Raw (vs) filtered output +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +subplot(3,1,1) +p1 = plot(1:BUFFER_SIZE,Ax(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Ax(1,1:BUFFER_SIZE),'b'); +title(['Accelerometer X-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); +subplot(3,1,2) +p1 = plot(1:BUFFER_SIZE,Ay(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Ay(1,1:BUFFER_SIZE),'b'); +title(['Accelerometer Y-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); +subplot(3,1,3) +p1 = plot(1:BUFFER_SIZE,Az(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Az(1,1:BUFFER_SIZE),'b'); +title(['Accelerometer Z-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); + +% Gyroscope Raw (vs) filtered output +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +subplot(3,1,1) +p1 = plot(1:BUFFER_SIZE,Gx(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Gx(1,1:BUFFER_SIZE),'b'); +title(['Gyroscope X-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); +subplot(3,1,2) +p1 = plot(1:BUFFER_SIZE,Gy(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Gy(1,1:BUFFER_SIZE),'b'); +title(['Gyroscope Y-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); +subplot(3,1,3) +p1 = plot(1:BUFFER_SIZE,Gz(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Gz(1,1:BUFFER_SIZE),'b'); +title(['Gyroscope Z-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); + +% Magnetometer Raw (vs) filtered output +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +subplot(3,1,1) +p1 = plot(1:BUFFER_SIZE,Mx(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Mx(1,1:BUFFER_SIZE),'b'); +title(['Magnetometer X-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); +subplot(3,1,2) +p1 = plot(1:BUFFER_SIZE,My(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_My(1,1:BUFFER_SIZE),'b'); +title(['Magnetometer Y-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); +subplot(3,1,3) +p1 = plot(1:BUFFER_SIZE,Mz(1,1:BUFFER_SIZE),'r'); +hold on; +grid on; +p2 = plot(1:BUFFER_SIZE,filt_Mz(1,1:BUFFER_SIZE),'b'); +title(['Magnetometer Z-Axis Plot']); +legend([p1 p2],'input signal','low-pass filtered signal'); + -- 2.7.4 From da3020481d5f98ca0d72ce5edef656fa8211c73e Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Mon, 28 Apr 2014 09:28:52 +0530 Subject: [PATCH 06/13] Separating sensor orientation as new function call Moved sensor orientation to new function as this will be called separately during estimation of orientation, gravity and linear acceleration independently. The input data used for sumulation and output data plotting will be different in each case. signed-off-by: Ramasamy Change-Id: I95ad1221887a2381f4c1e22c4e48b82f6950c179 --- .../design/lib/estimate_orientation.m | 431 ++++++++++++++++++ src/sensor_fusion/design/lib/quat2euler.m | 2 +- src/sensor_fusion/design/lib/quat2rot_mat.m | 1 - src/sensor_fusion/design/lib/quat_prod.m | 1 - src/sensor_fusion/design/lib/rot_mat2quat.m | 2 +- src/sensor_fusion/design/sf_orien.m | 491 --------------------- src/sensor_fusion/design/sf_orientation.m | 122 +++++ 7 files changed, 555 insertions(+), 495 deletions(-) create mode 100755 src/sensor_fusion/design/lib/estimate_orientation.m delete mode 100755 src/sensor_fusion/design/sf_orien.m create mode 100755 src/sensor_fusion/design/sf_orientation.m diff --git a/src/sensor_fusion/design/lib/estimate_orientation.m b/src/sensor_fusion/design/lib/estimate_orientation.m new file mode 100755 index 0000000..87d0515 --- /dev/null +++ b/src/sensor_fusion/design/lib/estimate_orientation.m @@ -0,0 +1,431 @@ +% estimate_orientation +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Orientation Estimation function +% +% - Orientation Estimation using Gyroscope as the driving system and Accelerometer+Geo-Magnetic Sensors as Aiding System. +% - Quaternion based approach +% - Estimation and correction of Euler errors and bias errors for gyroscope using Kalman filter + +function [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data, Mag_data) + + LOW_PASS_FILTERING_ON = 0; + PLOT_SCALED_SENSOR_COMPARISON_DATA = 0; + PLOT_INDIVIDUAL_SENSOR_INPUT_DATA = 0; + + GRAVITY = 9.80665; + PI = 3.141593; + NON_ZERO_VAL = 0.1; + + MOVING_AVERAGE_WINDOW_LENGTH = 20; + RAD2DEG = 57.2957795; + DEG2RAD = 0.0174532925; + US2S = 1.0 / 1000000.0; + + % Gyro Types + % Systron-donner "Horizon" + ZigmaW = 0.05 * DEG2RAD; %deg/s + TauW = 1000; %secs + % Crossbow DMU-6X + %ZigmaW = 0.05 * DEG2RAD; %deg/s + %TauW = 300; %secs + %FOGs (KVH Autogyro and Crossbow DMU-FOG) + %ZigmaW = 0; %deg/s + + BUFFER_SIZE = size(Accel_data,2); + Ax = Accel_data(1,:); + Ay = Accel_data(2,:); + Az = Accel_data(3,:); + ATime = Accel_data(4,:); + + Gx = Gyro_data(1,:); + Gy = Gyro_data(2,:); + Gz = Gyro_data(3,:); + GTime = Gyro_data(4,:); + + Mx = Mag_data(1,:); + My = Mag_data(2,:); + Mz = Mag_data(3,:); + MTime = Mag_data(4,:); + + % Gyroscope Bias Variables + Bx = 0; By = 0; Bz = 0; + + % 1st order smoothening filter + b = [0.98 0 ]; + a = [1.0000000 0.02 ]; + + % initialize filter output variables to zero + filt_Ax = zeros(1,BUFFER_SIZE); + filt_Ay = zeros(1,BUFFER_SIZE); + filt_Az = zeros(1,BUFFER_SIZE); + filt_Gx = zeros(1,BUFFER_SIZE); + filt_Gy = zeros(1,BUFFER_SIZE); + filt_Gz = zeros(1,BUFFER_SIZE); + filt_Mx = zeros(1,BUFFER_SIZE); + filt_My = zeros(1,BUFFER_SIZE); + filt_Mz = zeros(1,BUFFER_SIZE); + + acc_x = zeros(1,BUFFER_SIZE); + acc_y = zeros(1,BUFFER_SIZE); + acc_z = zeros(1,BUFFER_SIZE); + gyr_x = zeros(1,BUFFER_SIZE); + gyr_y = zeros(1,BUFFER_SIZE); + gyr_z = zeros(1,BUFFER_SIZE); + mag_x = zeros(1,BUFFER_SIZE); + mag_y = zeros(1,BUFFER_SIZE); + mag_z = zeros(1,BUFFER_SIZE); + + % User Acceleration mean and Variance + A_T = zeros(1,BUFFER_SIZE); + G_T = zeros(1,BUFFER_SIZE); + M_T = zeros(1,BUFFER_SIZE); + var_roll = zeros(1,BUFFER_SIZE); + var_pitch = zeros(1,BUFFER_SIZE); + var_yaw = zeros(1,BUFFER_SIZE); + var_Gx = zeros(1,BUFFER_SIZE); + var_Gy = zeros(1,BUFFER_SIZE); + var_Gz = zeros(1,BUFFER_SIZE); + + roll = zeros(1,BUFFER_SIZE); + pitch = zeros(1,BUFFER_SIZE); + yaw = zeros(1,BUFFER_SIZE); + quat_driv = zeros(BUFFER_SIZE,4); + quat_aid = zeros(BUFFER_SIZE,4); + quat_error = zeros(BUFFER_SIZE,4); + euler = zeros(BUFFER_SIZE,3); + Ro = zeros(3, 3, BUFFER_SIZE); + + OR_driv = zeros(3,BUFFER_SIZE); + OR_aid = zeros(3,BUFFER_SIZE); + OR_err = zeros(3,BUFFER_SIZE); + + % system covariance matrix + Q = zeros(6,6); + + % measurement covariance matrix + R = zeros(6,6); + + A_T(1) = 100000; + G_T(1) = 100000; + M_T(1) = 100000; + + acc_e = [0.0;0.0;1.0]; % gravity vector in earth frame + mag_e = [0.0;1.0;0.0]; % magnetic field vector in earth frame + + H = [eye(3) zeros(3,3); zeros(3,6)]; + x = zeros(6,BUFFER_SIZE); + e = zeros(1,6); + P = 1 * eye(6);% state covariance matrix + + quat_driv(1,:) = [1 0 0 0]; + + % first order filtering + for i = 1:BUFFER_SIZE + if LOW_PASS_FILTERING_ON == 1 + if i < 2 + filt_Ax(i) = Ax(i); + filt_Ay(i) = Ay(i); + filt_Az(i) = Az(i); + filt_Gx(i) = Gx(i); + filt_Gy(i) = Gy(i); + filt_Gz(i) = Gz(i); + filt_Mx(i) = Mx(i); + filt_My(i) = My(i); + filt_Mz(i) = Mz(i); + elseif i >= 2 + filt_Ax(i) = -a(2)*filt_Ax(i-1)+b(1)*Ax(i); + filt_Ay(i) = -a(2)*filt_Ay(i-1)+b(1)*Ay(i); + filt_Az(i) = -a(2)*filt_Az(i-1)+b(1)*Az(i); + filt_Gx(i) = -a(2)*filt_Gx(i-1)+b(1)*Gx(i); + filt_Gy(i) = -a(2)*filt_Gy(i-1)+b(1)*Gy(i); + filt_Gz(i) = -a(2)*filt_Gz(i-1)+b(1)*Gz(i); + filt_Mx(i) = -a(2)*filt_Mx(i-1)+b(1)*Mx(i); + filt_My(i) = -a(2)*filt_My(i-1)+b(1)*My(i); + filt_Mz(i) = -a(2)*filt_Mz(i-1)+b(1)*Mz(i); + end + else + filt_Ax(i) = Ax(i); + filt_Ay(i) = Ay(i); + filt_Az(i) = Az(i); + filt_Gx(i) = Gx(i); + filt_Gy(i) = Gy(i); + filt_Gz(i) = Gz(i); + filt_Mx(i) = Mx(i); + filt_My(i) = My(i); + filt_Mz(i) = Mz(i); + end + + % normalize accelerometer measurements + norm_acc = 1/sqrt(filt_Ax(i)^2 + filt_Ay(i)^2 + filt_Az(i)^2); + acc_x(i) = norm_acc * filt_Ax(i); + acc_y(i) = norm_acc * filt_Ay(i); + acc_z(i) = norm_acc * filt_Az(i); + + % normalize magnetometer measurements + norm_mag = 1/sqrt(filt_Mx(i)^2 + filt_My(i)^2 + filt_Mz(i)^2); + mag_x(i) = norm_mag * filt_Mx(i); + mag_y(i) = norm_mag * filt_My(i); + mag_z(i) = norm_mag * filt_Mz(i); + + gyr_x(i) = filt_Gx(i) * PI; + gyr_y(i) = filt_Gy(i) * PI; + gyr_z(i) = filt_Gz(i) * PI; + + UA(i) = sqrt(acc_x(i)^2 + acc_y(i)^2 + acc_z(i)^2) - GRAVITY; + + gyr_x(i) = gyr_x(i) - Bx; + gyr_y(i) = gyr_y(i) - By; + gyr_z(i) = gyr_z(i) - Bz; + + % Aiding System (Accelerometer + Geomagnetic) quaternion generation + % gravity vector in body frame + acc_b =[acc_x(i);acc_y(i);acc_z(i)]; + % magnetic field vector in body frame + mag_b =[mag_x(i);mag_y(i);mag_z(i)]; + + % compute measurement quaternion with TRIAD algorithm + acc_b_x_mag_b = cross(acc_b,mag_b); + acc_e_x_mag_e = cross(acc_e,mag_e); + M_b = [acc_b acc_b_x_mag_b cross(acc_b_x_mag_b,acc_b)]; + M_e = [acc_e acc_e_x_mag_e cross(acc_e_x_mag_e,acc_e)]; + Rot_m = M_e * M_b'; + quat_aid(i,:) = rot_mat2quat(Rot_m); + + euler = quat2euler(quat_aid(i,:)); + roll(i) = euler(1); + pitch(i) = euler(2); + yaw(i) = euler(3); + + if i <= MOVING_AVERAGE_WINDOW_LENGTH + var_Gx(i) = NON_ZERO_VAL; + var_Gy(i) = NON_ZERO_VAL; + var_Gz(i) = NON_ZERO_VAL; + var_roll(i) = NON_ZERO_VAL; + var_pitch(i) = NON_ZERO_VAL; + var_yaw(i) = NON_ZERO_VAL; + else + var_Gx(i) = var(gyr_x((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_Gy(i) = var(gyr_y((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_Gz(i) = var(gyr_z((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_roll(i) = var(roll((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_pitch(i) = var(pitch((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + var_yaw(i) = var(yaw((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); + end + if i > 1 + A_T(i) = ATime(i) - ATime(i-1); + G_T(i) = GTime(i) - GTime(i-1); + M_T(i) = MTime(i) - MTime(i-1); + end + + dt = G_T(i) * US2S; + + Qwn = [var_Gx(i) 0 0;0 var_Gy(i) 0;0 0 var_Gz(i);]; + Qwb = (2 * (ZigmaW^2) / TauW) * eye(3); + + % Process Noise Covariance + Q = [Qwn zeros(3,3);zeros(3,3) Qwb]; + + % Measurement Noise Covariance + R = [[var_roll(i) 0 0;0 var_pitch(i) 0;0 0 var_yaw(i)] zeros(3,3); zeros(3,3) zeros(3,3)]; + + % initialization for q + if i == 1 + q = quat_aid(i,:); + end + + q_t = [q(2) q(3) q(4)]'; + Rtan = (q(1)^2 - q_t'*q_t)*eye(3) + 2*q_t*q_t' - 2*q(1)*[0 -q(4) q(3);q(4) 0 -q(2);-q(3) q(2) 0]; + F = [[0 gyr_z(i) -gyr_y(i);-gyr_z(i) 0 gyr_x(i);gyr_y(i) -gyr_x(i) 0] Rtan; zeros(3,3) (-(1/TauW) * eye(3))]; + + % Time Update + if i > 1 + x(:,i) = F * x(:,i-1); + end + + % compute covariance of prediction + P = (F * P * F') + Q; + + % Driving System (Gyroscope) quaternion generation + % convert scaled gyro data to rad/s + qDot = 0.5 * quat_prod(q, [0 gyr_x(i) gyr_y(i) gyr_z(i)]); + + % Integrate to yield quaternion + q = q + qDot * dt * PI; + + % normalise quaternion + quat_driv(i,:) = q / norm(q); + + % Kalman Filtering + quat_error(i,:) = quat_prod(quat_aid(i,:), quat_driv(i,:)); + + euler_e = quat2euler(quat_error(i,:)); + x1 = euler_e(1)'/PI; + x2 = euler_e(2)'/PI; + x3 = euler_e(3)'/PI; + + q = quat_prod(quat_driv(i,:), [1 x1 x2 x3]) * PI; + q = q / norm(q); + + if i > 1 + e = [x1 x2 x3 x(4,i) x(5,i) x(6,i)]; + end + + for j =1:6 + % compute Kalman gain + K(:,j) = P(j ,:)./(P(j,j)+R(j,j)); + % update state vector + x(:,i) = x(:,i) + K(:,j) * e(j); + % update covariance matrix + P = (eye(6) - (K(:,j) * H(j,:))) * P; + end + + Bx = Bx + x(4,i); + By = By + x(5,i); + Bz = Bz + x(6,i); + end + + OR_aid(1,:) = roll * RAD2DEG; + OR_aid(2,:) = pitch * RAD2DEG; + OR_aid(3,:) = yaw * RAD2DEG; + + euler = quat2euler(quat_driv); + OR_driv(1,:) = euler(:,1)' * RAD2DEG; + OR_driv(2,:) = euler(:,2)' * RAD2DEG; + OR_driv(3,:) = -euler(:,3)' * RAD2DEG; + + euler = quat2euler(quat_error); + OR_err(1,:) = euler(:,1)' * RAD2DEG; + OR_err(2,:) = euler(:,2)' * RAD2DEG; + OR_err(3,:) = euler(:,3)' * RAD2DEG; + + if PLOT_SCALED_SENSOR_COMPARISON_DATA == 1 + % Accelerometer/Gyroscope/Magnetometer scaled Plot results + hfig=(figure); + scrsz = get(0,'ScreenSize'); + set(hfig,'position',scrsz); + subplot(3,1,1) + p1 = plot(1:BUFFER_SIZE,acc_x(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,gyr_x(1,1:BUFFER_SIZE),'b'); + hold on; + grid on; + p3 = plot(1:BUFFER_SIZE,mag_x(1,1:BUFFER_SIZE),'k'); + title(['Accelerometer/Gyroscope/Magnetometer X-Axis Plot']); + legend([p1 p2 p3],'Acc_X', 'Gyr_X', 'Mag_X'); + subplot(3,1,2) + p1 = plot(1:BUFFER_SIZE,acc_y(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,gyr_y(1,1:BUFFER_SIZE),'b'); + hold on; + grid on; + p3 = plot(1:BUFFER_SIZE,mag_y(1,1:BUFFER_SIZE),'k'); + title(['Accelerometer/Gyroscope/Magnetometer Y-Axis Plot']); + legend([p1 p2 p3],'Acc_Y', 'Gyr_Y', 'Mag_Y'); + subplot(3,1,3) + p1 = plot(1:BUFFER_SIZE,acc_z(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,gyr_z(1,1:BUFFER_SIZE),'b'); + hold on; + grid on; + p3 = plot(1:BUFFER_SIZE,mag_z(1,1:BUFFER_SIZE),'k'); + title(['Accelerometer/Gyroscope/Magnetometer Z-Axis Plot']); + legend([p1 p2 p3],'Acc_Z', 'Gyr_Z', 'Mag_Z'); + end + + if PLOT_INDIVIDUAL_SENSOR_INPUT_DATA == 1 + % Accelerometer Raw (vs) filtered output + hfig=(figure); + scrsz = get(0,'ScreenSize'); + set(hfig,'position',scrsz); + subplot(3,1,1) + p1 = plot(1:BUFFER_SIZE,Ax(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Ax(1,1:BUFFER_SIZE),'b'); + title(['Accelerometer X-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + subplot(3,1,2) + p1 = plot(1:BUFFER_SIZE,Ay(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Ay(1,1:BUFFER_SIZE),'b'); + title(['Accelerometer Y-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + subplot(3,1,3) + p1 = plot(1:BUFFER_SIZE,Az(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Az(1,1:BUFFER_SIZE),'b'); + title(['Accelerometer Z-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + + % Gyroscope Raw (vs) filtered output + hfig=(figure); + scrsz = get(0,'ScreenSize'); + set(hfig,'position',scrsz); + subplot(3,1,1) + p1 = plot(1:BUFFER_SIZE,Gx(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Gx(1,1:BUFFER_SIZE),'b'); + title(['Gyroscope X-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + subplot(3,1,2) + p1 = plot(1:BUFFER_SIZE,Gy(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Gy(1,1:BUFFER_SIZE),'b'); + title(['Gyroscope Y-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + subplot(3,1,3) + p1 = plot(1:BUFFER_SIZE,Gz(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Gz(1,1:BUFFER_SIZE),'b'); + title(['Gyroscope Z-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + + % Magnetometer Raw (vs) filtered output + hfig=(figure); + scrsz = get(0,'ScreenSize'); + set(hfig,'position',scrsz); + subplot(3,1,1) + p1 = plot(1:BUFFER_SIZE,Mx(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Mx(1,1:BUFFER_SIZE),'b'); + title(['Magnetometer X-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + subplot(3,1,2) + p1 = plot(1:BUFFER_SIZE,My(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_My(1,1:BUFFER_SIZE),'b'); + title(['Magnetometer Y-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + subplot(3,1,3) + p1 = plot(1:BUFFER_SIZE,Mz(1,1:BUFFER_SIZE),'r'); + hold on; + grid on; + p2 = plot(1:BUFFER_SIZE,filt_Mz(1,1:BUFFER_SIZE),'b'); + title(['Magnetometer Z-Axis Plot']); + legend([p1 p2],'input signal','low-pass filtered signal'); + end +end diff --git a/src/sensor_fusion/design/lib/quat2euler.m b/src/sensor_fusion/design/lib/quat2euler.m index 9cba0e1..16e46b3 100755 --- a/src/sensor_fusion/design/lib/quat2euler.m +++ b/src/sensor_fusion/design/lib/quat2euler.m @@ -29,4 +29,4 @@ function euler = quat2euler(q) psi = atan2(R(2,1,:), R(1,1,:) ); euler = [phi(1,:)' theta(1,:)' psi(1,:)']; -end \ No newline at end of file +end diff --git a/src/sensor_fusion/design/lib/quat2rot_mat.m b/src/sensor_fusion/design/lib/quat2rot_mat.m index 6e795fc..bb11d08 100755 --- a/src/sensor_fusion/design/lib/quat2rot_mat.m +++ b/src/sensor_fusion/design/lib/quat2rot_mat.m @@ -27,4 +27,3 @@ function R = quat2rot_mat(q) R(3,2,:) = 2.*(q(:,3).*q(:,4)-q(:,1).*q(:,2)); R(3,3,:) = 2.*q(:,1).^2-1+2.*q(:,4).^2; end - diff --git a/src/sensor_fusion/design/lib/quat_prod.m b/src/sensor_fusion/design/lib/quat_prod.m index 3ca9acf..40d2c57 100755 --- a/src/sensor_fusion/design/lib/quat_prod.m +++ b/src/sensor_fusion/design/lib/quat_prod.m @@ -22,4 +22,3 @@ function ab = quat_prod(a, b) ab(:,3) = a(:,1).*b(:,3)-a(:,2).*b(:,4)+a(:,3).*b(:,1)+a(:,4).*b(:,2); ab(:,4) = a(:,1).*b(:,4)+a(:,2).*b(:,3)-a(:,3).*b(:,2)+a(:,4).*b(:,1); end - diff --git a/src/sensor_fusion/design/lib/rot_mat2quat.m b/src/sensor_fusion/design/lib/rot_mat2quat.m index 133068c..dcc3410 100755 --- a/src/sensor_fusion/design/lib/rot_mat2quat.m +++ b/src/sensor_fusion/design/lib/rot_mat2quat.m @@ -41,4 +41,4 @@ function q = rot_mat2quat(R) q(i,:) = V(:,4)'; q(i,:) = [q(i,4) q(i,1) q(i,2) q(i,3)]; end -end \ No newline at end of file +end diff --git a/src/sensor_fusion/design/sf_orien.m b/src/sensor_fusion/design/sf_orien.m deleted file mode 100755 index eebc2c0..0000000 --- a/src/sensor_fusion/design/sf_orien.m +++ /dev/null @@ -1,491 +0,0 @@ -% SF_Orien -% -% Copyright (c) 2014 Samsung Electronics Co., Ltd. -% -% Licensed under the Apache License, Version 2.0 (the "License"); -% you may not use this file except in compliance with the License. -% You may obtain a copy of the License at -% -% http://www.apache.org/licenses/LICENSE-2.0 -% -% Unless required by applicable law or agreed to in writing, software -% distributed under the License is distributed on an "AS IS" BASIS, -% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -% See the License for the specific language governing permissions and -% limitations under the License. - -% Sensor Fusion Implementation - Orientation Estimation -% -% - Orientation Estimation using Gyroscope as the driving system and Accelerometer+Geo-Magnetic Sensors as Aiding System. -% - Quaternion based approach -% - Estimation and correction of Euler errors and bias errors for gyroscope using Kalman filter - -addpath('lib'); -clear -clc - -LOW_PASS_FILTERING_ON = 1; - -Max_Range_Accel = 39.203407; Min_Range_Accel = -39.204006; Res_Accel = 0.000598; -Max_Range_Gyro = 1146.862549; Min_Range_Gyro = -1146.880005; Res_Gyro = 0.017500; -Max_Range_Magnetic = 1200; Min_Range_Magnetic = -1200; Res_Magnetic = 1; - -PI = 3.141593; -GRAVITY = 9.80665; -NON_ZERO_VAL = 0.1; - -Bias_Ax = 0.098586; -Bias_Ay = 0.18385; -Bias_Az = 10.084 - GRAVITY; - -Bias_Gx = -5.3539; -Bias_Gy = 0.24325; -Bias_Gz = 2.3391; - -BUFFER_SIZE = 1095; -MOVING_AVERAGE_WINDOW_LENGTH = 20; -RAD2DEG = 57.2957795; -DEG2RAD = 0.0174532925; -US2S = 1.0 / 1000000.0; - -% Gyro Types -% Systron-donner "Horizon" -ZigmaW = 0.05 * DEG2RAD; %deg/s -TauW = 1000; %secs -% Crossbow DMU-6X -%ZigmaW = 0.05 * DEG2RAD; %deg/s -%TauW = 300; %secs -%FOGs (KVH Autogyro and Crossbow DMU-FOG) -%ZigmaW = 0; %deg/s - -% get accel x,y,z axis data from stored file -Ax = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,1))') - Bias_Ax)(1:BUFFER_SIZE); -Ay = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,2))') - Bias_Ay)(1:BUFFER_SIZE); -Az = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,3))') - Bias_Az)(1:BUFFER_SIZE); -ATime = ((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,4))'); - -% get gyro x,y,z axis data from stored file -Gx = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,1))') - Bias_Gx)(1:BUFFER_SIZE); -Gy = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,2))') - Bias_Gy)(1:BUFFER_SIZE); -Gz = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,3))') - Bias_Gz)(1:BUFFER_SIZE); -GTime = ((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,4))'); - -scale_Gyro = 575; -Gx = Gx/scale_Gyro; -Gy = Gy/scale_Gyro; -Gz = Gz/scale_Gyro; - -% get magnetometer x,y,z axis data from stored file -Mx = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,1))'))(1:BUFFER_SIZE); -My = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,2))'))(1:BUFFER_SIZE); -Mz = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,3))'))(1:BUFFER_SIZE); -MTime = ((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,4))'); - -% Gyroscope Bias Variables -Bx = 0; By = 0; Bz = 0; - -% 1st order smoothening filter -b = [0.98 0 ]; -a = [1.0000000 0.02 ]; - -% initialize filter output variables to zero -filt_Ax = zeros(1,BUFFER_SIZE); -filt_Ay = zeros(1,BUFFER_SIZE); -filt_Az = zeros(1,BUFFER_SIZE); -filt_Gx = zeros(1,BUFFER_SIZE); -filt_Gy = zeros(1,BUFFER_SIZE); -filt_Gz = zeros(1,BUFFER_SIZE); -filt_Mx = zeros(1,BUFFER_SIZE); -filt_My = zeros(1,BUFFER_SIZE); -filt_Mz = zeros(1,BUFFER_SIZE); - -acc_x = zeros(1,BUFFER_SIZE); -acc_y = zeros(1,BUFFER_SIZE); -acc_z = zeros(1,BUFFER_SIZE); -gyr_x = zeros(1,BUFFER_SIZE); -gyr_y = zeros(1,BUFFER_SIZE); -gyr_z = zeros(1,BUFFER_SIZE); -mag_x = zeros(1,BUFFER_SIZE); -mag_y = zeros(1,BUFFER_SIZE); -mag_z = zeros(1,BUFFER_SIZE); - -% User Acceleration mean and Variance -A_T = zeros(1,BUFFER_SIZE); -G_T = zeros(1,BUFFER_SIZE); -M_T = zeros(1,BUFFER_SIZE); -var_roll = zeros(1,BUFFER_SIZE); -var_pitch = zeros(1,BUFFER_SIZE); -var_yaw = zeros(1,BUFFER_SIZE); -var_Gx = zeros(1,BUFFER_SIZE); -var_Gy = zeros(1,BUFFER_SIZE); -var_Gz = zeros(1,BUFFER_SIZE); - -roll = zeros(1,BUFFER_SIZE); -pitch = zeros(1,BUFFER_SIZE); -yaw = zeros(1,BUFFER_SIZE); -quat_driv = zeros(BUFFER_SIZE,4); -quat_aid = zeros(BUFFER_SIZE,4); -quat_error = zeros(BUFFER_SIZE,4); -euler = zeros(BUFFER_SIZE,3); -Ro = zeros(3, 3, BUFFER_SIZE); - -% system covariance matrix -Q = zeros(6,6); - -% measurement covariance matrix -R = zeros(6,6); - -A_T(1) = 100000; -G_T(1) = 100000; -M_T(1) = 100000; - -acc_e = [0.0;0.0;1.0]; % gravity vector in earth frame -mag_e = [0.0;1.0;0.0]; % magnetic field vector in earth frame - -H = [eye(3) zeros(3,3); zeros(3,6)]; -x = zeros(6,BUFFER_SIZE); -e = zeros(1,6); -P = 1 * eye(6);% state covariance matrix - -quat_driv(1,:) = [1 0 0 0]; - -% first order filtering -for i = 1:BUFFER_SIZE - if LOW_PASS_FILTERING_ON == 1 - if i < 2 - filt_Ax(i) = Ax(i); - filt_Ay(i) = Ay(i); - filt_Az(i) = Az(i); - filt_Gx(i) = Gx(i); - filt_Gy(i) = Gy(i); - filt_Gz(i) = Gz(i); - filt_Mx(i) = Mx(i); - filt_My(i) = My(i); - filt_Mz(i) = Mz(i); - elseif i >= 2 - filt_Ax(i) = -a(2)*filt_Ax(i-1)+b(1)*Ax(i); - filt_Ay(i) = -a(2)*filt_Ay(i-1)+b(1)*Ay(i); - filt_Az(i) = -a(2)*filt_Az(i-1)+b(1)*Az(i); - filt_Gx(i) = -a(2)*filt_Gx(i-1)+b(1)*Gx(i); - filt_Gy(i) = -a(2)*filt_Gy(i-1)+b(1)*Gy(i); - filt_Gz(i) = -a(2)*filt_Gz(i-1)+b(1)*Gz(i); - filt_Mx(i) = -a(2)*filt_Mx(i-1)+b(1)*Mx(i); - filt_My(i) = -a(2)*filt_My(i-1)+b(1)*My(i); - filt_Mz(i) = -a(2)*filt_Mz(i-1)+b(1)*Mz(i); - end - else - filt_Ax(i) = Ax(i); - filt_Ay(i) = Ay(i); - filt_Az(i) = Az(i); - filt_Gx(i) = Gx(i); - filt_Gy(i) = Gy(i); - filt_Gz(i) = Gz(i); - filt_Mx(i) = Mx(i); - filt_My(i) = My(i); - filt_Mz(i) = Mz(i); - end - - % normalize accelerometer measurements - norm_acc = 1/sqrt(filt_Ax(i)^2 + filt_Ay(i)^2 + filt_Az(i)^2); - acc_x(i) = norm_acc * filt_Ax(i); - acc_y(i) = norm_acc * filt_Ay(i); - acc_z(i) = norm_acc * filt_Az(i); - - % normalize magnetometer measurements - norm_mag = 1/sqrt(filt_Mx(i)^2 + filt_My(i)^2 + filt_Mz(i)^2); - mag_x(i) = norm_mag * filt_Mx(i); - mag_y(i) = norm_mag * filt_My(i); - mag_z(i) = norm_mag * filt_Mz(i); - - gyr_x(i) = filt_Gx(i) * PI; - gyr_y(i) = filt_Gy(i) * PI; - gyr_z(i) = filt_Gz(i) * PI; - - UA(i) = sqrt(acc_x(i)^2 + acc_y(i)^2 + acc_z(i)^2) - GRAVITY; - - gyr_x(i) = gyr_x(i) - Bx; - gyr_y(i) = gyr_y(i) - By; - gyr_z(i) = gyr_z(i) - Bz; - - % Aiding System (Accelerometer + Geomagnetic) quaternion generation - % gravity vector in body frame - acc_b =[acc_x(i);acc_y(i);acc_z(i)]; - % magnetic field vector in body frame - mag_b =[mag_x(i);mag_y(i);mag_z(i)]; - - % compute measurement quaternion with TRIAD algorithm - acc_b_x_mag_b = cross(acc_b,mag_b); - acc_e_x_mag_e = cross(acc_e,mag_e); - M_b = [acc_b acc_b_x_mag_b cross(acc_b_x_mag_b,acc_b)]; - M_e = [acc_e acc_e_x_mag_e cross(acc_e_x_mag_e,acc_e)]; - Rot_m = M_e * M_b'; - quat_aid(i,:) = rot_mat2quat(Rot_m); - - euler = quat2euler(quat_aid(i,:)); - roll(i) = euler(1); - pitch(i) = euler(2); - yaw(i) = euler(3); - - if i <= MOVING_AVERAGE_WINDOW_LENGTH - var_Gx(i) = NON_ZERO_VAL; - var_Gy(i) = NON_ZERO_VAL; - var_Gz(i) = NON_ZERO_VAL; - var_roll(i) = NON_ZERO_VAL; - var_pitch(i) = NON_ZERO_VAL; - var_yaw(i) = NON_ZERO_VAL; - else - var_Gx(i) = var(gyr_x((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); - var_Gy(i) = var(gyr_y((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); - var_Gz(i) = var(gyr_z((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); - var_roll(i) = var(roll((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); - var_pitch(i) = var(pitch((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); - var_yaw(i) = var(yaw((i-MOVING_AVERAGE_WINDOW_LENGTH):i)); - end - if i > 1 - A_T(i) = ATime(i) - ATime(i-1); - G_T(i) = GTime(i) - GTime(i-1); - M_T(i) = MTime(i) - MTime(i-1); - end - - dt = G_T(i) * US2S; - - Qwn = [var_Gx(i) 0 0;0 var_Gy(i) 0;0 0 var_Gz(i);]; - Qwb = (2 * (ZigmaW^2) / TauW) * eye(3); - - % Process Noise Covariance - Q = [Qwn zeros(3,3);zeros(3,3) Qwb]; - - % Measurement Noise Covariance - R = [[var_roll(i) 0 0;0 var_pitch(i) 0;0 0 var_yaw(i)] zeros(3,3); zeros(3,3) zeros(3,3)]; - - % initialization for q - if i == 1 - q = quat_aid(i,:); - end - - q_t = [q(2) q(3) q(4)]'; - Rtan = (q(1)^2 - q_t'*q_t)*eye(3) + 2*q_t*q_t' - 2*q(1)*[0 -q(4) q(3);q(4) 0 -q(2);-q(3) q(2) 0]; - F = [[0 gyr_z(i) -gyr_y(i);-gyr_z(i) 0 gyr_x(i);gyr_y(i) -gyr_x(i) 0] Rtan; zeros(3,3) (-(1/TauW) * eye(3))]; - - % Time Update - if i > 1 - x(:,i) = F * x(:,i-1); - end - - % compute covariance of prediction - P = (F * P * F') + Q; - - % Driving System (Gyroscope) quaternion generation - % convert scaled gyro data to rad/s - qDot = 0.5 * quat_prod(q, [0 gyr_x(i) gyr_y(i) gyr_z(i)]); - - % Integrate to yield quaternion - q = q + qDot * dt * PI; - - % normalise quaternion - quat_driv(i,:) = q / norm(q); - - % Kalman Filtering - quat_error(i,:) = quat_prod(quat_aid(i,:), quat_driv(i,:)); - - euler_e = quat2euler(quat_error(i,:)); - x1 = euler_e(1)'/PI; - x2 = euler_e(2)'/PI; - x3 = euler_e(3)'/PI; - - q = quat_prod(quat_driv(i,:), [1 x1 x2 x3]) * PI; - q = q / norm(q); - - Bx = Bx + x(4,i); - By = By + x(5,i); - Bz = Bz + x(6,i); - - if i > 1 - e = [x1 x2 x3 x(4,i) x(5,i) x(6,i)]; - end - - for j =1:6 - % compute Kalman gain - K(:,j) = P(j ,:)./(P(j,j)+R(j,j)); - % update state vector - x(:,i) = x(:,i) + K(:,j) * e(j); - % update covariance matrix - P = (eye(6) - (K(:,j) * H(j,:))) * P; - end -end - - -roll = roll * RAD2DEG; -pitch = pitch * RAD2DEG; -yaw = yaw * RAD2DEG; - -euler = quat2euler(quat_driv); -phi = euler(:,1)' * RAD2DEG; -theta = euler(:,2)' * RAD2DEG; -psi = -euler(:,3)' * RAD2DEG; - -euler = quat2euler(quat_error); -roll_e = euler(:,1)' * RAD2DEG; -pitch_e = euler(:,2)' * RAD2DEG; -yaw_e = euler(:,3)' * RAD2DEG; - -% Plot results -close all - -% Rotation Plot Results -hfig=(figure); -scrsz = get(0,'ScreenSize'); -set(hfig,'position',scrsz); -subplot(3,1,1) -UA = pitch; -p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); -hold on; -grid on; -UA = theta; -p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); -hold on; -grid on; -UA = pitch_e; -p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); -title(['Pitch']); -legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); -subplot(3,1,2) -UA = roll; -p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); -hold on; -grid on; -UA = phi; -p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); -hold on; -grid on; -UA = roll_e; -p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); -title(['Roll']); -legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); -subplot(3,1,3) -UA = yaw; -p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); -hold on; -grid on; -UA = psi; -p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); -hold on; -grid on; -UA = yaw_e; -p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); -title(['Yaw']); -legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); - -% Accelerometer/Gyroscope/Magnetometer scaled Plot results -hfig=(figure); -scrsz = get(0,'ScreenSize'); -set(hfig,'position',scrsz); -subplot(3,1,1) -p1 = plot(1:BUFFER_SIZE,acc_x(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,gyr_x(1,1:BUFFER_SIZE),'b'); -hold on; -grid on; -p3 = plot(1:BUFFER_SIZE,mag_x(1,1:BUFFER_SIZE),'k'); -title(['Accelerometer/Gyroscope/Magnetometer X-Axis Plot']); -legend([p1 p2 p3],'Acc_X', 'Gyr_X', 'Mag_X'); -subplot(3,1,2) -p1 = plot(1:BUFFER_SIZE,acc_y(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,gyr_y(1,1:BUFFER_SIZE),'b'); -hold on; -grid on; -p3 = plot(1:BUFFER_SIZE,mag_y(1,1:BUFFER_SIZE),'k'); -title(['Accelerometer/Gyroscope/Magnetometer Y-Axis Plot']); -legend([p1 p2 p3],'Acc_Y', 'Gyr_Y', 'Mag_Y'); -subplot(3,1,3) -p1 = plot(1:BUFFER_SIZE,acc_z(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,gyr_z(1,1:BUFFER_SIZE),'b'); -hold on; -grid on; -p3 = plot(1:BUFFER_SIZE,mag_z(1,1:BUFFER_SIZE),'k'); -title(['Accelerometer/Gyroscope/Magnetometer Z-Axis Plot']); -legend([p1 p2 p3],'Acc_Z', 'Gyr_Z', 'Mag_Z'); - -% Accelerometer Raw (vs) filtered output -hfig=(figure); -scrsz = get(0,'ScreenSize'); -set(hfig,'position',scrsz); -subplot(3,1,1) -p1 = plot(1:BUFFER_SIZE,Ax(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Ax(1,1:BUFFER_SIZE),'b'); -title(['Accelerometer X-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); -subplot(3,1,2) -p1 = plot(1:BUFFER_SIZE,Ay(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Ay(1,1:BUFFER_SIZE),'b'); -title(['Accelerometer Y-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); -subplot(3,1,3) -p1 = plot(1:BUFFER_SIZE,Az(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Az(1,1:BUFFER_SIZE),'b'); -title(['Accelerometer Z-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); - -% Gyroscope Raw (vs) filtered output -hfig=(figure); -scrsz = get(0,'ScreenSize'); -set(hfig,'position',scrsz); -subplot(3,1,1) -p1 = plot(1:BUFFER_SIZE,Gx(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Gx(1,1:BUFFER_SIZE),'b'); -title(['Gyroscope X-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); -subplot(3,1,2) -p1 = plot(1:BUFFER_SIZE,Gy(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Gy(1,1:BUFFER_SIZE),'b'); -title(['Gyroscope Y-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); -subplot(3,1,3) -p1 = plot(1:BUFFER_SIZE,Gz(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Gz(1,1:BUFFER_SIZE),'b'); -title(['Gyroscope Z-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); - -% Magnetometer Raw (vs) filtered output -hfig=(figure); -scrsz = get(0,'ScreenSize'); -set(hfig,'position',scrsz); -subplot(3,1,1) -p1 = plot(1:BUFFER_SIZE,Mx(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Mx(1,1:BUFFER_SIZE),'b'); -title(['Magnetometer X-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); -subplot(3,1,2) -p1 = plot(1:BUFFER_SIZE,My(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_My(1,1:BUFFER_SIZE),'b'); -title(['Magnetometer Y-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); -subplot(3,1,3) -p1 = plot(1:BUFFER_SIZE,Mz(1,1:BUFFER_SIZE),'r'); -hold on; -grid on; -p2 = plot(1:BUFFER_SIZE,filt_Mz(1,1:BUFFER_SIZE),'b'); -title(['Magnetometer Z-Axis Plot']); -legend([p1 p2],'input signal','low-pass filtered signal'); - diff --git a/src/sensor_fusion/design/sf_orientation.m b/src/sensor_fusion/design/sf_orientation.m new file mode 100755 index 0000000..44ec7d8 --- /dev/null +++ b/src/sensor_fusion/design/sf_orientation.m @@ -0,0 +1,122 @@ +% sf_orientation +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Sensor Fusion Implementation for Orientation Estimation +% +% - Input Accelerometer, Gyroscope and Magnetometer sensor data +% - Call estimate_orientation function +% - Plot results for orientation + +addpath('lib'); +clear +close all +clc + +GRAVITY = 9.80665; + +Max_Range_Accel = 39.203407; Min_Range_Accel = -39.204006; Res_Accel = 0.000598; +Max_Range_Gyro = 1146.862549; Min_Range_Gyro = -1146.880005; Res_Gyro = 0.017500; +Max_Range_Magnetic = 1200; Min_Range_Magnetic = -1200; Res_Magnetic = 1; + +Bias_Ax = 0.098586; +Bias_Ay = 0.18385; +Bias_Az = 10.084 - GRAVITY; + +Bias_Gx = -5.3539; +Bias_Gy = 0.24325; +Bias_Gz = 2.3391; + +BUFFER_SIZE = 1095; + +Accel_data = zeros(4,BUFFER_SIZE); +Gyro_data = zeros(4,BUFFER_SIZE); +Mag_data = zeros(4,BUFFER_SIZE); + +OR_driv = zeros(3,BUFFER_SIZE); +OR_aid = zeros(3,BUFFER_SIZE); +OR_err = zeros(3,BUFFER_SIZE); + +% Sensor Data simulating orientation motions + +% get accel x,y,z axis data from stored file +Accel_data(1,:) = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,1))') - Bias_Ax)(1:BUFFER_SIZE); +Accel_data(2,:) = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,2))') - Bias_Ay)(1:BUFFER_SIZE); +Accel_data(3,:) = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,3))') - Bias_Az)(1:BUFFER_SIZE); +Accel_data(4,:) = ((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,4))')(1:BUFFER_SIZE); + +% get gyro x,y,z axis data from stored file +Gyro_data(1,:) = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,1))') - Bias_Gx)(1:BUFFER_SIZE); +Gyro_data(2,:) = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,2))') - Bias_Gy)(1:BUFFER_SIZE); +Gyro_data(3,:) = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,3))') - Bias_Gz)(1:BUFFER_SIZE); +Gyro_data(4,:) = ((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,4))')(1:BUFFER_SIZE); + +scale_Gyro = 575; +Gyro_data(1,:) = Gyro_data(1,:)/scale_Gyro; +Gyro_data(2,:) = Gyro_data(2,:)/scale_Gyro; +Gyro_data(3,:) = Gyro_data(3,:)/scale_Gyro; + +% get magnetometer x,y,z axis data from stored file +Mag_data(1,:) = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,1))'))(1:BUFFER_SIZE); +Mag_data(2,:) = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,2))'))(1:BUFFER_SIZE); +Mag_data(3,:) = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,3))'))(1:BUFFER_SIZE); +Mag_data(4,:) = ((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,4))')(1:BUFFER_SIZE); + +% estimate orientation +[OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data, Mag_data); + +% Rotation Plot Results +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +subplot(3,1,1) +UA = OR_aid(2,:); +p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +hold on; +grid on; +UA = OR_driv(2,:); +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = OR_err(2,:); +p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); +title(['Pitch']); +legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); +subplot(3,1,2) +UA = OR_aid(1,:); +p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +hold on; +grid on; +UA = OR_driv(1,:); +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = OR_err(1,:); +p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); +title(['Roll']); +legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); +subplot(3,1,3) +UA = OR_aid(3,:); +p1 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +hold on; +grid on; +UA = OR_driv(3,:); +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = OR_err(3,:); +p3 = plot(1:length(UA),UA(1,1:length(UA)),'g'); +title(['Yaw']); +legend([p1 p2 p3],'Aiding System', 'Driving System', 'Quaternion based error'); -- 2.7.4 From 6b63335e78888f34ae319a37b8383d084eb93b96 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Tue, 29 Apr 2014 15:13:28 +0530 Subject: [PATCH 07/13] Fix related to Bias calculation The changes are related to correction in the calculation of bias. signed-off-by: Ramasamy Change-Id: Ie88defc0d7fa7ae8b1272f33489fa6aae3eecab1 --- src/sensor_fusion/design/lib/estimate_orientation.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sensor_fusion/design/lib/estimate_orientation.m b/src/sensor_fusion/design/lib/estimate_orientation.m index 87d0515..7924e65 100755 --- a/src/sensor_fusion/design/lib/estimate_orientation.m +++ b/src/sensor_fusion/design/lib/estimate_orientation.m @@ -293,9 +293,9 @@ function [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data P = (eye(6) - (K(:,j) * H(j,:))) * P; end - Bx = Bx + x(4,i); - By = By + x(5,i); - Bz = Bz + x(6,i); + Bx = x(4,i); + By = x(5,i); + Bz = x(6,i); end OR_aid(1,:) = roll * RAD2DEG; -- 2.7.4 From 5eb0bf1c45bb971f5c8914c7f0b26ad009cf6bcc Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Wed, 30 Apr 2014 10:15:07 +0530 Subject: [PATCH 08/13] Adding sensor fusion documents - Added readme file for sensor fusion design/octave development signed-off-by: Ramasamy Change-Id: Iefbb1dbe274deace549f9cfbe34ba117ec7acbdd --- src/sensor_fusion/design/readme | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/sensor_fusion/design/readme diff --git a/src/sensor_fusion/design/readme b/src/sensor_fusion/design/readme new file mode 100644 index 0000000..2de08d8 --- /dev/null +++ b/src/sensor_fusion/design/readme @@ -0,0 +1,21 @@ +Important Information for developers who would like to contribute:- +--------------------------------------------------------------------------------- + +1. GNU Octave version 3.8.0 or above with GUI support is needed for executing + all sensor fusion code in this directory. + +2. The folder 'documents' contains the high level design for sensor fusion. + Please update any design changes in the documents along with the code changes. + (The .pptx documents could be opened and edited using LibreOffice Impress) + +3. The folder 'results' contains the output plots for the results for various + virtual sensors simulated using Octave. + +4. The folder 'lib' contains all the library files that that will be called by + the sf_xxx functions. + +5. The folder 'data' contains sample data taken from various sensors used on a + mobile phone target. + +6. Each sf_xxx file will individually simulate a virtual sensor that is developed + based on sensor fusion. -- 2.7.4 From 36d13e9c8f6b5db02d4cda073fd634fe1e4ca8d1 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Fri, 2 May 2014 14:25:23 +0530 Subject: [PATCH 09/13] Swapping Tilt values for correct Pitch and Roll - Swapping pitch and roll orientation values to reflect the sample sensor data reference axis correctly. - This correction is needed for determination of Gravity. - Gyroscope plots to use data scaled to 1 instead of PI. signed-off-by: Ramasamy Change-Id: I221e7efd0ab8278fa0caa3542edfb0d7efd55041 --- src/sensor_fusion/design/lib/estimate_orientation.m | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sensor_fusion/design/lib/estimate_orientation.m b/src/sensor_fusion/design/lib/estimate_orientation.m index 7924e65..dfbbc18 100755 --- a/src/sensor_fusion/design/lib/estimate_orientation.m +++ b/src/sensor_fusion/design/lib/estimate_orientation.m @@ -206,8 +206,8 @@ function [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data quat_aid(i,:) = rot_mat2quat(Rot_m); euler = quat2euler(quat_aid(i,:)); - roll(i) = euler(1); - pitch(i) = euler(2); + roll(i) = euler(2); + pitch(i) = euler(1); yaw(i) = euler(3); if i <= MOVING_AVERAGE_WINDOW_LENGTH @@ -303,13 +303,13 @@ function [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data OR_aid(3,:) = yaw * RAD2DEG; euler = quat2euler(quat_driv); - OR_driv(1,:) = euler(:,1)' * RAD2DEG; - OR_driv(2,:) = euler(:,2)' * RAD2DEG; + OR_driv(1,:) = euler(:,2)' * RAD2DEG; + OR_driv(2,:) = euler(:,1)' * RAD2DEG; OR_driv(3,:) = -euler(:,3)' * RAD2DEG; euler = quat2euler(quat_error); - OR_err(1,:) = euler(:,1)' * RAD2DEG; - OR_err(2,:) = euler(:,2)' * RAD2DEG; + OR_err(1,:) = euler(:,2)' * RAD2DEG; + OR_err(2,:) = euler(:,1)' * RAD2DEG; OR_err(3,:) = euler(:,3)' * RAD2DEG; if PLOT_SCALED_SENSOR_COMPARISON_DATA == 1 @@ -321,7 +321,7 @@ function [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data p1 = plot(1:BUFFER_SIZE,acc_x(1,1:BUFFER_SIZE),'r'); hold on; grid on; - p2 = plot(1:BUFFER_SIZE,gyr_x(1,1:BUFFER_SIZE),'b'); + p2 = plot(1:BUFFER_SIZE,filt_Gx(1,1:BUFFER_SIZE),'b'); hold on; grid on; p3 = plot(1:BUFFER_SIZE,mag_x(1,1:BUFFER_SIZE),'k'); @@ -331,7 +331,7 @@ function [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data p1 = plot(1:BUFFER_SIZE,acc_y(1,1:BUFFER_SIZE),'r'); hold on; grid on; - p2 = plot(1:BUFFER_SIZE,gyr_y(1,1:BUFFER_SIZE),'b'); + p2 = plot(1:BUFFER_SIZE,filt_Gy(1,1:BUFFER_SIZE),'b'); hold on; grid on; p3 = plot(1:BUFFER_SIZE,mag_y(1,1:BUFFER_SIZE),'k'); @@ -341,7 +341,7 @@ function [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data p1 = plot(1:BUFFER_SIZE,acc_z(1,1:BUFFER_SIZE),'r'); hold on; grid on; - p2 = plot(1:BUFFER_SIZE,gyr_z(1,1:BUFFER_SIZE),'b'); + p2 = plot(1:BUFFER_SIZE,filt_Gz(1,1:BUFFER_SIZE),'b'); hold on; grid on; p3 = plot(1:BUFFER_SIZE,mag_z(1,1:BUFFER_SIZE),'k'); -- 2.7.4 From 21650cf26e3a97c41c03b55ae076db091541b802 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Tue, 6 May 2014 11:15:05 +0530 Subject: [PATCH 10/13] Restructuring sensor data folder - Sensor data folder restructured to support multiple virtual sensors - cleanup of lib folder files signed-off-by: Ramasamy Change-Id: I93c4623891800d58246559fe3fc432ca5777aa57 --- .../data/100ms/{ => orientation}/pitch/accel.txt | 0 .../data/100ms/{ => orientation}/pitch/gyro.txt | 0 .../100ms/{ => orientation}/pitch/magnetic.txt | 0 .../data/100ms/{ => orientation}/roll/accel.txt | 0 .../data/100ms/{ => orientation}/roll/gyro.txt | 0 .../data/100ms/{ => orientation}/roll/magnetic.txt | 0 .../{ => orientation}/roll_pitch_yaw/accel.txt | 0 .../{ => orientation}/roll_pitch_yaw/gyro.txt | 0 .../{ => orientation}/roll_pitch_yaw/magnetic.txt | 0 .../data/100ms/{ => orientation}/yaw/accel.txt | 0 .../data/100ms/{ => orientation}/yaw/gyro.txt | 0 .../data/100ms/{ => orientation}/yaw/magnetic.txt | 0 src/sensor_fusion/design/lib/quat2euler.m | 2 +- src/sensor_fusion/design/lib/quat2rot_mat.m | 2 +- src/sensor_fusion/design/lib/quat_prod.m | 2 +- src/sensor_fusion/design/lib/rot_mat2quat.m | 2 +- src/sensor_fusion/design/sf_orientation.m | 24 +++++++++++----------- 17 files changed, 16 insertions(+), 16 deletions(-) rename src/sensor_fusion/design/data/100ms/{ => orientation}/pitch/accel.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/pitch/gyro.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/pitch/magnetic.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/roll/accel.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/roll/gyro.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/roll/magnetic.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/roll_pitch_yaw/accel.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/roll_pitch_yaw/gyro.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/roll_pitch_yaw/magnetic.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/yaw/accel.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/yaw/gyro.txt (100%) rename src/sensor_fusion/design/data/100ms/{ => orientation}/yaw/magnetic.txt (100%) diff --git a/src/sensor_fusion/design/data/100ms/pitch/accel.txt b/src/sensor_fusion/design/data/100ms/orientation/pitch/accel.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/pitch/accel.txt rename to src/sensor_fusion/design/data/100ms/orientation/pitch/accel.txt diff --git a/src/sensor_fusion/design/data/100ms/pitch/gyro.txt b/src/sensor_fusion/design/data/100ms/orientation/pitch/gyro.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/pitch/gyro.txt rename to src/sensor_fusion/design/data/100ms/orientation/pitch/gyro.txt diff --git a/src/sensor_fusion/design/data/100ms/pitch/magnetic.txt b/src/sensor_fusion/design/data/100ms/orientation/pitch/magnetic.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/pitch/magnetic.txt rename to src/sensor_fusion/design/data/100ms/orientation/pitch/magnetic.txt diff --git a/src/sensor_fusion/design/data/100ms/roll/accel.txt b/src/sensor_fusion/design/data/100ms/orientation/roll/accel.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/roll/accel.txt rename to src/sensor_fusion/design/data/100ms/orientation/roll/accel.txt diff --git a/src/sensor_fusion/design/data/100ms/roll/gyro.txt b/src/sensor_fusion/design/data/100ms/orientation/roll/gyro.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/roll/gyro.txt rename to src/sensor_fusion/design/data/100ms/orientation/roll/gyro.txt diff --git a/src/sensor_fusion/design/data/100ms/roll/magnetic.txt b/src/sensor_fusion/design/data/100ms/orientation/roll/magnetic.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/roll/magnetic.txt rename to src/sensor_fusion/design/data/100ms/orientation/roll/magnetic.txt diff --git a/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/accel.txt b/src/sensor_fusion/design/data/100ms/orientation/roll_pitch_yaw/accel.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/roll_pitch_yaw/accel.txt rename to src/sensor_fusion/design/data/100ms/orientation/roll_pitch_yaw/accel.txt diff --git a/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/gyro.txt b/src/sensor_fusion/design/data/100ms/orientation/roll_pitch_yaw/gyro.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/roll_pitch_yaw/gyro.txt rename to src/sensor_fusion/design/data/100ms/orientation/roll_pitch_yaw/gyro.txt diff --git a/src/sensor_fusion/design/data/100ms/roll_pitch_yaw/magnetic.txt b/src/sensor_fusion/design/data/100ms/orientation/roll_pitch_yaw/magnetic.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/roll_pitch_yaw/magnetic.txt rename to src/sensor_fusion/design/data/100ms/orientation/roll_pitch_yaw/magnetic.txt diff --git a/src/sensor_fusion/design/data/100ms/yaw/accel.txt b/src/sensor_fusion/design/data/100ms/orientation/yaw/accel.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/yaw/accel.txt rename to src/sensor_fusion/design/data/100ms/orientation/yaw/accel.txt diff --git a/src/sensor_fusion/design/data/100ms/yaw/gyro.txt b/src/sensor_fusion/design/data/100ms/orientation/yaw/gyro.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/yaw/gyro.txt rename to src/sensor_fusion/design/data/100ms/orientation/yaw/gyro.txt diff --git a/src/sensor_fusion/design/data/100ms/yaw/magnetic.txt b/src/sensor_fusion/design/data/100ms/orientation/yaw/magnetic.txt similarity index 100% rename from src/sensor_fusion/design/data/100ms/yaw/magnetic.txt rename to src/sensor_fusion/design/data/100ms/orientation/yaw/magnetic.txt diff --git a/src/sensor_fusion/design/lib/quat2euler.m b/src/sensor_fusion/design/lib/quat2euler.m index 16e46b3..f788ea4 100755 --- a/src/sensor_fusion/design/lib/quat2euler.m +++ b/src/sensor_fusion/design/lib/quat2euler.m @@ -1,5 +1,5 @@ function euler = quat2euler(q) -% Quat2Euler +% quat2euler % % Copyright (c) 2014 Samsung Electronics Co., Ltd. % diff --git a/src/sensor_fusion/design/lib/quat2rot_mat.m b/src/sensor_fusion/design/lib/quat2rot_mat.m index bb11d08..62db364 100755 --- a/src/sensor_fusion/design/lib/quat2rot_mat.m +++ b/src/sensor_fusion/design/lib/quat2rot_mat.m @@ -1,5 +1,5 @@ function R = quat2rot_mat(q) -% Quat2RotMat +% quat2rot_mat % % Copyright (c) 2014 Samsung Electronics Co., Ltd. % diff --git a/src/sensor_fusion/design/lib/quat_prod.m b/src/sensor_fusion/design/lib/quat_prod.m index 40d2c57..21a48dc 100755 --- a/src/sensor_fusion/design/lib/quat_prod.m +++ b/src/sensor_fusion/design/lib/quat_prod.m @@ -1,5 +1,5 @@ function ab = quat_prod(a, b) -% QuatProd +% quat_prod % % Copyright (c) 2014 Samsung Electronics Co., Ltd. % diff --git a/src/sensor_fusion/design/lib/rot_mat2quat.m b/src/sensor_fusion/design/lib/rot_mat2quat.m index dcc3410..53ad96c 100755 --- a/src/sensor_fusion/design/lib/rot_mat2quat.m +++ b/src/sensor_fusion/design/lib/rot_mat2quat.m @@ -1,5 +1,5 @@ function q = rot_mat2quat(R) -% RotMat2Quat +% rot_mat2quat % % Copyright (c) 2014 Samsung Electronics Co., Ltd. % diff --git a/src/sensor_fusion/design/sf_orientation.m b/src/sensor_fusion/design/sf_orientation.m index 44ec7d8..d1c927c 100755 --- a/src/sensor_fusion/design/sf_orientation.m +++ b/src/sensor_fusion/design/sf_orientation.m @@ -52,16 +52,16 @@ OR_err = zeros(3,BUFFER_SIZE); % Sensor Data simulating orientation motions % get accel x,y,z axis data from stored file -Accel_data(1,:) = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,1))') - Bias_Ax)(1:BUFFER_SIZE); -Accel_data(2,:) = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,2))') - Bias_Ay)(1:BUFFER_SIZE); -Accel_data(3,:) = (((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,3))') - Bias_Az)(1:BUFFER_SIZE); -Accel_data(4,:) = ((dlmread("data/100ms/roll_pitch_yaw/accel.txt")(:,4))')(1:BUFFER_SIZE); +Accel_data(1,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/accel.txt")(:,1))') - Bias_Ax)(1:BUFFER_SIZE); +Accel_data(2,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/accel.txt")(:,2))') - Bias_Ay)(1:BUFFER_SIZE); +Accel_data(3,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/accel.txt")(:,3))') - Bias_Az)(1:BUFFER_SIZE); +Accel_data(4,:) = ((dlmread("data/100ms/orientation/roll_pitch_yaw/accel.txt")(:,4))')(1:BUFFER_SIZE); % get gyro x,y,z axis data from stored file -Gyro_data(1,:) = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,1))') - Bias_Gx)(1:BUFFER_SIZE); -Gyro_data(2,:) = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,2))') - Bias_Gy)(1:BUFFER_SIZE); -Gyro_data(3,:) = (((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,3))') - Bias_Gz)(1:BUFFER_SIZE); -Gyro_data(4,:) = ((dlmread("data/100ms/roll_pitch_yaw/gyro.txt")(:,4))')(1:BUFFER_SIZE); +Gyro_data(1,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/gyro.txt")(:,1))') - Bias_Gx)(1:BUFFER_SIZE); +Gyro_data(2,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/gyro.txt")(:,2))') - Bias_Gy)(1:BUFFER_SIZE); +Gyro_data(3,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/gyro.txt")(:,3))') - Bias_Gz)(1:BUFFER_SIZE); +Gyro_data(4,:) = ((dlmread("data/100ms/orientation/roll_pitch_yaw/gyro.txt")(:,4))')(1:BUFFER_SIZE); scale_Gyro = 575; Gyro_data(1,:) = Gyro_data(1,:)/scale_Gyro; @@ -69,10 +69,10 @@ Gyro_data(2,:) = Gyro_data(2,:)/scale_Gyro; Gyro_data(3,:) = Gyro_data(3,:)/scale_Gyro; % get magnetometer x,y,z axis data from stored file -Mag_data(1,:) = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,1))'))(1:BUFFER_SIZE); -Mag_data(2,:) = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,2))'))(1:BUFFER_SIZE); -Mag_data(3,:) = (((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,3))'))(1:BUFFER_SIZE); -Mag_data(4,:) = ((dlmread("data/100ms/roll_pitch_yaw/magnetic.txt")(:,4))')(1:BUFFER_SIZE); +Mag_data(1,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/magnetic.txt")(:,1))'))(1:BUFFER_SIZE); +Mag_data(2,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/magnetic.txt")(:,2))'))(1:BUFFER_SIZE); +Mag_data(3,:) = (((dlmread("data/100ms/orientation/roll_pitch_yaw/magnetic.txt")(:,3))'))(1:BUFFER_SIZE); +Mag_data(4,:) = ((dlmread("data/100ms/orientation/roll_pitch_yaw/magnetic.txt")(:,4))')(1:BUFFER_SIZE); % estimate orientation [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data, Mag_data); -- 2.7.4 From f0be8d233127cee3696cc6d60a0a53282a622836 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 6 May 2014 11:51:19 +0530 Subject: [PATCH 11/13] Adding Gravity virtual sensor - adding octave code to measure gravitational force on device reference axes - adding sensor test data to test gravity virtual sensor signed-off-by: Ramasamy Change-Id: Ia1ff380f04145722432467d4f2e8b4fd94e0bfa3 --- .../100ms/gravity/orientation_change/accel.txt | 527 ++++++++++++++++++++ .../data/100ms/gravity/orientation_change/gyro.txt | 529 +++++++++++++++++++++ .../100ms/gravity/orientation_change/magnetic.txt | 524 ++++++++++++++++++++ .../data/100ms/gravity/single_roll_throw/accel.txt | 100 ++++ .../data/100ms/gravity/single_roll_throw/gyro.txt | 100 ++++ .../100ms/gravity/single_roll_throw/magnetic.txt | 100 ++++ .../design/data/100ms/gravity/throw/accel.txt | 135 ++++++ .../design/data/100ms/gravity/throw/gyro.txt | 136 ++++++ .../design/data/100ms/gravity/throw/magnetic.txt | 136 ++++++ src/sensor_fusion/design/lib/estimate_gravity.m | 45 ++ src/sensor_fusion/design/sf_gravity.m | 113 +++++ 11 files changed, 2445 insertions(+) create mode 100755 src/sensor_fusion/design/data/100ms/gravity/orientation_change/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/orientation_change/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/orientation_change/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/throw/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/throw/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/gravity/throw/magnetic.txt create mode 100755 src/sensor_fusion/design/lib/estimate_gravity.m create mode 100755 src/sensor_fusion/design/sf_gravity.m diff --git a/src/sensor_fusion/design/data/100ms/gravity/orientation_change/accel.txt b/src/sensor_fusion/design/data/100ms/gravity/orientation_change/accel.txt new file mode 100755 index 0000000..adc32ff --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/orientation_change/accel.txt @@ -0,0 +1,527 @@ +-0.013161 0.173480 10.108479 64210388.000000 +0.035892 0.166301 10.162319 64310524.000000 +0.025125 0.151944 10.188639 64410512.000000 +0.015553 0.167498 10.180264 64510568.000000 +0.029910 0.159123 10.181459 64610524.000000 +0.033500 0.167498 10.164711 64710512.000000 +0.020339 0.196211 10.217353 64810688.000000 +0.038285 0.163908 10.169496 64910984.000000 +0.008375 0.165105 10.194620 65010968.000000 +0.011964 0.131605 10.182656 65110924.000000 +0.033500 0.174676 10.201799 65211036.000000 +0.011964 0.139980 10.191031 65310964.000000 +0.049053 0.177069 10.189835 65410884.000000 +0.034696 0.150748 10.189835 65510880.000000 +0.017946 0.157926 10.179067 65611080.000000 +0.022732 0.161516 10.217353 65711344.000000 +0.008375 0.156730 10.211370 65811244.000000 +0.014357 0.185444 10.170692 65911064.000000 +0.001196 0.191426 10.185050 66016000.000000 +0.028714 0.174676 10.177871 66116696.000000 +0.028714 0.187837 10.229317 66215828.000000 +0.015553 0.177069 10.237692 66316416.000000 +0.027517 0.179462 10.193424 66416000.000000 +0.027517 0.189033 10.144372 66516532.000000 +0.033500 0.143569 10.192227 66616080.000000 +0.050249 0.147159 10.193424 66716516.000000 +0.037089 0.162712 10.205389 66815968.000000 +0.026321 0.173480 10.212566 66916712.000000 +0.023928 0.175872 10.195816 67016224.000000 +0.004786 0.165105 10.170692 67116528.000000 +0.001196 0.160319 10.152746 67216000.000000 +0.014357 0.161516 10.187442 67316544.000000 +0.033500 0.174676 10.195816 67416160.000000 +0.016750 0.166301 10.137194 67516504.000000 +0.004786 0.169890 10.194620 67616360.000000 +0.002393 0.195015 10.180264 67716168.000000 +0.021535 0.147159 10.173084 67816352.000000 +0.035892 0.150748 10.211370 67916608.000000 +0.008375 0.147159 10.185050 68017840.000000 +0.040678 0.168694 10.163515 68116832.000000 +0.001196 0.166301 10.176675 68216584.000000 +0.032303 0.151944 10.183852 68316376.000000 +0.028714 0.167498 10.218549 68416984.000000 +0.022732 0.174676 10.200603 68516368.000000 +0.019143 0.179462 10.165908 68616536.000000 +0.027517 0.181855 10.185050 68716824.000000 +0.028714 0.167498 10.157533 68816512.000000 +0.028714 0.187837 10.182656 68915760.000000 +0.051446 0.172283 10.156336 69016128.000000 +0.020339 0.156730 10.161121 69115856.000000 +0.055035 0.171087 10.188639 69217096.000000 +0.020339 0.183051 10.163515 69315920.000000 +0.031107 0.171087 10.169496 69416296.000000 +0.014357 0.137587 10.202995 69515928.000000 +0.023928 0.190229 10.189835 69616736.000000 +0.034696 0.191426 10.210175 69716504.000000 +0.053839 0.160319 10.169496 69816336.000000 +0.034696 0.165105 10.213763 69916768.000000 +0.025125 0.193819 10.187442 70016096.000000 +0.025125 0.168694 10.149158 70116384.000000 +0.046660 0.192622 10.207782 70216000.000000 +-0.002393 0.157926 10.214959 70316104.000000 +0.007178 0.153141 10.189835 70416424.000000 +0.137587 0.184247 9.906286 70515952.000000 +0.399601 0.138784 8.985049 70616864.000000 +0.228515 0.202193 10.163515 70716168.000000 +0.210568 0.159123 10.183852 70816320.000000 +0.239282 0.143569 10.171888 70916160.000000 +0.282353 0.148355 10.168301 71016528.000000 +0.552742 0.099302 10.046266 71116384.000000 +0.664008 0.084945 10.217353 71216320.000000 +0.960718 -0.068195 9.962516 71315912.000000 +1.259821 0.007178 10.378868 71416720.000000 +1.800599 0.029910 9.945767 71515944.000000 +2.437090 0.041874 9.785448 71616552.000000 +3.163311 0.108873 9.783055 71716016.000000 +4.147958 -0.031107 9.141779 71816320.000000 +4.985445 0.026321 8.675179 71916120.000000 +5.698507 0.102891 8.409575 72016328.000000 +6.285945 0.026321 8.093722 72116096.000000 +6.933204 0.015553 7.310073 72216440.000000 +7.312466 0.092124 7.456036 72316304.000000 +7.805387 0.025125 5.705685 72416064.000000 +8.086544 0.089731 5.960521 72516360.000000 +8.376076 0.076570 5.581259 72616040.000000 +8.621340 0.124427 4.352544 72716624.000000 +8.955138 0.061017 4.242475 72816040.000000 +9.113065 0.112463 4.095316 72916208.000000 +9.278170 0.075374 3.863212 73016120.000000 +9.419346 0.096909 3.876373 73116016.000000 +9.552148 0.098106 2.248057 73216304.000000 +9.552148 0.093320 2.361716 73316792.000000 +9.677772 0.063410 1.887937 73416464.000000 +9.690931 0.082552 1.743171 73516968.000000 +9.700503 0.084945 1.671387 73616264.000000 +9.718449 0.045464 1.216750 73716416.000000 +9.714860 0.050249 0.794417 73816840.000000 +9.762716 0.032303 0.480957 73916680.000000 +9.766305 0.086142 0.733400 74016184.000000 +9.747163 0.038285 0.697508 74116944.000000 +9.763913 0.025125 0.320638 74216808.000000 +9.748360 0.026321 0.577867 74316992.000000 +9.710074 0.043071 0.488136 74418520.000000 +9.755538 0.019143 0.531207 74516032.000000 +9.749557 0.025125 0.440279 74615920.000000 +9.743573 0.056231 0.705883 74715768.000000 +9.765109 0.013161 1.282553 74815760.000000 +9.743573 0.068195 1.452443 74916392.000000 +9.729217 0.034696 1.141376 75015600.000000 +9.738789 0.057428 1.027717 75115896.000000 +9.884750 0.022732 1.697708 75215616.000000 +9.753145 0.062213 0.935594 75315728.000000 +9.729217 0.056231 1.172483 75415568.000000 +9.734003 0.052642 0.655633 75515904.000000 +9.744770 0.049053 1.397408 75615568.000000 +9.744770 0.058624 1.051646 75715808.000000 +9.757930 0.038285 0.720240 75815760.000000 +9.726824 0.052642 1.252643 75915856.000000 +9.739985 0.052642 1.088734 76015736.000000 +9.741181 0.066999 0.832702 76115672.000000 +9.726824 0.049053 0.653241 76215936.000000 +9.763913 0.019143 1.131805 76315784.000000 +9.729217 0.040678 0.940379 76415888.000000 +9.750752 0.071785 0.882952 76515840.000000 +9.774680 0.050249 1.004985 76615560.000000 +9.777073 0.044267 0.470190 76715504.000000 +9.763913 0.022732 0.997807 76816256.000000 +9.716056 0.050249 0.681954 76915600.000000 +9.772287 0.045464 1.014557 77015840.000000 +9.731609 0.072981 0.933201 77115928.000000 +9.774680 0.045464 0.869791 77215952.000000 +9.787841 0.037089 0.770489 77315872.000000 +9.768698 0.021535 0.711865 77415744.000000 +9.731609 0.069392 1.130609 77515600.000000 +9.741181 0.069392 1.074377 77615704.000000 +9.712467 0.077767 1.207179 77715784.000000 +9.722038 0.059821 1.112662 77815768.000000 +9.729217 0.065803 1.136591 77915768.000000 +9.724431 0.062213 0.990629 78015776.000000 +9.705289 0.047856 1.015753 78115536.000000 +9.723234 0.072981 1.026521 78215720.000000 +9.747163 0.070588 0.933201 78319080.000000 +9.768698 0.026321 0.868595 78415416.000000 +9.756735 0.025125 0.897308 78515336.000000 +9.854840 -0.004786 0.726222 78615512.000000 +9.734003 0.131605 1.914258 78715440.000000 +9.751948 0.040678 0.884148 78815552.000000 +9.755538 0.037089 0.837488 78915616.000000 +9.754342 0.082552 1.119841 79015680.000000 +9.732806 0.081356 0.942772 79115848.000000 +9.728020 0.062213 0.989432 79215944.000000 +9.728020 0.063410 0.842274 79315800.000000 +9.755538 0.039482 0.952343 79415824.000000 +9.730413 0.040678 0.927219 79515824.000000 +9.725628 0.051446 1.129412 79615616.000000 +9.743573 0.063410 1.025324 79715760.000000 +9.711270 0.059821 1.182054 79815552.000000 +9.737592 0.033500 0.788435 79915864.000000 +9.756735 0.055035 0.823131 80017760.000000 +9.786645 0.026321 0.693919 80115744.000000 +9.762716 0.031107 0.710668 80215800.000000 +9.763913 0.053839 0.964308 80315568.000000 +9.763913 0.049053 1.160519 80416112.000000 +9.744770 0.061017 0.959522 80515808.000000 +9.738789 0.041874 0.714258 80615760.000000 +9.750752 0.050249 0.732204 80715584.000000 +9.719646 0.076570 0.467797 80815816.000000 +9.777073 0.065803 0.725025 80915768.000000 +9.743573 0.034696 0.510868 81015648.000000 +9.749557 0.041874 0.618545 81115816.000000 +9.767502 0.038285 0.631705 81215896.000000 +9.753145 0.069392 0.612563 81315944.000000 +9.732806 0.057428 0.750150 81416000.000000 +9.726824 0.040678 0.668794 81515832.000000 +9.759127 0.063410 0.966700 81615808.000000 +9.731609 0.072981 0.740579 81715616.000000 +9.783055 0.045464 0.748954 81816896.000000 +9.763913 0.065803 0.559920 81916256.000000 +9.731609 0.050249 0.545564 82021088.000000 +9.755538 0.041874 0.817149 82121000.000000 +9.751948 0.040678 0.669990 82221296.000000 +9.755538 0.053839 0.943969 82321824.000000 +9.745967 0.034696 0.658026 82421032.000000 +9.760324 0.081356 0.908076 82522288.000000 +9.674182 0.098106 0.920040 82622224.000000 +9.718449 0.057428 1.164108 82721104.000000 +9.646665 0.112463 1.798206 82821768.000000 +9.669396 0.033500 1.828116 82921392.000000 +9.571291 0.045464 1.992025 83021784.000000 +9.434900 0.059821 2.836691 83121840.000000 +9.382257 0.089731 2.818745 83223152.000000 +9.231510 0.028714 3.136991 83321528.000000 +9.006584 0.034696 3.820141 83422040.000000 +8.685946 0.066999 4.780859 83521024.000000 +8.271988 0.049053 5.554938 83621432.000000 +7.974082 -0.039482 6.092126 83722232.000000 +7.459624 0.086142 6.790830 83822064.000000 +7.032506 0.044267 6.976274 83922048.000000 +6.455836 0.039482 7.880762 84020496.000000 +5.882754 0.045464 7.990831 84120768.000000 +4.971089 0.053839 8.947960 84220544.000000 +4.173083 -0.022732 9.316455 84320528.000000 +3.071188 0.083749 9.887143 84420520.000000 +2.431108 0.049053 9.714860 84520504.000000 +1.560120 0.010768 9.865608 84620776.000000 +1.245464 0.051446 9.917053 84720472.000000 +1.335195 0.195015 10.153944 84820784.000000 +1.416551 0.084945 10.037891 84920608.000000 +1.318445 0.108873 10.011569 85020536.000000 +1.293321 0.045464 10.063015 85120720.000000 +0.885344 0.088534 10.024731 85221272.000000 +1.147358 -0.035892 10.170692 85321416.000000 +0.924826 0.025125 10.226924 85421096.000000 +0.671187 0.090927 10.175477 85521416.000000 +0.632902 0.081356 10.183852 85620752.000000 +0.599402 0.063410 10.145569 85720936.000000 +0.204586 0.154337 10.181459 85821544.000000 +0.223729 0.166301 10.229317 85921072.000000 +0.027517 0.397209 10.219746 86021336.000000 +0.095713 0.130409 9.899107 86121040.000000 +-0.003589 0.216550 10.230514 86221408.000000 +-0.041874 0.184247 10.431510 86321048.000000 +0.008375 0.154337 10.159925 86421136.000000 +0.033500 0.183051 10.199407 86521360.000000 +0.016750 0.181855 10.165908 86620792.000000 +0.045464 0.216550 10.173084 86721416.000000 +0.008375 0.178265 10.199407 86820976.000000 +0.008375 0.154337 10.177871 86921456.000000 +0.001196 0.167498 10.174281 87020984.000000 +0.002393 0.169890 10.216157 87121432.000000 +0.019143 0.147159 10.197014 87221336.000000 +0.040678 0.166301 10.189835 87321408.000000 +0.040678 0.169890 10.199407 87420800.000000 +0.047856 0.178265 10.188639 87520856.000000 +0.040678 0.163908 10.181459 87621360.000000 +-0.015553 0.156730 10.198210 87720992.000000 +0.011964 0.153141 10.158729 87820936.000000 +0.022732 0.163908 10.187442 87920976.000000 +0.015553 0.174676 10.163515 88021080.000000 +0.002393 0.154337 10.188639 88121352.000000 +0.020339 0.175872 10.173084 88221096.000000 +0.003589 0.167498 10.226924 88321552.000000 +0.047856 0.150748 10.158729 88420880.000000 +0.013161 0.148355 10.149158 88520816.000000 +0.029910 0.175872 10.139585 88620928.000000 +-0.020339 0.150748 10.296316 88721016.000000 +-0.025125 0.181855 10.339387 88821048.000000 +0.007178 0.171087 10.241282 88921232.000000 +0.003589 0.163908 10.181459 89021304.000000 +0.021535 0.157926 10.161121 89121008.000000 +0.015553 0.165105 10.168301 89221064.000000 +0.038285 0.165105 10.198210 89321064.000000 +0.022732 0.177069 10.165908 89421056.000000 +0.015553 0.172283 10.180264 89520792.000000 +-0.007178 0.160319 10.168301 89620776.000000 +-0.007178 0.183051 10.141978 89720944.000000 +0.021535 0.143569 10.167104 89820872.000000 +0.002393 0.167498 10.192227 89921024.000000 +0.033500 0.162712 10.194620 90022224.000000 +-0.001196 0.155533 10.185050 90122096.000000 +0.020339 0.172283 10.193424 90221344.000000 +0.023928 0.172283 10.161121 90321408.000000 +-0.007178 0.161516 10.173084 90422312.000000 +0.023928 0.137587 10.193424 90521280.000000 +0.028714 0.155533 10.188639 90621440.000000 +0.008375 0.192622 10.185050 90723992.000000 +-0.001196 0.167498 10.169496 90821352.000000 +0.019143 0.128016 10.210175 90922520.000000 +0.020339 0.139980 10.191031 91021328.000000 +0.032303 0.162712 10.197014 91122032.000000 +0.101695 0.133998 10.043874 91221536.000000 +0.032303 0.181855 10.173084 91321368.000000 +-0.016750 0.165105 10.173084 91422168.000000 +0.095713 0.155533 10.187442 91521232.000000 +0.094516 0.155533 10.347760 91621960.000000 +-0.244068 0.242871 10.350154 91721792.000000 +-0.019143 0.401994 9.728020 91822544.000000 +0.669990 0.455833 10.658829 91921432.000000 +-0.040678 1.100698 10.418350 92021488.000000 +-0.144766 1.785046 10.402797 92122304.000000 +-0.190229 2.585445 9.760324 92222376.000000 +0.218943 3.451647 9.535398 92322440.000000 +0.222532 4.307081 9.360723 92421568.000000 +0.349352 5.302495 8.640482 92522536.000000 +-0.026321 6.156733 7.834101 92620992.000000 +0.443869 6.721439 7.422535 92722600.000000 +0.790828 7.250252 6.851848 92821784.000000 +0.386441 8.037491 6.099305 92921184.000000 +0.587438 8.648857 4.864608 93020704.000000 +0.372084 8.846266 4.746164 93120512.000000 +0.515653 9.292527 3.330809 93220664.000000 +0.573081 9.481560 1.942972 93320624.000000 +0.168694 9.713664 1.526621 93420536.000000 +0.723829 9.698111 1.445265 93520720.000000 +0.410369 9.821341 0.677169 93620544.000000 +0.136391 9.815358 0.135194 93720696.000000 +0.393619 9.829715 0.577867 93820536.000000 +0.532403 9.818949 0.746561 93920880.000000 +0.309871 9.818949 0.368495 94020640.000000 +0.254836 9.841680 0.577867 94120544.000000 +0.368495 9.840484 0.631705 94220736.000000 +0.234497 9.883554 0.403191 94320504.000000 +0.017946 9.871590 0.277567 94420752.000000 +0.386441 9.795020 0.512064 94520472.000000 +0.464208 9.799806 0.631705 94620768.000000 +0.315853 9.814162 0.500100 94720504.000000 +0.089731 9.824929 0.415155 94820528.000000 +0.049053 9.858429 0.373280 94920712.000000 +0.715454 9.791430 0.658026 95020520.000000 +0.007178 9.824929 -0.046660 95120752.000000 +0.016750 9.844072 0.247657 95220528.000000 +0.228515 9.817751 0.591027 95320704.000000 +-0.118445 9.885946 0.546760 95421440.000000 +0.142373 9.845268 0.441476 95520528.000000 +0.090927 9.850054 0.394816 95620736.000000 +-0.245264 9.856036 0.269193 95720448.000000 +0.035892 9.815358 0.331406 95820744.000000 +-0.148355 9.854840 0.333799 95920496.000000 +-0.180658 9.865608 0.555135 96020688.000000 +-0.229711 9.833304 -0.221336 96120640.000000 +0.099302 9.829715 0.212961 96222312.000000 +-0.179462 9.851252 -0.046660 96322168.000000 +0.313460 9.799806 -0.020339 96422960.000000 +-0.178265 9.883554 -0.250050 96521488.000000 +0.095713 9.810574 -0.478565 96622128.000000 +-0.063410 9.876375 0.186640 96722096.000000 +0.084945 9.832108 0.250050 96820736.000000 +0.247657 9.824929 0.029910 96921168.000000 +0.209372 9.792626 0.028714 97021384.000000 +0.160319 9.806983 -0.081356 97121424.000000 +0.155533 9.811769 -0.437887 97221096.000000 +-0.065803 9.780663 -0.199801 97320736.000000 +-0.007178 9.832108 0.478565 97421568.000000 +0.007178 9.840484 0.342174 97521744.000000 +0.223729 9.818949 0.044267 97621544.000000 +0.092124 9.805787 0.177069 97721944.000000 +0.095713 9.836893 0.547956 97821248.000000 +-0.399601 9.907482 0.528814 97922560.000000 +-0.262014 9.854840 0.561117 98022072.000000 +-0.149551 9.841680 0.406780 98121240.000000 +0.031107 9.786645 0.212961 98221120.000000 +0.591027 9.732806 0.515653 98320784.000000 +-0.250050 9.834501 0.591027 98421376.000000 +-0.269193 9.846465 0.579063 98522752.000000 +-0.149551 9.817751 0.323031 98621160.000000 +-0.064606 9.805787 0.141177 98721632.000000 +-0.282353 9.826126 0.142373 98820840.000000 +-0.290728 9.852448 0.665205 98921240.000000 +-0.302692 9.875179 0.453440 99021208.000000 +-0.099302 9.829715 0.308674 99121368.000000 +0.119641 9.723234 0.746561 99220896.000000 +-0.040678 9.827322 0.464208 99320896.000000 +-0.284746 9.864411 0.623330 99420968.000000 +-0.247657 9.835697 0.568295 99521096.000000 +-0.325424 9.879964 0.336192 99621400.000000 +-0.061017 9.851252 -0.013161 99721488.000000 +-0.033500 9.826126 0.516850 99820976.000000 +-0.202193 9.854840 0.531207 99920968.000000 +-0.132802 9.850054 0.278764 100021064.000000 +-0.099302 9.830912 0.191426 100121272.000000 +0.126820 9.804591 0.263210 100221216.000000 +-0.259621 9.860823 0.620937 100320864.000000 +-0.198604 9.845268 0.442672 100420680.000000 +-0.227318 9.863215 0.296710 100522464.000000 +-0.070588 9.832108 0.092124 100620928.000000 +-0.477368 9.913465 0.040678 100720808.000000 +-0.376870 9.883554 0.697508 100821136.000000 +0.022732 9.823733 0.251246 100921664.000000 +-0.179462 9.863215 0.178265 101021032.000000 +-0.122034 9.860823 0.045464 101120760.000000 +-0.647258 9.881162 -0.716650 101220912.000000 +0.391227 9.791430 0.186640 101321008.000000 +-0.198604 9.864411 0.632902 101421680.000000 +0.068195 9.816555 0.078963 101521552.000000 +-0.040678 9.836893 0.137587 101621600.000000 +-0.099302 9.859627 0.397209 101721464.000000 +-0.346959 9.876375 0.501296 101821544.000000 +0.056231 9.824929 -0.099302 101922544.000000 +-0.129212 9.842876 -0.264407 102021880.000000 +-0.142373 9.830912 -0.063410 102124256.000000 +-0.253639 9.862019 0.132802 102221384.000000 +-0.340977 9.863215 0.305085 102321920.000000 +-0.265603 9.871590 0.284746 102421272.000000 +-0.680758 9.931411 0.087338 102521184.000000 +0.101695 9.832108 -0.076570 102622336.000000 +-0.217747 9.885946 0.111266 102721272.000000 +-0.032303 9.938589 0.211765 102822032.000000 +0.340977 9.784252 -0.315853 102921200.000000 +-0.104088 9.866804 0.074178 103020760.000000 +-0.102891 9.836893 -0.224925 103120520.000000 +-0.180658 9.862019 -0.287139 103220496.000000 +0.305085 9.839286 0.111266 103320528.000000 +0.070588 9.852448 0.045464 103420752.000000 +0.172283 9.810574 -0.017946 103520528.000000 +0.233300 9.804591 -0.077767 103620696.000000 +0.270389 9.842876 0.295514 103720720.000000 +0.573081 9.803394 0.412762 103822304.000000 +0.454636 9.823733 0.224925 103921344.000000 +0.021535 9.858429 0.144766 104022096.000000 +0.288335 9.817751 0.179462 104121488.000000 +0.234497 9.844072 0.260818 104222160.000000 +0.263210 9.860823 0.393619 104321608.000000 +0.233300 9.810574 0.308674 104422376.000000 +0.238086 9.857233 0.379262 104521712.000000 +0.342174 9.822537 0.491725 104621368.000000 +0.238086 9.835697 0.200997 104722304.000000 +0.247657 9.839286 0.242871 104821616.000000 +0.150748 9.826126 0.179462 104922104.000000 +0.238086 9.806983 0.343370 105021328.000000 +0.117248 9.836893 0.196211 105124704.000000 +0.163908 9.829715 0.276371 105225552.000000 +0.333799 9.835697 0.296710 105325568.000000 +0.088534 9.877571 0.300299 105425584.000000 +0.026321 9.851252 0.659223 105526656.000000 +0.156730 9.817751 0.815953 105625576.000000 +-0.008375 9.820145 0.699901 105725584.000000 +-0.065803 9.765109 0.412762 105825960.000000 +-0.075374 9.707682 2.415555 105925696.000000 +-0.017946 9.596415 1.792224 106025544.000000 +-0.216550 9.410972 2.965904 106126240.000000 +0.512064 9.053245 4.157529 106226128.000000 +0.427119 8.834301 4.512863 106325816.000000 +0.223729 8.599805 5.222335 106425568.000000 +-0.348156 8.356933 5.632704 106525888.000000 +-0.143569 7.954939 5.583652 106625608.000000 +-0.296710 7.562516 6.668797 106725584.000000 +-0.342174 7.123433 7.130611 106826024.000000 +-0.765703 7.021738 7.343572 106925552.000000 +-0.885344 6.134001 8.208578 107025904.000000 +-0.894916 5.606383 8.757731 107125528.000000 +-0.970290 4.831109 8.975478 107226072.000000 +-1.067199 4.299902 9.078369 107325608.000000 +-1.330409 3.396612 9.438489 107425696.000000 +-1.143769 2.842674 9.730413 107526360.000000 +-0.934397 2.409572 9.851252 107625896.000000 +-0.942772 1.826920 9.779467 107725768.000000 +-0.885344 1.515853 9.964910 107825480.000000 +-0.435494 1.039681 10.362118 107925424.000000 +0.105284 0.492921 10.993823 108025520.000000 +-0.034696 0.417548 10.181459 108125688.000000 +0.266800 0.247657 10.358529 108225456.000000 +0.227318 0.185444 10.137194 108325488.000000 +-0.001196 0.116052 10.197014 108425520.000000 +-0.090927 0.296710 10.188639 108525496.000000 +0.287139 0.114855 10.141978 108626496.000000 +0.035892 0.173480 10.310673 108725528.000000 +0.055035 0.174676 10.060623 108825512.000000 +0.009571 0.178265 10.275976 108926272.000000 +0.032303 0.165105 10.218549 109025560.000000 +0.045464 0.172283 10.229317 109125728.000000 +0.014357 0.153141 10.199407 109225776.000000 +0.098106 0.144766 10.000802 109330096.000000 +0.025125 0.165105 10.278370 109430472.000000 +0.246461 0.149551 9.607183 109530488.000000 +-0.092124 0.150748 10.551151 109630600.000000 +0.043071 0.139980 10.159925 109730584.000000 +0.023928 0.175872 10.133603 109830536.000000 +0.189033 0.141177 9.675378 109930448.000000 +0.055035 0.172283 10.147961 110030424.000000 +0.065803 0.155533 10.091729 110130552.000000 +0.031107 0.155533 10.246067 110230752.000000 +0.209372 0.059821 9.711270 110330400.000000 +0.057428 0.162712 10.248460 110430496.000000 +0.051446 0.169890 10.082158 110530616.000000 +0.027517 0.175872 10.200603 110630784.000000 +0.034696 0.160319 10.165908 110731088.000000 +-0.224925 0.125623 11.474781 110830408.000000 +0.095713 0.173480 10.030712 110930792.000000 +-0.009571 0.189033 10.264012 111030624.000000 +0.049053 0.162712 10.157533 111130616.000000 +0.056231 0.175872 10.210175 111230776.000000 +0.039482 0.163908 10.174281 111330584.000000 +0.045464 0.161516 10.208978 111430552.000000 +0.001196 0.126820 10.212566 111530616.000000 +0.059821 0.163908 10.200603 111630656.000000 +0.025125 0.161516 10.181459 111730736.000000 +0.032303 0.150748 10.157533 111830536.000000 +0.037089 0.139980 10.205389 111931480.000000 +0.055035 0.166301 10.206585 112030544.000000 +0.026321 0.172283 10.139585 112130800.000000 +0.061017 0.180658 10.177871 112230576.000000 +0.009571 0.180658 10.206585 112330520.000000 +0.038285 0.161516 10.181459 112431016.000000 +0.028714 0.163908 10.165908 112531664.000000 +0.039482 0.166301 10.202995 112630928.000000 +0.039482 0.172283 10.204191 112730608.000000 +0.039482 0.147159 10.175477 112830896.000000 +0.046660 0.162712 10.222138 112930512.000000 +0.041874 0.153141 10.173084 113030536.000000 +0.025125 0.163908 10.176675 113130792.000000 +0.003589 0.155533 10.186246 113230560.000000 +0.052642 0.160319 10.226924 113331152.000000 +0.008375 0.175872 10.175477 113430720.000000 +0.039482 0.157926 10.134801 113531008.000000 +0.025125 0.142373 10.191031 113630608.000000 +0.025125 0.155533 10.155140 113731064.000000 +0.021535 0.173480 10.189835 113830632.000000 +0.039482 0.155533 10.174281 113930832.000000 +0.029910 0.149551 10.218549 114030824.000000 +0.025125 0.141177 10.169496 114130760.000000 +0.038285 0.165105 10.186246 114230896.000000 +0.025125 0.174676 10.217353 114330672.000000 +0.023928 0.148355 10.191031 114430576.000000 +0.040678 0.149551 10.214959 114530824.000000 +0.015553 0.179462 10.199407 114630576.000000 +0.026321 0.157926 10.174281 114730896.000000 +0.037089 0.172283 10.145569 114830656.000000 +0.020339 0.159123 10.210175 114930688.000000 +0.037089 0.156730 10.218549 115030568.000000 +0.040678 0.154337 10.202995 115130544.000000 +0.053839 0.168694 10.206585 115230824.000000 +0.029910 0.135194 10.224532 115330560.000000 +0.029910 0.202193 10.187442 115430768.000000 +0.022732 0.149551 10.164711 115530520.000000 +0.023928 0.163908 10.157533 115630912.000000 +0.015553 0.142373 10.212566 115730760.000000 +0.044267 0.149551 10.193424 115830640.000000 +0.014357 0.163908 10.183852 115930824.000000 +0.043071 0.149551 10.191031 116030728.000000 +0.040678 0.153141 10.164711 116130904.000000 +0.056231 0.175872 10.182656 116230576.000000 +0.004786 0.167498 10.161121 116430736.000000 +0.041874 0.169890 10.191031 116630824.000000 +0.025125 0.155533 10.179067 116730632.000000 +0.023928 0.136391 10.194620 116830768.000000 +0.033500 0.162712 10.165908 116930640.000000 +0.010768 0.178265 10.181459 117030776.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/orientation_change/gyro.txt b/src/sensor_fusion/design/data/100ms/gravity/orientation_change/gyro.txt new file mode 100755 index 0000000..a40075b --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/orientation_change/gyro.txt @@ -0,0 +1,529 @@ +1.890000 0.472500 -0.472500 64211028.000000 +-3.290000 2.152500 -31.990000 64311292.000000 +-5.355000 0.227500 2.117500 64411184.000000 +-5.407500 0.227500 2.117500 64511276.000000 +-5.407500 0.192500 2.117500 64611292.000000 +-5.425000 0.227500 2.135000 64711240.000000 +-5.425000 0.262500 2.135000 64811132.000000 +-5.407500 0.227500 2.135000 64911248.000000 +-5.442500 0.227500 2.135000 65010520.000000 +-5.407500 0.227500 2.135000 65110496.000000 +-5.442500 0.262500 2.100000 65210616.000000 +-5.425000 0.227500 2.135000 65310504.000000 +-5.442500 0.297500 2.117500 65410440.000000 +-5.442500 0.227500 2.135000 65510460.000000 +-5.460000 0.227500 2.135000 65610520.000000 +-5.460000 0.262500 2.117500 65710660.000000 +-5.442500 0.227500 2.082500 65810688.000000 +-5.407500 0.262500 2.100000 65910520.000000 +-5.442500 0.227500 2.135000 66015548.000000 +-5.390000 0.262500 2.117500 66115640.000000 +-5.442500 0.227500 2.152500 66215452.000000 +-5.442500 0.227500 2.117500 66315812.000000 +-5.460000 0.227500 2.170000 66415564.000000 +-5.407500 0.262500 2.100000 66515752.000000 +-5.460000 0.297500 2.117500 66615608.000000 +-5.407500 0.227500 2.135000 66715732.000000 +-5.407500 0.262500 2.117500 66815536.000000 +-5.442500 0.227500 2.135000 66915796.000000 +-5.495000 0.192500 2.100000 67015636.000000 +-5.442500 0.227500 2.135000 67115864.000000 +-5.442500 0.262500 2.100000 67215656.000000 +-5.460000 0.262500 2.135000 67315872.000000 +-5.442500 0.262500 2.135000 67415680.000000 +-5.442500 0.262500 2.152500 67515824.000000 +-5.460000 0.262500 2.100000 67615784.000000 +-5.460000 0.227500 2.117500 67715688.000000 +-5.442500 0.227500 2.135000 67815784.000000 +-5.442500 0.262500 2.117500 67915816.000000 +-5.460000 0.227500 2.135000 68016368.000000 +-5.442500 0.227500 2.117500 68115976.000000 +-5.460000 0.262500 2.187500 68215792.000000 +-5.425000 0.227500 2.100000 68315816.000000 +-5.442500 0.227500 2.135000 68415872.000000 +-5.460000 0.227500 2.152500 68515680.000000 +-5.442500 0.227500 2.117500 68615960.000000 +-5.442500 0.227500 2.117500 68716040.000000 +-5.425000 0.297500 2.135000 68815856.000000 +-5.442500 0.262500 2.135000 68915384.000000 +-5.460000 0.262500 2.117500 69015552.000000 +-5.477500 0.227500 2.152500 69115424.000000 +-5.495000 0.227500 2.117500 69216528.000000 +-5.442500 0.192500 2.152500 69315440.000000 +-5.495000 0.262500 2.117500 69415608.000000 +-5.460000 0.227500 2.100000 69515440.000000 +-5.460000 0.227500 2.152500 69615832.000000 +-5.442500 0.262500 2.135000 69715928.000000 +-5.442500 0.262500 2.135000 69815768.000000 +-5.442500 0.227500 2.117500 69915904.000000 +-5.460000 0.227500 2.135000 70015680.000000 +-5.425000 0.717500 2.117500 70115816.000000 +-5.460000 -0.192500 2.152500 70215656.000000 +-5.442500 0.262500 2.152500 70315520.000000 +-5.460000 0.612500 2.152500 70415824.000000 +-5.372500 -5.897500 2.275000 70515608.000000 +-5.320000 -4.322500 2.292500 70615920.000000 +-5.635000 -1.732500 2.187500 70715688.000000 +-5.547500 -0.157500 2.152500 70815760.000000 +-5.582500 -0.437500 2.152500 70915688.000000 +-6.580000 -4.567500 2.292500 71015848.000000 +-9.152500 -14.962500 2.607500 71115816.000000 +-7.770000 -8.312500 3.377500 71215768.000000 +-6.370000 -13.772500 -0.175000 71315568.000000 +-6.965000 -24.062500 -5.390000 71415856.000000 +-6.300000 -38.027500 -1.890000 71515584.000000 +-5.040000 -44.887501 5.617500 71615848.000000 +-4.410000 -52.832500 7.175000 71715632.000000 +-4.637500 -64.032501 4.480000 71815768.000000 +-8.207500 -65.852501 -2.590000 71915688.000000 +-7.840000 -58.817501 -1.190000 72015776.000000 +-8.295000 -51.887501 -0.945000 72115664.000000 +-3.762500 -54.582500 4.602500 72215896.000000 +-0.245000 -43.767502 7.647500 72315752.000000 +1.155000 -56.507500 7.892500 72415544.000000 +-2.800000 -31.832500 3.325000 72515776.000000 +-3.482500 -27.597500 2.660000 72615624.000000 +-4.025000 -42.647499 2.362500 72715968.000000 +-3.482500 -40.267502 2.905000 72815680.000000 +-4.567500 -35.332500 2.222500 72915624.000000 +-4.900000 -27.667500 2.345000 73015680.000000 +-3.692500 -33.267502 2.765000 73115568.000000 +-4.462500 -41.982502 2.782500 73215728.000000 +-2.975000 -19.022501 3.045000 73315912.000000 +-3.115000 -21.507500 2.975000 73415816.000000 +-4.217500 -10.517500 2.555000 73516176.000000 +-4.812500 -8.452500 2.432500 73615616.000000 +-2.397500 -9.502500 2.660000 73715672.000000 +-5.582500 -14.017500 2.467500 73815896.000000 +-4.620000 -20.982500 2.432500 73915800.000000 +-2.712500 -4.777500 2.397500 74015584.000000 +-3.290000 -4.112500 2.345000 74116056.000000 +-3.815000 -6.317500 2.362500 74215920.000000 +-5.600000 3.307500 2.065000 74315896.000000 +-5.495000 -1.382500 2.222500 74416336.000000 +-5.477500 -0.192500 2.187500 74515672.000000 +-5.477500 0.017500 2.152500 74616872.000000 +-5.477500 4.462500 2.082500 74716808.000000 +-24.097500 20.842501 1.172500 74816720.000000 +-7.822500 12.792500 1.785000 74918184.000000 +-5.197500 -4.042500 2.275000 75016240.000000 +-5.530000 -0.052500 2.117500 75117040.000000 +-4.865000 -0.857500 2.205000 75216200.000000 +0.927500 -3.797500 2.642500 75316416.000000 +-5.320000 -0.507500 2.222500 75416048.000000 +-4.427500 1.102500 2.222500 75516840.000000 +-8.872500 9.082500 1.820000 75616192.000000 +-5.355000 -4.637500 2.362500 75716744.000000 +-5.425000 0.542500 2.187500 75816704.000000 +-5.477500 8.207500 1.907500 75916912.000000 +-5.635000 -5.862500 2.170000 76016656.000000 +-6.055000 -8.907500 2.345000 76116880.000000 +-5.932500 -5.722500 2.275000 76216968.000000 +-1.977500 13.807500 2.012500 76316944.000000 +-5.582500 -4.392500 2.100000 76417048.000000 +-5.565000 -3.482500 2.240000 76517208.000000 +-5.530000 -2.432500 2.187500 76616168.000000 +-5.425000 -3.657500 2.222500 76716048.000000 +-5.477500 4.322500 2.065000 76817984.000000 +-5.460000 -1.067500 2.222500 76916248.000000 +-5.477500 1.557500 2.100000 77016784.000000 +-5.477500 -0.577500 2.222500 77117336.000000 +-5.442500 1.312500 2.170000 77216880.000000 +-6.947500 7.332500 1.855000 77316880.000000 +-9.205000 3.482500 1.890000 77416256.000000 +-5.460000 2.082500 2.065000 77516120.000000 +-5.460000 0.402500 2.152500 77616120.000000 +-5.460000 -0.682500 2.222500 77716664.000000 +-5.460000 -0.122500 2.135000 77816376.000000 +-5.425000 1.382500 2.187500 77916344.000000 +-5.512500 -1.872500 2.205000 78016184.000000 +-5.460000 0.087500 2.152500 78115880.000000 +-5.460000 -0.962500 2.187500 78216240.000000 +-5.495000 -4.357500 2.240000 78319456.000000 +-5.477500 -2.152500 2.170000 78415848.000000 +-5.460000 -0.997500 2.135000 78515632.000000 +-5.442500 -1.312500 2.152500 78615816.000000 +-14.455000 3.342500 1.715000 78715736.000000 +-6.177500 0.997500 2.100000 78815880.000000 +-4.515000 3.237500 2.030000 78916168.000000 +-5.407500 3.412500 2.065000 79016120.000000 +-5.425000 -1.242500 2.222500 79116360.000000 +-5.442500 0.192500 2.100000 79216496.000000 +-5.477500 0.542500 2.100000 79316552.000000 +-5.477500 1.557500 2.082500 79416608.000000 +-5.477500 -3.202500 2.205000 79516536.000000 +-5.477500 2.607500 2.100000 79616112.000000 +-5.442500 2.852500 2.135000 79716528.000000 +-5.477500 -1.802500 2.187500 79816024.000000 +-5.547500 -4.987500 2.240000 79916632.000000 +-5.547500 -1.767500 2.135000 80019072.000000 +-5.460000 -1.417500 2.275000 80116912.000000 +-5.495000 2.677500 2.082500 80216504.000000 +-5.425000 2.782500 2.117500 80316208.000000 +-5.477500 3.272500 2.135000 80417336.000000 +-5.547500 -6.527500 2.362500 80516736.000000 +-5.372500 -2.677500 2.240000 80616688.000000 +-5.477500 -1.102500 2.205000 80716336.000000 +-5.582500 -6.352500 2.240000 80816768.000000 +-5.057500 -4.497500 2.205000 80916720.000000 +-5.495000 -1.452500 2.205000 81016416.000000 +-5.495000 -0.472500 2.100000 81116472.000000 +-5.495000 0.507500 2.187500 81215568.000000 +-5.547500 3.097500 2.082500 81316728.000000 +-5.460000 5.022500 2.065000 81415648.000000 +-5.477500 1.207500 2.117500 81516808.000000 +-5.460000 2.047500 2.152500 81616832.000000 +-5.582500 -5.582500 2.257500 81716000.000000 +-5.512500 -3.132500 2.205000 81815856.000000 +-5.495000 -2.257500 2.135000 81915568.000000 +-5.460000 3.482500 2.117500 82020224.000000 +-5.355000 8.067500 2.012500 82120400.000000 +-5.512500 -1.522500 2.310000 82220664.000000 +-5.390000 5.267500 2.100000 82320744.000000 +-5.477500 0.122500 2.152500 82420384.000000 +-5.442500 1.557500 2.065000 82520848.000000 +-5.145000 0.297500 2.257500 82620736.000000 +-5.127500 15.242500 2.205000 82720448.000000 +-1.960000 29.487499 1.960000 82820752.000000 +-1.557500 23.747499 2.275000 82920520.000000 +-5.110000 19.617500 1.750000 83020720.000000 +-7.962500 23.502501 1.172500 83120552.000000 +-6.807500 27.072500 1.820000 83221848.000000 +-2.222500 36.452499 3.342500 83320416.000000 +-0.455000 44.642502 4.130000 83420520.000000 +-5.670000 47.372501 2.450000 83520496.000000 +-7.227500 54.442501 2.187500 83620480.000000 +-6.860000 47.792500 2.502500 83720880.000000 +-10.430000 47.582500 -1.750000 83820472.000000 +-7.700000 43.242500 -0.175000 83923216.000000 +-4.200000 56.367500 3.080000 84021232.000000 +-1.610000 49.962502 6.527500 84121888.000000 +-4.777500 70.612503 2.450000 84221560.000000 +-5.582500 66.552498 1.172500 84321512.000000 +-5.757500 58.257500 0.385000 84421480.000000 +-4.217500 52.552502 5.600000 84521200.000000 +-4.462500 54.092499 5.372500 84622384.000000 +-4.305000 27.527500 6.020000 84721264.000000 +-5.302500 6.212500 1.575000 84823144.000000 +-5.337500 3.377500 3.465000 84921544.000000 +-5.582500 2.572500 3.080000 85021248.000000 +-5.792500 4.112500 1.032500 85122584.000000 +-5.635000 7.507500 2.625000 85221968.000000 +-5.635000 8.592500 2.905000 85320784.000000 +-6.247500 12.092500 -1.050000 85420528.000000 +-5.670000 14.717500 0.875000 85520768.000000 +-5.197500 0.997500 2.800000 85620376.000000 +-5.127500 1.452500 2.380000 85720448.000000 +1.120000 27.562500 -0.437500 85820712.000000 +-5.337500 0.752500 2.275000 85920544.000000 +-5.442500 0.297500 2.187500 86020704.000000 +-5.897500 11.882500 2.712500 86120528.000000 +-5.530000 1.697500 2.275000 86220776.000000 +-5.425000 -0.297500 2.257500 86320544.000000 +-5.442500 0.157500 2.135000 86420576.000000 +-5.460000 0.262500 2.100000 86520728.000000 +-5.460000 0.262500 2.152500 86620424.000000 +-5.460000 0.262500 2.117500 86720784.000000 +-5.460000 0.227500 2.135000 86820488.000000 +-5.495000 0.227500 2.100000 86920752.000000 +-5.425000 0.227500 2.082500 87020784.000000 +-5.460000 0.262500 2.187500 87120720.000000 +-5.495000 0.262500 2.135000 87220664.000000 +-5.442500 0.192500 2.135000 87320768.000000 +-5.460000 0.577500 2.082500 87420384.000000 +-5.477500 -0.122500 2.135000 87520392.000000 +-5.495000 0.297500 2.135000 87620712.000000 +-5.442500 0.297500 2.117500 87720496.000000 +-5.460000 0.227500 2.117500 87820496.000000 +-5.477500 0.262500 2.152500 87920456.000000 +-5.495000 0.262500 2.117500 88020480.000000 +-5.495000 0.192500 2.100000 88120728.000000 +-5.495000 0.192500 2.117500 88220608.000000 +-5.512500 0.227500 2.117500 88320840.000000 +-5.477500 0.262500 2.135000 88420456.000000 +-5.460000 0.192500 2.117500 88520448.000000 +-5.390000 -0.192500 2.170000 88620544.000000 +-5.547500 1.102500 2.187500 88720544.000000 +-5.442500 -0.157500 2.222500 88820600.000000 +-5.477500 0.017500 2.135000 88920608.000000 +-5.442500 0.262500 2.135000 89020696.000000 +-5.477500 0.262500 2.100000 89120512.000000 +-5.460000 0.227500 2.117500 89220616.000000 +-5.425000 0.227500 2.117500 89320576.000000 +-5.477500 0.227500 2.117500 89420464.000000 +-5.477500 0.227500 2.100000 89520376.000000 +-5.460000 0.227500 2.117500 89620464.000000 +-5.495000 0.192500 2.117500 89720632.000000 +-5.460000 0.227500 2.117500 89820448.000000 +-5.477500 0.262500 2.117500 89920592.000000 +-5.495000 0.227500 2.117500 90020664.000000 +-5.495000 0.227500 2.117500 90120544.000000 +-5.477500 0.262500 2.082500 90220496.000000 +-5.477500 0.262500 2.100000 90320520.000000 +-5.477500 0.262500 2.100000 90420752.000000 +-5.495000 0.262500 2.082500 90520512.000000 +-5.495000 0.262500 2.100000 90620560.000000 +-5.512500 0.262500 2.100000 90720696.000000 +-5.530000 0.472500 2.082500 90820464.000000 +-5.477500 0.087500 2.100000 90920744.000000 +-5.512500 0.297500 2.100000 91020488.000000 +-5.512500 0.262500 2.100000 91120800.000000 +-5.442500 -1.872500 2.240000 91220584.000000 +-5.495000 0.437500 2.187500 91320504.000000 +-5.495000 -0.017500 3.692500 91420720.000000 +-5.512500 -0.192500 4.287500 91520472.000000 +-5.495000 1.592500 4.270000 91620784.000000 +-3.167500 2.852500 4.357500 91720480.000000 +3.325000 -14.052500 4.777500 91820792.000000 +10.517500 3.237500 6.160000 91920472.000000 +30.415001 8.347500 -0.962500 92020552.000000 +42.700001 8.522500 2.187500 92120792.000000 +54.985001 4.252500 5.197500 92220480.000000 +60.322502 -1.522500 7.245000 92320800.000000 +61.564999 -6.107500 9.677500 92420472.000000 +61.827499 -7.962500 9.065000 92520784.000000 +60.270000 -2.082500 6.667500 92620384.000000 +57.802502 -0.472500 8.102500 92720608.000000 +59.797501 -3.832500 5.110000 92820704.000000 +59.447502 0.892500 2.957500 92920656.000000 +59.570000 -6.142500 4.532500 93022168.000000 +57.697502 5.197500 2.835000 93121688.000000 +59.080002 -9.467500 1.470000 93221584.000000 +53.865002 -10.307500 -0.962500 93321304.000000 +37.642502 -4.777500 -5.425000 93421200.000000 +26.337500 -2.012500 2.432500 93521760.000000 +27.352501 -8.207500 -3.377500 93621528.000000 +18.830000 -1.802500 -6.685000 93721712.000000 +0.402500 7.647500 -0.420000 93821696.000000 +-4.637500 3.307500 3.517500 93922456.000000 +-1.977500 0.752500 -0.420000 94021472.000000 +-8.522500 4.042500 0.770000 94121616.000000 +-8.732500 3.167500 4.287500 94222768.000000 +-3.010000 0.962500 0.490000 94321328.000000 +-3.657500 -2.222500 -0.385000 94422352.000000 +-7.857500 3.307500 5.460000 94521456.000000 +-7.472500 1.452500 2.940000 94622456.000000 +-4.480000 -6.037500 -0.595000 94723016.000000 +-1.382500 -4.672500 -2.117500 94821280.000000 +-3.167500 3.797500 3.027500 94922320.000000 +-4.952500 4.532500 9.415000 95021408.000000 +0.437500 -2.082500 -3.342500 95122560.000000 +-9.012500 5.407500 -1.067500 95221560.000000 +-12.442500 4.812500 3.185000 95322408.000000 +-5.740000 3.097500 -0.822500 95420624.000000 +-2.467500 4.042500 -2.660000 95522400.000000 +-3.762500 2.362500 -0.507500 95622352.000000 +-2.660000 2.467500 -0.192500 95721576.000000 +-2.957500 2.292500 2.432500 95824240.000000 +-4.707500 -0.297500 3.535000 95921480.000000 +-4.725000 2.537500 4.550000 96023936.000000 +-2.572500 0.122500 3.972500 96121376.000000 +-2.240000 16.957500 3.850000 96220480.000000 +0.455000 -9.852500 1.207500 96320736.000000 +-0.805000 -2.432500 5.127500 96420528.000000 +-2.187500 -6.457500 -2.275000 96520456.000000 +-2.380000 2.852500 1.382500 96621016.000000 +-10.990000 -8.312500 4.497500 96721008.000000 +-9.957500 -6.492500 5.827500 96820416.000000 +-8.032500 -8.837500 5.232500 96920752.000000 +-5.302500 3.027500 0.070000 97020696.000000 +1.977500 5.057500 -2.012500 97120568.000000 +-0.962500 1.067500 3.622500 97220624.000000 +-13.230000 2.922500 0.017500 97320408.000000 +-18.094999 -0.087500 -3.307500 97420528.000000 +-9.240000 -1.137500 1.907500 97520736.000000 +-1.470000 -2.257500 5.775000 97620520.000000 +-5.180000 0.647500 1.522500 97720624.000000 +-10.832500 4.742500 -1.522500 97820512.000000 +-11.707500 -0.647500 -3.132500 97920536.000000 +-6.440000 0.122500 1.452500 98020512.000000 +-3.185000 -0.717500 3.290000 98120520.000000 +-2.030000 -0.822500 4.042500 98220528.000000 +-9.695000 3.097500 2.730000 98320440.000000 +-12.267500 -0.437500 -3.780000 98420624.000000 +-5.477500 0.822500 0.525000 98520560.000000 +0.542500 -0.612500 4.567500 98620512.000000 +0.455000 -0.717500 5.022500 98720592.000000 +-10.955000 1.382500 1.557500 98820392.000000 +-10.500000 -0.402500 0.280000 98920480.000000 +-2.887500 -0.717500 3.727500 99020512.000000 +0.140000 -0.017500 4.340000 99120496.000000 +-1.225000 3.237500 3.062500 99220400.000000 +-10.955000 -2.432500 -0.630000 99320392.000000 +-11.637500 0.857500 -1.697500 99420440.000000 +-4.812500 0.822500 1.207500 99520576.000000 +0.070000 -0.227500 3.605000 99620696.000000 +-3.342500 0.192500 4.812500 99720400.000000 +-10.097500 -1.032500 1.732500 99820496.000000 +-5.985000 0.122500 1.697500 99920448.000000 +-0.192500 -0.472500 3.745000 100020560.000000 +-2.065000 0.087500 3.640000 100120696.000000 +-7.280000 2.187500 1.907500 100220632.000000 +-10.290000 -0.647500 -0.087500 100320400.000000 +-3.972500 -0.157500 2.275000 100420360.000000 +-0.262500 -0.332500 3.727500 100521680.000000 +0.000000 -0.262500 4.602500 100620576.000000 +-6.912500 4.217500 0.717500 100720464.000000 +-13.125000 0.507500 -0.875000 100820560.000000 +-4.760000 -0.017500 4.095000 100920608.000000 +-1.872500 0.717500 2.362500 101020584.000000 +-0.997500 0.332500 3.657500 101120424.000000 +-7.227500 2.712500 2.835000 101220432.000000 +-14.875000 -3.167500 5.407500 101320528.000000 +-9.730000 2.957500 -1.680000 101421080.000000 +1.085000 -0.227500 3.412500 101520624.000000 +-2.345000 1.557500 1.207500 101620688.000000 +-7.665000 1.067500 1.277500 101720608.000000 +-5.687500 0.717500 1.015000 101820576.000000 +3.377500 0.787500 3.902500 101920704.000000 +-0.437500 0.122500 1.032500 102020528.000000 +-7.122500 0.157500 0.157500 102120704.000000 +-10.832500 -1.347500 1.487500 102220528.000000 +-8.750000 -0.262500 1.977500 102320752.000000 +-3.535000 -0.927500 4.952500 102420456.000000 +-0.560000 -1.977500 3.640000 102520544.000000 +-1.732500 0.857500 10.342500 102620776.000000 +-8.925000 -0.542500 2.397500 102720496.000000 +-9.712500 13.177500 -0.175000 102820744.000000 +-2.765000 -15.522500 3.955000 102920648.000000 +-3.867500 6.002500 0.175000 103021832.000000 +-4.025000 2.887500 2.240000 103121560.000000 +-7.875000 3.447500 3.692500 103221520.000000 +-10.255000 5.687500 5.740000 103321312.000000 +-6.055000 1.977500 2.642500 103421832.000000 +-5.565000 -0.087500 4.322500 103521408.000000 +-6.720000 -0.402500 5.390000 103621992.000000 +-9.975000 1.837500 6.037500 103721384.000000 +-12.092500 1.977500 6.475000 103820752.000000 +-5.862500 -3.167500 2.310000 103920496.000000 +-3.395000 -3.482500 -3.290000 104020704.000000 +-4.987500 0.507500 1.452500 104120688.000000 +-7.157500 2.362500 1.435000 104221176.000000 +-7.175000 1.207500 1.330000 104320528.000000 +-5.057500 2.117500 1.277500 104420720.000000 +-6.562500 1.767500 1.732500 104520544.000000 +-6.265000 1.487500 2.712500 104620504.000000 +-3.290000 -1.067500 1.067500 104720880.000000 +-6.037500 0.017500 1.172500 104820536.000000 +-5.810000 0.612500 2.555000 104920736.000000 +-6.790000 2.082500 3.045000 105020672.000000 +-6.685000 1.522500 2.625000 105121256.000000 +-8.120000 0.227500 5.460000 105220464.000000 +-8.137500 0.017500 2.257500 105320536.000000 +-9.695000 -0.577500 -3.500000 105420472.000000 +-15.155000 1.697500 -1.575000 105520880.000000 +-17.010000 1.977500 1.697500 105620464.000000 +-16.100000 0.017500 0.070000 105720448.000000 +-22.382500 1.697500 0.280000 105820704.000000 +-41.720001 38.412498 -0.630000 105920480.000000 +-43.697498 -27.772501 -0.962500 106020496.000000 +-52.027500 -13.772500 2.100000 106120664.000000 +-61.722500 12.617500 7.665000 106220624.000000 +-53.532501 -2.852500 2.887500 106320728.000000 +-47.285000 6.457500 -4.567500 106420512.000000 +-44.799999 3.447500 -8.767500 106520720.000000 +-45.779999 5.652500 -6.160000 106620464.000000 +-50.785000 1.837500 -2.555000 106720536.000000 +-50.575001 -3.587500 -5.950000 106820664.000000 +-50.959999 0.542500 -8.662500 106920464.000000 +-59.150002 -0.402500 -4.060000 107020688.000000 +-58.310001 3.202500 0.665000 107120464.000000 +-53.340000 2.397500 -2.730000 107220688.000000 +-52.272499 3.482500 -6.177500 107320520.000000 +-54.687500 4.882500 -5.705000 107420488.000000 +-53.480000 -2.152500 0.840000 107520696.000000 +-41.615002 -7.227500 1.190000 107620488.000000 +-35.507500 -2.502500 -0.035000 107720432.000000 +-33.827499 -8.382500 0.105000 107820384.000000 +-33.897499 -3.762500 0.525000 107920376.000000 +-28.927500 -12.057500 -1.802500 108020456.000000 +-25.322500 -14.227500 3.202500 108120376.000000 +-15.610000 -14.297500 0.927500 108220376.000000 +-10.010000 5.092500 1.942500 108320384.000000 +-8.032500 4.952500 0.752500 108420376.000000 +-5.477500 0.192500 1.505000 108520384.000000 +-5.442500 -2.117500 2.345000 108620816.000000 +-5.617500 2.747500 2.117500 108720432.000000 +-5.460000 -2.537500 2.170000 108820512.000000 +-5.512500 1.907500 2.047500 108920688.000000 +-5.477500 0.297500 2.117500 109020504.000000 +-5.477500 0.052500 2.100000 109120656.000000 +-5.477500 0.192500 2.135000 109220520.000000 +-5.460000 0.297500 2.135000 109320688.000000 +-5.460000 1.312500 2.100000 109420424.000000 +-5.425000 -3.272500 2.222500 109520448.000000 +-5.530000 3.832500 2.047500 109620480.000000 +-5.460000 -0.717500 2.135000 109720488.000000 +-5.477500 -0.192500 2.117500 109820592.000000 +-5.390000 -3.657500 2.152500 109921120.000000 +-5.600000 5.302500 1.995000 110020416.000000 +-5.477500 -1.487500 2.135000 110120672.000000 +-5.512500 1.102500 2.065000 110220480.000000 +-5.442500 0.892500 2.152500 110320400.000000 +-5.512500 0.892500 2.170000 110420560.000000 +-5.477500 -1.172500 2.152500 110520448.000000 +-5.495000 0.787500 2.100000 110620464.000000 +-5.460000 0.227500 2.065000 110720504.000000 +-5.390000 -0.437500 2.100000 110820376.000000 +-5.565000 -1.242500 2.117500 110920488.000000 +-5.547500 2.607500 2.030000 111020600.000000 +-5.477500 -0.612500 2.082500 111120472.000000 +-5.512500 0.332500 2.117500 111220648.000000 +-5.495000 0.297500 2.100000 111320392.000000 +-5.477500 0.227500 2.082500 111420472.000000 +-5.512500 0.227500 2.100000 111520512.000000 +-5.512500 0.227500 2.100000 111620528.000000 +-5.512500 0.192500 2.082500 111720688.000000 +-5.530000 0.227500 2.100000 111820464.000000 +-5.512500 0.262500 2.100000 111920744.000000 +-5.512500 0.227500 2.100000 112020456.000000 +-5.530000 0.192500 2.100000 112120720.000000 +-5.512500 0.227500 2.100000 112220560.000000 +-5.530000 0.262500 2.065000 112320704.000000 +-5.530000 0.192500 2.082500 112420712.000000 +-5.495000 0.262500 2.100000 112520544.000000 +-5.512500 0.262500 2.117500 112620720.000000 +-5.530000 0.227500 2.117500 112720488.000000 +-5.512500 0.227500 2.117500 112820736.000000 +-5.512500 0.262500 2.100000 112920496.000000 +-5.477500 0.227500 2.117500 113020480.000000 +-5.530000 0.227500 2.117500 113120672.000000 +-5.495000 0.227500 2.135000 113220576.000000 +-5.530000 0.262500 2.117500 113320760.000000 +-5.512500 0.227500 2.100000 113420480.000000 +-5.547500 0.227500 2.135000 113520776.000000 +-5.495000 0.227500 2.135000 113620464.000000 +-5.495000 0.262500 2.117500 113720608.000000 +-5.512500 0.192500 2.135000 113820480.000000 +-5.477500 0.227500 2.082500 113920664.000000 +-5.495000 0.262500 2.117500 114020688.000000 +-5.495000 0.227500 2.135000 114120480.000000 +-5.512500 0.227500 2.117500 114220768.000000 +-5.512500 0.262500 2.135000 114320480.000000 +-5.530000 0.227500 2.117500 114420536.000000 +-5.495000 0.227500 2.117500 114520680.000000 +-5.512500 0.157500 2.100000 114620472.000000 +-5.495000 0.227500 2.117500 114720704.000000 +-5.512500 0.297500 2.100000 114820512.000000 +-5.530000 0.227500 2.117500 114920480.000000 +-5.512500 0.262500 2.100000 115020464.000000 +-5.512500 0.227500 2.135000 115120472.000000 +-5.530000 0.192500 2.117500 115220864.000000 +-5.512500 0.262500 2.117500 115320440.000000 +-5.477500 0.262500 2.135000 115420720.000000 +-5.477500 0.192500 2.170000 115520504.000000 +-5.495000 0.227500 2.135000 115620712.000000 +-5.512500 0.262500 2.100000 115720368.000000 +-5.495000 0.192500 2.135000 115820488.000000 +-5.512500 0.262500 2.100000 115920664.000000 +-5.530000 0.262500 2.100000 116020480.000000 +-5.495000 0.227500 2.100000 116120696.000000 +-5.460000 0.192500 2.082500 116220464.000000 +-5.495000 0.262500 2.117500 116320784.000000 +-5.530000 0.227500 2.117500 116420512.000000 +-5.460000 0.227500 2.082500 116520512.000000 +-5.495000 0.262500 2.117500 116620672.000000 +-5.512500 0.192500 2.117500 116720672.000000 +-5.460000 0.227500 2.100000 116820656.000000 +-5.477500 0.262500 2.100000 116920496.000000 +-5.460000 0.262500 2.100000 117020712.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/orientation_change/magnetic.txt b/src/sensor_fusion/design/data/100ms/gravity/orientation_change/magnetic.txt new file mode 100755 index 0000000..ffb0ff0 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/orientation_change/magnetic.txt @@ -0,0 +1,524 @@ +15.312500 -42.500000 -19.062500 64214520.000000 +15.562500 -41.562500 -20.562500 64314520.000000 +15.437500 -40.750000 -20.625000 64414520.000000 +15.312500 -41.187500 -20.375000 64514520.000000 +15.062500 -40.625000 -20.812500 64614520.000000 +14.875000 -40.187500 -20.625000 64714520.000000 +15.000000 -40.125000 -21.250000 64814520.000000 +15.062500 -40.750000 -20.687500 64914520.000000 +15.125000 -40.437500 -21.000000 65014520.000000 +15.000000 -40.500000 -20.812500 65114520.000000 +14.875000 -40.437500 -21.000000 65214520.000000 +15.000000 -40.500000 -21.000000 65314520.000000 +14.562500 -40.500000 -20.750000 65414520.000000 +14.562500 -40.812500 -20.750000 65514520.000000 +14.687500 -40.875000 -20.625000 65614520.000000 +14.875000 -40.812500 -20.687500 65714520.000000 +14.625000 -41.000000 -20.687500 65814520.000000 +14.625000 -41.125000 -20.687500 65914520.000000 +14.625000 -41.125000 -20.625000 66014520.000000 +13.937500 -41.062500 -20.062500 66114520.000000 +14.187500 -41.062500 -20.000000 66214520.000000 +13.937500 -41.000000 -19.812500 66314520.000000 +13.625000 -41.000000 -19.625000 66414520.000000 +13.375000 -41.125000 -19.500000 66514520.000000 +13.375000 -41.187500 -19.187500 66614520.000000 +13.187500 -41.187500 -19.187500 66714520.000000 +13.062500 -41.250000 -19.125000 66814520.000000 +13.437500 -41.375000 -19.625000 66914520.000000 +13.625000 -41.437500 -19.750000 67014520.000000 +13.812500 -41.562500 -19.875000 67114520.000000 +13.937500 -41.625000 -20.062500 67214520.000000 +13.812500 -41.562500 -20.187500 67314520.000000 +13.875000 -41.562500 -20.250000 67414520.000000 +13.937500 -41.375000 -20.250000 67514520.000000 +14.125000 -41.437500 -20.375000 67614520.000000 +14.125000 -41.500000 -20.250000 67714520.000000 +14.125000 -41.500000 -20.187500 67814520.000000 +14.062500 -41.375000 -20.125000 67914520.000000 +14.312500 -41.375000 -20.062500 68014520.000000 +14.500000 -41.250000 -19.937500 68114520.000000 +14.625000 -41.187500 -20.062500 68214520.000000 +14.687500 -41.250000 -20.125000 68314520.000000 +14.812500 -41.250000 -20.187500 68414520.000000 +14.937500 -41.187500 -20.312500 68514520.000000 +14.937500 -41.000000 -20.437500 68614520.000000 +14.937500 -40.875000 -20.500000 68714520.000000 +14.687500 -40.750000 -20.500000 68814520.000000 +14.562500 -40.750000 -20.375000 68914520.000000 +14.500000 -40.625000 -20.437500 69014520.000000 +14.375000 -40.562500 -20.312500 69114520.000000 +14.250000 -40.500000 -20.375000 69214520.000000 +14.062500 -40.375000 -20.187500 69314520.000000 +14.062500 -40.312500 -20.187500 69414520.000000 +14.125000 -40.375000 -20.187500 69514520.000000 +14.125000 -40.250000 -20.312500 69614520.000000 +14.250000 -40.375000 -20.437500 69714520.000000 +14.250000 -40.437500 -20.437500 69814520.000000 +14.375000 -40.437500 -20.625000 69914520.000000 +14.562500 -40.375000 -20.437500 70014520.000000 +14.687500 -40.375000 -20.625000 70114520.000000 +14.437500 -40.625000 -20.500000 70214520.000000 +14.187500 -40.625000 -20.437500 70314520.000000 +14.250000 -40.875000 -20.312500 70414520.000000 +14.187500 -40.937500 -20.312500 70514520.000000 +14.250000 -41.062500 -20.187500 70614520.000000 +14.187500 -41.125000 -19.875000 70714520.000000 +14.062500 -41.250000 -19.875000 70814520.000000 +14.000000 -41.562500 -19.750000 70914520.000000 +14.125000 -41.625000 -19.687500 71014520.000000 +14.312500 -41.687500 -19.812500 71114520.000000 +14.187500 -41.812500 -19.875000 71214520.000000 +14.000000 -41.625000 -19.937500 71314520.000000 +13.812500 -41.625000 -20.062500 71414520.000000 +13.375000 -41.562500 -20.312500 71514520.000000 +12.937500 -41.687500 -20.375000 71614520.000000 +11.875000 -41.437500 -20.562500 71714520.000000 +11.000000 -41.187500 -20.875000 71814520.000000 +9.875000 -41.250000 -20.875000 71914520.000000 +8.812500 -41.125000 -20.937500 72014520.000000 +7.562500 -41.062500 -21.000000 72114520.000000 +6.062500 -41.062500 -21.000000 72214520.000000 +5.125000 -41.187500 -21.000000 72314520.000000 +3.375000 -40.875000 -20.562500 72414520.000000 +2.562500 -40.812500 -20.437500 72514520.000000 +1.500000 -40.937500 -20.125000 72614520.000000 +0.562500 -40.750000 -19.500000 72714520.000000 +-0.500000 -40.687500 -19.062500 72814520.000000 +-1.875000 -40.875000 -18.375000 72914520.000000 +-2.687500 -40.875000 -17.750000 73014520.000000 +-3.625000 -40.500000 -17.187500 73114520.000000 +-3.937500 -40.500000 -17.000000 73214520.000000 +-4.750000 -40.312500 -16.437500 73314520.000000 +-5.250000 -40.187500 -15.812500 73414520.000000 +-5.687500 -39.875000 -15.375000 73514520.000000 +-6.062500 -39.875000 -14.875000 73614520.000000 +-5.812500 -39.750000 -14.812500 73714520.000000 +-6.000000 -39.562500 -14.500000 73814520.000000 +-6.125000 -39.750000 -14.062500 73914520.000000 +-6.375000 -39.875000 -13.812500 74014520.000000 +-6.187500 -40.125000 -13.750000 74114520.000000 +-6.250000 -40.125000 -13.500000 74214520.000000 +-6.562500 -40.500000 -13.625000 74314520.000000 +-6.500000 -40.437500 -13.687500 74414520.000000 +-7.000000 -40.437500 -13.437500 74514520.000000 +-7.000000 -40.625000 -13.500000 74614520.000000 +-6.937500 -40.562500 -13.812500 74714520.000000 +-6.812500 -40.500000 -14.062500 74814520.000000 +-6.687500 -40.187500 -14.187500 74914520.000000 +-6.750000 -40.437500 -14.562500 75014520.000000 +-6.687500 -40.250000 -14.687500 75114520.000000 +-6.750000 -40.187500 -14.750000 75214520.000000 +-6.375000 -40.125000 -15.000000 75314520.000000 +-6.375000 -40.062500 -14.937500 75414520.000000 +-6.437500 -39.937500 -15.125000 75514520.000000 +-6.437500 -39.937500 -15.062500 75614520.000000 +-6.375000 -40.125000 -15.062500 75714520.000000 +-6.250000 -39.875000 -15.062500 75814520.000000 +-6.437500 -40.062500 -14.812500 75914520.000000 +-6.437500 -40.125000 -14.812500 76014520.000000 +-6.437500 -39.937500 -14.875000 76114520.000000 +-6.312500 -39.937500 -14.937500 76214520.000000 +-6.437500 -40.062500 -14.875000 76314520.000000 +-6.437500 -40.000000 -14.875000 76414520.000000 +-6.500000 -40.125000 -14.812500 76514520.000000 +-6.750000 -40.062500 -14.625000 76614520.000000 +-6.750000 -39.812500 -14.500000 76714520.000000 +-6.625000 -39.812500 -14.437500 76814520.000000 +-6.750000 -40.062500 -14.562500 76914520.000000 +-6.687500 -39.812500 -14.500000 77014520.000000 +-6.625000 -39.750000 -14.375000 77114520.000000 +-6.750000 -39.812500 -14.250000 77214520.000000 +-7.437500 -39.500000 -14.125000 77314520.000000 +-7.437500 -39.312500 -14.250000 77414520.000000 +-7.250000 -39.375000 -14.500000 77514520.000000 +-7.312500 -39.000000 -14.625000 77614520.000000 +-7.562500 -38.812500 -14.375000 77714520.000000 +-7.625000 -39.000000 -14.500000 77814520.000000 +-7.750000 -39.062500 -14.750000 77914520.000000 +-7.937500 -38.937500 -14.375000 78014520.000000 +-7.750000 -39.000000 -14.437500 78114520.000000 +-8.125000 -39.062500 -14.187500 78214520.000000 +-8.375000 -39.125000 -13.875000 78314520.000000 +-9.000000 -39.312500 -13.250000 78414520.000000 +-9.250000 -39.312500 -12.875000 78514520.000000 +-9.812500 -38.937500 -12.375000 78614520.000000 +-10.250000 -38.687500 -11.812500 78714520.000000 +-10.187500 -38.375000 -11.937500 78814520.000000 +-10.062500 -38.500000 -12.000000 78914520.000000 +-9.750000 -38.437500 -12.312500 79014520.000000 +-9.500000 -38.375000 -12.750000 79114520.000000 +-9.062500 -38.437500 -13.437500 79214520.000000 +-8.500000 -38.687500 -13.875000 79314520.000000 +-7.750000 -38.812500 -14.312500 79414520.000000 +-7.187500 -38.937500 -14.875000 79514520.000000 +-6.812500 -39.250000 -15.187500 79614520.000000 +-6.625000 -39.375000 -15.500000 79714520.000000 +-6.312500 -39.687500 -15.437500 79814520.000000 +-6.125000 -39.812500 -15.562500 79914520.000000 +-5.875000 -39.937500 -15.562500 80014520.000000 +-5.812500 -39.875000 -15.875000 80114520.000000 +-6.125000 -40.125000 -16.125000 80214520.000000 +-6.125000 -40.250000 -16.187500 80314520.000000 +-6.062500 -40.312500 -16.312500 80414520.000000 +-6.000000 -40.000000 -16.312500 80514520.000000 +-6.062500 -39.937500 -16.625000 80614520.000000 +-6.125000 -39.750000 -16.437500 80714520.000000 +-6.000000 -39.562500 -16.437500 80814520.000000 +-5.937500 -39.312500 -16.375000 80914520.000000 +-5.812500 -39.187500 -16.062500 81014520.000000 +-5.875000 -39.187500 -16.000000 81114520.000000 +-6.125000 -39.312500 -15.750000 81214520.000000 +-6.187500 -39.312500 -15.687500 81314520.000000 +-6.062500 -39.187500 -15.500000 81414520.000000 +-6.062500 -39.250000 -15.812500 81514520.000000 +-5.937500 -39.312500 -15.875000 81614520.000000 +-6.250000 -39.500000 -15.937500 81714520.000000 +-6.062500 -39.500000 -16.312500 81814520.000000 +-5.875000 -39.375000 -16.250000 81914520.000000 +-5.625000 -39.312500 -16.437500 82014520.000000 +-5.562500 -39.375000 -16.312500 82114520.000000 +-5.500000 -39.250000 -16.125000 82214520.000000 +-5.500000 -39.250000 -15.937500 82314520.000000 +-5.500000 -39.375000 -15.937500 82414520.000000 +-5.312500 -39.500000 -15.875000 82514520.000000 +-5.500000 -39.812500 -15.687500 82614520.000000 +-5.750000 -39.937500 -15.687500 82714520.000000 +-5.562500 -40.000000 -15.937500 82814520.000000 +-5.375000 -40.250000 -16.000000 82914520.000000 +-5.375000 -40.437500 -16.125000 83014520.000000 +-5.125000 -40.625000 -16.437500 83114520.000000 +-4.812500 -40.625000 -16.812500 83214520.000000 +-4.937500 -40.687500 -16.875000 83314520.000000 +-4.625000 -40.375000 -17.312500 83414520.000000 +-4.312500 -40.312500 -17.437500 83514520.000000 +-3.937500 -40.312500 -17.625000 83614520.000000 +-3.250000 -40.062500 -18.250000 83714520.000000 +-2.437500 -40.125000 -18.750000 83814520.000000 +-1.625000 -40.000000 -19.187500 83914520.000000 +-0.812500 -39.937500 -19.250000 84014520.000000 +0.437500 -39.875000 -19.875000 84114520.000000 +1.625000 -40.000000 -20.062500 84214520.000000 +3.125000 -40.125000 -20.750000 84314520.000000 +4.312500 -40.062500 -20.812500 84414520.000000 +5.500000 -40.187500 -20.750000 84514520.000000 +6.750000 -40.250000 -20.812500 84614520.000000 +7.812500 -40.250000 -20.750000 84714520.000000 +9.000000 -40.437500 -21.000000 84814520.000000 +10.000000 -40.500000 -20.937500 84914520.000000 +10.250000 -40.375000 -20.562500 85014520.000000 +10.937500 -40.250000 -20.562500 85114520.000000 +11.312500 -40.437500 -20.750000 85214520.000000 +11.625000 -40.437500 -20.687500 85314520.000000 +11.687500 -40.500000 -20.687500 85414520.000000 +12.000000 -40.750000 -20.812500 85514520.000000 +12.250000 -40.750000 -20.625000 85614520.000000 +12.250000 -40.875000 -20.687500 85714520.000000 +12.937500 -41.125000 -21.000000 85814520.000000 +13.250000 -41.312500 -20.625000 85914520.000000 +13.562500 -41.375000 -20.312500 86014520.000000 +13.875000 -41.500000 -20.375000 86114520.000000 +14.000000 -41.625000 -20.375000 86214520.000000 +14.125000 -41.562500 -20.187500 86314520.000000 +13.937500 -41.625000 -20.187500 86414520.000000 +14.125000 -41.312500 -20.062500 86514520.000000 +14.062500 -41.187500 -19.687500 86614520.000000 +14.062500 -41.125000 -19.937500 86714520.000000 +14.062500 -40.812500 -20.062500 86814520.000000 +13.937500 -40.687500 -20.125000 86914520.000000 +14.125000 -40.562500 -20.062500 87014520.000000 +14.000000 -40.437500 -20.312500 87114520.000000 +14.062500 -40.500000 -20.375000 87214520.000000 +14.187500 -40.500000 -20.312500 87314520.000000 +14.250000 -40.875000 -20.500000 87414520.000000 +14.187500 -40.875000 -20.437500 87514520.000000 +14.125000 -41.250000 -20.500000 87614520.000000 +14.187500 -41.437500 -20.312500 87714520.000000 +13.875000 -41.187500 -20.062500 87814520.000000 +14.062500 -41.312500 -19.812500 87914520.000000 +14.000000 -41.437500 -19.750000 88014520.000000 +14.125000 -41.500000 -19.750000 88114520.000000 +14.000000 -41.437500 -19.625000 88214520.000000 +14.125000 -41.312500 -19.687500 88314520.000000 +13.937500 -41.250000 -19.437500 88414520.000000 +13.812500 -41.250000 -19.562500 88514520.000000 +13.562500 -41.312500 -19.500000 88614520.000000 +13.000000 -41.000000 -19.062500 88714520.000000 +12.562500 -40.500000 -18.750000 88814520.000000 +11.937500 -40.062500 -18.625000 88914520.000000 +12.000000 -40.000000 -18.750000 89014520.000000 +11.687500 -40.187500 -18.750000 89114520.000000 +11.562500 -40.062500 -18.875000 89214520.000000 +11.687500 -39.875000 -18.875000 89314520.000000 +11.750000 -40.125000 -18.812500 89414520.000000 +12.062500 -40.250000 -19.062500 89514520.000000 +12.125000 -40.500000 -19.187500 89614520.000000 +12.187500 -41.000000 -18.937500 89714520.000000 +11.812500 -40.812500 -18.375000 89814520.000000 +11.625000 -40.750000 -18.000000 89914520.000000 +11.312500 -40.562500 -17.750000 90014520.000000 +10.687500 -40.312500 -17.437500 90114520.000000 +11.000000 -40.375000 -17.875000 90214520.000000 +11.187500 -40.625000 -18.125000 90314520.000000 +11.562500 -40.562500 -18.437500 90414520.000000 +12.000000 -40.437500 -18.875000 90514520.000000 +12.562500 -40.500000 -19.562500 90614520.000000 +12.875000 -40.500000 -19.875000 90714520.000000 +13.625000 -40.812500 -20.250000 90814520.000000 +14.187500 -41.125000 -20.812500 90914520.000000 +14.250000 -41.000000 -20.625000 91014520.000000 +14.312500 -40.937500 -20.937500 91114520.000000 +14.125000 -40.875000 -20.750000 91214520.000000 +14.062500 -40.750000 -20.875000 91314520.000000 +14.062500 -40.812500 -20.687500 91414520.000000 +14.000000 -40.750000 -20.687500 91514520.000000 +14.062500 -40.625000 -20.812500 91614520.000000 +14.000000 -40.562500 -20.500000 91714520.000000 +13.937500 -40.687500 -20.375000 91814520.000000 +13.937500 -40.562500 -19.937500 91914520.000000 +13.875000 -40.875000 -19.312500 92014520.000000 +13.875000 -41.500000 -18.062500 92114520.000000 +13.562500 -41.875000 -16.250000 92214520.000000 +13.500000 -42.187500 -13.937500 92314520.000000 +13.437500 -42.562500 -10.875000 92414520.000000 +13.500000 -42.750000 -7.375000 92514520.000000 +13.187500 -42.375000 -3.437500 92614520.000000 +12.937500 -42.062500 0.937500 92714520.000000 +13.062500 -41.125000 5.250000 92814520.000000 +12.937500 -39.687500 9.625000 92914520.000000 +13.250000 -37.750000 13.812500 93014520.000000 +13.812500 -35.562500 17.750000 93114520.000000 +14.250000 -32.625000 21.375000 93214520.000000 +14.750000 -29.750000 24.687500 93314520.000000 +15.750000 -27.062500 27.375000 93414520.000000 +16.687500 -24.125000 29.500000 93514520.000000 +17.625000 -21.187500 31.437500 93614520.000000 +18.687500 -18.562500 33.125000 93714520.000000 +19.250000 -16.625000 34.250000 93814520.000000 +19.687500 -14.750000 35.062500 93914520.000000 +19.937500 -13.687500 35.562500 94014520.000000 +20.062500 -12.812500 35.937500 94114520.000000 +20.125000 -12.250000 36.062500 94214520.000000 +20.000000 -11.687500 36.312500 94314520.000000 +20.000000 -11.687500 36.437500 94414520.000000 +19.812500 -11.687500 36.250000 94514520.000000 +19.750000 -11.625000 36.187500 94614520.000000 +19.812500 -11.812500 35.937500 94714520.000000 +19.562500 -11.750000 36.000000 94814520.000000 +19.750000 -11.625000 35.812500 94914520.000000 +19.625000 -11.375000 35.875000 95014520.000000 +19.687500 -11.500000 35.812500 95114520.000000 +19.500000 -11.625000 35.875000 95214520.000000 +19.437500 -11.625000 36.125000 95314520.000000 +19.375000 -11.500000 36.312500 95414520.000000 +18.750000 -11.187500 36.625000 95514520.000000 +19.062500 -11.250000 36.437500 95614520.000000 +18.812500 -11.187500 36.812500 95714520.000000 +18.812500 -10.937500 37.000000 95814520.000000 +18.750000 -10.625000 37.187500 95914520.000000 +18.687500 -10.375000 37.375000 96014520.000000 +18.625000 -10.250000 37.250000 96114520.000000 +18.250000 -10.125000 37.062500 96214520.000000 +18.375000 -10.000000 37.125000 96314520.000000 +18.062500 -9.437500 37.562500 96414520.000000 +17.750000 -9.062500 37.875000 96514520.000000 +17.000000 -8.750000 38.250000 96614520.000000 +16.250000 -8.625000 38.750000 96714520.000000 +15.937500 -8.437500 39.000000 96814520.000000 +15.875000 -8.062500 39.125000 96914520.000000 +16.062500 -7.937500 39.312500 97014520.000000 +16.125000 -7.937500 39.500000 97114520.000000 +16.062500 -7.937500 39.250000 97214520.000000 +16.312500 -8.000000 38.812500 97314520.000000 +16.750000 -8.312500 38.562500 97414520.000000 +17.312500 -8.375000 38.250000 97514520.000000 +17.250000 -8.500000 38.125000 97614520.000000 +17.437500 -8.687500 38.125000 97714520.000000 +17.250000 -8.875000 38.375000 97814520.000000 +17.000000 -8.812500 38.375000 97914520.000000 +16.875000 -8.875000 39.000000 98014520.000000 +16.437500 -9.125000 39.312500 98114520.000000 +16.687500 -9.437500 39.250000 98214520.000000 +16.500000 -9.625000 39.500000 98314520.000000 +16.687500 -9.750000 39.375000 98414520.000000 +16.062500 -9.750000 39.625000 98514520.000000 +16.062500 -9.562500 39.875000 98614520.000000 +16.312500 -9.625000 39.750000 98714520.000000 +16.500000 -9.812500 39.312500 98814520.000000 +16.500000 -9.812500 39.500000 98914520.000000 +15.937500 -9.312500 39.687500 99014520.000000 +16.062500 -9.312500 39.312500 99114520.000000 +16.125000 -9.062500 39.562500 99214520.000000 +16.437500 -9.125000 39.437500 99314520.000000 +16.375000 -9.062500 39.187500 99414520.000000 +16.187500 -9.125000 39.625000 99514520.000000 +16.375000 -9.125000 39.437500 99614520.000000 +16.812500 -9.250000 39.250000 99714520.000000 +17.125000 -9.312500 39.250000 99814520.000000 +17.125000 -9.062500 39.500000 99914520.000000 +16.812500 -9.187500 39.500000 100014520.000000 +17.000000 -9.187500 39.187500 100114520.000000 +17.062500 -9.125000 39.187500 100214520.000000 +16.875000 -9.000000 39.125000 100314520.000000 +16.187500 -8.750000 39.687500 100414520.000000 +15.437500 -8.625000 40.187500 100514520.000000 +15.187500 -8.312500 40.500000 100614520.000000 +15.000000 -8.312500 40.562500 100714520.000000 +15.000000 -8.250000 40.750000 100814520.000000 +14.812500 -8.125000 41.125000 100914520.000000 +14.937500 -8.250000 40.875000 101014520.000000 +15.375000 -8.375000 40.500000 101114520.000000 +15.687500 -8.625000 40.062500 101214520.000000 +16.062500 -8.750000 39.812500 101314520.000000 +16.312500 -9.062500 39.500000 101414520.000000 +16.750000 -9.000000 39.500000 101514520.000000 +17.125000 -9.187500 38.875000 101614520.000000 +17.375000 -9.312500 38.625000 101714520.000000 +17.125000 -9.500000 38.750000 101814520.000000 +17.312500 -9.375000 38.687500 101914520.000000 +17.750000 -9.312500 38.562500 102014520.000000 +18.500000 -9.250000 38.187500 102114520.000000 +18.875000 -9.125000 37.875000 102214520.000000 +18.937500 -9.500000 37.375000 102314520.000000 +18.875000 -9.312500 37.562500 102414520.000000 +18.937500 -9.437500 37.375000 102514520.000000 +19.250000 -9.125000 37.187500 102614520.000000 +19.125000 -9.250000 37.250000 102714520.000000 +19.062500 -9.187500 37.375000 102814520.000000 +18.875000 -9.187500 37.187500 102914520.000000 +18.687500 -9.375000 37.062500 103014520.000000 +18.500000 -9.250000 37.000000 103114520.000000 +18.437500 -9.562500 36.937500 103214520.000000 +18.375000 -9.375000 36.937500 103314520.000000 +18.312500 -9.375000 36.937500 103414520.000000 +18.312500 -9.500000 36.812500 103514520.000000 +18.312500 -9.250000 36.750000 103614520.000000 +18.250000 -9.187500 36.875000 103714520.000000 +18.250000 -9.375000 36.937500 103814520.000000 +18.250000 -9.375000 37.187500 103914520.000000 +18.437500 -9.500000 37.125000 104014520.000000 +18.250000 -9.750000 37.062500 104114520.000000 +18.250000 -10.000000 36.937500 104214520.000000 +18.375000 -10.062500 37.062500 104314520.000000 +18.250000 -10.437500 36.875000 104414520.000000 +18.312500 -10.562500 36.812500 104514520.000000 +18.250000 -10.437500 36.875000 104614520.000000 +18.125000 -10.500000 36.687500 104714520.000000 +18.000000 -10.500000 36.687500 104814520.000000 +18.000000 -10.437500 36.812500 104914520.000000 +17.750000 -10.375000 37.062500 105014520.000000 +17.750000 -10.500000 37.062500 105114520.000000 +17.812500 -10.625000 37.000000 105214520.000000 +17.437500 -10.625000 37.062500 105314520.000000 +17.437500 -11.062500 37.187500 105414520.000000 +17.500000 -11.250000 37.062500 105514520.000000 +17.500000 -11.375000 37.250000 105614520.000000 +17.437500 -11.625000 37.187500 105714520.000000 +17.375000 -12.312500 36.812500 105814520.000000 +17.125000 -13.062500 36.625000 105914520.000000 +16.875000 -14.125000 36.250000 106014520.000000 +16.500000 -15.875000 35.500000 106114520.000000 +16.125000 -17.687500 34.437500 106214520.000000 +15.875000 -20.062500 33.250000 106314520.000000 +15.437500 -22.687500 31.625000 106414520.000000 +14.937500 -25.625000 29.812500 106514520.000000 +14.625000 -28.375000 28.187500 106614520.000000 +14.437500 -31.062500 26.062500 106714520.000000 +14.125000 -33.500000 23.625000 106814520.000000 +14.125000 -35.562500 21.125000 106914520.000000 +14.125000 -37.562500 18.437500 107014520.000000 +14.125000 -39.000000 15.750000 107114520.000000 +14.312500 -40.250000 12.625000 107214520.000000 +14.562500 -41.250000 9.375000 107314520.000000 +14.437500 -41.937500 6.250000 107414520.000000 +14.312500 -42.625000 2.750000 107514520.000000 +14.375000 -43.250000 -0.250000 107614520.000000 +14.437500 -43.625000 -3.500000 107714520.000000 +14.312500 -43.750000 -6.312500 107814520.000000 +14.312500 -43.750000 -9.125000 107914520.000000 +14.125000 -43.625000 -11.375000 108014520.000000 +14.062500 -43.312500 -13.312500 108114520.000000 +14.250000 -43.062500 -15.562500 108214520.000000 +14.375000 -42.750000 -16.812500 108314520.000000 +14.437500 -42.250000 -18.125000 108414520.000000 +14.562500 -41.875000 -18.750000 108514520.000000 +14.562500 -41.562500 -19.500000 108614520.000000 +14.500000 -41.250000 -19.812500 108714520.000000 +14.562500 -41.187500 -20.000000 108814520.000000 +14.437500 -41.125000 -20.312500 108914520.000000 +14.625000 -41.312500 -20.250000 109014520.000000 +14.687500 -41.375000 -20.500000 109114520.000000 +14.562500 -41.500000 -20.500000 109214520.000000 +14.500000 -41.875000 -20.625000 109314520.000000 +14.250000 -41.687500 -20.312500 109414520.000000 +13.625000 -41.625000 -19.750000 109514520.000000 +13.500000 -41.437500 -19.750000 109614520.000000 +13.187500 -41.312500 -19.187500 109714520.000000 +12.687500 -41.125000 -19.250000 109814520.000000 +12.000000 -40.812500 -18.750000 109914520.000000 +11.687500 -40.687500 -18.500000 110014520.000000 +11.437500 -40.437500 -18.125000 110114520.000000 +11.187500 -40.312500 -18.125000 110214520.000000 +11.937500 -40.562500 -18.687500 110314520.000000 +12.062500 -40.437500 -18.687500 110414520.000000 +12.000000 -40.187500 -18.562500 110514520.000000 +12.187500 -40.187500 -18.375000 110614520.000000 +12.250000 -40.312500 -18.500000 110714520.000000 +12.250000 -40.375000 -18.437500 110814520.000000 +12.187500 -40.250000 -18.312500 110914520.000000 +12.187500 -40.250000 -18.312500 111014520.000000 +11.687500 -40.312500 -18.437500 111114520.000000 +11.562500 -40.687500 -18.562500 111214520.000000 +12.062500 -41.062500 -19.000000 111314520.000000 +12.187500 -41.000000 -19.062500 111414520.000000 +12.812500 -41.250000 -19.250000 111514520.000000 +13.250000 -41.375000 -19.625000 111614520.000000 +13.562500 -41.562500 -19.875000 111714520.000000 +14.187500 -42.000000 -20.125000 111814520.000000 +14.687500 -41.875000 -20.312500 111914520.000000 +15.000000 -41.875000 -20.437500 112014520.000000 +15.000000 -41.937500 -20.562500 112114520.000000 +15.062500 -42.062500 -20.750000 112214520.000000 +14.937500 -41.875000 -20.812500 112314520.000000 +15.062500 -41.875000 -20.812500 112414520.000000 +15.187500 -42.125000 -20.750000 112514520.000000 +15.187500 -42.125000 -20.937500 112614520.000000 +15.187500 -42.250000 -20.937500 112714520.000000 +15.062500 -42.062500 -21.125000 112814520.000000 +15.187500 -42.000000 -21.250000 112914520.000000 +15.062500 -42.000000 -21.437500 113014520.000000 +15.187500 -42.062500 -21.625000 113114520.000000 +15.187500 -42.187500 -21.687500 113214520.000000 +15.312500 -42.125000 -22.125000 113314520.000000 +15.250000 -42.187500 -22.125000 113414520.000000 +15.375000 -42.375000 -21.937500 113514520.000000 +15.437500 -42.562500 -21.875000 113614520.000000 +15.312500 -42.500000 -21.750000 113714520.000000 +15.437500 -42.562500 -21.500000 113814520.000000 +15.437500 -42.937500 -21.312500 113914520.000000 +14.937500 -42.750000 -21.125000 114014520.000000 +14.562500 -42.750000 -20.875000 114114520.000000 +14.562500 -42.687500 -20.812500 114214520.000000 +14.312500 -42.812500 -20.750000 114314520.000000 +14.062500 -42.875000 -20.562500 114414520.000000 +14.000000 -43.250000 -20.500000 114514520.000000 +14.000000 -43.250000 -20.312500 114614520.000000 +14.125000 -43.187500 -20.437500 114714520.000000 +14.437500 -43.375000 -20.562500 114814520.000000 +14.437500 -43.687500 -20.562500 114914520.000000 +14.375000 -43.687500 -20.687500 115014520.000000 +14.375000 -43.625000 -20.500000 115114520.000000 +14.500000 -43.687500 -20.562500 115214520.000000 +14.500000 -43.562500 -20.437500 115314520.000000 +14.500000 -43.812500 -20.687500 115414520.000000 +14.125000 -43.687500 -20.437500 115614520.000000 +14.312500 -43.187500 -20.375000 115814520.000000 +14.500000 -43.187500 -20.437500 115914520.000000 +14.562500 -43.125000 -20.562500 116014520.000000 +14.437500 -43.062500 -20.500000 116214520.000000 +14.687500 -42.875000 -20.625000 116314520.000000 +14.875000 -42.750000 -20.437500 116414520.000000 +14.875000 -42.937500 -20.500000 116514520.000000 +14.812500 -43.125000 -20.687500 116614520.000000 +14.375000 -43.000000 -20.562500 116814520.000000 +14.375000 -42.812500 -20.562500 117014520.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/accel.txt b/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/accel.txt new file mode 100755 index 0000000..1199540 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/accel.txt @@ -0,0 +1,100 @@ +-0.110070 0.220140 10.134801 54450704.000000 +-0.075374 0.215354 10.174281 54550448.000000 +-0.072981 0.200997 10.216157 54650552.000000 +-0.062213 0.216550 10.150353 54750520.000000 +-0.100499 0.193819 10.174281 54850652.000000 +-0.105284 0.200997 10.138390 54950560.000000 +-0.077767 0.215354 10.167104 55050660.000000 +-0.088534 0.203390 10.198210 55150500.000000 +-0.069392 0.220140 10.124033 55250584.000000 +-0.086142 0.174676 10.212566 55350648.000000 +-0.088534 0.209372 10.208978 55450632.000000 +-0.205783 0.253639 10.152746 55550544.000000 +-0.076570 0.217747 10.167104 55650624.000000 +-0.859023 0.041874 10.103694 55750540.000000 +0.145962 0.144766 10.161121 55850744.000000 +-0.513260 0.512064 10.012767 55950640.000000 +0.284746 0.591027 8.718249 56050544.000000 +0.185444 -0.296710 10.158729 56150588.000000 +0.102891 -0.081356 9.842876 56250688.000000 +0.628116 0.825524 10.989038 56350624.000000 +-0.407976 0.989432 10.313066 56450544.000000 +-0.937986 1.119841 10.993823 56550640.000000 +-0.951147 0.442672 10.141978 56650632.000000 +-0.173480 -0.131605 9.574880 56750588.000000 +-0.334995 -0.120838 9.659825 56850644.000000 +0.171087 -0.064606 9.523434 56950640.000000 +0.879362 1.653440 11.251052 57050616.000000 +0.636491 -0.058624 10.332209 57150560.000000 +1.007378 -1.350748 9.897911 57250636.000000 +1.948954 -1.764707 13.225130 57350744.000000 +1.048056 -1.521835 8.654840 57450556.000000 +0.147159 -0.545564 10.390833 57550672.000000 +0.411566 -0.537189 10.717452 57650680.000000 +0.303888 0.043071 9.418150 57750588.000000 +-1.088734 -0.151944 11.448460 57850464.000000 +-0.976272 -0.368495 10.161121 57950636.000000 +-1.426122 -0.124427 9.869196 58050580.000000 +-1.763510 -0.204586 9.534202 58150680.000000 +-3.476771 -0.093320 9.701699 58250664.000000 +-6.753742 -2.792424 10.630114 58350392.000000 +-19.424934 -3.227918 9.656236 58450424.000000 +-19.601404 9.693325 -4.322634 58550516.000000 +-19.601404 -7.629515 3.986443 58650384.000000 +-13.190435 -0.837488 -0.433101 58751056.000000 +-11.155338 -2.000400 5.217549 58850396.000000 +-3.607180 -2.468197 2.904887 58950336.000000 +-0.507278 -1.883151 -7.222735 59050352.000000 +-6.306284 1.954936 -5.812167 59150356.000000 +-11.350355 -5.115855 -19.601404 59250656.000000 +-2.642873 -2.417947 -11.161322 59350416.000000 +0.934397 -2.043471 -11.907881 59450384.000000 +0.259621 -2.866602 -10.616954 59550364.000000 +2.067399 -3.853641 -9.090333 59650424.000000 +3.711268 -2.377269 -7.372287 59750416.000000 +-1.008575 3.231507 -11.486745 59850328.000000 +5.073980 -0.150748 -6.860222 59951560.000000 +6.709475 -0.045464 -6.244071 60050496.000000 +6.832705 -0.396012 -7.374680 60150372.000000 +7.124629 -0.601795 -7.688138 60250360.000000 +8.078169 0.577867 -8.215756 60350512.000000 +6.043073 -1.325624 -1.184447 60450392.000000 +3.087937 3.060420 6.233303 60550388.000000 +16.403996 -0.290728 8.063812 60650524.000000 +4.113262 2.408376 5.692525 60750520.000000 +-0.874577 1.441676 13.183256 60850680.000000 +-3.014957 0.689133 9.600004 60950572.000000 +-3.687340 -1.356731 12.537193 61050484.000000 +-9.014959 -0.283549 8.413164 61150512.000000 +-11.459228 -1.623530 6.793223 61250408.000000 +-19.601404 -1.052842 0.314656 61350344.000000 +-19.601404 -17.771494 7.665407 61450416.000000 +-19.601404 1.293321 6.126822 61550356.000000 +-19.601404 -1.220340 4.425525 61650436.000000 +-11.587244 1.722832 3.351148 61750480.000000 +-10.828719 -18.870996 11.247462 61855700.000000 +0.788435 -0.778864 16.261621 61955568.000000 +3.418147 -1.215554 10.576276 62055560.000000 +-1.140180 1.844866 13.178471 62155472.000000 +-0.565903 -1.062413 8.269595 62255480.000000 +-1.895115 0.344566 9.172886 62355472.000000 +-3.073581 1.178465 9.213564 62455460.000000 +-3.032902 1.623530 11.525031 62555488.000000 +-4.545166 0.930808 9.824929 62655472.000000 +-5.492724 0.598206 9.954143 62755480.000000 +-3.634698 -1.295713 10.127622 62855552.000000 +-0.613759 -1.082752 10.183852 62955472.000000 +-1.063610 -1.552942 8.632108 63055504.000000 +-0.622134 -2.335395 10.441081 63155504.000000 +-0.619741 2.432304 7.567302 63255472.000000 +-3.267399 1.110270 15.515062 63355784.000000 +-1.685743 1.356731 10.205389 63455688.000000 +-2.658426 -0.406780 14.849857 63555464.000000 +-1.479961 1.024128 9.591630 63655560.000000 +-0.413958 1.846063 8.557930 63755512.000000 +-0.799203 -0.257228 13.779069 63855512.000000 +0.975075 -2.660819 19.601404 63956088.000000 +-4.083352 -0.078963 9.388239 64055472.000000 +-3.936193 -0.138784 10.436296 64155488.000000 +-1.643869 0.490529 7.874779 64255504.000000 +-1.491925 -0.716650 10.613364 64355524.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/gyro.txt b/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/gyro.txt new file mode 100755 index 0000000..5c4004f --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/gyro.txt @@ -0,0 +1,100 @@ +1.890000 0.472500 -0.472500 54380384.000000 +-2.957500 1.697500 -33.127499 54480488.000000 +-5.390000 0.227500 2.135000 54580464.000000 +-5.390000 0.192500 2.100000 54680476.000000 +-5.407500 0.227500 2.117500 54780516.000000 +-5.425000 0.227500 2.100000 54880488.000000 +-5.425000 0.262500 2.100000 54980460.000000 +-5.425000 0.262500 2.082500 55080480.000000 +-5.390000 0.227500 2.065000 55180620.000000 +-5.425000 0.227500 2.100000 55280484.000000 +-5.425000 0.192500 2.100000 55380636.000000 +-5.407500 0.192500 2.117500 55480480.000000 +-5.477500 0.262500 4.112500 55580464.000000 +-5.425000 0.472500 4.760000 55680488.000000 +-5.897500 1.207500 27.405001 55780664.000000 +-1.522500 6.212500 17.832500 55880604.000000 +0.227500 10.727500 29.049999 55980532.000000 +-19.320000 -0.542500 12.110000 56080688.000000 +-10.290000 -17.167500 11.060000 56180516.000000 +-2.327500 -2.677500 -7.560000 56280664.000000 +8.767500 15.102500 -4.760000 56380616.000000 +33.075001 23.572500 -7.892500 56480464.000000 +-17.692499 -3.237500 6.965000 56580628.000000 +-29.592501 -6.317500 8.330000 56680612.000000 +-15.382500 -23.152500 5.845000 56780484.000000 +-7.560000 -4.707500 -0.035000 56880640.000000 +-11.777500 -10.587500 1.365000 56980600.000000 +11.550000 -9.747500 27.772501 57080608.000000 +-32.830002 8.732500 56.735001 57180480.000000 +-8.242500 -35.857502 31.465000 57280632.000000 +-62.492500 -45.237499 20.282499 57380716.000000 +-27.160000 22.802500 13.842500 57480484.000000 +24.115000 1.417500 13.615000 57580672.000000 +19.145000 23.467501 7.997500 57680664.000000 +13.230000 38.097500 -3.535000 57780476.000000 +1.417500 78.347504 4.235000 57880484.000000 +-6.282500 3.937500 11.830000 57980500.000000 +-11.970000 11.777500 1.540000 58080508.000000 +-4.392500 34.457500 3.465000 58180648.000000 +-2.765000 83.947502 4.480000 58280652.000000 +-8.610000 151.112503 31.867500 58380376.000000 +-62.772499 242.882507 34.334999 58480488.000000 +-50.049999 -573.002502 -146.457504 58580524.000000 +-455.000000 -573.002502 -105.647499 58680384.000000 +565.022522 -573.002502 -334.494995 58780844.000000 +-93.047501 -573.002502 361.707489 58880448.000000 +-277.987488 -573.002502 86.485001 58980352.000000 +-279.667511 -573.002502 -248.080002 59080364.000000 +-325.202515 -109.987503 -61.040001 59181048.000000 +118.702499 47.897499 -52.884998 59281616.000000 +25.129999 153.002502 -222.214996 59380588.000000 +6.720000 124.722504 -191.047501 59480492.000000 +-17.605000 2.922500 -114.135002 59580388.000000 +42.122501 -18.707500 -72.555000 59680380.000000 +-66.202499 176.767502 -73.657501 59780352.000000 +12.950000 83.842499 -156.222504 59880368.000000 +25.480000 31.062500 8.592500 59980372.000000 +15.312500 23.782499 -28.525000 60080632.000000 +-12.915000 24.447500 -23.467501 60180344.000000 +-17.937500 22.977501 -29.627501 60280428.000000 +-14.175000 66.937500 -13.002500 60380432.000000 +-30.555000 466.672516 0.472500 60480376.000000 +-35.927502 436.257507 -86.117500 60580380.000000 +64.312500 196.122498 94.989998 60680496.000000 +-81.077499 192.167496 -62.212502 60780604.000000 +-8.050000 201.302505 2.275000 60880904.000000 +-34.090000 244.702499 88.794998 60980472.000000 +-26.407499 170.432495 23.100000 61080520.000000 +-3.885000 197.277496 16.030001 61181020.000000 +-68.022499 263.182495 1.942500 61280684.000000 +25.532499 -573.002502 85.224998 61380392.000000 +7.490000 -573.002502 -172.602493 61480368.000000 +-257.372498 -573.002502 73.587502 61580544.000000 +171.342499 -573.002502 -171.639999 61680408.000000 +347.970001 -573.002502 153.352493 61780456.000000 +470.785004 -313.827515 4.532500 61880564.000000 +49.139999 -47.057499 147.857498 61980608.000000 +-19.460001 205.292496 9.660000 62080844.000000 +-2.537500 48.562500 -4.077500 62180532.000000 +3.535000 77.437500 -6.195000 62280464.000000 +56.857502 13.142500 17.674999 62380524.000000 +21.542500 13.247500 8.067500 62480468.000000 +-48.299999 27.107500 -2.712500 62580464.000000 +-2.397500 35.402500 1.225000 62680512.000000 +-35.805000 -3.482500 -0.945000 62780476.000000 +-125.160004 -59.902500 27.755001 62880484.000000 +-55.667500 -91.192497 73.167503 62980500.000000 +38.570000 -39.707500 37.432499 63080476.000000 +17.535000 -23.852501 -18.077499 63180528.000000 +157.307495 7.402500 -43.627499 63280588.000000 +-50.207500 130.847504 -19.512501 63380664.000000 +-46.987499 -21.577499 14.245000 63480488.000000 +-71.347504 16.047501 -19.582500 63580524.000000 +0.157500 -85.872498 -5.827500 63680524.000000 +53.095001 -144.182495 18.882500 63781080.000000 +9.940000 91.612503 -10.710000 63880528.000000 +-42.665001 161.017502 114.065002 63980536.000000 +-17.867500 83.387497 -2.030000 64080576.000000 +-25.812500 -10.412500 -10.517500 64180508.000000 +-43.224998 -189.157501 -7.595000 64280664.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/magnetic.txt b/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/magnetic.txt new file mode 100755 index 0000000..9f00d1c --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/single_roll_throw/magnetic.txt @@ -0,0 +1,100 @@ +-29.500000 -18.500000 -18.250000 54382660.000000 +-29.875000 -19.750000 -18.750000 54482660.000000 +-29.562500 -20.250000 -18.750000 54582660.000000 +-29.750000 -19.875000 -18.750000 54682660.000000 +-29.312500 -20.125000 -18.625000 54782660.000000 +-29.000000 -20.000000 -18.625000 54882660.000000 +-29.500000 -19.812500 -18.375000 54982660.000000 +-29.562500 -19.687500 -18.500000 55082660.000000 +-29.562500 -19.937500 -18.500000 55182660.000000 +-29.500000 -19.750000 -18.625000 55282660.000000 +-29.750000 -19.937500 -18.687500 55382660.000000 +-29.562500 -19.937500 -18.625000 55482660.000000 +-29.812500 -19.937500 -18.750000 55582660.000000 +-29.875000 -19.812500 -18.687500 55682660.000000 +-29.625000 -19.812500 -19.000000 55782660.000000 +-29.562500 -19.500000 -19.062500 55882660.000000 +-29.625000 -19.000000 -19.437500 55982660.000000 +-29.750000 -18.437500 -19.187500 56082660.000000 +-30.000000 -17.937500 -19.187500 56182660.000000 +-30.375000 -17.187500 -19.437500 56282660.000000 +-30.562500 -17.000000 -19.500000 56382660.000000 +-30.812500 -16.812500 -19.625000 56482660.000000 +-30.812500 -16.375000 -19.687500 56582660.000000 +-30.875000 -16.250000 -19.437500 56682660.000000 +-31.000000 -16.250000 -18.875000 56782660.000000 +-30.937500 -16.187500 -18.625000 56882660.000000 +-30.937500 -16.187500 -18.187500 56982660.000000 +-30.937500 -15.875000 -17.750000 57082660.000000 +-31.125000 -14.937500 -17.187500 57182660.000000 +-31.437500 -14.000000 -16.375000 57282660.000000 +-31.875000 -13.062500 -15.625000 57382660.000000 +-32.562500 -12.000000 -14.875000 57482660.000000 +-33.062500 -10.875000 -14.562500 57582660.000000 +-33.375000 -9.937500 -14.500000 57682660.000000 +-33.312500 -8.687500 -15.375000 57782660.000000 +-33.187500 -8.000000 -16.125000 57882660.000000 +-33.000000 -7.500000 -17.125000 57982660.000000 +-32.562500 -7.187500 -18.375000 58082660.000000 +-31.937500 -7.000000 -20.250000 58182660.000000 +-30.312500 -6.875000 -23.187500 58282660.000000 +-27.250000 -6.187500 -26.500000 58382660.000000 +-20.937500 -4.875000 -29.812500 58482660.000000 +-16.250000 -6.312500 -22.812500 58582660.000000 +-14.812500 -9.937500 -20.625000 58682660.000000 +-8.375000 -12.062500 -20.750000 58782660.000000 +-1.312500 -15.000000 -15.750000 58882660.000000 +4.750000 -18.437500 -9.875000 58982660.000000 +10.312500 -22.187500 -5.500000 59082660.000000 +14.562500 -26.437500 0.687500 59182660.000000 +16.500000 -30.062500 7.687500 59282660.000000 +20.187500 -29.750000 6.312500 59382660.000000 +26.937500 -26.625000 9.875000 59482660.000000 +29.562500 -24.250000 15.562500 59582660.000000 +30.250000 -20.750000 17.062500 59682660.000000 +31.562500 -16.250000 18.750000 59782660.000000 +32.437500 -11.187500 22.812500 59882660.000000 +32.750000 -5.750000 26.125000 59982660.000000 +31.875000 -1.562500 28.687500 60082660.000000 +30.562500 1.500000 30.500000 60182660.000000 +28.875000 3.687500 32.187500 60282660.000000 +22.312500 4.625000 33.875000 60382660.000000 +14.687500 4.625000 32.375000 60482660.000000 +6.437500 5.000000 29.562500 60582660.000000 +-1.562500 4.750000 26.125000 60682660.000000 +-9.187500 3.250000 20.562500 60782660.000000 +-16.500000 2.312500 13.687500 60882660.000000 +-22.125000 1.687500 5.000000 60982660.000000 +-26.375000 1.500000 -4.500000 61082660.000000 +-25.562500 2.000000 -14.062500 61182660.000000 +-19.625000 3.937500 -20.562500 61282660.000000 +-19.750000 1.500000 -20.625000 61382660.000000 +-16.062500 -2.000000 -17.437500 61482660.000000 +-6.437500 -3.250000 -16.187500 61582660.000000 +-6.562500 -3.625000 -13.250000 61682660.000000 +-7.812500 -5.625000 -11.625000 61782660.000000 +-10.437500 -8.375000 -7.125000 61882660.000000 +-14.437500 -10.375000 -3.250000 61982660.000000 +-21.312500 -13.250000 -1.312500 62082660.000000 +-20.812500 -12.875000 -5.375000 62182660.000000 +-24.312500 -11.187500 -12.437500 62282660.000000 +-33.562500 -11.125000 -15.812500 62382660.000000 +-33.125000 -12.250000 -19.750000 62482660.000000 +-32.937500 -12.125000 -20.937500 62582660.000000 +-32.062500 -11.687500 -24.375000 62682660.000000 +-30.625000 -11.687500 -27.312500 62782660.000000 +-30.125000 -10.750000 -27.875000 62882660.000000 +-30.062500 -9.187500 -27.687500 62982660.000000 +-30.000000 -7.437500 -26.937500 63082660.000000 +-30.062500 -6.187500 -26.125000 63182660.000000 +-30.312500 -5.750000 -25.562500 63282660.000000 +-30.312500 -4.937500 -25.500000 63382660.000000 +-30.500000 -3.812500 -25.187500 63482660.000000 +-31.312500 -3.062500 -24.062500 63582660.000000 +-31.937500 -2.687500 -22.750000 63682660.000000 +-32.437500 -3.437500 -21.750000 63782660.000000 +-32.750000 -3.312500 -21.750000 63882660.000000 +-32.062500 -2.312500 -23.062500 63982660.000000 +-31.000000 -0.687500 -24.187500 64082660.000000 +-30.937500 0.187500 -23.812500 64182660.000000 +-31.437500 1.312500 -22.562500 64282660.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/throw/accel.txt b/src/sensor_fusion/design/data/100ms/gravity/throw/accel.txt new file mode 100755 index 0000000..0ad1a01 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/throw/accel.txt @@ -0,0 +1,135 @@ +0.044267 0.132802 10.029516 400455552.000000 +0.070588 0.175872 10.113264 400555680.000000 +0.074178 0.180658 10.112068 400655520.000000 +0.034696 0.186640 10.118051 400756224.000000 +0.086142 0.193819 10.083356 400855712.000000 +0.083749 0.165105 10.130014 400955552.000000 +0.065803 0.161516 10.152746 401055456.000000 +0.072981 0.183051 10.153944 401155488.000000 +0.061017 0.169890 10.145569 401255456.000000 +0.056231 0.196211 10.116854 401355616.000000 +0.061017 0.183051 10.110871 401455488.000000 +0.061017 0.174676 10.120443 401555616.000000 +0.035892 0.177069 10.094121 401655616.000000 +0.053839 0.173480 10.114462 401755520.000000 +0.047856 0.157926 10.097712 401855584.000000 +0.050249 0.167498 10.124033 401955520.000000 +0.064606 0.160319 10.120443 402055648.000000 +0.068195 0.137587 10.090532 402155488.000000 +0.065803 0.181855 10.096515 402255680.000000 +0.037089 0.175872 10.089336 402355424.000000 +-0.025125 0.161516 10.370493 402455456.000000 +0.020339 0.157926 10.156336 402555712.000000 +0.051446 0.168694 10.120443 402655520.000000 +0.074178 0.178265 10.119246 402755488.000000 +0.046660 0.169890 10.110871 402855456.000000 +0.039482 0.169890 10.157533 402955648.000000 +-0.013161 0.168694 10.265208 403055424.000000 +0.029910 0.177069 10.151550 403156352.000000 +0.058624 0.181855 10.139585 403255424.000000 +0.046660 0.183051 10.175477 403355584.000000 +0.064606 0.191426 10.131211 403455648.000000 +0.047856 0.150748 10.103694 403555456.000000 +0.038285 0.153141 10.158729 403655456.000000 +0.055035 0.195015 10.096515 403755776.000000 +0.059821 0.154337 10.139585 403855392.000000 +0.068195 0.174676 10.097712 403955360.000000 +0.047856 0.171087 10.114462 404055456.000000 +0.051446 0.199801 10.121639 404155360.000000 +0.056231 0.174676 10.140782 404255392.000000 +0.074178 0.190229 10.125229 404355360.000000 +0.047856 0.196211 10.121639 404455328.000000 +0.044267 0.189033 10.104890 404555360.000000 +0.051446 0.192622 10.134801 404655328.000000 +0.051446 0.172283 10.063015 404755456.000000 +0.064606 0.169890 10.133603 404855840.000000 +0.082552 0.173480 10.106087 404955520.000000 +0.062213 0.166301 10.125229 405055488.000000 +0.011964 0.177069 10.131211 405155648.000000 +-0.029910 0.077767 10.119246 405256192.000000 +-0.101695 0.223729 10.112068 405355456.000000 +-0.078963 0.093320 10.107283 405455488.000000 +-0.104088 0.165105 10.122837 405556096.000000 +-0.230907 0.248854 10.139585 405655456.000000 +-0.260818 0.208176 10.134801 405755456.000000 +-0.175872 0.049053 10.186246 405855488.000000 +-0.178265 0.326620 10.336994 405955488.000000 +1.323231 -1.849652 12.643675 406055456.000000 +4.271189 -2.665605 10.762917 406155552.000000 +9.960124 -2.788835 9.620343 406255488.000000 +-0.136391 0.130409 0.601795 406355456.000000 +-0.045464 -0.004786 0.662812 406455456.000000 +-11.874382 -1.155733 4.161119 406555520.000000 +-4.564309 4.808377 19.601404 406655488.000000 +0.886541 -0.769292 11.824133 406755584.000000 +0.132802 -0.264407 10.162319 406855520.000000 +0.071785 -0.289532 10.133603 406955488.000000 +0.141177 -0.263210 10.122837 407055488.000000 +0.110070 -0.276371 10.141978 407155520.000000 +0.117248 -0.256032 10.143176 407255488.000000 +0.122034 -0.239282 10.131211 407355488.000000 +0.128016 -0.242871 10.119246 407455456.000000 +0.090927 -0.252443 10.127622 407555552.000000 +0.117248 -0.254836 10.140782 407655488.000000 +0.124427 -0.234497 10.124033 407755648.000000 +0.128016 -0.214158 10.116854 407855520.000000 +0.106481 -0.217747 10.151550 407956032.000000 +0.114855 -0.241675 10.169496 408055456.000000 +0.099302 -0.259621 10.150353 408155456.000000 +0.129212 -0.242871 10.113264 408255840.000000 +0.136391 -0.247657 10.157533 408355616.000000 +0.137587 -0.212961 10.139585 408455616.000000 +0.142373 -0.228515 10.131211 408556000.000000 +0.117248 -0.251246 10.145569 408655776.000000 +0.132802 -0.223729 10.124033 408755584.000000 +0.138784 -0.252443 10.090532 408855552.000000 +0.107677 -0.232104 10.139585 408955616.000000 +0.130409 -0.238086 10.153944 409056000.000000 +0.112463 -0.248854 10.133603 409155680.000000 +0.148355 -0.214158 10.138390 409255584.000000 +0.138784 -0.229711 10.131211 409356032.000000 +0.094516 -0.246461 10.170692 409455712.000000 +0.126820 -0.260818 10.101300 409555456.000000 +0.123230 -0.229711 10.153944 409655680.000000 +0.099302 -0.235693 10.193424 409755744.000000 +0.108873 -0.215354 10.139585 409855456.000000 +0.120838 -0.254836 10.133603 409961664.000000 +0.112463 -0.223729 10.115658 410061024.000000 +0.122034 -0.223729 10.119246 410160448.000000 +0.107677 -0.218943 10.138390 410260512.000000 +0.130409 -0.257228 10.116854 410360448.000000 +0.135194 -0.233300 10.131211 410460448.000000 +0.129212 -0.204586 10.125229 410560608.000000 +0.117248 -0.232104 10.147961 410660576.000000 +0.095713 -0.236889 10.110871 410760512.000000 +0.113659 -0.229711 10.122837 410860448.000000 +0.138784 -0.234497 10.101300 410960896.000000 +0.135194 -0.221336 10.152746 411061888.000000 +0.124427 -0.203390 10.104890 411160480.000000 +0.131605 -0.233300 10.109675 411261056.000000 +0.118445 -0.235693 10.141978 411360480.000000 +0.128016 -0.215354 10.140782 411460544.000000 +0.138784 -0.234497 10.118051 411560480.000000 +0.112463 -0.246461 10.134801 411660608.000000 +0.136391 -0.224925 10.144372 411760768.000000 +0.123230 -0.209372 10.097712 411860480.000000 +0.099302 -0.229711 10.103694 411960512.000000 +0.128016 -0.206979 10.112068 412061056.000000 +0.150748 -0.212961 10.127622 412160768.000000 +0.101695 -0.227318 10.125229 412261184.000000 +0.138784 -0.222532 10.155140 412360448.000000 +0.136391 -0.252443 10.126426 412460512.000000 +0.132802 -0.229711 10.143176 412560512.000000 +0.112463 -0.246461 10.147961 412660480.000000 +0.132802 -0.209372 10.124033 412760864.000000 +0.149551 -0.228515 10.144372 412860640.000000 +0.126820 -0.256032 10.125229 412960640.000000 +0.101695 -0.215354 10.133603 413061120.000000 +0.130409 -0.236889 10.089336 413160448.000000 +0.132802 -0.220140 10.112068 413260576.000000 +0.113659 -0.236889 10.133603 413360928.000000 +0.114855 -0.228515 10.115658 413461056.000000 +0.124427 -0.215354 10.098907 413560736.000000 +0.144766 -0.210568 10.120443 413660672.000000 +0.108873 -0.240479 10.146765 413760480.000000 +0.122034 -0.229711 10.128819 413860448.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/throw/gyro.txt b/src/sensor_fusion/design/data/100ms/gravity/throw/gyro.txt new file mode 100755 index 0000000..77e420a --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/throw/gyro.txt @@ -0,0 +1,136 @@ +1.890000 0.472500 -0.472500 400380896.000000 +-1.872500 1.312500 -34.755001 400481024.000000 +-4.882500 0.157500 2.082500 400580480.000000 +-4.882500 0.157500 2.065000 400680512.000000 +-4.935000 0.157500 2.100000 400780800.000000 +-4.987500 0.122500 2.030000 400880480.000000 +-4.900000 0.157500 2.082500 400980512.000000 +-4.865000 0.227500 2.065000 401080512.000000 +-4.900000 0.192500 2.030000 401180480.000000 +-4.952500 0.157500 2.065000 401280480.000000 +-4.952500 0.157500 2.065000 401380544.000000 +-4.935000 0.157500 2.047500 401480480.000000 +-4.952500 0.157500 2.082500 401580512.000000 +-4.935000 0.157500 2.065000 401680480.000000 +-4.935000 0.157500 2.047500 401780480.000000 +-4.935000 0.157500 2.047500 401880640.000000 +-4.935000 0.157500 2.082500 401980480.000000 +-4.970000 0.157500 2.047500 402080512.000000 +-4.987500 0.157500 2.047500 402180480.000000 +-4.952500 0.192500 2.082500 402280480.000000 +-4.987500 2.747500 2.012500 402380608.000000 +-4.970000 -2.047500 2.135000 402480384.000000 +-4.952500 -0.612500 2.082500 402580480.000000 +-4.987500 0.682500 2.082500 402680608.000000 +-4.970000 0.017500 2.065000 402780544.000000 +-4.970000 0.157500 2.065000 402880512.000000 +-5.005000 0.192500 2.065000 402980512.000000 +-4.987500 3.692500 1.977500 403080416.000000 +-4.917500 -3.587500 2.152500 403180384.000000 +-5.005000 0.577500 2.082500 403280416.000000 +-4.970000 0.087500 2.030000 403380800.000000 +-4.987500 0.122500 2.047500 403480608.000000 +-4.987500 0.227500 2.047500 403580448.000000 +-4.987500 0.157500 2.030000 403680448.000000 +-5.005000 0.192500 2.030000 403780576.000000 +-4.970000 0.157500 2.065000 403880384.000000 +-4.987500 0.157500 2.047500 403980416.000000 +-5.022500 0.157500 2.012500 404080608.000000 +-5.005000 0.122500 2.030000 404180384.000000 +-5.005000 0.157500 2.030000 404280416.000000 +-5.022500 0.157500 2.047500 404380384.000000 +-5.005000 0.157500 2.030000 404480384.000000 +-5.040000 0.157500 2.012500 404580384.000000 +-5.022500 0.157500 2.030000 404680352.000000 +-5.040000 0.227500 2.030000 404780640.000000 +-5.040000 -1.207500 2.030000 404880608.000000 +-5.040000 1.207500 1.977500 404980512.000000 +-5.022500 0.577500 1.995000 405080448.000000 +-5.075000 1.067500 1.977500 405180480.000000 +-5.197500 2.992500 2.065000 405280800.000000 +-5.460000 2.712500 0.997500 405380512.000000 +-5.477500 3.377500 0.140000 405480512.000000 +-5.197500 1.522500 -0.227500 405580800.000000 +-5.442500 1.137500 1.172500 405680512.000000 +-7.350000 0.472500 2.607500 405780480.000000 +-9.030000 -0.507500 4.602500 405880448.000000 +-14.700000 -7.647500 1.557500 405980512.000000 +-52.587502 -28.052500 9.905000 406080512.000000 +-22.785000 -32.882500 -14.385000 406180480.000000 +-14.262500 -13.632500 -63.402500 406280544.000000 +-11.987500 -11.462500 -81.129997 406380640.000000 +0.175000 52.517502 -66.500000 406480512.000000 +57.697502 131.722504 -36.032501 406580448.000000 +-55.317501 -78.242500 129.237503 406680512.000000 +4.987500 17.972500 -22.295000 406780512.000000 +-5.512500 0.507500 1.155000 406880448.000000 +-4.952500 -0.052500 2.082500 406980544.000000 +-4.987500 0.087500 2.082500 407080512.000000 +-5.022500 0.122500 2.047500 407180512.000000 +-4.987500 0.157500 2.082500 407280544.000000 +-5.005000 0.157500 2.082500 407380512.000000 +-5.022500 0.122500 2.082500 407480512.000000 +-5.022500 0.157500 2.082500 407580480.000000 +-5.022500 0.122500 2.082500 407680544.000000 +-5.005000 0.192500 2.082500 407780480.000000 +-5.057500 0.122500 2.065000 407880576.000000 +-5.057500 0.157500 2.100000 407980864.000000 +-5.022500 0.157500 2.065000 408080512.000000 +-5.040000 0.157500 2.100000 408180480.000000 +-5.040000 0.157500 2.100000 408280480.000000 +-5.075000 0.122500 2.082500 408380512.000000 +-5.040000 0.157500 2.100000 408480512.000000 +-5.057500 0.157500 2.082500 408580928.000000 +-5.057500 0.157500 2.082500 408680576.000000 +-5.040000 0.122500 2.082500 408780480.000000 +-5.040000 0.157500 2.065000 408880512.000000 +-5.022500 0.157500 2.100000 408980512.000000 +-5.057500 0.157500 2.100000 409080864.000000 +-5.075000 0.157500 2.065000 409180512.000000 +-5.057500 0.157500 2.117500 409280480.000000 +-5.057500 0.122500 2.082500 409381056.000000 +-5.040000 0.157500 2.117500 409480448.000000 +-5.057500 0.157500 2.082500 409580480.000000 +-5.022500 0.157500 2.082500 409680448.000000 +-5.057500 0.157500 2.100000 409780512.000000 +-5.040000 0.157500 2.065000 409880480.000000 +-5.057500 0.157500 2.082500 409980672.000000 +-5.057500 0.157500 2.065000 410080864.000000 +-5.057500 0.157500 2.065000 410180512.000000 +-5.040000 0.157500 2.065000 410280672.000000 +-5.040000 0.157500 2.117500 410380608.000000 +-5.057500 0.157500 2.117500 410480512.000000 +-5.092500 0.157500 2.100000 410580480.000000 +-5.057500 0.157500 2.082500 410680640.000000 +-5.075000 0.157500 2.100000 410780576.000000 +-5.075000 0.157500 2.082500 410880544.000000 +-5.075000 0.157500 2.065000 410981248.000000 +-5.057500 0.157500 2.082500 411080864.000000 +-5.057500 0.192500 2.100000 411181056.000000 +-5.057500 0.157500 2.100000 411281216.000000 +-5.075000 0.122500 2.100000 411380576.000000 +-5.075000 0.122500 2.100000 411480544.000000 +-5.057500 0.157500 2.100000 411580480.000000 +-5.022500 0.157500 2.100000 411680736.000000 +-5.040000 0.192500 2.100000 411780928.000000 +-5.057500 0.157500 2.135000 411880512.000000 +-5.075000 0.157500 2.100000 411980672.000000 +-5.040000 0.157500 2.135000 412081120.000000 +-5.040000 0.157500 2.100000 412180512.000000 +-5.057500 0.192500 2.100000 412280992.000000 +-5.022500 0.192500 2.100000 412380576.000000 +-5.057500 0.122500 2.100000 412480640.000000 +-5.075000 0.157500 2.117500 412580608.000000 +-5.057500 0.157500 2.100000 412680544.000000 +-5.075000 0.192500 2.117500 412780736.000000 +-5.040000 0.157500 2.135000 412880672.000000 +-5.092500 0.157500 2.135000 412980512.000000 +-5.075000 0.157500 2.100000 413081664.000000 +-5.057500 0.192500 2.100000 413180768.000000 +-5.075000 0.157500 2.135000 413280512.000000 +-5.092500 0.122500 2.100000 413380896.000000 +-5.092500 0.157500 2.100000 413480992.000000 +-5.075000 0.192500 2.100000 413580480.000000 +-5.075000 0.157500 2.100000 413680640.000000 +-5.092500 0.192500 2.117500 413780576.000000 +-5.092500 0.157500 2.082500 413880544.000000 diff --git a/src/sensor_fusion/design/data/100ms/gravity/throw/magnetic.txt b/src/sensor_fusion/design/data/100ms/gravity/throw/magnetic.txt new file mode 100755 index 0000000..fc35bc2 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/gravity/throw/magnetic.txt @@ -0,0 +1,136 @@ +23.750000 -35.500000 -16.687500 400385920.000000 +23.875000 -36.562500 -17.250000 400485920.000000 +24.250000 -37.125000 -17.250000 400585920.000000 +24.500000 -36.750000 -17.000000 400685920.000000 +24.812500 -36.562500 -16.875000 400785920.000000 +25.250000 -35.937500 -16.750000 400885920.000000 +25.250000 -35.937500 -16.875000 400985920.000000 +24.750000 -36.125000 -17.187500 401085920.000000 +24.812500 -36.312500 -17.312500 401185920.000000 +24.875000 -36.062500 -17.562500 401285920.000000 +24.937500 -36.125000 -17.687500 401385920.000000 +24.875000 -35.937500 -17.625000 401485920.000000 +24.750000 -36.062500 -17.812500 401585920.000000 +24.625000 -36.375000 -17.750000 401685920.000000 +24.687500 -36.500000 -17.812500 401785920.000000 +24.812500 -36.562500 -17.687500 401885920.000000 +24.812500 -36.375000 -17.812500 401985920.000000 +24.937500 -36.437500 -17.500000 402085920.000000 +24.937500 -36.375000 -17.437500 402185920.000000 +24.812500 -36.625000 -17.500000 402285920.000000 +24.625000 -36.500000 -17.187500 402385920.000000 +24.062500 -36.125000 -16.500000 402485920.000000 +23.937500 -35.812500 -16.375000 402585920.000000 +23.437500 -35.562500 -16.000000 402685920.000000 +23.250000 -35.625000 -15.625000 402785920.000000 +23.062500 -35.687500 -15.500000 402885920.000000 +22.937500 -35.562500 -15.437500 402985920.000000 +22.625000 -34.937500 -15.250000 403085920.000000 +22.500000 -34.875000 -15.312500 403185920.000000 +22.625000 -34.812500 -15.750000 403285920.000000 +22.437500 -34.875000 -15.812500 403385920.000000 +22.687500 -34.875000 -16.125000 403485920.000000 +22.812500 -34.937500 -16.125000 403585920.000000 +22.937500 -34.750000 -16.312500 403685920.000000 +23.062500 -34.625000 -16.250000 403785920.000000 +22.937500 -34.875000 -16.000000 403885920.000000 +22.937500 -35.000000 -15.812500 403985920.000000 +22.875000 -35.000000 -15.500000 404085920.000000 +22.187500 -35.000000 -15.000000 404185920.000000 +21.562500 -35.250000 -14.437500 404285920.000000 +21.250000 -35.125000 -14.187500 404385920.000000 +20.625000 -35.062500 -13.875000 404485920.000000 +20.125000 -35.062500 -13.875000 404585920.000000 +20.375000 -35.125000 -14.312500 404685920.000000 +19.937500 -35.062500 -14.125000 404785920.000000 +20.062500 -35.125000 -14.250000 404885920.000000 +20.625000 -35.000000 -14.187500 404985920.000000 +21.500000 -34.937500 -14.625000 405085920.000000 +22.000000 -35.062500 -14.875000 405185920.000000 +22.750000 -35.187500 -15.187500 405285920.000000 +23.187500 -35.312500 -15.312500 405385920.000000 +23.437500 -35.312500 -15.250000 405485920.000000 +24.125000 -35.187500 -15.625000 405585920.000000 +24.625000 -35.375000 -15.937500 405685920.000000 +25.125000 -35.562500 -16.312500 405785920.000000 +24.812500 -35.437500 -16.562500 405885920.000000 +24.687500 -35.312500 -17.062500 405985920.000000 +24.250000 -35.125000 -17.875000 406085920.000000 +24.562500 -35.062500 -18.375000 406185920.000000 +26.000000 -34.937500 -19.000000 406285920.000000 +28.312500 -33.875000 -19.125000 406385920.000000 +30.687500 -32.312500 -18.187500 406485920.000000 +32.437500 -31.500000 -18.187500 406585920.000000 +34.437500 -30.500000 -17.750000 406685920.000000 +36.437500 -29.437500 -16.875000 406785920.000000 +38.875000 -28.437500 -15.562500 406885920.000000 +40.687500 -27.312500 -14.687500 406985920.000000 +41.312500 -26.375000 -13.687500 407085920.000000 +41.000000 -26.375000 -13.375000 407185920.000000 +40.562500 -26.937500 -14.125000 407285920.000000 +40.812500 -26.562500 -13.750000 407385920.000000 +40.937500 -26.562500 -13.687500 407485920.000000 +41.187500 -26.562500 -13.812500 407585920.000000 +41.062500 -26.687500 -13.750000 407685920.000000 +40.687500 -26.687500 -13.812500 407785920.000000 +40.687500 -26.750000 -14.000000 407885920.000000 +40.875000 -26.750000 -14.062500 407985920.000000 +40.875000 -26.625000 -13.875000 408085920.000000 +40.625000 -26.687500 -14.062500 408185920.000000 +40.625000 -26.562500 -13.937500 408285920.000000 +40.500000 -26.562500 -13.812500 408385920.000000 +40.500000 -26.375000 -14.062500 408485920.000000 +40.687500 -26.500000 -13.937500 408585920.000000 +40.687500 -26.375000 -13.875000 408685920.000000 +40.312500 -26.625000 -13.812500 408785920.000000 +40.437500 -26.750000 -13.812500 408885920.000000 +40.625000 -26.750000 -13.625000 408985920.000000 +40.625000 -26.875000 -13.750000 409085920.000000 +40.687500 -26.812500 -13.937500 409185920.000000 +40.750000 -26.937500 -13.750000 409285920.000000 +40.875000 -26.750000 -13.875000 409385920.000000 +40.812500 -26.812500 -13.812500 409485920.000000 +41.062500 -26.750000 -13.562500 409585920.000000 +40.750000 -26.625000 -13.625000 409685920.000000 +40.812500 -26.687500 -13.875000 409785920.000000 +40.687500 -26.750000 -13.937500 409885920.000000 +40.437500 -26.875000 -13.687500 409985920.000000 +40.437500 -27.125000 -13.812500 410085920.000000 +40.312500 -27.187500 -13.812500 410185920.000000 +40.437500 -27.312500 -13.625000 410285920.000000 +40.375000 -27.187500 -13.937500 410385920.000000 +40.500000 -27.187500 -13.875000 410485920.000000 +40.312500 -27.125000 -13.500000 410585920.000000 +40.250000 -27.062500 -13.625000 410685920.000000 +40.562500 -27.125000 -13.562500 410785920.000000 +40.562500 -27.062500 -13.500000 410885920.000000 +40.562500 -26.875000 -13.500000 410985920.000000 +40.812500 -26.937500 -13.875000 411085920.000000 +40.562500 -27.000000 -13.875000 411185920.000000 +40.750000 -26.937500 -14.062500 411285920.000000 +41.000000 -26.875000 -14.562500 411385920.000000 +41.312500 -26.875000 -14.562500 411485920.000000 +41.125000 -26.750000 -14.875000 411585920.000000 +41.187500 -26.750000 -15.062500 411685920.000000 +41.312500 -26.937500 -15.312500 411785920.000000 +41.187500 -26.937500 -15.125000 411885920.000000 +41.500000 -26.750000 -15.125000 411985920.000000 +41.375000 -26.875000 -14.937500 412085920.000000 +41.250000 -27.000000 -14.625000 412185920.000000 +41.375000 -27.062500 -14.625000 412285920.000000 +41.437500 -27.062500 -14.625000 412385920.000000 +41.500000 -26.875000 -14.562500 412485920.000000 +41.500000 -27.000000 -14.437500 412585920.000000 +41.500000 -26.875000 -14.375000 412685920.000000 +41.437500 -27.062500 -14.437500 412785920.000000 +41.500000 -26.937500 -14.312500 412885920.000000 +41.437500 -26.937500 -14.500000 412985920.000000 +41.062500 -26.812500 -14.250000 413085920.000000 +40.687500 -26.750000 -13.812500 413185920.000000 +40.375000 -26.687500 -13.750000 413285920.000000 +40.125000 -26.437500 -13.562500 413385920.000000 +39.937500 -26.250000 -13.812500 413485920.000000 +39.875000 -26.250000 -13.625000 413585920.000000 +39.750000 -26.250000 -13.687500 413685920.000000 +39.875000 -26.187500 -13.562500 413785920.000000 +39.875000 -26.062500 -13.625000 413885920.000000 diff --git a/src/sensor_fusion/design/lib/estimate_gravity.m b/src/sensor_fusion/design/lib/estimate_gravity.m new file mode 100755 index 0000000..5f62c4d --- /dev/null +++ b/src/sensor_fusion/design/lib/estimate_gravity.m @@ -0,0 +1,45 @@ +% estimate_gravity +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Gravitational Force Estimation function +% +% - Orientation Estimation using estimate_orientation function +% - Project the orientation on the device reference axes to obtain +% gravitational force on specific reference axes + + +function [Gravity] = estimate_gravity(Accel_data, Gyro_data, Mag_data) + +GRAVITY = 9.80665; + +BUFFER_SIZE = size(Accel_data,2); + +OR_driv = zeros(3,BUFFER_SIZE); +OR_aid = zeros(3,BUFFER_SIZE); +OR_err = zeros(3,BUFFER_SIZE); + +Gravity = zeros(3,BUFFER_SIZE); + +% estimate orientation +[OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data, Mag_data); + +Gx = GRAVITY * -sind(OR_driv(1,:)); +Gy = GRAVITY * sind(OR_driv(2,:)); +Gz = GRAVITY * cosd(OR_driv(2,:)) .* cosd(OR_driv(1,:)); + +Gravity = [Gx; Gy; Gz]; + +end \ No newline at end of file diff --git a/src/sensor_fusion/design/sf_gravity.m b/src/sensor_fusion/design/sf_gravity.m new file mode 100755 index 0000000..48dba10 --- /dev/null +++ b/src/sensor_fusion/design/sf_gravity.m @@ -0,0 +1,113 @@ +% sf_gravity +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Sensor Fusion Implementation for Determination of Gravity +% +% - Input Accelerometer, Gyroscope and Magnetometer sensor data +% - Call estimate_gravity +% - Plot results for gravitational force on reference axis + +addpath('lib'); +clear +close all +clc + +GRAVITY = 9.80665; + +Max_Range_Accel = 39.203407; Min_Range_Accel = -39.204006; Res_Accel = 0.000598; +Max_Range_Gyro = 1146.862549; Min_Range_Gyro = -1146.880005; Res_Gyro = 0.017500; +Max_Range_Magnetic = 1200; Min_Range_Magnetic = -1200; Res_Magnetic = 1; + +Bias_Ax = 0.098586; +Bias_Ay = 0.18385; +Bias_Az = 10.084 - GRAVITY; + +Bias_Gx = -5.3539; +Bias_Gy = 0.24325; +Bias_Gz = 2.3391; + +BUFFER_SIZE = 100; + +Accel_data = zeros(4,BUFFER_SIZE); +Gyro_data = zeros(4,BUFFER_SIZE); +Mag_data = zeros(4,BUFFER_SIZE); + +OR_driv = zeros(3,BUFFER_SIZE); +OR_aid = zeros(3,BUFFER_SIZE); +OR_err = zeros(3,BUFFER_SIZE); + +% Sensor Data simulating orientation motions + +% get accel x,y,z axis data from stored file +Accel_data(1,:) = (((dlmread("data/100ms/gravity/single_roll_throw/accel.txt")(:,1))') - Bias_Ax)(1:BUFFER_SIZE); +Accel_data(2,:) = (((dlmread("data/100ms/gravity/single_roll_throw/accel.txt")(:,2))') - Bias_Ay)(1:BUFFER_SIZE); +Accel_data(3,:) = (((dlmread("data/100ms/gravity/single_roll_throw/accel.txt")(:,3))') - Bias_Az)(1:BUFFER_SIZE); +Accel_data(4,:) = ((dlmread("data/100ms/gravity/single_roll_throw/accel.txt")(:,4))')(1:BUFFER_SIZE); + +% get gyro x,y,z axis data from stored file +Gyro_data(1,:) = (((dlmread("data/100ms/gravity/single_roll_throw/gyro.txt")(:,1))') - Bias_Gx)(1:BUFFER_SIZE); +Gyro_data(2,:) = (((dlmread("data/100ms/gravity/single_roll_throw/gyro.txt")(:,2))') - Bias_Gy)(1:BUFFER_SIZE); +Gyro_data(3,:) = (((dlmread("data/100ms/gravity/single_roll_throw/gyro.txt")(:,3))') - Bias_Gz)(1:BUFFER_SIZE); +Gyro_data(4,:) = ((dlmread("data/100ms/gravity/single_roll_throw/gyro.txt")(:,4))')(1:BUFFER_SIZE); + +scale_Gyro = 575; +Gyro_data(1,:) = Gyro_data(1,:)/scale_Gyro; +Gyro_data(2,:) = Gyro_data(2,:)/scale_Gyro; +Gyro_data(3,:) = Gyro_data(3,:)/scale_Gyro; + +% get magnetometer x,y,z axis data from stored file +Mag_data(1,:) = (((dlmread("data/100ms/gravity/single_roll_throw/magnetic.txt")(:,1))'))(1:BUFFER_SIZE); +Mag_data(2,:) = (((dlmread("data/100ms/gravity/single_roll_throw/magnetic.txt")(:,2))'))(1:BUFFER_SIZE); +Mag_data(3,:) = (((dlmread("data/100ms/gravity/single_roll_throw/magnetic.txt")(:,3))'))(1:BUFFER_SIZE); +Mag_data(4,:) = ((dlmread("data/100ms/gravity/single_roll_throw/magnetic.txt")(:,4))')(1:BUFFER_SIZE); + +% estimate orientation +Gravity = estimate_gravity(Accel_data, Gyro_data, Mag_data); + +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +% Accelerometer Raw data +subplot(2,1,1) +UA = Accel_data(1,:); +p1 = plot(1:length(UA),UA(1,1:length(UA)),'k'); +hold on; +grid on; +UA = Accel_data(2,:); +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = Accel_data(3,:); +p3 = plot(1:length(UA),UA(1,1:length(UA)),'r'); + +% Gravity Plot Results +subplot(2,1,2) +UA = Gravity(1,:); +p1 = plot(1:length(UA),UA(1,1:length(UA)),'k'); +hold on; +grid on; +UA = Gravity(2,:); +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = Gravity(3,:); +p3 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +title(['Gravity']); +legend([p1 p2 p3],'x-axis', 'y-axis', 'z-axis'); + + + + -- 2.7.4 From 61bf53759178427fa7a1e4ee743cdc2377025c50 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Thu, 8 May 2014 14:51:36 +0530 Subject: [PATCH 12/13] Adding linear acceleration virtual sensor - adding octave code for computing linear acceleration. - adding sensor data to test linear acceleration. - fixing sign in gravity computation to correct phase. signed-off-by: Ramasamy Change-Id: I86356a58ed27f013693f28234d29fa1922da2323 --- .../100ms/linear_acceleration/move_x/accel.txt | 134 +++++++++++++++ .../data/100ms/linear_acceleration/move_x/gyro.txt | 134 +++++++++++++++ .../100ms/linear_acceleration/move_x/magnetic.txt | 135 +++++++++++++++ .../100ms/linear_acceleration/move_x_y_z/accel.txt | 170 +++++++++++++++++++ .../100ms/linear_acceleration/move_x_y_z/gyro.txt | 171 +++++++++++++++++++ .../linear_acceleration/move_x_y_z/magnetic.txt | 171 +++++++++++++++++++ .../100ms/linear_acceleration/move_y/accel.txt | 128 ++++++++++++++ .../data/100ms/linear_acceleration/move_y/gyro.txt | 128 ++++++++++++++ .../100ms/linear_acceleration/move_y/magnetic.txt | 127 ++++++++++++++ .../100ms/linear_acceleration/move_z/accel.txt | 183 +++++++++++++++++++++ .../data/100ms/linear_acceleration/move_z/gyro.txt | 183 +++++++++++++++++++++ .../100ms/linear_acceleration/move_z/magnetic.txt | 183 +++++++++++++++++++++ src/sensor_fusion/design/lib/estimate_gravity.m | 4 +- .../design/lib/estimate_linear_acceleration.m | 36 ++++ src/sensor_fusion/design/sf_linear_acceleration.m | 111 +++++++++++++ 15 files changed, 1996 insertions(+), 2 deletions(-) create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/magnetic.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/accel.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/gyro.txt create mode 100755 src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/magnetic.txt create mode 100755 src/sensor_fusion/design/lib/estimate_linear_acceleration.m create mode 100755 src/sensor_fusion/design/sf_linear_acceleration.m diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/accel.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/accel.txt new file mode 100755 index 0000000..be2a3c7 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/accel.txt @@ -0,0 +1,134 @@ +0.873380 0.113659 10.185050 63620448.000000 +0.775275 0.041874 10.211370 63720592.000000 +0.736989 0.186640 10.325029 63820512.000000 +0.652044 0.153141 10.115658 63920524.000000 +0.400798 0.017946 10.033106 64020552.000000 +0.658026 0.088534 10.040283 64120532.000000 +0.552742 0.105284 10.405190 64220552.000000 +0.519243 0.080160 9.923036 64320564.000000 +0.483350 0.053839 10.085747 64420556.000000 +0.553938 0.098106 10.226924 64520552.000000 +0.424726 0.148355 10.275976 64620568.000000 +0.766900 0.057428 10.481760 64720512.000000 +0.586242 0.076570 9.896714 64820580.000000 +0.494118 0.244068 10.197014 64920552.000000 +0.222532 1.239482 10.725827 65020580.000000 +-0.071785 2.029114 10.066606 65123060.000000 +-0.486939 2.309074 10.287941 65220548.000000 +0.044267 0.894916 9.565309 65320512.000000 +0.947558 -0.057428 10.253245 65420520.000000 +0.702293 -0.498904 10.925629 65520596.000000 +-0.429512 -1.333999 10.520043 65620544.000000 +-0.484547 -1.386641 9.822537 65720564.000000 +0.070588 -1.147358 10.173084 65820560.000000 +0.093320 -1.238286 11.227123 65920564.000000 +0.180658 -0.512064 11.686546 66020556.000000 +-0.551546 0.723829 9.211170 66120556.000000 +0.338584 2.458625 9.529416 66220504.000000 +0.149551 3.943372 10.289137 66320568.000000 +0.177069 2.906083 10.901700 66420512.000000 +1.075574 1.198804 10.858629 66520608.000000 +-0.040678 0.713061 9.954143 66620504.000000 +0.333799 0.177069 9.209974 66720736.000000 +0.334995 0.331406 10.603793 66820548.000000 +-0.076570 0.591027 9.956534 66920592.000000 +0.451047 0.595813 10.393225 67020552.000000 +0.405583 0.614955 9.992428 67120584.000000 +0.214158 0.855434 9.919446 67220552.000000 +0.260818 1.869991 10.715059 67320592.000000 +-0.212961 3.278167 9.938589 67420512.000000 +-0.656830 3.655036 10.403993 67520560.000000 +1.144966 2.082952 10.271191 67620504.000000 +1.481157 1.381855 11.145767 67720536.000000 +0.137587 -1.852045 9.055637 67820496.000000 +0.927219 -3.217150 11.166106 67920560.000000 +-0.027517 -1.889133 10.281959 68020544.000000 +-1.164108 -0.620937 9.505488 68120584.000000 +0.138784 -2.001596 9.978070 68220672.000000 +0.229711 -2.486143 11.088341 68320584.000000 +0.513260 -1.899901 9.474380 68420552.000000 +0.063410 0.625723 8.815158 68520600.000000 +0.504886 3.439682 8.979067 68620496.000000 +0.965504 4.766503 9.964910 68720512.000000 +0.527617 3.059224 10.782058 68820528.000000 +-0.061017 2.084148 10.046266 68920512.000000 +-0.985843 1.958525 10.103694 69020480.000000 +0.069392 1.256232 9.997212 69120512.000000 +-0.064606 1.320838 10.090532 69220512.000000 +0.094516 1.134198 10.284351 69320560.000000 +0.447458 0.960718 9.905089 69420504.000000 +0.104088 0.824327 9.815358 69520584.000000 +0.013161 1.140180 10.643275 69620504.000000 +0.052642 1.307678 10.387242 69720704.000000 +0.032303 1.191626 9.907482 69820520.000000 +-0.130409 1.256232 10.412368 69920568.000000 +-0.223729 1.798206 10.441081 70020512.000000 +-0.337388 2.664408 9.994821 70120560.000000 +0.257228 3.909872 10.194620 70220512.000000 +-0.547956 3.700500 10.856236 70320568.000000 +0.618545 1.328017 10.911271 70420512.000000 +-0.382852 -0.501296 9.597611 70520568.000000 +-0.165105 -1.398605 10.934003 70620584.000000 +-1.137787 -1.858027 11.070394 70720536.000000 +-0.570688 -1.214357 10.652846 70820496.000000 +0.275175 -1.427319 10.853845 70920552.000000 +-0.253639 -2.112862 9.728020 71020536.000000 +-0.053839 -1.817349 10.593026 71120552.000000 +-0.202193 -0.623330 10.399208 71220648.000000 +0.343370 1.076770 9.952947 71320632.000000 +1.381855 3.005385 10.291530 71420528.000000 +-1.508675 4.090530 9.220742 71520568.000000 +-0.252443 2.627320 12.151951 71620496.000000 +-0.156730 1.197608 10.022337 71720560.000000 +-0.192622 0.673580 10.197014 71820528.000000 +-0.271585 0.559920 9.378669 71920560.000000 +-0.137587 0.606581 10.380065 72020568.000000 +-0.072981 0.527617 9.801002 72120512.000000 +0.107677 0.762114 10.299905 72220576.000000 +-0.151944 0.750150 10.247264 72320520.000000 +-0.331406 0.704686 10.212566 72420592.000000 +-0.189033 0.713061 9.939785 72520576.000000 +-0.116052 0.617348 10.130014 72620592.000000 +-0.314656 0.510868 9.748360 72720616.000000 +-0.075374 0.616152 10.228121 72820560.000000 +0.186640 0.771685 10.278370 72920576.000000 +-0.102891 0.715454 10.406385 73025632.000000 +0.184247 0.526421 10.188639 73125384.000000 +-0.173480 0.868595 10.241282 73225496.000000 +-0.334995 0.628116 10.045070 73325656.000000 +-0.062213 0.683151 9.985250 73425632.000000 +-0.192622 0.882952 10.015160 73525632.000000 +-0.468993 0.543171 9.494720 73625576.000000 +-0.211765 0.707079 9.859627 73725632.000000 +-0.592224 0.597009 9.812965 73825520.000000 +-1.113859 0.570688 10.825130 73925744.000000 +-1.007378 0.238086 12.628120 74025640.000000 +-0.997807 0.216550 10.536794 74125616.000000 +-0.443869 0.498904 10.843077 74225704.000000 +0.130409 0.792024 9.018548 74325472.000000 +-0.278764 0.662812 9.462417 74425464.000000 +-0.139980 0.606581 8.922836 74525536.000000 +-0.083749 0.955933 9.736395 74625488.000000 +-0.131605 0.865005 10.631311 74725480.000000 +0.083749 0.715454 10.845469 74825544.000000 +0.080160 0.709472 10.380065 74925464.000000 +-0.065803 0.671187 10.106087 75025488.000000 +-0.289532 0.647258 9.772287 75125552.000000 +-0.390030 0.537189 9.859627 75225488.000000 +-0.178265 0.656830 10.807183 75325480.000000 +-0.364905 0.515653 10.377672 75425552.000000 +-0.379262 0.886541 10.323833 75525488.000000 +-0.001196 0.728615 10.462617 75625472.000000 +-0.154337 0.212961 9.391829 75725696.000000 +-0.197408 0.196211 9.847661 75825464.000000 +-0.392423 0.309871 10.232906 75925488.000000 +-0.112463 0.583849 9.931411 76025536.000000 +-0.215354 0.788435 10.302298 76125472.000000 +-0.290728 0.643669 10.173084 76225496.000000 +0.043071 0.434297 10.045070 76325536.000000 +-0.397209 0.842274 10.347760 76525472.000000 +-0.404387 0.715454 10.216157 76625528.000000 +-0.074178 0.611366 10.242477 76725472.000000 +-0.349352 0.776471 10.244871 76825472.000000 +-0.410369 0.650848 9.905089 76925504.000000 +0.022732 0.636491 9.986445 77025496.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/gyro.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/gyro.txt new file mode 100755 index 0000000..6dca03a --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/gyro.txt @@ -0,0 +1,134 @@ +1.890000 0.472500 -0.472500 63560404.000000 +-3.657500 2.362500 -31.377501 63660552.000000 +-5.512500 -0.227500 1.645000 63760476.000000 +-4.830000 0.157500 1.697500 63860468.000000 +-6.510000 -0.542500 2.782500 63960488.000000 +-5.005000 0.542500 3.010000 64060464.000000 +-7.507500 -0.227500 3.027500 64160512.000000 +-3.342500 0.507500 2.572500 64260512.000000 +-6.125000 0.892500 2.940000 64360468.000000 +-6.772500 0.227500 2.555000 64460512.000000 +-4.462500 1.102500 2.467500 64560520.000000 +-7.332500 0.717500 3.867500 64660560.000000 +-3.290000 1.872500 2.222500 64760492.000000 +-7.052500 -0.052500 3.360000 64860516.000000 +-10.255000 -2.957500 5.337500 64960528.000000 +0.245000 16.887501 18.952499 65060680.000000 +-9.292500 3.202500 36.802502 65160488.000000 +-11.112500 -17.377501 53.235001 65260464.000000 +18.480000 9.082500 43.295002 65360456.000000 +19.162500 -4.112500 16.292500 65460464.000000 +30.450001 5.302500 -8.190000 65560528.000000 +19.512501 24.377501 -9.135000 65660516.000000 +-20.335001 11.322500 9.485000 65760584.000000 +-21.507500 -2.362500 6.685000 65860496.000000 +-22.190001 -11.427500 -0.052500 65960540.000000 +-11.917500 -5.372500 -15.732500 66060500.000000 +6.702500 -6.317500 -33.705002 66160512.000000 +-11.095000 -14.542500 -29.260000 66260476.000000 +-17.639999 -9.747500 -31.325001 66360512.000000 +-15.470000 7.752500 -18.059999 66460476.000000 +-14.262500 -6.527500 0.490000 66560752.000000 +-0.332500 7.822500 0.052500 66660452.000000 +4.217500 8.942500 2.450000 66760544.000000 +-8.557500 -3.727500 0.612500 66860468.000000 +-1.890000 2.432500 -2.152500 66960520.000000 +-4.375000 -2.537500 3.482500 67060508.000000 +-2.677500 -3.167500 1.557500 67160552.000000 +-2.730000 2.502500 0.210000 67260504.000000 +-10.675000 2.292500 2.642500 67360536.000000 +-2.800000 0.752500 10.010000 67460464.000000 +-14.892500 -2.397500 27.860001 67560504.000000 +-9.310000 9.922500 43.697498 67660544.000000 +-2.520000 -1.487500 36.137501 67760504.000000 +33.197498 15.277500 7.437500 67860472.000000 +-10.167500 2.782500 7.035000 67960528.000000 +-10.535000 9.887500 -1.487500 68060576.000000 +-2.975000 -1.732500 -6.125000 68160496.000000 +-11.602500 0.647500 5.092500 68260480.000000 +-30.030001 -11.217500 8.522500 68360544.000000 +-9.100000 -4.707500 -2.502500 68460520.000000 +15.855000 -9.887500 -20.860001 68560528.000000 +35.279999 7.472500 -36.557499 68660456.000000 +-9.905000 -30.782499 -47.967499 68760472.000000 +-19.792500 0.192500 -25.305000 68860480.000000 +-6.632500 10.132500 2.292500 68960464.000000 +-3.552500 5.547500 -1.417500 69060480.000000 +0.980000 6.177500 5.425000 69160584.000000 +-3.937500 4.357500 1.470000 69260520.000000 +-13.177500 -3.097500 5.775000 69360592.000000 +-5.372500 -1.067500 7.980000 69460528.000000 +-2.257500 5.547500 4.130000 69560736.000000 +-9.852500 2.537500 2.642500 69660528.000000 +-1.592500 1.907500 4.235000 69760528.000000 +-6.755000 0.472500 5.250000 69860528.000000 +-3.185000 -1.277500 3.622500 69960592.000000 +-1.645000 -1.347500 9.047500 70060520.000000 +-11.130000 -1.487500 24.237499 70160584.000000 +-19.530001 -0.822500 42.070000 70260528.000000 +-25.129999 24.027500 49.910000 70360592.000000 +-9.030000 5.827500 39.095001 70460536.000000 +-7.945000 -5.197500 20.737499 70560752.000000 +-0.227500 6.737500 -1.662500 70660504.000000 +-1.575000 2.327500 2.537500 70760568.000000 +-11.060000 -3.062500 6.457500 70860472.000000 +-13.527500 -1.977500 3.517500 70960544.000000 +-21.070000 -9.327500 0.087500 71060600.000000 +5.040000 1.557500 -14.087500 71160544.000000 +16.485001 -1.032500 -28.385000 71260488.000000 +-8.907500 -24.272501 -34.860001 71360616.000000 +-2.100000 5.162500 -47.512501 71460472.000000 +-11.917500 3.272500 -1.907500 71560552.000000 +1.820000 -4.707500 2.625000 71660504.000000 +-8.627500 15.592500 -6.597500 71760536.000000 +-3.167500 1.872500 1.470000 71860576.000000 +-14.315001 -2.992500 0.822500 71960528.000000 +-1.470000 0.892500 2.887500 72060536.000000 +-5.477500 0.367500 3.570000 72160504.000000 +-4.392500 0.892500 4.287500 72260584.000000 +-4.812500 1.592500 1.295000 72360488.000000 +-5.635000 -0.262500 1.977500 72460488.000000 +-5.057500 0.367500 1.400000 72560592.000000 +-6.335000 2.152500 2.782500 72660520.000000 +-4.112500 2.432500 2.327500 72760464.000000 +-7.472500 1.347500 4.410000 72860536.000000 +-5.390000 1.137500 3.342500 72960528.000000 +-5.670000 0.647500 2.187500 73061936.000000 +-6.160000 0.997500 3.657500 73160384.000000 +-5.005000 0.647500 1.872500 73260544.000000 +-4.130000 2.852500 2.555000 73360440.000000 +-6.807500 2.222500 4.515000 73460480.000000 +-3.955000 2.852500 3.150000 73560448.000000 +3.202500 4.287500 4.935000 73660456.000000 +-5.460000 11.567500 2.730000 73760472.000000 +-9.082500 11.322500 -1.995000 73860512.000000 +-20.422501 -0.017500 -0.420000 73960440.000000 +-21.385000 -9.607500 6.300000 74060640.000000 +-2.327500 4.007500 -1.925000 74160456.000000 +1.715000 -14.892500 4.357500 74260488.000000 +10.727500 -6.947500 0.437500 74360520.000000 +4.357500 -3.587500 2.100000 74460512.000000 +-1.557500 -4.217500 5.162500 74560512.000000 +-7.052500 1.522500 7.017500 74660560.000000 +-12.565000 2.887500 6.020000 74760544.000000 +-10.150000 2.782500 6.177500 74860544.000000 +-6.405000 -0.962500 2.852500 74960552.000000 +-5.547500 -0.647500 2.397500 75060544.000000 +-4.917500 -0.157500 2.975000 75160544.000000 +-7.262500 4.462500 3.290000 75260560.000000 +-12.687500 0.752500 2.292500 75360528.000000 +-5.267500 0.332500 0.770000 75460552.000000 +-4.760000 0.192500 0.245000 75560712.000000 +-6.300000 0.507500 4.935000 75660528.000000 +-1.050000 0.262500 7.157500 75760536.000000 +-6.037500 0.577500 7.752500 75860552.000000 +-6.807500 -0.017500 2.747500 75960536.000000 +-3.185000 -0.332500 0.437500 76060536.000000 +-4.725000 0.367500 0.385000 76160560.000000 +-5.792500 -0.787500 3.482500 76260512.000000 +-5.880000 0.297500 2.782500 76360536.000000 +-3.605000 2.292500 0.000000 76460544.000000 +-4.130000 2.047500 2.887500 76560488.000000 +-4.340000 0.507500 4.900000 76660472.000000 +-5.162500 -1.382500 2.030000 76760512.000000 +-4.742500 -1.452500 3.885000 76960528.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/magnetic.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/magnetic.txt new file mode 100755 index 0000000..6e9c2ba --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x/magnetic.txt @@ -0,0 +1,135 @@ +29.687500 -33.750000 -12.937500 63562260.000000 +31.437500 -33.750000 -13.312500 63662260.000000 +32.937500 -33.500000 -13.687500 63762260.000000 +32.250000 -33.562500 -13.312500 63862260.000000 +32.875000 -33.750000 -13.562500 63962260.000000 +32.562500 -33.375000 -13.687500 64062260.000000 +32.500000 -33.375000 -13.875000 64162260.000000 +32.250000 -33.562500 -13.875000 64262260.000000 +32.562500 -33.437500 -14.187500 64362260.000000 +32.312500 -33.437500 -14.437500 64462260.000000 +32.000000 -33.375000 -14.312500 64562260.000000 +32.000000 -33.375000 -14.437500 64662260.000000 +31.937500 -33.312500 -14.375000 64762260.000000 +31.937500 -33.437500 -14.375000 64862260.000000 +31.750000 -33.562500 -14.250000 64962260.000000 +31.375000 -33.562500 -14.000000 65062260.000000 +30.687500 -34.062500 -13.750000 65162260.000000 +29.812500 -34.625000 -13.375000 65262260.000000 +28.750000 -35.375000 -13.625000 65362260.000000 +26.750000 -35.812500 -13.250000 65462260.000000 +25.062500 -35.812500 -13.187500 65562260.000000 +23.187500 -35.750000 -13.000000 65662260.000000 +21.562500 -35.750000 -13.250000 65762260.000000 +20.062500 -36.062500 -13.125000 65862260.000000 +19.250000 -36.187500 -13.125000 65962260.000000 +19.062500 -36.375000 -13.000000 66062260.000000 +19.750000 -36.125000 -12.437500 66162260.000000 +21.312500 -36.125000 -12.500000 66262260.000000 +23.125000 -36.000000 -12.562500 66362260.000000 +25.187500 -36.000000 -12.687500 66462260.000000 +27.000000 -35.937500 -12.687500 66562260.000000 +28.687500 -35.625000 -12.687500 66662260.000000 +30.125000 -35.062500 -12.625000 66762260.000000 +31.125000 -34.250000 -12.562500 66862260.000000 +31.875000 -34.125000 -13.062500 66962260.000000 +32.250000 -33.750000 -13.062500 67062260.000000 +32.375000 -33.812500 -12.937500 67162256.000000 +32.187500 -33.875000 -12.562500 67262256.000000 +32.312500 -33.875000 -12.000000 67362256.000000 +32.187500 -34.125000 -12.000000 67462256.000000 +31.687500 -34.500000 -11.750000 67562256.000000 +30.750000 -34.937500 -11.937500 67662256.000000 +29.000000 -35.375000 -11.875000 67762256.000000 +26.937500 -35.437500 -12.375000 67862256.000000 +25.062500 -35.125000 -12.750000 67962256.000000 +23.312500 -34.750000 -13.437500 68062256.000000 +21.375000 -34.312500 -14.250000 68162256.000000 +19.750000 -34.000000 -14.750000 68262256.000000 +18.750000 -34.187500 -15.000000 68362256.000000 +18.687500 -34.187500 -14.687500 68462256.000000 +20.125000 -33.937500 -14.187500 68562256.000000 +22.062500 -33.937500 -13.500000 68662256.000000 +23.750000 -34.062500 -12.875000 68762256.000000 +25.812500 -34.500000 -12.000000 68862256.000000 +28.312500 -34.875000 -11.250000 68962256.000000 +30.437500 -34.500000 -10.375000 69062256.000000 +32.125000 -33.937500 -9.937500 69162256.000000 +33.625000 -33.375000 -9.812500 69262256.000000 +34.250000 -32.875000 -9.937500 69362256.000000 +34.312500 -32.687500 -9.875000 69462256.000000 +34.500000 -32.812500 -9.812500 69562256.000000 +34.312500 -32.812500 -9.812500 69662256.000000 +33.875000 -32.687500 -9.500000 69762256.000000 +33.687500 -33.062500 -9.562500 69862256.000000 +33.625000 -33.125000 -9.375000 69962256.000000 +33.312500 -33.375000 -9.250000 70062256.000000 +32.875000 -33.812500 -9.250000 70162256.000000 +32.062500 -34.375000 -9.500000 70262256.000000 +30.937500 -34.937500 -9.500000 70362256.000000 +29.312500 -35.562500 -9.687500 70462256.000000 +27.562500 -36.187500 -10.437500 70562256.000000 +25.750000 -36.250000 -11.062500 70662256.000000 +24.250000 -36.250000 -11.687500 70762256.000000 +22.500000 -36.125000 -12.437500 70862256.000000 +20.812500 -36.312500 -13.125000 70962256.000000 +20.000000 -36.312500 -13.500000 71062256.000000 +19.875000 -36.375000 -13.812500 71162256.000000 +20.812500 -36.250000 -13.875000 71262256.000000 +22.250000 -36.125000 -13.625000 71362256.000000 +24.000000 -36.000000 -13.437500 71462256.000000 +25.562500 -35.937500 -13.312500 71562256.000000 +27.437500 -35.937500 -13.062500 71662256.000000 +29.375000 -35.562500 -12.562500 71762256.000000 +31.062500 -35.125000 -12.500000 71862256.000000 +32.312500 -34.687500 -12.375000 71962256.000000 +33.000000 -34.250000 -12.500000 72062256.000000 +33.250000 -34.062500 -12.500000 72162256.000000 +33.375000 -34.187500 -12.312500 72262256.000000 +33.500000 -34.125000 -12.437500 72362256.000000 +33.375000 -34.250000 -12.312500 72462256.000000 +33.375000 -34.312500 -12.187500 72562256.000000 +33.375000 -34.125000 -12.062500 72662256.000000 +33.062500 -34.000000 -12.125000 72762256.000000 +33.125000 -34.062500 -12.000000 72862256.000000 +33.062500 -34.000000 -11.875000 72962256.000000 +33.000000 -34.062500 -11.562500 73062256.000000 +32.500000 -34.125000 -11.187500 73162256.000000 +32.625000 -34.000000 -11.062500 73262256.000000 +32.562500 -34.000000 -10.750000 73362256.000000 +32.562500 -34.187500 -10.437500 73462256.000000 +32.625000 -34.312500 -10.062500 73562256.000000 +32.437500 -34.312500 -9.812500 73662256.000000 +32.375000 -34.437500 -9.625000 73762256.000000 +32.437500 -34.437500 -9.687500 73862256.000000 +32.750000 -34.625000 -9.687500 73962256.000000 +32.562500 -34.687500 -9.750000 74062256.000000 +32.437500 -34.625000 -10.000000 74162256.000000 +32.125000 -34.562500 -10.000000 74262256.000000 +32.312500 -34.625000 -10.062500 74362256.000000 +32.375000 -34.562500 -10.250000 74462256.000000 +32.375000 -34.500000 -10.312500 74562256.000000 +32.250000 -34.312500 -10.250000 74662256.000000 +32.000000 -34.312500 -10.312500 74762256.000000 +32.000000 -34.437500 -10.312500 74862256.000000 +32.000000 -34.437500 -10.312500 74962256.000000 +32.062500 -34.687500 -10.312500 75062256.000000 +31.812500 -34.437500 -10.312500 75162256.000000 +31.937500 -34.562500 -10.062500 75262256.000000 +31.875000 -34.687500 -10.125000 75362256.000000 +31.875000 -34.625000 -10.187500 75462256.000000 +31.812500 -34.500000 -10.437500 75562256.000000 +31.562500 -34.375000 -10.562500 75662256.000000 +31.250000 -34.437500 -10.562500 75762256.000000 +31.125000 -34.312500 -10.687500 75862256.000000 +31.062500 -34.500000 -10.500000 75962256.000000 +30.562500 -34.625000 -10.562500 76062256.000000 +30.500000 -34.687500 -10.625000 76162256.000000 +30.125000 -34.937500 -10.687500 76262256.000000 +30.250000 -35.062500 -10.437500 76362256.000000 +30.687500 -35.250000 -10.250000 76462256.000000 +30.750000 -35.437500 -10.062500 76562256.000000 +30.437500 -35.500000 -9.875000 76662256.000000 +30.562500 -35.375000 -9.937500 76762256.000000 +30.750000 -35.187500 -9.937500 76862256.000000 +30.750000 -35.187500 -9.687500 76962256.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/accel.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/accel.txt new file mode 100755 index 0000000..27d9479 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/accel.txt @@ -0,0 +1,170 @@ +0.118445 0.745364 10.156336 79430400.000000 +-0.098106 0.589831 10.029516 79530616.000000 +-0.141177 0.689133 10.407581 79630952.000000 +-0.137587 0.658026 9.830912 79730664.000000 +-0.106481 0.665205 10.057034 79830752.000000 +-0.119641 0.813560 10.140782 79930960.000000 +0.009571 0.875773 10.402797 80030960.000000 +-0.083749 0.708275 10.327423 80130920.000000 +0.055035 0.679562 10.104890 80230728.000000 +-0.114855 0.794417 10.237692 80330624.000000 +-0.181855 0.825524 10.149158 80430792.000000 +0.153141 0.547956 10.260423 80530824.000000 +-0.151944 0.624527 10.155140 80630640.000000 +-0.198604 0.836291 10.372886 80730768.000000 +-0.071785 0.711865 9.930215 80830856.000000 +-0.257228 0.569492 9.950554 80931360.000000 +-0.131605 0.939183 10.347760 81030576.000000 +-0.070588 0.869791 10.567901 81130672.000000 +-0.092124 0.798006 10.211370 81231200.000000 +0.016750 0.649651 10.031910 81330584.000000 +-0.217747 0.847059 9.912268 81430856.000000 +-0.535992 1.892723 10.003194 81530704.000000 +-0.445065 2.396412 10.437491 81630736.000000 +-0.624527 2.640480 10.646864 81730776.000000 +-0.266800 2.338984 10.767702 81830952.000000 +0.778864 0.801596 10.563116 81930704.000000 +0.419940 -0.461815 11.133803 82030744.000000 +-0.874577 -2.377269 9.683753 82134168.000000 +-0.664008 -1.390230 9.665807 82230456.000000 +-0.844666 0.161516 10.034302 82330536.000000 +-0.305085 0.606581 10.225728 82430552.000000 +0.318245 0.425922 10.144372 82530496.000000 +0.120838 -0.569492 10.022337 82630592.000000 +-0.524028 -1.989632 10.660025 82730552.000000 +-0.392423 -1.513460 10.939985 82830592.000000 +-0.412762 -0.136391 9.699306 82930752.000000 +0.080160 1.999203 10.281959 83030488.000000 +-0.805185 4.059423 9.012567 83130664.000000 +-0.537189 3.383451 10.968699 83230544.000000 +-0.483350 1.104288 9.534202 83330584.000000 +-0.345763 0.778864 10.658829 83430640.000000 +-0.368495 0.482154 10.226924 83530728.000000 +-0.532403 0.689133 10.674382 83630536.000000 +0.285942 0.423530 9.920642 83730568.000000 +-0.364905 0.285942 9.616754 83830560.000000 +-0.043071 0.535992 10.618150 83930512.000000 +-0.191426 0.538385 10.057034 84030632.000000 +-0.440279 0.386441 10.186246 84130720.000000 +-0.033500 0.599402 10.134801 84230560.000000 +-0.504886 0.612563 9.982857 84330584.000000 +-0.321835 0.543171 10.411172 84430832.000000 +-0.114855 0.441476 9.891929 84530640.000000 +-0.136391 0.781257 10.314261 84630600.000000 +-0.406780 0.565903 10.036695 84730832.000000 +-0.333799 0.553938 10.157533 84830584.000000 +-0.037089 0.579063 10.376474 84930576.000000 +-0.047856 0.683151 9.963714 85030536.000000 +-0.273978 0.696311 10.358529 85131072.000000 +-0.116052 0.631705 10.456635 85230464.000000 +-0.669990 0.582652 10.131211 85330528.000000 +-0.108873 0.604188 9.994821 85430840.000000 +-0.382852 0.338584 9.895518 85530736.000000 +-0.532403 0.221336 10.120443 85630776.000000 +-0.418744 0.392423 10.299905 85730752.000000 +-0.306281 0.522832 10.174281 85830744.000000 +-0.679562 0.664008 10.157533 85930688.000000 +-0.357727 0.534796 9.961320 86030848.000000 +-0.302692 0.545564 9.936196 86130656.000000 +0.046660 0.665205 10.470992 86230896.000000 +1.046860 0.681954 11.063215 86331752.000000 +2.268396 0.537189 10.545169 86431488.000000 +4.289135 -0.667598 10.208978 86530616.000000 +0.976272 -1.460818 9.914660 86630776.000000 +-2.866602 -0.266800 11.763116 86730472.000000 +-1.154537 1.178465 11.097912 86833976.000000 +-0.224925 0.979861 9.988838 86930600.000000 +0.196211 0.601795 9.895518 87031048.000000 +0.721436 0.512064 10.077373 87130568.000000 +-0.075374 0.847059 9.704092 87230704.000000 +0.184247 0.455833 9.401401 87330544.000000 +-1.354338 0.900898 9.109475 87430720.000000 +-2.524428 -0.040678 10.034302 87533808.000000 +-1.030110 -0.272782 10.602598 87630528.000000 +0.222532 -0.281157 10.454242 87730568.000000 +2.682354 1.178465 10.127622 87831672.000000 +0.881755 0.751346 7.633104 87930552.000000 +1.938186 0.872184 10.920842 88030792.000000 +-0.563510 0.987039 10.898110 88130520.000000 +-0.929612 0.725025 10.264012 88230656.000000 +-0.606581 0.934397 9.930215 88330560.000000 +-0.463011 0.626920 9.702895 88430880.000000 +-0.163908 0.784846 10.500903 88530704.000000 +-0.303888 0.801596 10.357333 88630496.000000 +-0.708275 0.721436 10.135997 88730592.000000 +-0.248854 0.647258 10.549955 88830504.000000 +-0.650848 0.541974 9.755538 88930672.000000 +-0.344566 0.835095 10.453046 89030968.000000 +-0.293121 0.912862 10.256834 89130544.000000 +-0.153141 0.812363 10.204191 89230664.000000 +-0.108873 0.635294 9.996017 89330728.000000 +-0.329013 0.628116 9.968499 89430544.000000 +-0.116052 0.762114 10.436296 89530680.000000 +-0.388834 0.533599 10.199407 89630512.000000 +-0.227318 0.331406 10.319048 89730560.000000 +-0.650848 0.500100 10.195816 89830528.000000 +-0.206979 0.448654 10.180264 89930544.000000 +-0.217747 0.478565 10.150353 90030544.000000 +-0.226122 0.319442 9.929017 90130528.000000 +-0.338584 0.453440 10.165908 90230520.000000 +-0.510868 0.327817 10.268798 90330696.000000 +-0.506082 0.285942 10.181459 90430640.000000 +-0.363709 0.478565 10.284351 90530984.000000 +-0.189033 0.360120 10.247264 90630552.000000 +-0.576670 0.440279 10.996217 90730736.000000 +-1.392623 0.118445 12.747763 90831000.000000 +-0.083749 1.308874 16.910078 90930528.000000 +0.004786 0.064606 11.936595 91030552.000000 +-0.391227 -0.230907 6.978668 91130520.000000 +-0.216550 1.185644 6.803991 91230616.000000 +2.784049 0.788435 6.863811 91330544.000000 +2.522035 1.354338 8.933603 91431040.000000 +2.423929 1.133002 9.559326 91530544.000000 +2.453840 1.995614 9.964910 91630528.000000 +2.132005 2.023132 10.007980 91730512.000000 +1.491925 1.999203 10.326227 91830640.000000 +1.665405 1.738386 9.950554 91930632.000000 +1.502693 1.570888 8.611769 92030584.000000 +1.185644 1.618744 7.057630 92130664.000000 +1.746760 0.579063 5.046463 92230496.000000 +-0.166301 0.238086 7.265806 92330552.000000 +-0.254836 -0.428315 12.075379 92430536.000000 +-2.549552 0.427119 14.888142 92530520.000000 +-0.659223 0.084945 14.871392 92630504.000000 +-0.597009 0.659223 12.859028 92730544.000000 +-0.386441 0.358923 10.119246 92830528.000000 +-0.120838 0.287139 9.683753 92930664.000000 +-0.033500 0.413958 9.900303 93030712.000000 +-0.740579 0.508475 10.224532 93130552.000000 +-0.162712 0.133998 10.113264 93231256.000000 +-0.474975 -0.074178 10.528419 93330992.000000 +-0.827917 -0.122034 10.090532 93430848.000000 +-0.574277 0.064606 10.437491 93531272.000000 +-1.406980 0.267996 9.483953 93630672.000000 +-1.386641 0.436690 9.778270 93730592.000000 +-0.795613 0.269193 10.200603 93830512.000000 +-0.465404 0.679562 10.999805 93934096.000000 +-0.643669 0.400798 10.025927 94035488.000000 +-0.985843 0.284746 10.222138 94137736.000000 +-0.556331 0.111266 10.315458 94235744.000000 +-0.987039 0.449851 10.438687 94335800.000000 +-1.024128 0.208176 9.583255 94435552.000000 +-0.774078 0.396012 10.662418 94537936.000000 +-1.281357 0.179462 9.858429 94635592.000000 +-0.973879 0.516850 10.516455 94735632.000000 +-0.780060 0.528814 9.954143 94835608.000000 +-0.957129 0.253639 10.484153 94935888.000000 +-0.954736 0.241675 9.814162 95035552.000000 +-0.678365 0.453440 10.494920 95135816.000000 +-0.646062 0.246461 10.194620 95236008.000000 +-0.720240 0.339781 10.295119 95335536.000000 +-1.054038 0.313460 10.125229 95435600.000000 +-0.963111 0.145962 10.095319 95535672.000000 +-1.123430 0.142373 10.182656 95635576.000000 +-0.823131 0.199801 10.003194 95735592.000000 +-0.857827 0.363709 10.241282 95835616.000000 +-0.870987 0.284746 10.244871 95935600.000000 +-1.268196 0.218943 10.232906 96135616.000000 +-0.825524 0.269193 10.130014 96335456.000000 +-0.982254 0.223729 10.096515 96435608.000000 +-0.721436 0.256032 10.469796 96535688.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/gyro.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/gyro.txt new file mode 100755 index 0000000..0e4dd90 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/gyro.txt @@ -0,0 +1,171 @@ +1.890000 0.472500 -0.472500 79401624.000000 +-0.752500 6.947500 -31.867500 79500520.000000 +-7.577500 -0.647500 2.712500 79600568.000000 +-2.870000 -0.892500 1.785000 79700520.000000 +-5.390000 -0.892500 3.010000 79800488.000000 +-4.795000 0.437500 2.747500 79900520.000000 +-6.527500 0.717500 3.185000 80000472.000000 +-5.757500 0.367500 3.552500 80100512.000000 +-4.270000 0.962500 3.412500 80200584.000000 +-5.425000 0.367500 2.222500 80300520.000000 +-4.480000 0.087500 2.677500 80400640.000000 +-5.617500 0.612500 2.695000 80500560.000000 +-7.595000 2.852500 0.332500 80600496.000000 +-6.002500 -0.717500 1.767500 80700488.000000 +-1.925000 -0.017500 4.095000 80800544.000000 +-5.250000 -0.052500 4.480000 80900624.000000 +-5.075000 3.027500 2.572500 81000464.000000 +-6.912500 1.277500 2.222500 81100472.000000 +-4.777500 -0.262500 3.640000 81200488.000000 +-5.530000 -0.367500 4.410000 81300456.000000 +-4.917500 -0.052500 3.272500 81400560.000000 +-8.977500 -0.577500 4.497500 81500472.000000 +-12.092500 6.387500 5.862500 81600528.000000 +-15.400000 7.227500 16.887501 81700552.000000 +-15.067500 -4.777500 40.302502 81800456.000000 +-2.800000 0.927500 47.652500 81900448.000000 +6.387500 4.042500 29.505001 82000520.000000 +15.785000 5.757500 10.412500 82100480.000000 +0.402500 -3.097500 6.615000 82200352.000000 +-5.337500 -3.272500 -0.315000 82300576.000000 +-7.577500 0.577500 -0.962500 82400544.000000 +-6.737500 0.927500 2.310000 82500496.000000 +-3.517500 6.037500 -1.802500 82600840.000000 +-9.730000 -1.032500 -7.857500 82700696.000000 +-15.312500 -11.917500 -15.697500 82800472.000000 +-8.050000 -8.207500 -34.160000 82901168.000000 +-14.910000 -7.472500 -45.500000 83000552.000000 +7.997500 7.017500 -36.942501 83101192.000000 +-8.225000 -5.442500 -15.995000 83200464.000000 +1.050000 4.357500 -3.727500 83300520.000000 +-12.740000 3.657500 0.962500 83400488.000000 +-7.227500 2.502500 1.085000 83500480.000000 +-7.402500 0.122500 0.997500 83600488.000000 +-1.557500 0.507500 7.105000 83700456.000000 +-4.060000 -1.102500 5.372500 83800456.000000 +-11.515000 -0.472500 4.567500 83900696.000000 +-3.745000 0.857500 1.575000 84000544.000000 +-5.757500 0.262500 0.297500 84100472.000000 +-10.780000 -3.622500 1.295000 84200512.000000 +-3.640000 1.802500 3.220000 84300504.000000 +-3.202500 0.052500 4.497500 84400464.000000 +-4.217500 1.732500 5.687500 84500496.000000 +-2.117500 1.802500 4.567500 84600632.000000 +-7.787500 0.857500 4.007500 84700488.000000 +-4.760000 1.242500 2.397500 84800504.000000 +-5.845000 0.507500 3.290000 84900456.000000 +-5.302500 0.227500 2.485000 85010784.000000 +-3.832500 0.857500 1.330000 85111504.000000 +-5.757500 0.437500 2.292500 85210320.000000 +-5.495000 0.927500 3.780000 85310520.000000 +-8.382500 3.657500 5.442500 85410712.000000 +-6.422500 -3.762500 8.067500 85510520.000000 +-6.212500 2.047500 3.045000 85610576.000000 +-6.860000 1.487500 1.925000 85710528.000000 +-4.847500 0.262500 2.100000 85810488.000000 +-3.727500 1.522500 2.275000 85910584.000000 +-3.902500 0.542500 4.217500 86010544.000000 +-4.392500 0.682500 4.165000 86110472.000000 +-8.837500 0.437500 2.992500 86210600.000000 +-12.145000 7.752500 4.585000 86310544.000000 +1.050000 6.282500 8.627500 86410496.000000 +-16.957500 -18.007500 3.605000 86510536.000000 +-18.725000 -38.027500 -21.717501 86610512.000000 +-16.292500 -31.937500 -66.815002 86711120.000000 +4.970000 -1.452500 -46.602501 86810448.000000 +29.085001 16.047501 -5.005000 86910488.000000 +-1.680000 13.982500 2.362500 87010520.000000 +-5.950000 5.057500 5.967500 87110392.000000 +-4.042500 8.347500 -3.657500 87210544.000000 +-6.825000 0.157500 11.287500 87310536.000000 +-10.797500 4.217500 0.507500 87410520.000000 +-25.707500 0.332500 18.637501 87510448.000000 +-25.637501 -5.057500 26.985001 87610408.000000 +-1.645000 -19.897501 -7.752500 87710576.000000 +9.957500 25.567499 26.582500 87810472.000000 +25.059999 24.482500 29.977501 87910480.000000 +-15.925000 9.082500 33.477501 88010496.000000 +-3.937500 6.737500 5.792500 88110368.000000 +-2.975000 -1.872500 2.502500 88210512.000000 +-3.850000 -2.362500 0.367500 88310496.000000 +-3.955000 0.507500 2.940000 88410712.000000 +-9.205000 0.647500 5.530000 88510480.000000 +-5.005000 2.572500 4.550000 88610544.000000 +-7.752500 -0.297500 3.325000 88710504.000000 +-10.027500 1.347500 5.267500 88810488.000000 +-2.240000 0.787500 -0.192500 88910472.000000 +-6.702500 -0.052500 2.397500 89010488.000000 +-5.757500 -0.507500 3.937500 89110376.000000 +-4.602500 0.017500 4.847500 89210480.000000 +-4.830000 -0.507500 4.270000 89310496.000000 +-4.847500 2.537500 2.730000 89410368.000000 +-10.132500 0.227500 5.407500 89510480.000000 +-7.945000 -1.662500 2.397500 89610544.000000 +-10.360000 1.662500 3.990000 89710464.000000 +-9.765000 0.227500 3.570000 89810456.000000 +-5.145000 -0.122500 3.710000 89910696.000000 +-5.600000 2.012500 4.340000 90010464.000000 +-4.532500 0.192500 5.075000 90110464.000000 +-8.592500 -1.137500 5.670000 90210536.000000 +-7.875000 2.187500 5.495000 90310464.000000 +-4.200000 2.502500 1.417500 90410464.000000 +-5.495000 0.752500 1.592500 90510496.000000 +-4.392500 -1.522500 4.357500 90610368.000000 +-4.970000 2.502500 1.592500 90710464.000000 +-5.075000 2.012500 2.940000 90810496.000000 +-5.827500 -0.262500 3.115000 90910376.000000 +-30.380001 -15.977500 18.252501 91010456.000000 +20.072500 -26.267500 -2.187500 91110544.000000 +9.712500 -23.537500 -30.344999 91210472.000000 +19.512501 -35.332500 -14.945000 91310456.000000 +14.315001 -22.767500 2.310000 91410672.000000 +-5.722500 -16.852501 -5.845000 91510464.000000 +1.172500 -4.882500 -5.705000 91610464.000000 +0.997500 1.452500 1.190000 91710512.000000 +-1.400000 7.017500 7.350000 91810480.000000 +-5.180000 4.882500 4.620000 91910456.000000 +-1.802500 -0.927500 3.552500 92010544.000000 +-4.707500 0.052500 3.587500 92110472.000000 +-7.717500 13.072500 9.957500 92210480.000000 +-33.687500 32.182499 -5.670000 92310496.000000 +-49.682499 35.367500 21.192499 92410464.000000 +-32.357502 43.382500 14.822500 92510464.000000 +-33.442501 16.327499 12.915000 92610520.000000 +-12.722500 0.857500 -0.472500 92710480.000000 +10.412500 -5.232500 -5.687500 92810464.000000 +8.382500 -5.897500 -1.907500 92910712.000000 +0.350000 -2.327500 0.087500 93010464.000000 +-4.480000 2.957500 1.820000 93110584.000000 +-7.420000 3.272500 7.525000 93210544.000000 +-7.035000 5.967500 7.630000 93310512.000000 +-7.367500 2.327500 3.972500 93410496.000000 +-6.440000 3.062500 3.255000 93510536.000000 +6.562500 8.662500 3.675000 93610504.000000 +-1.365000 1.977500 2.380000 93710504.000000 +-7.472500 3.657500 6.667500 93810600.000000 +-10.885000 3.307500 9.117500 93910464.000000 +-0.035000 4.952500 4.130000 94010408.000000 +-7.507500 -0.752500 2.047500 94110528.000000 +-3.535000 3.202500 2.905000 94210376.000000 +-9.695000 -2.117500 0.980000 94310464.000000 +-4.077500 -0.577500 0.997500 94410440.000000 +-6.632500 2.397500 3.360000 94510504.000000 +0.927500 3.202500 0.997500 94610408.000000 +-7.787500 0.122500 1.050000 94710544.000000 +-4.165000 -0.297500 0.717500 94810512.000000 +-7.630000 -0.192500 2.835000 94910520.000000 +-4.147500 1.277500 2.607500 95010512.000000 +-10.885000 -0.647500 0.192500 95110544.000000 +-4.882500 -0.647500 0.857500 95210496.000000 +-7.157500 0.087500 2.765000 95310400.000000 +-5.582500 0.052500 2.747500 95410544.000000 +-5.862500 0.612500 4.042500 95510600.000000 +-6.825000 -0.577500 2.345000 95610480.000000 +-5.057500 0.437500 1.365000 95710520.000000 +-5.250000 0.297500 2.800000 95910608.000000 +-4.830000 1.172500 3.675000 96010536.000000 +-6.580000 -1.137500 3.220000 96110512.000000 +-5.285000 0.857500 3.237500 96210456.000000 +-7.035000 -2.152500 2.170000 96311064.000000 +-3.937500 -0.787500 1.977500 96410512.000000 +-6.615000 0.052500 2.975000 96510488.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/magnetic.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/magnetic.txt new file mode 100755 index 0000000..0e406e9 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_x_y_z/magnetic.txt @@ -0,0 +1,171 @@ +28.125000 -34.937500 -9.000000 79406976.000000 +29.875000 -35.312500 -9.000000 79506976.000000 +29.625000 -35.937500 -9.937500 79606976.000000 +29.000000 -36.250000 -10.000000 79706976.000000 +29.437500 -36.500000 -10.375000 79806976.000000 +29.125000 -36.750000 -10.875000 79906976.000000 +29.562500 -36.625000 -10.375000 80006976.000000 +29.312500 -36.250000 -10.000000 80106976.000000 +29.625000 -36.500000 -10.062500 80206976.000000 +29.250000 -36.562500 -10.187500 80306976.000000 +29.437500 -36.562500 -9.875000 80406976.000000 +29.562500 -36.500000 -9.687500 80506976.000000 +29.437500 -36.500000 -9.687500 80606976.000000 +29.437500 -36.375000 -9.562500 80706976.000000 +29.375000 -36.562500 -9.687500 80806976.000000 +29.437500 -36.625000 -9.750000 80906976.000000 +29.312500 -36.625000 -9.875000 81006976.000000 +29.312500 -36.750000 -9.875000 81106976.000000 +29.375000 -37.062500 -9.812500 81206976.000000 +29.125000 -37.187500 -9.875000 81306976.000000 +29.187500 -37.375000 -9.875000 81406976.000000 +28.937500 -37.562500 -9.750000 81506976.000000 +28.750000 -37.687500 -9.625000 81606976.000000 +28.062500 -37.812500 -9.812500 81706976.000000 +27.000000 -38.125000 -10.125000 81806976.000000 +25.687500 -38.500000 -10.562500 81906976.000000 +23.875000 -38.125000 -11.375000 82006976.000000 +22.625000 -37.625000 -11.937500 82106976.000000 +20.937500 -36.937500 -12.437500 82206976.000000 +19.562500 -36.062500 -13.375000 82306976.000000 +18.187500 -35.312500 -14.125000 82406976.000000 +17.312500 -34.750000 -14.500000 82506976.000000 +16.812500 -33.875000 -14.812500 82606976.000000 +16.750000 -33.562500 -15.250000 82706976.000000 +17.000000 -34.250000 -15.250000 82806976.000000 +17.875000 -34.937500 -14.937500 82906976.000000 +19.625000 -35.687500 -14.437500 83006976.000000 +21.437500 -36.312500 -13.687500 83106976.000000 +23.312500 -36.750000 -13.125000 83206976.000000 +25.250000 -36.937500 -12.625000 83306976.000000 +27.000000 -37.437500 -12.000000 83406976.000000 +28.937500 -37.125000 -11.187500 83506976.000000 +30.937500 -36.500000 -10.687500 83606976.000000 +31.875000 -36.187500 -10.500000 83706976.000000 +32.187500 -35.812500 -10.250000 83806976.000000 +32.312500 -35.875000 -10.375000 83906976.000000 +32.250000 -36.125000 -10.437500 84006976.000000 +32.375000 -35.875000 -10.625000 84106976.000000 +32.437500 -35.875000 -10.687500 84206976.000000 +32.500000 -36.062500 -10.625000 84306976.000000 +32.312500 -36.062500 -10.687500 84406976.000000 +32.437500 -36.000000 -10.750000 84506976.000000 +32.312500 -36.062500 -10.937500 84606976.000000 +32.125000 -36.250000 -10.812500 84706976.000000 +32.250000 -35.812500 -10.875000 84806976.000000 +31.937500 -36.125000 -10.812500 84906976.000000 +31.937500 -36.312500 -10.687500 85006976.000000 +31.125000 -36.125000 -10.187500 85106976.000000 +30.750000 -36.062500 -9.875000 85206976.000000 +30.625000 -36.000000 -9.750000 85306976.000000 +30.562500 -36.000000 -9.687500 85406976.000000 +30.437500 -35.937500 -9.562500 85506976.000000 +30.250000 -36.187500 -9.375000 85606976.000000 +30.187500 -36.187500 -9.312500 85706976.000000 +30.000000 -36.125000 -9.125000 85806976.000000 +30.312500 -36.250000 -9.687500 85906976.000000 +30.500000 -36.312500 -9.750000 86006976.000000 +30.312500 -36.250000 -9.750000 86106976.000000 +30.125000 -36.375000 -9.562500 86206976.000000 +30.187500 -36.375000 -9.625000 86306976.000000 +30.062500 -36.437500 -9.562500 86406976.000000 +30.062500 -36.562500 -9.562500 86506976.000000 +30.750000 -36.250000 -10.000000 86606976.000000 +31.812500 -35.437500 -10.187500 86706976.000000 +32.937500 -34.500000 -10.375000 86806976.000000 +34.187500 -33.687500 -10.250000 86906976.000000 +35.687500 -32.750000 -10.312500 87006976.000000 +36.937500 -31.750000 -10.125000 87106976.000000 +38.437500 -30.750000 -9.875000 87206976.000000 +39.625000 -29.875000 -9.812500 87306976.000000 +40.187500 -29.250000 -9.437500 87406976.000000 +40.312500 -29.375000 -9.062500 87506976.000000 +40.062500 -29.875000 -9.125000 87606976.000000 +39.687500 -30.437500 -9.562500 87706976.000000 +38.625000 -31.187500 -9.687500 87806976.000000 +37.500000 -32.000000 -9.687500 87906976.000000 +35.937500 -32.812500 -9.812500 88006976.000000 +34.625000 -33.687500 -9.562500 88106976.000000 +33.312500 -34.562500 -9.437500 88206976.000000 +32.437500 -35.125000 -9.375000 88306976.000000 +31.750000 -35.437500 -8.937500 88406976.000000 +30.875000 -35.750000 -8.562500 88506976.000000 +30.437500 -36.062500 -8.500000 88606976.000000 +30.125000 -36.250000 -8.625000 88706976.000000 +30.312500 -36.250000 -8.562500 88806976.000000 +30.375000 -36.312500 -8.687500 88906976.000000 +30.437500 -36.437500 -8.687500 89006976.000000 +30.187500 -36.562500 -8.750000 89106976.000000 +30.187500 -36.625000 -8.625000 89206976.000000 +30.250000 -36.625000 -8.562500 89306976.000000 +30.187500 -36.562500 -8.500000 89406976.000000 +30.187500 -36.625000 -8.562500 89506976.000000 +30.187500 -36.750000 -8.625000 89606976.000000 +29.937500 -36.812500 -8.625000 89706976.000000 +29.875000 -36.875000 -8.687500 89806976.000000 +29.750000 -36.875000 -8.625000 89906976.000000 +29.562500 -36.875000 -9.000000 90006976.000000 +29.312500 -36.875000 -9.000000 90106976.000000 +29.062500 -36.937500 -9.375000 90206976.000000 +29.000000 -36.812500 -9.312500 90306976.000000 +28.812500 -36.875000 -9.375000 90406976.000000 +29.062500 -36.875000 -9.437500 90506976.000000 +29.000000 -36.562500 -9.500000 90606976.000000 +29.000000 -36.750000 -9.687500 90706976.000000 +28.875000 -36.937500 -9.500000 90806976.000000 +28.750000 -37.125000 -9.687500 90906976.000000 +29.000000 -37.062500 -9.562500 91006976.000000 +29.250000 -36.812500 -9.875000 91106976.000000 +29.625000 -36.500000 -9.750000 91206976.000000 +29.937500 -36.062500 -9.875000 91306976.000000 +30.250000 -36.000000 -10.125000 91406976.000000 +30.937500 -35.625000 -10.312500 91506976.000000 +31.500000 -35.187500 -10.625000 91606976.000000 +32.312500 -34.937500 -10.750000 91706976.000000 +32.625000 -34.562500 -10.625000 91806976.000000 +32.875000 -34.500000 -10.437500 91906976.000000 +32.937500 -34.625000 -10.437500 92006976.000000 +32.687500 -34.750000 -10.375000 92106976.000000 +32.437500 -34.812500 -10.000000 92206976.000000 +32.000000 -34.937500 -9.562500 92306976.000000 +31.625000 -35.187500 -9.312500 92406976.000000 +30.937500 -35.312500 -9.437500 92506976.000000 +30.500000 -35.750000 -9.812500 92606976.000000 +30.125000 -36.125000 -10.187500 92706976.000000 +29.687500 -36.187500 -10.625000 92806976.000000 +29.437500 -36.312500 -10.812500 92906976.000000 +29.375000 -36.312500 -11.312500 93006976.000000 +29.062500 -36.437500 -11.750000 93106976.000000 +29.125000 -36.562500 -12.000000 93206976.000000 +29.125000 -36.562500 -11.875000 93306976.000000 +29.000000 -36.500000 -11.562500 93406976.000000 +29.187500 -36.500000 -11.250000 93506976.000000 +29.187500 -36.750000 -10.750000 93606976.000000 +29.125000 -36.750000 -10.500000 93706976.000000 +28.937500 -36.875000 -10.250000 93806976.000000 +28.937500 -36.937500 -10.000000 93906976.000000 +28.812500 -36.875000 -9.875000 94006976.000000 +28.562500 -37.062500 -9.812500 94106976.000000 +28.500000 -37.125000 -9.562500 94206976.000000 +28.125000 -37.312500 -9.625000 94306976.000000 +28.000000 -37.062500 -9.687500 94406976.000000 +28.062500 -37.250000 -9.625000 94506976.000000 +28.000000 -37.437500 -9.375000 94606976.000000 +28.000000 -37.500000 -9.312500 94706976.000000 +28.000000 -37.625000 -9.000000 94806976.000000 +28.125000 -37.750000 -8.812500 94906976.000000 +28.187500 -37.750000 -9.000000 95006976.000000 +28.250000 -37.562500 -8.937500 95106976.000000 +28.312500 -37.625000 -8.875000 95206976.000000 +28.062500 -37.500000 -9.000000 95306976.000000 +28.312500 -37.500000 -9.187500 95406976.000000 +28.250000 -37.500000 -9.312500 95506976.000000 +28.125000 -37.687500 -9.625000 95606976.000000 +28.312500 -37.437500 -9.687500 95706976.000000 +28.250000 -37.375000 -9.875000 95806976.000000 +28.312500 -37.500000 -9.875000 95906976.000000 +28.312500 -37.625000 -9.937500 96006976.000000 +28.500000 -37.687500 -10.062500 96106976.000000 +28.500000 -37.625000 -10.250000 96206976.000000 +28.625000 -37.500000 -10.250000 96306976.000000 +28.812500 -37.250000 -10.312500 96506976.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/accel.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/accel.txt new file mode 100755 index 0000000..9acc487 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/accel.txt @@ -0,0 +1,128 @@ +0.153141 0.454636 10.515260 109665472.000000 +0.108873 0.634098 10.139585 109765600.000000 +0.189033 0.559920 10.084551 109865656.000000 +0.228515 0.495314 9.969695 109965520.000000 +0.172283 0.485743 10.375278 110065440.000000 +0.234497 0.483350 10.375278 110166232.000000 +0.165105 0.498904 10.151550 110265384.000000 +0.153141 0.470190 10.084551 110365376.000000 +0.320638 0.624527 10.317852 110465408.000000 +0.265603 0.622134 10.210175 110565424.000000 +1.861616 0.105284 10.219746 110665392.000000 +2.836691 -0.396012 10.454242 110765376.000000 +2.161915 0.058624 10.593026 110865376.000000 +-1.399801 -0.269193 8.100902 110965384.000000 +-4.444668 -0.687937 8.457432 111065376.000000 +-2.726621 0.020339 9.690931 111165384.000000 +-1.488336 -0.378066 8.909675 111265464.000000 +0.092124 0.635294 9.595219 111365376.000000 +-0.507278 0.435494 9.541381 111465384.000000 +0.267996 0.574277 10.584651 111565384.000000 +-0.327817 0.311067 9.997212 111665384.000000 +0.330210 0.407976 10.577473 111765376.000000 +-0.144766 0.435494 9.992428 111865416.000000 +0.083749 0.538385 9.960124 111965408.000000 +-0.118445 0.661615 10.109675 112065376.000000 +-1.399801 0.721436 9.052048 112165368.000000 +-1.792224 0.514457 11.009377 112265384.000000 +-3.908676 -0.452243 10.165908 112365384.000000 +-0.926022 -0.813560 8.383254 112465376.000000 +3.533003 0.081356 9.623933 112565384.000000 +2.178665 0.090927 10.151550 112665384.000000 +0.690329 0.441476 10.764113 112765472.000000 +0.635294 0.540778 10.922039 112865384.000000 +-0.284746 0.451047 10.169496 112965384.000000 +-0.178265 0.329013 10.078569 113065384.000000 +-0.311067 0.250050 9.925428 113165384.000000 +0.265603 0.445065 9.993625 113265376.000000 +0.043071 0.281157 10.170692 113365384.000000 +0.407976 0.436690 10.278370 113465384.000000 +0.269193 0.497707 10.110871 113565384.000000 +0.150748 0.492921 9.986445 113665384.000000 +0.287139 0.418744 9.830912 113765392.000000 +0.285942 0.321835 10.602598 113865384.000000 +0.177069 0.299103 9.978070 113965384.000000 +0.492921 0.295514 10.394422 114065384.000000 +2.598605 0.075374 9.767502 114165384.000000 +3.771089 0.173480 11.480762 114265456.000000 +3.842873 -0.379262 10.625329 114365928.000000 +-3.887140 -1.731207 8.994620 114465520.000000 +-5.313262 1.588834 10.996217 114565616.000000 +-0.390030 0.445065 7.659425 114665560.000000 +0.617348 1.037289 11.568101 114765536.000000 +0.552742 0.857827 10.850254 114865536.000000 +-0.136391 0.502493 9.881162 114965368.000000 +0.004786 0.553938 10.253245 115065400.000000 +0.595813 0.415155 10.254441 115165408.000000 +-0.439083 0.445065 9.390633 115265400.000000 +-0.878166 0.775275 10.319048 115365416.000000 +-2.500499 -0.017946 8.932407 115465376.000000 +-2.785245 0.168694 10.895718 115565408.000000 +-0.180658 -1.030110 8.970692 115665416.000000 +2.967100 0.557528 9.706485 115765448.000000 +1.501496 0.358923 8.957531 115865360.000000 +-0.362513 0.165105 10.792826 115965376.000000 +-1.071985 0.262014 10.459028 116065360.000000 +-0.757328 0.440279 9.755538 116165536.000000 +-0.364905 0.467797 10.216157 116265376.000000 +-0.696311 0.315853 9.665807 116365384.000000 +-0.209372 0.507278 10.851451 116465368.000000 +0.045464 0.290728 10.431510 116565400.000000 +0.126820 0.220140 10.068997 116665376.000000 +0.245264 0.327817 10.027123 116765376.000000 +0.380459 0.289532 9.783055 116865376.000000 +1.060020 0.477368 9.926624 116965376.000000 +2.135594 0.250050 10.225728 117065368.000000 +6.082555 -0.917647 11.399406 117165408.000000 +-0.842274 0.349352 9.494720 117265504.000000 +-5.557331 -1.740778 7.099504 117365384.000000 +-6.290731 1.612763 11.675778 117465384.000000 +-0.273978 -0.745364 9.221939 117565376.000000 +1.665405 -0.550349 10.439885 117665384.000000 +-0.352941 0.178265 9.480364 117765376.000000 +0.022732 0.324227 9.450454 117865416.000000 +-0.143569 0.551546 10.616954 117965384.000000 +-0.515653 0.390030 9.749557 118065384.000000 +-0.226122 0.313460 10.526026 118165432.000000 +-0.464208 0.262014 10.424332 118265408.000000 +-0.787239 0.355334 9.725628 118365384.000000 +-0.997807 0.235693 10.256834 118465384.000000 +-5.715257 -0.029910 9.846465 118565456.000000 +-5.871986 -1.435694 7.805387 118665368.000000 +5.534599 0.440279 11.954542 118765472.000000 +0.697508 0.031107 8.725428 118865384.000000 +1.994418 0.928415 11.016556 118965384.000000 +0.872184 0.841077 10.170692 119065384.000000 +0.236889 0.555135 9.741181 119165376.000000 +-0.677169 0.567099 9.773483 119265400.000000 +-0.123230 1.149751 10.770095 119365408.000000 +-0.248854 1.162912 10.375278 119465448.000000 +-0.655633 1.154537 10.655239 119565552.000000 +0.669990 0.946361 10.158729 119665472.000000 +0.557528 0.908076 9.900303 119765480.000000 +0.120838 0.794417 9.986445 119865472.000000 +-0.028714 0.738186 9.931411 119965464.000000 +0.035892 0.698704 10.281959 120065488.000000 +0.096909 0.656830 10.540384 120165456.000000 +0.083749 0.750150 10.433903 120265616.000000 +0.199801 0.638884 10.289137 120365464.000000 +0.266800 0.313460 10.435099 120465472.000000 +0.169890 0.509671 9.909874 120565472.000000 +0.302692 0.413958 9.882358 120665472.000000 +0.369691 0.433101 10.064213 120765472.000000 +0.190229 0.278764 9.923036 120865520.000000 +0.107677 0.273978 10.692327 120965464.000000 +0.279960 0.223729 10.150353 121065472.000000 +-0.128016 0.418744 9.713664 121165456.000000 +-0.099302 0.514457 10.025927 121265472.000000 +-0.135194 0.406780 10.437491 121365464.000000 +-0.019143 0.453440 10.516455 121465472.000000 +-0.020339 0.417548 10.144372 121565528.000000 +-0.029910 0.410369 9.839286 121665472.000000 +-0.023928 0.425922 10.132407 121765568.000000 +-0.282353 0.381655 9.900303 121865472.000000 +-0.133998 0.288335 10.010373 121965448.000000 +0.154337 0.303888 10.092925 122065528.000000 +-0.011964 0.276371 10.249657 122165888.000000 +0.003589 0.220140 10.013963 122265448.000000 +0.283549 0.334995 10.491331 122365512.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/gyro.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/gyro.txt new file mode 100755 index 0000000..860e091 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/gyro.txt @@ -0,0 +1,128 @@ +1.890000 0.472500 -0.472500 109620704.000000 +-1.470000 -3.307500 -30.835001 109720408.000000 +-4.182500 -0.717500 3.430000 109820512.000000 +-5.162500 0.157500 3.185000 109920608.000000 +-6.510000 -0.052500 3.097500 110020624.000000 +-5.180000 -0.297500 3.640000 110120432.000000 +-4.550000 0.017500 3.220000 110220384.000000 +-5.180000 0.437500 2.835000 110320384.000000 +-5.670000 -1.032500 2.695000 110420384.000000 +-5.547500 -1.802500 4.095000 110520416.000000 +-11.917500 -6.877500 8.750000 110620384.000000 +-14.595000 1.872500 -10.027500 110720384.000000 +-8.155000 -15.137500 -11.200000 110820384.000000 +7.945000 0.052500 -19.879999 110920384.000000 +-3.640000 30.957500 -57.505001 111020384.000000 +-30.309999 -14.332500 -42.752499 111120464.000000 +9.905000 12.127500 -12.092500 111220376.000000 +1.890000 4.777500 0.577500 111320368.000000 +6.090000 5.267500 0.087500 111420384.000000 +-6.282500 -1.557500 4.077500 111520392.000000 +-7.315000 -1.767500 2.957500 111620384.000000 +-6.895000 -3.237500 3.237500 111720384.000000 +-3.045000 0.332500 -0.735000 111820384.000000 +-3.360000 -0.577500 1.242500 111920408.000000 +-5.757500 -1.837500 1.820000 112020400.000000 +-6.772500 4.707500 -3.185000 112120392.000000 +-26.337500 19.547501 0.000000 112220376.000000 +-6.335000 2.327500 20.877501 112320376.000000 +11.007500 -6.562500 29.855000 112420376.000000 +-23.065001 3.377500 40.180000 112520392.000000 +-4.217500 0.507500 20.020000 112620456.000000 +7.017500 -11.497500 -13.282500 112720392.000000 +-4.322500 3.692500 -2.135000 112820376.000000 +-1.015000 -6.457500 -4.707500 112920384.000000 +-7.875000 -5.687500 3.237500 113020384.000000 +-8.837500 -5.092500 1.872500 113120384.000000 +-5.845000 -1.732500 6.125000 113220384.000000 +-2.082500 -3.412500 4.515000 113320376.000000 +-2.992500 0.752500 3.850000 113420704.000000 +-2.747500 -2.992500 2.677500 113520392.000000 +-5.687500 -0.227500 3.395000 113620384.000000 +-4.427500 0.787500 6.527500 113720384.000000 +-9.782500 -0.682500 5.285000 113820384.000000 +-5.915000 2.957500 3.500000 113920384.000000 +-7.192500 2.012500 5.705000 114020384.000000 +-5.005000 -4.707500 13.212500 114120456.000000 +-0.612500 -9.467500 32.392502 114220376.000000 +-23.082500 -19.862499 29.855000 114320624.000000 +6.072500 -8.452500 -15.820000 114420472.000000 +21.735001 -18.287500 -89.022499 114520512.000000 +-22.645000 3.762500 -103.687500 114620480.000000 +10.902500 28.787500 -26.320000 114720456.000000 +-36.610001 1.802500 20.860001 114820504.000000 +-10.360000 6.842500 16.764999 114920384.000000 +-3.850000 -1.277500 6.387500 115020368.000000 +-6.790000 -1.767500 2.607500 115120368.000000 +-0.420000 -2.572500 4.095000 115220376.000000 +1.627500 0.647500 -0.507500 115320376.000000 +-14.490000 -3.447500 2.152500 115420360.000000 +-3.325000 19.897501 0.822500 115520384.000000 +-28.139999 14.367500 17.500000 115620448.000000 +6.002500 37.502499 32.305000 115720424.000000 +-12.022500 -5.302500 24.850000 115820408.000000 +12.232500 -2.852500 4.952500 115920416.000000 +-10.167500 -22.172501 16.117500 116020416.000000 +-8.452500 -9.362500 5.582500 116120632.000000 +0.542500 -7.577500 4.392500 116220408.000000 +-8.995000 -3.937500 1.225000 116320384.000000 +-4.847500 -6.667500 -1.032500 116420376.000000 +-10.640000 5.407500 0.770000 116520416.000000 +-4.795000 1.277500 3.185000 116620368.000000 +-2.782500 2.467500 2.922500 116720376.000000 +-5.285000 0.052500 4.707500 116820368.000000 +-3.412500 0.472500 5.862500 116920384.000000 +-7.122500 2.887500 7.297500 117020376.000000 +-13.422500 14.752501 22.504999 117120560.000000 +-16.852501 -4.812500 8.487500 117220416.000000 +8.907500 -28.507500 -40.564999 117320392.000000 +35.892502 17.867500 -23.327499 117420376.000000 +-39.777500 -36.417500 -57.994999 117520416.000000 +-5.302500 9.957500 -8.750000 117620384.000000 +-23.625000 6.807500 20.440001 117720384.000000 +4.532500 17.587500 -3.850000 117820392.000000 +3.850000 3.587500 -2.187500 117920400.000000 +2.450000 4.357500 -2.747500 118020400.000000 +-7.892500 2.152500 1.120000 118120384.000000 +-5.810000 4.007500 1.960000 118220408.000000 +-0.175000 8.872500 1.732500 118320376.000000 +-4.217500 9.467500 5.705000 118420384.000000 +-8.487500 9.327500 -1.872500 118520392.000000 +3.150000 -10.937500 22.960001 118620456.000000 +-24.622499 -34.352501 56.420002 118720416.000000 +20.965000 21.017500 19.547501 118820400.000000 +-7.472500 3.657500 0.735000 118920376.000000 +-0.805000 -1.872500 9.362500 119020376.000000 +-1.820000 -7.787500 10.150000 119120384.000000 +2.607500 -2.607500 2.992500 119220376.000000 +-0.700000 0.437500 4.287500 119320376.000000 +-0.070000 -8.172500 2.415000 119420472.000000 +-0.962500 5.512500 1.207500 119520504.000000 +-6.860000 0.227500 8.067500 119620504.000000 +-12.635000 1.137500 6.090000 119720512.000000 +-10.972500 -1.067500 2.432500 119820464.000000 +-8.715000 1.242500 3.132500 119920512.000000 +-10.272500 1.102500 2.012500 120020504.000000 +-8.260000 1.137500 1.977500 120120640.000000 +-9.222500 1.977500 2.240000 120220472.000000 +-8.715000 5.267500 3.465000 120320504.000000 +-14.892500 -4.637500 6.527500 120420504.000000 +-4.112500 -1.032500 5.442500 120520504.000000 +-3.255000 0.122500 7.000000 120620496.000000 +-6.632500 -0.682500 5.005000 120720480.000000 +-6.930000 2.012500 2.082500 120820464.000000 +-9.520000 -1.207500 2.695000 120920488.000000 +-3.010000 -4.462500 3.517500 121020472.000000 +-0.612500 -4.742500 4.007500 121120480.000000 +-6.457500 1.697500 3.972500 121220472.000000 +-7.017500 1.942500 2.327500 121320480.000000 +-5.897500 1.207500 2.625000 121420464.000000 +-3.272500 -1.522500 2.362500 121520512.000000 +-2.327500 0.157500 1.627500 121620568.000000 +-6.772500 -0.367500 2.695000 121720480.000000 +-5.635000 0.612500 3.622500 121820496.000000 +-9.292500 -2.012500 6.265000 121920480.000000 +-6.982500 1.522500 4.025000 122020472.000000 +-5.547500 -0.087500 2.625000 122120744.000000 +-4.550000 -1.067500 3.237500 122221168.000000 +-6.790000 -1.907500 2.747500 122320592.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/magnetic.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/magnetic.txt new file mode 100755 index 0000000..e334e50 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_y/magnetic.txt @@ -0,0 +1,127 @@ +23.562500 -37.437500 -13.750000 109624992.000000 +23.625000 -37.687500 -13.375000 109724992.000000 +23.375000 -38.812500 -12.625000 109824992.000000 +23.187500 -38.437500 -12.875000 109924992.000000 +23.062500 -38.687500 -13.000000 110024992.000000 +22.687500 -38.812500 -12.875000 110124992.000000 +22.500000 -38.750000 -12.812500 110224992.000000 +22.812500 -38.437500 -12.875000 110324992.000000 +22.875000 -38.625000 -12.750000 110424992.000000 +22.687500 -38.625000 -12.625000 110524992.000000 +22.687500 -38.625000 -12.812500 110624992.000000 +22.750000 -38.750000 -13.375000 110724992.000000 +22.812500 -39.375000 -13.375000 110824992.000000 +23.937500 -40.500000 -13.437500 110924992.000000 +26.312500 -40.875000 -13.187500 111024992.000000 +29.187500 -41.062500 -13.062500 111124992.000000 +32.125000 -41.062500 -12.625000 111224992.000000 +35.125000 -41.125000 -12.250000 111324992.000000 +38.250000 -41.062500 -11.375000 111424992.000000 +41.250000 -41.062500 -10.312500 111524992.000000 +44.125000 -40.312500 -9.312500 111624992.000000 +46.062500 -39.250000 -8.687500 111724992.000000 +46.750000 -38.625000 -8.437500 111824992.000000 +46.812500 -38.437500 -7.812500 111924992.000000 +46.625000 -38.437500 -7.687500 112024992.000000 +46.562500 -38.250000 -7.562500 112124992.000000 +46.000000 -38.437500 -8.125000 112224992.000000 +44.500000 -38.750000 -8.875000 112324992.000000 +42.000000 -38.812500 -9.687500 112424992.000000 +39.500000 -38.437500 -10.250000 112524992.000000 +37.375000 -38.125000 -10.812500 112624992.000000 +35.250000 -37.812500 -11.437500 112724992.000000 +33.062500 -37.500000 -12.000000 112824992.000000 +31.062500 -37.125000 -12.375000 112924992.000000 +29.187500 -36.437500 -12.562500 113024992.000000 +28.375000 -35.562500 -12.500000 113124992.000000 +28.562500 -35.000000 -12.500000 113224992.000000 +28.750000 -34.750000 -12.625000 113324992.000000 +28.750000 -34.750000 -12.562500 113424992.000000 +28.437500 -34.625000 -12.750000 113524992.000000 +28.312500 -34.500000 -12.687500 113624992.000000 +28.062500 -34.437500 -12.937500 113724992.000000 +28.000000 -34.437500 -13.000000 113824992.000000 +27.937500 -34.500000 -13.062500 113924992.000000 +27.750000 -34.812500 -13.125000 114024992.000000 +27.437500 -35.125000 -13.000000 114124992.000000 +26.375000 -35.625000 -13.250000 114224992.000000 +26.062500 -36.375000 -13.875000 114324992.000000 +26.937500 -37.750000 -14.000000 114424992.000000 +29.500000 -37.687500 -13.687500 114524992.000000 +32.312500 -36.875000 -13.062500 114624992.000000 +35.062500 -35.937500 -12.437500 114724992.000000 +38.000000 -35.437500 -11.750000 114824992.000000 +40.687500 -34.812500 -11.187500 114924992.000000 +44.000000 -33.875000 -10.625000 115024992.000000 +46.937500 -32.625000 -9.375000 115124992.000000 +48.812500 -30.937500 -8.937500 115224992.000000 +49.000000 -30.625000 -8.812500 115324992.000000 +48.562500 -31.000000 -8.875000 115424992.000000 +48.125000 -32.187500 -9.312500 115524992.000000 +46.250000 -33.062500 -9.875000 115624992.000000 +44.375000 -33.375000 -10.375000 115724992.000000 +42.437500 -33.687500 -10.750000 115824992.000000 +40.375000 -33.875000 -11.437500 115924992.000000 +38.125000 -33.937500 -11.937500 116024992.000000 +35.812500 -34.437500 -12.312500 116124992.000000 +33.625000 -34.312500 -12.875000 116224992.000000 +31.687500 -33.562500 -13.187500 116324992.000000 +30.937500 -32.750000 -13.125000 116424992.000000 +30.750000 -32.687500 -13.125000 116524992.000000 +30.625000 -32.562500 -13.125000 116624992.000000 +30.625000 -32.500000 -13.250000 116724992.000000 +30.625000 -32.625000 -13.125000 116824992.000000 +30.625000 -32.312500 -13.062500 116924992.000000 +30.687500 -32.437500 -13.125000 117024992.000000 +30.312500 -32.875000 -13.250000 117124992.000000 +30.562500 -33.875000 -13.500000 117224992.000000 +32.562500 -34.687500 -13.062500 117324992.000000 +34.812500 -34.500000 -12.625000 117424992.000000 +37.062500 -34.312500 -12.000000 117524992.000000 +39.062500 -34.187500 -11.562500 117624992.000000 +41.562500 -34.187500 -11.250000 117724992.000000 +43.875000 -34.000000 -10.500000 117824992.000000 +46.437500 -33.562500 -9.500000 117924992.000000 +48.687500 -32.187500 -8.562500 118024992.000000 +49.125000 -31.125000 -8.312500 118124992.000000 +49.187500 -31.187500 -8.062500 118224992.000000 +49.187500 -31.062500 -7.750000 118324992.000000 +49.562500 -31.000000 -7.562500 118424992.000000 +49.125000 -31.250000 -7.125000 118524992.000000 +48.250000 -32.125000 -7.437500 118624992.000000 +46.062500 -32.875000 -8.312500 118724992.000000 +43.625000 -33.812500 -8.875000 118824992.000000 +41.375000 -34.375000 -9.312500 118924992.000000 +38.937500 -34.875000 -10.125000 119024992.000000 +36.375000 -35.562500 -11.000000 119124992.000000 +33.750000 -35.875000 -11.375000 119224992.000000 +31.375000 -36.125000 -12.000000 119324992.000000 +30.000000 -35.687500 -12.062500 119424992.000000 +29.750000 -35.625000 -11.625000 119524992.000000 +29.750000 -35.500000 -11.687500 119624992.000000 +29.437500 -35.562500 -12.187500 119724992.000000 +29.312500 -35.625000 -12.062500 119824992.000000 +29.375000 -35.687500 -12.000000 119924992.000000 +29.375000 -36.000000 -12.312500 120024992.000000 +29.500000 -36.000000 -12.687500 120124992.000000 +29.375000 -36.062500 -12.875000 120224992.000000 +29.500000 -36.062500 -13.062500 120324992.000000 +29.437500 -35.812500 -13.250000 120424992.000000 +29.250000 -35.750000 -13.062500 120524992.000000 +29.062500 -35.750000 -13.375000 120624992.000000 +28.875000 -35.750000 -13.437500 120724992.000000 +28.625000 -35.437500 -13.562500 120824992.000000 +28.562500 -35.500000 -13.750000 120924992.000000 +28.250000 -35.437500 -13.875000 121024992.000000 +27.937500 -35.375000 -14.187500 121124992.000000 +27.625000 -35.562500 -14.250000 121224992.000000 +27.625000 -35.812500 -14.500000 121324992.000000 +27.625000 -35.812500 -14.562500 121424992.000000 +27.687500 -36.062500 -14.562500 121524992.000000 +27.625000 -36.250000 -14.500000 121624992.000000 +27.375000 -36.312500 -14.250000 121724992.000000 +27.375000 -36.375000 -14.500000 121824992.000000 +27.312500 -36.562500 -14.625000 121924992.000000 +27.000000 -36.500000 -14.625000 122124992.000000 +26.937500 -36.625000 -14.687500 122224992.000000 +26.812500 -36.437500 -14.812500 122324992.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/accel.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/accel.txt new file mode 100755 index 0000000..15d5d71 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/accel.txt @@ -0,0 +1,183 @@ +0.114855 0.102891 10.100104 728390400.000000 +0.151944 0.129212 10.143176 728490496.000000 +0.173480 0.104088 10.150353 728590528.000000 +0.122034 0.133998 10.140782 728690624.000000 +0.156730 0.132802 10.161121 728790528.000000 +0.147159 0.131605 10.182656 728890752.000000 +0.142373 0.106481 10.177871 728990528.000000 +0.159123 0.112463 10.155140 729090560.000000 +0.162712 0.099302 10.180264 729190528.000000 +0.167498 0.130409 10.177871 729290560.000000 +0.141177 0.111266 10.226924 729390464.000000 +0.136391 0.135194 10.147961 729490624.000000 +0.125623 0.126820 10.126426 729590528.000000 +0.159123 0.144766 10.164711 729690624.000000 +0.150748 0.142373 10.170692 729790464.000000 +0.100499 0.129212 10.141978 729890560.000000 +0.144766 0.125623 10.181459 729990464.000000 +0.111266 0.126820 10.182656 730090560.000000 +0.145962 0.144766 10.182656 730190464.000000 +0.139980 0.142373 10.161121 730290560.000000 +0.162712 0.148355 10.185050 730390592.000000 +0.133998 0.131605 10.150353 730490560.000000 +0.161516 0.135194 10.224532 730590528.000000 +0.173480 0.118445 10.141978 730690496.000000 +0.161516 0.101695 10.205389 730790464.000000 +0.143569 0.141177 10.198210 730890560.000000 +0.306281 0.189033 10.171888 730990528.000000 +0.131605 0.107677 10.244871 731090560.000000 +0.356531 -0.010768 10.868200 731190464.000000 +-0.674776 -0.307478 11.479566 731290560.000000 +-1.259821 -0.903291 10.462617 731390464.000000 +0.027517 -1.137787 11.156535 731490560.000000 +0.582652 -0.853041 11.491530 731590464.000000 +-1.030110 0.177069 12.045469 731690496.000000 +-0.200997 0.760918 11.010573 731790464.000000 +2.090131 0.801596 10.954341 731890688.000000 +1.016950 1.293321 8.823533 731990464.000000 +1.440479 1.213161 7.247860 732090624.000000 +1.186840 1.259821 7.633104 732190528.000000 +1.561317 1.173679 7.854440 732290560.000000 +0.555135 1.507478 8.353344 732390528.000000 +1.018146 0.671187 9.801002 732490560.000000 +0.979861 0.613759 8.854640 732590464.000000 +1.360320 0.873380 10.094121 732690496.000000 +-0.666401 0.574277 10.467402 732790528.000000 +-0.692722 0.229711 11.028521 732890496.000000 +-1.375873 -0.089731 11.320443 732990528.000000 +0.844666 -0.863809 12.251251 733090496.000000 +-2.315056 -0.794417 9.308081 733190464.000000 +0.312263 -0.059821 10.158729 733290560.000000 +0.180658 0.066999 10.152746 733390592.000000 +0.168694 0.063410 10.192227 733490560.000000 +0.132802 0.086142 10.451849 733590464.000000 +0.175872 0.099302 10.217353 733690496.000000 +0.175872 0.111266 10.128819 733790464.000000 +0.203390 0.101695 10.192227 733890496.000000 +0.169890 0.105284 10.161121 733990528.000000 +0.187837 0.078963 10.214959 734090560.000000 +0.178265 0.123230 10.153944 734190464.000000 +0.196211 0.083749 10.173084 734290496.000000 +0.202193 0.089731 10.174281 734390464.000000 +0.173480 0.106481 10.161121 734490560.000000 +0.195015 0.113659 10.208978 734590464.000000 +0.148355 0.086142 10.094121 734690560.000000 +0.132802 0.089731 10.120443 734790464.000000 +0.187837 0.108873 10.140782 734890688.000000 +0.123230 0.102891 10.189835 734990464.000000 +0.117248 0.093320 10.179067 735090560.000000 +0.099302 0.101695 10.198210 735190464.000000 +0.211765 0.050249 10.346564 735290496.000000 +0.075374 -0.802792 13.761123 735390464.000000 +-0.675972 -0.771685 13.362719 735490560.000000 +-0.530010 -1.214357 12.378072 735590464.000000 +0.291924 -1.441676 11.819347 735690560.000000 +1.306481 -0.300299 8.915657 735790464.000000 +2.524428 0.113659 6.929615 735890560.000000 +2.382055 0.105284 6.480960 735990528.000000 +1.475175 0.677169 8.743374 736090560.000000 +2.380858 0.324227 7.613962 736190528.000000 +1.101895 0.343370 10.085747 736290560.000000 +-0.486939 0.385244 6.634101 736390592.000000 +0.480957 0.218943 8.067402 736490560.000000 +-0.171087 0.265603 8.874979 736590464.000000 +0.977468 -0.196211 11.708081 736690560.000000 +-0.522832 -1.200001 11.339586 736790528.000000 +-0.368495 -1.123430 14.310277 736890560.000000 +0.178265 -0.297906 8.699106 736990464.000000 +1.338784 -0.218943 10.252048 737090560.000000 +0.212961 0.111266 9.987641 737190464.000000 +0.133998 0.117248 10.151550 737290496.000000 +0.122034 0.122034 10.162319 737390528.000000 +0.156730 0.122034 10.201799 737490560.000000 +0.145962 0.123230 10.135997 737590528.000000 +0.149551 0.151944 10.141978 737690560.000000 +0.156730 0.131605 10.171888 737790464.000000 +0.162712 0.136391 10.138390 737890752.000000 +0.124427 0.145962 10.162319 737990464.000000 +0.154337 0.143569 10.134801 738090496.000000 +0.136391 0.143569 10.193424 738190464.000000 +0.148355 0.150748 10.140782 738290496.000000 +0.136391 0.139980 10.177871 738390464.000000 +0.175872 0.150748 10.159925 738490560.000000 +0.150748 0.104088 10.167104 738590528.000000 +0.160319 0.111266 10.141978 738690560.000000 +0.169890 0.128016 10.219746 738790464.000000 +0.174676 0.150748 10.137194 738890560.000000 +0.133998 0.149551 10.162319 738990528.000000 +0.022732 0.096909 10.223334 739090560.000000 +0.157926 0.122034 10.144372 739190528.000000 +0.047856 -0.118445 10.191031 739290496.000000 +0.320638 -0.303888 10.345367 739390592.000000 +-1.144966 -1.384248 14.679967 739490560.000000 +1.143769 -0.887737 16.286747 739590464.000000 +2.104487 -2.044667 13.148561 739690560.000000 +1.125823 -1.150948 10.589437 739790464.000000 +0.806381 -0.260818 5.862415 739890496.000000 +0.047856 0.905683 3.601198 739990528.000000 +2.098505 1.256232 4.718646 740090560.000000 +0.898505 1.452443 9.875179 740190528.000000 +1.935793 0.964308 9.655040 740290560.000000 +0.744168 1.144966 9.658628 740390464.000000 +-1.048056 2.019542 7.960921 740490496.000000 +1.263410 1.606780 7.347162 740590464.000000 +1.014557 0.915255 8.461020 740690496.000000 +1.438086 -0.137587 10.022337 740790528.000000 +1.764707 -0.253639 10.748559 740890688.000000 +1.592424 -0.662812 11.239087 740990464.000000 +0.569492 -0.896112 15.446867 741090624.000000 +-0.277567 -0.739382 12.169895 741190528.000000 +1.149751 -0.326620 12.220145 741290560.000000 +0.650848 0.111266 10.157533 741390464.000000 +-0.440279 -0.381655 11.070394 741490496.000000 +0.124427 0.151944 10.195816 741590528.000000 +0.126820 0.133998 10.175477 741690560.000000 +0.132802 0.132802 10.156336 741790464.000000 +0.148355 0.123230 10.156336 741890496.000000 +0.130409 0.145962 10.180264 741990528.000000 +0.173480 0.131605 10.171888 742090560.000000 +0.136391 0.133998 10.156336 742190464.000000 +0.145962 0.144766 10.153944 742290496.000000 +0.165105 0.144766 10.152746 742390592.000000 +0.122034 0.143569 10.174281 742490560.000000 +0.159123 0.131605 10.150353 742590464.000000 +0.150748 0.122034 10.188639 742690560.000000 +0.135194 0.151944 10.084551 742790464.000000 +0.154337 0.116052 10.169496 742890496.000000 +0.147159 0.150748 10.104890 742990464.000000 +0.156730 0.138784 10.146765 743090560.000000 +0.139980 0.130409 10.193424 743190464.000000 +0.162712 0.154337 10.155140 743290560.000000 +0.148355 0.136391 10.158729 743390528.000000 +0.144766 0.149551 10.127622 743490560.000000 +0.155533 0.136391 10.189835 743590528.000000 +0.153141 0.166301 10.173084 743690560.000000 +0.151944 0.154337 10.135997 743790464.000000 +0.151944 0.154337 10.163515 743890688.000000 +0.148355 0.168694 10.135997 743990464.000000 +0.138784 0.139980 10.173084 744090496.000000 +0.132802 0.173480 10.191031 744190464.000000 +0.163908 0.142373 10.158729 744290496.000000 +0.112463 0.153141 10.141978 744390464.000000 +0.157926 0.144766 10.199407 744490560.000000 +0.144766 0.122034 10.163515 744590528.000000 +0.149551 0.154337 10.118051 744690560.000000 +0.143569 0.119641 10.164711 744790464.000000 +0.167498 0.144766 10.128819 744890560.000000 +0.156730 0.122034 10.146765 744990464.000000 +0.150748 0.163908 10.171888 745090496.000000 +0.139980 0.132802 10.199407 745190528.000000 +0.133998 0.150748 10.188639 745290560.000000 +0.126820 0.142373 10.106087 745390656.000000 +0.147159 0.155533 10.174281 745490560.000000 +0.144766 0.154337 10.137194 745590464.000000 +0.160319 0.139980 10.133603 745690496.000000 +0.148355 0.157926 10.146765 745790528.000000 +0.163908 0.155533 10.162319 745890496.000000 +0.130409 0.169890 10.173084 745990464.000000 +0.137587 0.157926 10.150353 746090560.000000 +0.126820 0.123230 10.176675 746190464.000000 +0.149551 0.154337 10.100104 746290560.000000 +0.141177 0.156730 10.149158 746390464.000000 +0.163908 0.167498 10.126426 746490560.000000 +0.157926 0.112463 10.113264 746590464.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/gyro.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/gyro.txt new file mode 100755 index 0000000..d36ffc3 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/gyro.txt @@ -0,0 +1,183 @@ +1.890000 0.472500 -0.472500 728335488.000000 +-1.855000 1.417500 -34.177502 728435456.000000 +-4.830000 0.087500 2.222500 728535488.000000 +-4.795000 0.087500 2.222500 728635520.000000 +-4.795000 0.087500 2.257500 728735488.000000 +-4.847500 0.122500 2.275000 728835456.000000 +-4.847500 0.122500 2.275000 728935488.000000 +-4.847500 0.122500 2.275000 729035456.000000 +-4.812500 0.122500 2.292500 729135488.000000 +-4.865000 0.122500 2.240000 729235456.000000 +-4.882500 0.122500 2.240000 729335488.000000 +-4.847500 0.122500 2.240000 729435456.000000 +-4.847500 0.122500 2.257500 729535488.000000 +-4.865000 0.122500 2.275000 729635520.000000 +-4.847500 0.087500 2.257500 729735488.000000 +-4.865000 0.087500 2.257500 729835584.000000 +-4.865000 0.087500 2.257500 729935552.000000 +-4.830000 0.122500 2.257500 730035520.000000 +-4.847500 -0.262500 2.257500 730135488.000000 +-4.865000 0.122500 2.275000 730235456.000000 +-4.830000 0.367500 2.275000 730335488.000000 +-4.830000 0.192500 2.275000 730435456.000000 +-4.742500 -1.662500 2.310000 730535488.000000 +-4.602500 -0.227500 2.240000 730635456.000000 +-4.795000 0.647500 2.205000 730735488.000000 +-4.917500 2.642500 1.330000 730835456.000000 +-5.425000 2.537500 -0.805000 730935488.000000 +-6.195000 1.872500 -0.892500 731035456.000000 +-12.145000 -0.857500 1.382500 731135488.000000 +-34.107502 -6.352500 -4.462500 731235456.000000 +-2.642500 2.327500 -0.210000 731335680.000000 +-7.665000 -6.282500 3.290000 731435456.000000 +-3.920000 -1.767500 0.332500 731535552.000000 +11.427500 4.532500 1.382500 731635520.000000 +28.174999 -9.117500 11.987500 731735552.000000 +19.985001 -17.412500 11.707500 731835520.000000 +38.255001 -28.682501 -2.047500 731935552.000000 +11.112500 -6.142500 -6.317500 732035520.000000 +1.417500 -8.627500 -6.650000 732135488.000000 +-6.405000 2.537500 2.975000 732235456.000000 +-2.712500 10.762500 6.720000 732335488.000000 +-29.575001 12.512500 16.047501 732435456.000000 +-23.537500 19.652500 24.710001 732535488.000000 +-5.687500 11.427500 18.934999 732635456.000000 +-12.057500 22.102501 3.447500 732735552.000000 +-28.070000 15.837500 -12.372500 732835584.000000 +-32.584999 7.717500 -10.307500 732935552.000000 +-27.177500 2.607500 -8.907500 733035456.000000 +-20.195000 -5.442500 -9.730000 733135488.000000 +27.072500 -29.102501 -18.707500 733235456.000000 +-1.610000 3.412500 -3.937500 733335488.000000 +-3.745000 3.482500 3.412500 733435520.000000 +-3.675000 0.787500 5.022500 733535488.000000 +-4.270000 -3.027500 2.397500 733635456.000000 +-4.567500 2.012500 2.082500 733735488.000000 +-4.707500 -0.122500 2.240000 733835456.000000 +-4.760000 -0.052500 2.240000 733935488.000000 +-4.777500 -0.017500 2.275000 734035456.000000 +-4.795000 -0.052500 2.257500 734135488.000000 +-4.812500 -0.017500 2.275000 734235456.000000 +-4.847500 0.017500 2.275000 734335680.000000 +-4.830000 0.052500 2.257500 734435456.000000 +-4.882500 0.367500 2.257500 734535488.000000 +-4.795000 1.522500 2.170000 734635456.000000 +-4.812500 0.927500 2.257500 734735488.000000 +-4.830000 0.437500 2.292500 734835456.000000 +-4.847500 -0.332500 2.275000 734935488.000000 +-4.830000 0.332500 2.292500 735035456.000000 +-4.812500 1.767500 2.275000 735135488.000000 +-5.162500 2.257500 2.222500 735235456.000000 +-8.277500 2.467500 6.475000 735335488.000000 +-43.365002 2.817500 20.160000 735435456.000000 +-44.362499 2.537500 3.710000 735535488.000000 +-6.230000 -5.932500 4.812500 735635520.000000 +-12.740000 -28.717501 4.445000 735735488.000000 +71.294998 -37.852501 10.062500 735835584.000000 +33.670002 -28.332500 -1.452500 735935488.000000 +6.615000 2.922500 -6.072500 736035456.000000 +-12.897500 3.797500 -9.590000 736135488.000000 +14.157500 1.382500 8.890000 736235456.000000 +-23.467501 8.382500 15.382500 736335488.000000 +28.035000 17.342501 21.472500 736435456.000000 +-20.510000 34.562500 10.745000 736535552.000000 +-32.707500 14.297500 2.257500 736635520.000000 +-44.747501 33.407501 2.257500 736735488.000000 +-7.910000 5.442500 -14.962500 736835456.000000 +-44.467499 -6.387500 -10.640000 736935488.000000 +61.635002 -23.642500 -4.007500 737035456.000000 +-5.145000 -4.917500 -2.275000 737135552.000000 +-2.117500 6.877500 -9.502500 737235520.000000 +-4.392500 1.382500 2.257500 737335680.000000 +-4.637500 0.052500 2.275000 737435456.000000 +-4.672500 0.227500 2.275000 737535488.000000 +-4.777500 0.122500 2.292500 737635456.000000 +-4.777500 0.087500 2.275000 737735488.000000 +-4.847500 0.087500 2.292500 737835456.000000 +-4.847500 0.052500 2.292500 737935488.000000 +-4.812500 0.087500 2.292500 738035456.000000 +-4.830000 0.087500 2.327500 738135488.000000 +-4.847500 0.087500 2.310000 738235520.000000 +-4.830000 0.052500 2.327500 738335488.000000 +-4.847500 0.122500 2.292500 738435456.000000 +-4.830000 0.122500 2.292500 738535488.000000 +-4.847500 0.122500 2.275000 738635456.000000 +-4.847500 0.087500 2.275000 738735488.000000 +-4.865000 0.087500 2.275000 738835584.000000 +-4.795000 0.997500 2.240000 738935488.000000 +-4.760000 -0.717500 1.715000 739035456.000000 +-4.620000 0.017500 0.612500 739135552.000000 +-5.530000 0.262500 4.480000 739235456.000000 +-16.607500 5.757500 6.947500 739335488.000000 +-52.920002 46.707500 9.047500 739435456.000000 +-39.235001 -31.657499 26.075001 739535488.000000 +-1.680000 -62.072502 21.805000 739635456.000000 +17.692499 -41.807499 4.077500 739735488.000000 +52.884998 -52.447498 -19.145000 739835456.000000 +31.325001 -15.347500 -28.525000 739935488.000000 +47.915001 33.617500 -2.467500 740035520.000000 +-18.760000 3.342500 -5.127500 740135552.000000 +-4.690000 5.862500 5.845000 740235520.000000 +-25.200001 4.497500 0.577500 740335744.000000 +0.962500 9.887500 16.152500 740435456.000000 +25.585001 23.537500 38.867500 740535552.000000 +-21.629999 18.637501 23.415001 740635456.000000 +-44.152500 19.862499 15.715000 740735552.000000 +-26.565001 32.462502 8.190000 740835456.000000 +-16.695000 14.892500 -13.912500 740935488.000000 +-37.205002 3.517500 -21.822500 741035520.000000 +-13.947500 -1.802500 -18.514999 741135488.000000 +18.305000 3.867500 -3.675000 741235456.000000 +15.330000 -23.432501 -1.347500 741335488.000000 +0.437500 4.602500 -5.215000 741435456.000000 +-3.867500 5.057500 -3.395000 741535488.000000 +-4.585000 0.297500 2.257500 741635456.000000 +-4.690000 0.052500 2.292500 741735488.000000 +-4.742500 0.052500 2.257500 741835584.000000 +-4.760000 0.052500 2.275000 741935488.000000 +-4.812500 0.052500 2.292500 742035456.000000 +-4.760000 0.087500 2.310000 742135488.000000 +-4.830000 0.052500 2.240000 742235456.000000 +-4.847500 0.052500 2.275000 742335488.000000 +-4.865000 0.052500 2.292500 742435520.000000 +-4.830000 0.087500 2.292500 742535488.000000 +-4.830000 0.087500 2.292500 742635456.000000 +-4.830000 0.087500 2.275000 742735488.000000 +-4.900000 0.087500 2.292500 742835456.000000 +-4.952500 0.087500 2.275000 742935552.000000 +-4.900000 0.087500 2.292500 743035520.000000 +-4.865000 0.122500 2.275000 743135488.000000 +-4.865000 0.052500 2.275000 743235456.000000 +-4.847500 0.087500 2.310000 743335616.000000 +-4.847500 0.087500 2.292500 743435456.000000 +-4.865000 0.087500 2.257500 743535488.000000 +-4.882500 0.157500 2.292500 743635456.000000 +-4.865000 0.122500 2.275000 743735488.000000 +-4.847500 0.122500 2.310000 743835456.000000 +-4.865000 0.122500 2.257500 743935488.000000 +-4.882500 0.122500 2.292500 744035520.000000 +-4.900000 0.122500 2.275000 744135552.000000 +-4.865000 0.122500 2.257500 744235520.000000 +-4.865000 0.087500 2.275000 744335488.000000 +-4.882500 0.087500 2.275000 744435520.000000 +-4.882500 0.122500 2.257500 744535488.000000 +-4.900000 0.122500 2.310000 744635520.000000 +-4.900000 0.087500 2.257500 744735488.000000 +-4.865000 0.122500 2.275000 744835584.000000 +-4.847500 0.122500 2.292500 744935488.000000 +-4.865000 0.122500 2.275000 745035520.000000 +-4.847500 0.087500 2.275000 745135488.000000 +-4.882500 0.087500 2.292500 745235456.000000 +-4.847500 0.087500 2.292500 745335488.000000 +-4.865000 0.122500 2.257500 745435456.000000 +-4.847500 0.122500 2.275000 745535552.000000 +-4.882500 0.087500 2.257500 745635456.000000 +-4.865000 0.087500 2.292500 745735488.000000 +-4.882500 0.122500 2.275000 745835456.000000 +-4.865000 0.122500 2.257500 745935488.000000 +-4.830000 0.122500 2.327500 746035456.000000 +-4.882500 0.122500 2.292500 746135488.000000 +-4.830000 0.122500 2.292500 746235456.000000 +-4.865000 0.122500 2.275000 746335616.000000 +-4.882500 0.122500 2.257500 746435456.000000 +-4.882500 0.087500 2.345000 746535488.000000 diff --git a/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/magnetic.txt b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/magnetic.txt new file mode 100755 index 0000000..eab1c61 --- /dev/null +++ b/src/sensor_fusion/design/data/100ms/linear_acceleration/move_z/magnetic.txt @@ -0,0 +1,183 @@ +23.562500 -36.687500 -14.812500 728340864.000000 +23.750000 -36.562500 -15.312500 728440896.000000 +24.000000 -37.687500 -15.562500 728540864.000000 +24.000000 -36.812500 -15.250000 728640896.000000 +24.562500 -36.812500 -15.375000 728740864.000000 +24.312500 -36.750000 -15.437500 728840896.000000 +24.437500 -36.187500 -15.562500 728940864.000000 +24.250000 -36.687500 -15.437500 729040896.000000 +24.437500 -36.812500 -15.312500 729140864.000000 +24.687500 -36.875000 -15.375000 729240896.000000 +24.687500 -36.687500 -15.250000 729340864.000000 +24.875000 -36.875000 -15.125000 729440896.000000 +24.937500 -36.937500 -15.187500 729540864.000000 +25.125000 -37.000000 -15.062500 729640896.000000 +25.125000 -37.000000 -14.937500 729740864.000000 +25.125000 -37.000000 -14.937500 729840896.000000 +25.000000 -36.812500 -15.375000 729940864.000000 +25.000000 -36.875000 -15.062500 730040896.000000 +25.250000 -36.687500 -15.312500 730140864.000000 +25.062500 -36.625000 -15.500000 730240896.000000 +24.875000 -36.562500 -15.562500 730340864.000000 +24.812500 -36.500000 -15.500000 730440896.000000 +24.875000 -36.437500 -15.625000 730540864.000000 +24.812500 -36.562500 -15.750000 730640896.000000 +24.875000 -36.500000 -15.437500 730740864.000000 +24.750000 -36.312500 -15.250000 730840896.000000 +24.687500 -36.500000 -15.125000 730940864.000000 +24.750000 -36.500000 -15.187500 731040896.000000 +24.687500 -36.625000 -15.187500 731140864.000000 +24.875000 -36.687500 -15.375000 731240896.000000 +24.875000 -36.625000 -15.625000 731340864.000000 +24.875000 -36.500000 -15.750000 731440896.000000 +25.000000 -36.687500 -15.875000 731540864.000000 +25.000000 -37.187500 -15.937500 731640896.000000 +24.812500 -37.812500 -15.312500 731740864.000000 +24.750000 -38.500000 -13.937500 731840896.000000 +25.000000 -38.500000 -12.125000 731940864.000000 +25.375000 -38.687500 -10.500000 732040896.000000 +25.812500 -38.812500 -8.750000 732140864.000000 +26.375000 -38.937500 -7.062500 732240896.000000 +26.437500 -39.000000 -5.312500 732340864.000000 +26.250000 -39.250000 -4.187500 732440896.000000 +25.812500 -39.375000 -3.750000 732540864.000000 +25.187500 -39.625000 -4.312500 732640896.000000 +24.750000 -40.000000 -5.250000 732740864.000000 +24.250000 -40.062500 -6.375000 732840896.000000 +23.812500 -40.125000 -7.812500 732940864.000000 +23.250000 -39.937500 -9.375000 733040896.000000 +23.250000 -39.750000 -11.125000 733140864.000000 +23.625000 -39.062500 -12.375000 733240896.000000 +24.375000 -37.937500 -13.250000 733340864.000000 +25.250000 -37.187500 -14.062500 733440896.000000 +25.625000 -36.687500 -14.812500 733540864.000000 +25.875000 -36.437500 -15.125000 733640896.000000 +26.250000 -36.437500 -15.250000 733740864.000000 +26.437500 -36.562500 -15.312500 733840896.000000 +26.437500 -36.562500 -15.312500 733940864.000000 +26.250000 -36.562500 -15.437500 734040896.000000 +26.250000 -36.937500 -15.750000 734140864.000000 +26.250000 -36.812500 -15.750000 734240896.000000 +26.250000 -36.750000 -15.750000 734340864.000000 +26.187500 -36.750000 -15.750000 734440896.000000 +26.000000 -36.625000 -15.812500 734540864.000000 +26.062500 -36.687500 -15.687500 734640896.000000 +26.062500 -36.625000 -15.750000 734740864.000000 +26.125000 -36.687500 -15.812500 734840896.000000 +26.187500 -36.500000 -15.750000 734940864.000000 +26.250000 -36.500000 -15.687500 735040896.000000 +26.250000 -36.437500 -15.625000 735140864.000000 +26.312500 -36.437500 -15.562500 735240896.000000 +26.312500 -36.312500 -15.687500 735340864.000000 +26.250000 -36.187500 -16.125000 735440896.000000 +26.125000 -36.312500 -16.375000 735540864.000000 +25.625000 -36.937500 -16.937500 735640896.000000 +25.250000 -37.625000 -16.187500 735740864.000000 +25.062500 -38.187500 -15.125000 735840896.000000 +25.375000 -38.437500 -14.062500 735940864.000000 +25.687500 -38.375000 -13.187500 736040896.000000 +25.937500 -38.562500 -11.875000 736140864.000000 +25.937500 -38.812500 -10.187500 736240896.000000 +25.625000 -39.062500 -8.500000 736340864.000000 +25.500000 -39.312500 -6.812500 736440896.000000 +24.937500 -39.312500 -7.000000 736540864.000000 +24.250000 -39.062500 -8.187500 736640896.000000 +23.625000 -38.937500 -9.250000 736740864.000000 +23.000000 -38.812500 -10.625000 736840896.000000 +22.437500 -38.937500 -11.687500 736940864.000000 +22.187500 -38.875000 -12.687500 737040896.000000 +22.500000 -38.312500 -14.125000 737140864.000000 +23.062500 -37.437500 -15.000000 737240896.000000 +23.875000 -36.750000 -15.375000 737340864.000000 +24.625000 -36.500000 -15.375000 737440896.000000 +24.875000 -36.375000 -15.500000 737540864.000000 +24.750000 -36.500000 -14.937500 737640896.000000 +24.812500 -36.562500 -15.062500 737740864.000000 +24.937500 -36.437500 -15.250000 737840896.000000 +24.937500 -36.437500 -15.125000 737940864.000000 +25.062500 -36.437500 -15.312500 738040896.000000 +24.937500 -36.500000 -15.500000 738140864.000000 +24.875000 -36.437500 -15.375000 738240896.000000 +24.875000 -36.562500 -15.375000 738340864.000000 +25.125000 -36.500000 -15.500000 738440896.000000 +25.250000 -36.187500 -15.500000 738540864.000000 +25.375000 -36.375000 -15.562500 738640896.000000 +25.437500 -36.437500 -15.562500 738740864.000000 +25.375000 -36.562500 -15.562500 738840896.000000 +25.437500 -36.562500 -15.500000 738940864.000000 +25.250000 -36.437500 -15.562500 739040896.000000 +25.250000 -36.375000 -15.562500 739140864.000000 +25.125000 -36.375000 -15.375000 739240896.000000 +25.125000 -36.562500 -15.312500 739340864.000000 +25.187500 -36.375000 -15.125000 739440896.000000 +24.625000 -36.375000 -15.750000 739540864.000000 +23.500000 -36.562500 -16.062500 739640896.000000 +22.625000 -37.500000 -16.000000 739740864.000000 +22.687500 -37.812500 -15.375000 739840896.000000 +23.000000 -37.937500 -14.437500 739940864.000000 +23.375000 -38.125000 -13.562500 740040896.000000 +23.750000 -38.125000 -12.562500 740140864.000000 +24.125000 -38.250000 -11.687500 740240896.000000 +24.875000 -38.312500 -10.062500 740340864.000000 +26.125000 -38.187500 -8.375000 740440896.000000 +26.812500 -37.687500 -7.125000 740540864.000000 +25.937500 -38.312500 -6.312500 740640896.000000 +24.437500 -38.937500 -6.562500 740740864.000000 +23.250000 -39.250000 -7.312500 740840896.000000 +22.437500 -39.312500 -8.250000 740940864.000000 +21.500000 -39.375000 -9.250000 741040896.000000 +20.937500 -39.250000 -10.625000 741140864.000000 +20.562500 -39.062500 -12.062500 741240896.000000 +20.625000 -38.562500 -13.687500 741340864.000000 +21.312500 -37.812500 -15.000000 741440896.000000 +22.312500 -37.062500 -15.750000 741540864.000000 +23.000000 -36.562500 -16.062500 741640896.000000 +23.312500 -36.312500 -16.187500 741740864.000000 +23.687500 -36.312500 -16.187500 741840896.000000 +23.875000 -36.375000 -15.750000 741940864.000000 +23.875000 -36.312500 -15.375000 742040896.000000 +23.812500 -36.437500 -15.250000 742140864.000000 +23.937500 -36.437500 -15.062500 742240896.000000 +24.062500 -36.625000 -14.812500 742340864.000000 +23.875000 -36.687500 -14.750000 742440896.000000 +23.812500 -36.875000 -14.625000 742540864.000000 +23.500000 -36.750000 -14.687500 742640896.000000 +23.375000 -36.875000 -15.062500 742740864.000000 +23.500000 -36.937500 -15.312500 742840896.000000 +23.437500 -36.875000 -15.187500 742940864.000000 +23.500000 -36.937500 -15.187500 743040896.000000 +23.500000 -36.937500 -15.437500 743140864.000000 +23.750000 -36.937500 -15.437500 743240896.000000 +23.812500 -37.062500 -15.562500 743340864.000000 +24.125000 -37.000000 -15.375000 743440896.000000 +24.250000 -36.937500 -15.062500 743540864.000000 +24.250000 -37.125000 -14.937500 743640896.000000 +24.500000 -37.187500 -15.250000 743740864.000000 +24.375000 -37.125000 -15.187500 743840896.000000 +24.125000 -37.125000 -14.937500 743940864.000000 +23.937500 -37.062500 -14.937500 744040896.000000 +23.937500 -36.875000 -15.062500 744140864.000000 +23.750000 -36.937500 -15.062500 744240896.000000 +23.687500 -36.812500 -15.062500 744340864.000000 +23.500000 -36.937500 -15.187500 744440896.000000 +23.812500 -36.812500 -15.062500 744540864.000000 +23.875000 -36.937500 -14.937500 744640896.000000 +23.937500 -36.875000 -15.062500 744740864.000000 +23.937500 -36.750000 -15.125000 744840896.000000 +23.875000 -36.937500 -14.937500 744940864.000000 +24.250000 -36.875000 -14.937500 745040896.000000 +24.187500 -36.875000 -15.187500 745140864.000000 +24.125000 -36.812500 -15.250000 745240896.000000 +23.937500 -36.812500 -15.187500 745340864.000000 +23.750000 -36.687500 -15.500000 745440896.000000 +23.875000 -36.625000 -15.375000 745540864.000000 +24.062500 -36.750000 -15.375000 745640896.000000 +23.937500 -36.500000 -15.375000 745740864.000000 +23.687500 -36.562500 -15.312500 745840896.000000 +23.687500 -36.500000 -15.250000 745940864.000000 +23.687500 -36.562500 -15.000000 746040896.000000 +23.687500 -36.375000 -15.062500 746140864.000000 +23.812500 -36.125000 -15.125000 746240896.000000 +23.937500 -36.187500 -15.312500 746340864.000000 +23.812500 -36.125000 -15.250000 746440896.000000 +23.937500 -36.250000 -15.250000 746540864.000000 diff --git a/src/sensor_fusion/design/lib/estimate_gravity.m b/src/sensor_fusion/design/lib/estimate_gravity.m index 5f62c4d..0531a17 100755 --- a/src/sensor_fusion/design/lib/estimate_gravity.m +++ b/src/sensor_fusion/design/lib/estimate_gravity.m @@ -36,10 +36,10 @@ Gravity = zeros(3,BUFFER_SIZE); % estimate orientation [OR_driv, OR_aid, OR_err] = estimate_orientation(Accel_data, Gyro_data, Mag_data); -Gx = GRAVITY * -sind(OR_driv(1,:)); +Gx = GRAVITY * sind(OR_driv(1,:)); Gy = GRAVITY * sind(OR_driv(2,:)); Gz = GRAVITY * cosd(OR_driv(2,:)) .* cosd(OR_driv(1,:)); Gravity = [Gx; Gy; Gz]; -end \ No newline at end of file +end diff --git a/src/sensor_fusion/design/lib/estimate_linear_acceleration.m b/src/sensor_fusion/design/lib/estimate_linear_acceleration.m new file mode 100755 index 0000000..0ac6735 --- /dev/null +++ b/src/sensor_fusion/design/lib/estimate_linear_acceleration.m @@ -0,0 +1,36 @@ +% estimate_linear_acceleration +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Linear Acceleration Estimation function +% +% - Gravity estimation using the estimate_gravity function +% - compute linear acceleration based gravitational force computed for each axes + +function [Linear_Acceleration] = estimate_linear_acceleration(Accel_data, Gyro_data, Mag_data) + +GRAVITY = 9.80665; + +BUFFER_SIZE = size(Accel_data,2); + +Gravity = zeros(3,BUFFER_SIZE); +Linear_Acceleration = zeros(3,BUFFER_SIZE); + +% estimate orientation +Gravity = estimate_gravity(Accel_data, Gyro_data, Mag_data); + +Linear_Acceleration = Accel_data(1:3,:) - [Gravity(2,:); Gravity(1,:); Gravity(3,:);]; + +end diff --git a/src/sensor_fusion/design/sf_linear_acceleration.m b/src/sensor_fusion/design/sf_linear_acceleration.m new file mode 100755 index 0000000..edb78e0 --- /dev/null +++ b/src/sensor_fusion/design/sf_linear_acceleration.m @@ -0,0 +1,111 @@ +% sf_linear_acceleration +% +% Copyright (c) 2014 Samsung Electronics Co., Ltd. +% +% Licensed under the Apache License, Version 2.0 (the "License"); +% you may not use this file except in compliance with the License. +% You may obtain a copy of the License at +% +% http://www.apache.org/licenses/LICENSE-2.0 +% +% Unless required by applicable law or agreed to in writing, software +% distributed under the License is distributed on an "AS IS" BASIS, +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Sensor Fusion Implementation for Determination of linear acceleration +% +% - Input Accelerometer, Gyroscope and Magnetometer sensor data +% - Call estimate_linear_acceleration +% - Plot results for linear acceleration on different reference axes + +addpath('lib'); +clear +close all +clc + +GRAVITY = 9.80665; + +Max_Range_Accel = 39.203407; Min_Range_Accel = -39.204006; Res_Accel = 0.000598; +Max_Range_Gyro = 1146.862549; Min_Range_Gyro = -1146.880005; Res_Gyro = 0.017500; +Max_Range_Magnetic = 1200; Min_Range_Magnetic = -1200; Res_Magnetic = 1; + +Bias_Ax = 0.098586; +Bias_Ay = 0.18385; +Bias_Az = 10.084 - GRAVITY; + +Bias_Gx = -5.3539; +Bias_Gy = 0.24325; +Bias_Gz = 2.3391; + +BUFFER_SIZE = 125; + +Accel_data = zeros(4,BUFFER_SIZE); +Gyro_data = zeros(4,BUFFER_SIZE); +Mag_data = zeros(4,BUFFER_SIZE); + +OR_driv = zeros(3,BUFFER_SIZE); +OR_aid = zeros(3,BUFFER_SIZE); +OR_err = zeros(3,BUFFER_SIZE); + +% Sensor Data simulating orientation motions + +% get accel x,y,z axis data from stored file +Accel_data(1,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/accel.txt")(:,1))') - Bias_Ax)(1:BUFFER_SIZE); +Accel_data(2,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/accel.txt")(:,2))') - Bias_Ay)(1:BUFFER_SIZE); +Accel_data(3,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/accel.txt")(:,3))') - Bias_Az)(1:BUFFER_SIZE); +Accel_data(4,:) = ((dlmread("data/100ms/linear_acceleration/move_x_y_z/accel.txt")(:,4))')(1:BUFFER_SIZE); + +% get gyro x,y,z axis data from stored file +Gyro_data(1,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/gyro.txt")(:,1))') - Bias_Gx)(1:BUFFER_SIZE); +Gyro_data(2,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/gyro.txt")(:,2))') - Bias_Gy)(1:BUFFER_SIZE); +Gyro_data(3,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/gyro.txt")(:,3))') - Bias_Gz)(1:BUFFER_SIZE); +Gyro_data(4,:) = ((dlmread("data/100ms/linear_acceleration/move_x_y_z/gyro.txt")(:,4))')(1:BUFFER_SIZE); + +scale_Gyro = 575; +Gyro_data(1,:) = Gyro_data(1,:)/scale_Gyro; +Gyro_data(2,:) = Gyro_data(2,:)/scale_Gyro; +Gyro_data(3,:) = Gyro_data(3,:)/scale_Gyro; + +% get magnetometer x,y,z axis data from stored file +Mag_data(1,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/magnetic.txt")(:,1))'))(1:BUFFER_SIZE); +Mag_data(2,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/magnetic.txt")(:,2))'))(1:BUFFER_SIZE); +Mag_data(3,:) = (((dlmread("data/100ms/linear_acceleration/move_x_y_z/magnetic.txt")(:,3))'))(1:BUFFER_SIZE); +Mag_data(4,:) = ((dlmread("data/100ms/linear_acceleration/move_x_y_z/magnetic.txt")(:,4))')(1:BUFFER_SIZE); + +% estimate orientation +Linear_acceleration = estimate_linear_acceleration(Accel_data, Gyro_data, Mag_data); + +hfig=(figure); +scrsz = get(0,'ScreenSize'); +set(hfig,'position',scrsz); +% Accelerometer Raw data +subplot(2,1,1) +UA = Accel_data(1,:); +p1 = plot(1:length(UA),UA(1,1:length(UA)),'k'); +hold on; +grid on; +UA = Accel_data(2,:); +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = Accel_data(3,:); +p3 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +title(['Raw Accelerometer Data']); +legend([p1 p2 p3],'x-axis', 'y-axis', 'z-axis'); + +% Linear Acceleration Plot Results +subplot(2,1,2) +UA = Linear_acceleration(1,:); +p1 = plot(1:length(UA),UA(1,1:length(UA)),'k'); +hold on; +grid on; +UA = Linear_acceleration(2,:); +p2 = plot(1:length(UA),UA(1,1:length(UA)),'b'); +hold on; +grid on; +UA = Linear_acceleration(3,:); +p3 = plot(1:length(UA),UA(1,1:length(UA)),'r'); +title(['Linear Acceleration']); +legend([p1 p2 p3],'x-axis', 'y-axis', 'z-axis'); -- 2.7.4 From 9ef1c61e59d278f1792eff338ebc49327557ae12 Mon Sep 17 00:00:00 2001 From: Ramasamy Date: Fri, 9 May 2014 13:04:16 +0530 Subject: [PATCH 13/13] Adding results for virtual sensors implementations - adding simulation result plots for orientation, gravity and linear acceleration estimation - corrected octave code for displaying accelerometer plot title in sf_gravity.m file signed-off-by: Ramasamy Change-Id: Ib5f4694660d1f50c0b823c8b9daa44c5f624a059 --- .../gravity/gravity_output_single_roll_throw.png | Bin 0 -> 81851 bytes .../linear_acceleration_on_x_y_z_axis.png | Bin 0 -> 79371 bytes .../corrected_orientation_with_sensor_fusion.png | Bin 0 -> 79806 bytes .../orientation/orientation_without_sensor_fusion.png | Bin 0 -> 145789 bytes src/sensor_fusion/design/sf_gravity.m | 2 ++ 5 files changed, 2 insertions(+) create mode 100755 src/sensor_fusion/design/results/gravity/gravity_output_single_roll_throw.png create mode 100755 src/sensor_fusion/design/results/linear_acceleration/linear_acceleration_on_x_y_z_axis.png create mode 100755 src/sensor_fusion/design/results/orientation/corrected_orientation_with_sensor_fusion.png create mode 100755 src/sensor_fusion/design/results/orientation/orientation_without_sensor_fusion.png diff --git a/src/sensor_fusion/design/results/gravity/gravity_output_single_roll_throw.png b/src/sensor_fusion/design/results/gravity/gravity_output_single_roll_throw.png new file mode 100755 index 0000000000000000000000000000000000000000..1c838092e23f7725ab931f775151144d39daa4f8 GIT binary patch literal 81851 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%0Di$rzZj-t)zl{9pQ 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 WHhf}=JV{w1)GuATn0wy%!G8fOBfXyh literal 0 HcmV?d00001 diff --git a/src/sensor_fusion/design/results/linear_acceleration/linear_acceleration_on_x_y_z_axis.png b/src/sensor_fusion/design/results/linear_acceleration/linear_acceleration_on_x_y_z_axis.png new file mode 100755 index 0000000000000000000000000000000000000000..addedfb320640337f4a8d3d7ea4956b5b828af84 GIT binary patch literal 79371 zcmV*wKtI2UP)w0ssI2b}wr600001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D|D{PpK~#8N?EMFL z9NBrNkMgml{d@IT_ez?(E3dt__P*)>QkpqpAPlosltlS z{lmY4e@FZm@Nd7$`QO2>{L9}E|C#g4|NPfHzY^j6mXGe2Bjv3P%G(j~fi+?B3b~)W zXFY-cE!;29`&WM~Kl|mcJ;49U{L;Li1s81ggwoQ&3tyf-`609CM#?MvkK=!NWO+|q zDDQAU-Ui`v#eR|bPvHOWK0fzE@(TH=$~$TleWv8S9nfVc?>I+a`F;7mw9A)r$P^wcS^-Skp$`Tznb@-{_2Zi!o$$2FEjaP z`aHwZhOcpcX;J^_zkQMUkN@op;Q#t>pI=O}>L0l+;VJw=sN9aicfHW?nuK;u_daiM zVQ5DWDK@gqpex4b{+;I-ILkRY`v=aM`y1Nkq4J*iKm!lcA0}@V=WL|BwF?X{@S*w^ z(>opR`=06d*>s`qkW+kJ57asNz7wWQn4f&#u|WF*N7!^CC|yG2Jq#_mzr%d*g=@RJ zBo2K5c||QQ)O?}5Z5ETauRnrTa2%YwpF_Zco)NoSY)6*+YYsUUY4|EC?}^Wv zyw+GmUIRWY@{R)i2+8Zi=rba(8$6-B4~jpIygDp6v=2qzE*?)_g_lU)P8S>k`k}~c z~tnfc8(Kf#3{*Qawjjm(>E&b{1hBnpdFkH$(=Iu z&Z$9mx;=mPz2Mv&1lq%>Hid`mv}Ge`!o0cuyXaf_djfsFJIy2J|wPf`|vCI z#H?tu-y@FPYaN+u9+_(zo&_6*X6vmpb(Wc0%XE!-sv0zgX`)NaQ?RPWGF1)RSf^{P z({&512QBk9glp!kH&20e=BZlKR4pr$78@!Ytg=j1g663T(^R=>vdlDDY9y9`24Zn= zrqno9LM=5-m71r@LYg?qa#(AaDq-q_8m5Y&9Q|Z5%osU~h|@(TVxeiO&^TE@%{NTu zQFHX*L^d@`Kan{|OxN87@96HP4ctu~7*ExX-vTw`DQa*Gybh|yu7S$2tIAREO3=%S z(Mxh-vV8QSEWo@#JufAml?2X817{?G(~`g`$>=F@AW0lZ6bDX<0w<`)s0pILQBfeC z8Yc?G3IlP%K&-$YGA?{7gqc9dSfW3+-yajQk9aufp+5h?pa*(=`@tUH-fk}#-Q@xI zgt@z$>E&j+JiB0F$WCgP7u-XqyZCx`c5?3MV7j+=c;@XSZi8u8Nbe5n&Tj86D(rm^ zH9F|tE-J0_-fpOTP&g2BEWT(W91f`!vC~VdN@^Hh$(=!Wba{wSNh+z;e0{?81`RE7 zZ|_{F3*6Q|?^b4;YYWi{ZVrT>U(?gYEtyL&(nxQ80u+!@C-B7!i3y;{e@yH@F7}_Go)r5NC4nSq;FL6Q8k7aj$O30&fphY}d3oT1eDs21 zG#ONmftQqHmz85zRAX0zURRA@SC8LNk#ql>s?nROv0JLqTS|Yb(tlg-O;h-YO1~*E z^Mg0vvyD#69e3qUPQ?P1AzhKug{nx00#irNBzq=iRrXQU$f#;KptAW@HlJ$9tFjW+ zRu9#y9`dPeKJ{=wJu<4ckEtEwYR6rTGfWrJHac^8-J+@PQRzp|_&YQ&H$57CS47 z9bAFMP%@Nnt|&HA4dunU(qfxfyrOM{q*q*kH4M%+*=8GtW*SI+Gd)DIh#S-O!LsZE!Loxd7DA=bW=#nbR$i;xY!G- zL7XO08VR$es?1!HRc0WT8YaOK!$hfJqJ*VdG@>GL6_;L3mzk!^iF6^X0?8AnO7+BG zhBe7)U=i4KF=(2%$T(FW?0vuPbJ=7iWi?>I%6XY-75CE*lx3mBGLZDoeit7Zqd zt;tSov~Q>GXtM8Yc7VHDK-dh7*Ch}gUaCv=TF~j;B_fgM2_PNgi-e<)J_fZ0@;8zd$ zA$;%fp2%F#4hvnZO+cs{ufj`YL_0toXgfT6U%?-`yw(F3y!4A2>I{$hjUU{Yla;`F z*W&W_i$2xzUff`4#gn(qyu8vrsJx#41W6Xlu%f~;tVLt2O^d}?TX`{7Cl_OZyB5S) zdxJ3+OR^TmSTS6TPV>d{E zMZBf--%|Kf<=)#wl3|4cEScjj$*{syM5<(lhgo5g=*qzy9|}yxvjB@ruY9T@(4)4x z)s`^fq1B^?RlE#qu>k8*)O#Z;wXP_isV~Ym7K6E#;#_NS?oe^=aB&XkD9&*fXFH3s z-9=gM!YmJGCN=o52+Z~rgE__IYojHbi*t>|IfkMJ-=v8WL-mVPpGa5A0CuqM)IjFqards8!hQ$3zS)2r)>(W{_* z^ol%iSr)hiN{Pu*|3#+6e?ja&FZO}wMEi5O=`QrMxDGRgW`~2Y1d40rQUtABh+e_^6#RiRG_WBNY zd%;6p-h*A9gPorJot}Lip1mFJpkZNFFqtBDxc9UNZ6ofc)A@ze-AtCPw1OmU+1WxQ z!-$xzE@GQ&M>|P>c6NA(!9-~{-CcC27xumv>PFq)!FeD|sQkfBFOeJz@jxd?HrvAqo3NGJ9v^Kb!-nxMpRMR0IN`# z6>=Nc;v}Q4Xl}KwVPso9IJ~WHczfOOj{4yp4I?`nMs_vYcQp}rH#}VoU z7nHEI(Y~c|WOL)lriPJ?jUyWx?cn-GdsLHsU6XxnP=0{LORt#Z_ZE{oks!aJd0&Cg znDf5|NNYs?oaMFNQ|00@*28~oKY?Lw_^iuonT7JU|3LD3GWwC1*8vtY*wffMo%^&8 zx-_3@4+*fC%K7-O|n>q zH6LSj+$Y8g8;!NA8zdRl!WfHWSiuTu@Y&9#bT_5L$U4` zW07GiDiUCUDaz5C3jZxR=)EQL(iqEUBmvgDEWl#Y^lF@FA6I}5qLME^z+&;1$}!FY zteB+pB*0>0uZDcws4J3NxgsPPmX~Z`^Q%V!YWpZ1gf+e}z`D5lcQ%Dmos$U;#8hGqopO@puDsjsyfjb#9j2=w-Bpm` zEXZ)=XN=@$4CiN9sZcVMZ^+Bg=Va(|G6r%o)Y%!vW5Cy45z*HayclJkx2P>9Ws)Jq~cL*E!e6bj>86sLizQz)2!p-AzFNtUuIZ*BHa?5H>ad!`SQ8b- z$qK_{xiKV3uPW$3t%~pf3zmb1sd7EBY;ba3JxB&*l^LeXjNG6tn34fpRF-Fv>k18A zhQ(s60{v9Jo=dWF=|zRX3@bDaYa&g1H&t`@mU{fAYWxOGudc~QugL;eq@e$j1oS0~ zeaRxH|e-lKiKcp@1^MTb+7&?>f<7}x8K?e)Sm9;Q9s_#WTU9$!K)wZ{t{?e-q+ z@__N3#5iUbF_!3!>GCj-bb1bVx({`@54O7xw7d7Wx%LI!+wKOVJ0gW8ZLU47)E4J% zD$Fb@S<8YI8nx_f1V?r>P#f*UCi@P0S=`Q6*UmPOi;zOYyP`>;Ml!X1P&Zn`18tz| zAlOPg)aE9(yAQW}4tG#Hz2Kn^4>=;(xYf14#ksG=xwqNDjBa*Dw-C8{wz_t6l87zj zPNIt$9NYxX=Uha1NSD*ioI6__oXv1t5pHkdG-rX>=E6kk@BrGB4ZKI@^{y+a~J9 zy5WuW!y6h#z^KNNbznq*HNs@+)qQ`L!v^FBG<@|2e?ULN&*+b;-0y(k=|u4C;*Wh+ zvqW+|VgA=PHFS(%3&{I*^#soUoON^X2g!X1vlr_z+JP6`piEvXG5LL9QMs4E zKL6$TD4ii}V`8X~h|l?O7wi{(x(&Xv>_sR2XEE>FC3vNM2u5`NunddI%dkLRj1|nV z9zVvq-)OAx7^~~CM`MAZ42xV*C?Xlw{bH;IR}_wdG{Yh>7B9oP2Iu}t5@6j>j;1L5 zDRLhRuwa@h_Zj^&|M$&zE&fTNEx;6kLjm!SpD77x0|OzY!=sC93z)nUhfbbzj84id zUYXe~Gr43Yr`+g}8|){~-FV~es0VoRLaKatR6fESliP_~WiwxQ|vp=mOrYGkIzG22I+>vzrx-E$)1JxNH{J&ALU z=m2Ml_Mju2;^7%kNEJ}~hiCf0k(oaGOfSpD>@(dYCY$LPnQj}VBeSeijTVxr)tM)2 zOp{ecVkMP?S*EE9BMGp`#fIkT3KP``&Zk%9gOgyHj!5R|fGo1sFkKE?nx@OmGvSt* zX2`HCBfDD`u}}|Af&~VUgjsn(bM;f%G|39TmT*46qUqIDiT|?LcS+<;7J4rVJr@L? z^ZlS3JO}o<&-N0}^mtvVnc&GDNy8}$56r4YPJOId(QX={0dAOWH#RNks?u zyRX%?pVWNc7;TGo+u+wc4_!%Cfo2vI(rVZmbysH`LnJ*9}M253g$&UfVdr zTn#qSDHmG|zjr^IK>DkleZ@B0SMv?~N&OL*94~8xkZ_j8wGXe|o^H7x-}DFfQpj({ zXH{OaER?tX2QutE`&jbc1?aMs_rei*ePA&ox?J$no__N4KNdb5-;I>Fc3!R~+}R!P zxE37yqsS|P7}*p&gKffVmL+SM#U*(IOZ@=hMZRCqfI?rPMak~Vs{}UgWVS(Wp);j9r##o^w zi^W(h$zm}UOR^$ktohMcb)uR&gaQytdnPTO?%Fo~A> z?6U&roX9mNcHfhD?#Vp&MSlIfwk!8wI%PT`zWG96SqI4kFzk&aO9GZOoZ*ghiy z9kU`QI45+@37oJal9cs2X1YgaI)|s*Y}2jQDH3CuC+p1SG-_#Y z6EPZOiBQ5(`1irhQo1!aji6= zYjwr6IFB?t4ma8lHH;jrA3jiL+gCfZug1E!b_k4S*4g$@cT;J~Ht!D3;hj)7Ry{Vv zDHw9?YGlKmM#x&&5{`l;zEjR7}E9T`|xZJq4%&?`* zu(`~*sm!>s%($W4w4uVhp~|wp+Pc1GD5`d7U7c-h{qWib;_61uRba#Ldkwa5-;I12 z{29%DL(l&j3%d^SS&{wJ2yY51J;xx;7}1i@jLY2c+J+fCmig1C$CB4LiwbRsGI=et zP~P?*$oZekk1X#kfG%@+FCVW1Ea+V!Bj3gBz268Q{=5$dBJX4530xUw`0~gdg+79~ zN(R4oKG0Xs{o5zh6ye^dS@>0rIEu&hVeP>G3g)*1Khk3IlPq42^DG~ z82dwQR~3Qlpxl3h23RRlPm0V7k^t+Cl^T1XK|S1{wl%74O{$?Lr4?*eSilx)D@>K3 zwM7LEwWx<$G`1G)aEo@N6&wKVZ3821T5wo3?AsZ8(&8R%S6JHRrgoX3U8?Vp40cEc z!o#CQfeqRRMmj*9o$BZqbZ8ub)4%w!p{uL+%*nnpCk1Ct3eTPtpF1f%cS3&dg!0^R z^||BPv&VJkj_J=Pn9dwEgQw%Hr(?l$TekBOD{hX?pWC|AdM?3oF2Q{Mxas_HJym!9 zxR#a)B}4hrbH^oTP6*GO5S%&DfBJ;Bwt7W=o9s?yJ2S1aEv*7(*8=7jdPBxk8 zP%P7At!c8_$egM&Pgj}1sY)gduqq8CrK%X5BGF-|aZtWk1_#KhtSH-7#{ieIyBN8&0I2Y#&K% z8#&oJa)NrSd6?K_JK8*Sv~eiD!5Y_KjcpvF+G3i9W12={S{$)$&e(QW3>_^M)8VGV zL)Vcu=aE*&krqcxi#@g(B*|2K^T^Srk%XqMTSu0}jR255?Bo zVjDPP8f-`EZHMcJ4%H7GtQ$H|H?)sgZ`)Ttyq7q_j3y56W{Fj`b!U}jXQi1~VG3&G zEN2>al8{Bey>xI}iEdl*z*g#(qJb?iEzxZ$9o$-G*jjGfR%zZ|ZQW5jM3N&iVv8Hk z70t#>)el2u_Se~e)Bk@gkVzc9DixZ}CP4<|E5prm? zLkDZD2dXXmD^2?B)x2CC zmiDVBvMG4pr&)OQ`~W_r1(@7^X}qqQvA4TF~hf?FNB{{gu7tZ=u<3xO+zm_OnK=Q^S)hzSK5au?_EHA@)+wONml3< z?~fH@J@IHPa)0+=jCJ2D3R#TBySY1yu@s}1$<40=SLOcepwtWAka$>zW$@2D|HewC z%~vC{5T&MCsi{t4tdkh(#d@#-lrRlMsi9tKY>=56pmW*uB=#5R9Y#LsYNo? z0@Y$Uv7)}CqOKjxDJZE^jPwrA2>{$NNS zcu(gA=X9PqoqJB_0%r$6=j?!ER!f}GIA+xLX;9^u0hP{KqH9*^o>jQ#6rMRbiLquu ziHi)&63`5*dzg#`Yag0wwN5tC%L(gghE-!EL$RvK?Xjk-%u`&3Wt^%a`BX5#ib$_$ zfCbC-bnKN8o<-8DY70rP*p!7?mByJ0!%Vq;nq6;LI>`MU!%}+FcTRGvteIldOp$TA zfDFYVmlI~`CNs1Xchq-Nm18$$qu0g0D?-nuKKI2Q*ZD5z*$(^Zw&Bxlwxm{DQp->x z^OuaRZ6lIAAYt8XBrnnkoTs3Hj zt1`q^>0>MPFpa5%dC(YJZHlcn#@3i(YD`DKYSZCr)1fNUfhyDfD$~9y(_XOJytmr2 zx7r$AL#?*%skZK7p;d)xN10)JseXIOAV_kPqJi!6YKes!a9g2zTY+k8zH&>RVsoxy z6H&e?N4^ne@|2tM)td@5n~Mgvl#nEATZL(R6}vKyTocCzaP6tKM3ZWm_f?spZU?H2 z2P=(-sE4bJN2-i5)#lh*ICf~vq4;{+(T3rpjl(dFtGC70T4QP~hpSAm@qu#v{<6V+ zrGtA*2cxNbN(Xm?W%^xZ`kkfv9dJ0M^l+$KLzaU2t!4UcP{VSN3~?gD42`JBa@YX2 zEY^`=j)X^A=H^1C2HX^~NVBPUU{i^1Q_0|_QvK#~!{$okmMZg>YS6+74=YTY%M6=J z^qY!wn+mlX^EDguR2y@Z;3hCf0YZ~fmEn@Lxe93E4LQX1xyqC+L*7un8&!X>w zv>k#%v(P4jhT=8d(<>ZHNOp8!eYln|t>{xB>AH_5ug{}TqwJ;R^?^kU{}2l|^a;TG zaQHBMCrsX|dAScC?yKiR|K52>`*0ucVGR;;Y1-sLa=Yfff+HJ&{5Qj@1{;y)SqqXZ za$d?ya8NM(yq$Mqzql-eV1{Q>3lb}y5gW6p0_5iu;V#%U`V`B1aYJ2bfxOKk%IyYN@G4YOax)YvmRq%*f1Avuo?2V+Mz>R;a5JXzTjab$zP(9%X&E z{EfGxMkz2;*Q2QGRg$&++VJJ|a!b7;sL~3`hP;U{Kd)4-lBcEum+i9ghra7d7F z0F)d(AWPVw&q|!LQrDc^b5G^9UH|!tc}_?SooC_SL!Iv%0`D9A_Y6Lw-ZM7{ zy5|O6v!Koi&gdM|15Eq0);_HP9n%`;wAwkNcFn5XRL>l!q{=-s!*b8oXTPyx#i@*u z>F!}V4$C^#V&TSN(F|*<);vl7QsFeququt@mRMx?6$!9NV#T7Xc?YM;_0tvf`oT)m zOch9@t8mFe<4kylMPe*?qG6idHj9kUGBIaMO|vB=!U?JcctH*+~c~?>Ca|i2f2kNW` zYApw9%m=GY2g!2{Ui3o#qAQHxZtAXb50z#FT1t3YFwiL2hiW^5pWI+|If^G6uoAZ<; zmE&?cF0CU6$SK>v%$0A*Q*6jrZYWT1DAH^!9@tc>+f=6CT&~|-Vc;w`Y$_exRIJ-r zq}^Dc*^s9qX;ij+LzZkqrgTH5gqR`T2xjty<>2}ZaTIl3hGcD~6kL-nUz4j`ldoP= zs994yu%=YEx@>TDg?@FVVHH?qc(2OvE_EgK9isl7$_2tgwzisS1XqGJ#&?OPXV#UR zq$!|5g6+dvGT5GrHtDjJRd~MsL8}cbYaS|Xhxukfm#@5@jDFRHe-Ag@`V0>t^&V20Y{!)_T)uH^Z42z>=d zv;+N*sQ2nD#Cq#07G|*<1vHJY3~NoZgSa5ULBY^@JMYAP5xIN(hXRPOSc>i?I&U`@4sRVu7J63WKAu{KtYZ7B>_t7-NO5C=3n70+VTg zby@DeBK2LBdap@HfWxtavlQ~U^ISonK^{Y1@eq+H< zsc=_sjX71)eY%YEOexq^-miUg{hmIptc?H%0%gSN!fmZY@iQ|V2ovl`(zH5!xO=N++gx5>?(=rFT}YE`O0FWh+i) zI%axCrn~4MtQPBJvt_c;JXKF_>rVbUA^ih|G{B<6uSkX!ymxyUy>~l{uDF}HlU4I~ zzhc9$m^DGGVIizC%v6GUB6$jpz3BCcGnJ-UBDrA}vCK?jtYVsB5!=Vbpp(?|nO2dIl!@(-!fok)?TI<2up@Vg{gY`oP>uoS|pl)b?tz|zMi)7qa zY1m((-%lc^frF*mL#5ioB$?6>OVwa(i7K{48C$G~DO4OOlm}HDDN@7~DPxLNF~#bb z65`|cZbfM%u{mG0rBJiANV~0AyS-#!2kepTSG&7dyQf$aU98zxtlkfmEGAWj3Pa6fN;R=% z+PHFEeC6QLD*e$aLqfF?JX&pxuhhp?491iV9D&9u)*LKS9Vk@pD^P%Y^A*wgiaq&? z-T8`L`HG!+iXC~1ZMpKTxg>PkOx=`C+z94?WYicLI|h}^1C>-ZrVLiWmeP$`(v2in z5_6KYj&ps`s0?9Lx{ypWMNwIjs2piju6%u-VncyyBT2Hf8%wmCz|sMjk|hOdl5^!M z)@RGsXGuvQl`e|9BP8vX)*rNQ{q1?9g08#Wx0bplt$$6LVD%m0>U7cSOv&nO+3H-y z>U`CzLiMU*&8kxEsi z3(8v_l6(r0n#|X5iN1IE4Z;lDZ>T{y=_lk;w8^5-tS0-K#WO7DGc2zuIC&@Vyfb`ac!otnhphoA~LaBR9=h)hBB;Bk`)TDxD1QNSfL~<6k~0rL$N}m zu~>}7GAu5}>Y5*l#bPX)Va@-U!pJKMxfm-r6wAjltne6XKEt9h);a2VS>U2PkSq&a zlKL-8eODyjt6~p$P3*ZY_UL`n-+z5&g-{oh(-M=@9Gl%7pV<(fQFkmIta)R>m3KT~ zgA;}ACyF{w7E_Bl5{uePd)2>Ox4TDeCMj4}T~bDMQhH@lT6t1xDQs_}zzomO^3$bV z%rj+R_nGpZ3gN*1zx)3P?%clfZ{N=Rw{K^?@a^0ezFqLbw~Jo*R@slfRr#ZD*8cEc z8-Mh#O)vgy+mHUG>qr06^TU7c`{CF6USR%H!fUUE$`1ic5`O;k{ulq1+4s`dyI=Zx z=SyF2f9dPZFMYlK#jn@?=<8KK`bPPWzFGXjH}n7PTe&ZMEBoKRmGy&fwI`ie(bnFn z)7v+ktJs)azU6w!w$!4X83l5=-tTpX2Uw}K{UpE=n?y9glDXy-WcbxREf-*o7y>N4 z`h%JCeIm)Q?wNe|jNUn;XU^cBHMnN=t{J^^X3#OMvvUp*r?mEIF2Hh8-LqQHtj0S> zomG2hRo+6E*^Zgsk(sXH>5d^X2&>sL*<_ibgRrJZhGm|rF;7>Sr`h#` z?BYQZT?PO0AXrL;B_zON1F1~(23YLkK`V={=4z=m=Ghw4Y_)L)tTNCfOFvx&!b4aH zt3dM{m0WUIVVW&7&6XNxiw!e{gHyQ!lUbU(>B{j`Y2b#?ccssr+~qvqVL#hCe5%Qs z*kC!?U_M@F4yISeqqW9(qA8AOj;k}p(&&mSYRf*NX>X-*Z-qX(Ot-gGySG%cw^+TeNOhn{d9X-%xJYrhSaGCS5mO|O zDU!t$g3_1*>5&4-kvuVHz66ZPhvl*(g-rQj>Y)Pp!2_L=WC%BAi8tj)H|NT?mcqKYe3$Cqi3mJb}Q7)YqlB~;59G`C=SlbFN%!VSqjRNua;3X-rMq$^J98vEawOZb#apw)Te3u(GvS~_ zo1jV=LNa8G3>G7j@l9EvWK%Yg%##sMBD$GiL%IMCgv3dFd!v}Qd)IOHth>{$U zhG1QmC@M$1K2N$KU%sJ00d6c*GB@NaHss0I=g8J)OV($KN$hn;5S7+X^Qqpb)E<%s z-U7QwOGdgDyxFw|yw$z>R?q6xo>jMdSEco>N*Aok6s^jZtjd+H%9E`sP^>CazE@0q z7c5b(q`p&3{QaX?LM>HM)!@o!+jnRqgbB?8?X#fWo<_OX`ca(k59sn2I_>@Bb#L^e zC+`(spekgJTcZ4#8$C(I>i zll#cM1gdwKrK*)g^~y30v0S^dLicXv;Ja0Z_h^i@s?NH)VQ6*Z@S3I(BF(VYwuI|M zL0+WAJAq$B?!rteyOsVUWLWI)KF?p>8Gfs>mixJ2*XUC$@5SYHp)i+0mk7Nb<_(Ln zKwf}Fb*>9DiW)uwiwr;1z}a zVHwtf7>moW#DOFlW3jtpkvqH70PDOoa8VXWmim(=-pdm26|v{4$bD5zoDZ;aTVr!t zVzZm#vKr$v>k~+ZRr|)tzmxOB?_~em zcREg=Skchbs?*z#WYllEUi8kTJHNSd<2N@h%SnLcu@WpkpEskUGgsKc1z7eO3Aw%c zoYHeoO#`f(zgY2dAqlWdB((a2Ww7dJE8e=J`-64#ePO|y+<2*Fke4XW~& zSG;jcP6Dh!S=q}gUcV`u(#cAHvf}jvaj(OM`ZAcyi)D%nu-FJJ8emnEKSwxKVVEo@e|(SxSfyYvy5b}Y$*ru)=w*Nv z`0~ znu!e6_-)x}iqLzt&wZ)Od7+&ISV>Joi4E2h4VL5e=Fr%y_&SzbnaNC@IhJUNt+m9^ zDY@fS4ZHaixuX*qcvT4+V7kB3w4dDa$+EA?Oz%5xjIJP;(M6Z(qD!^W#p*pp%IG4+ z-a`4l0vULqKzgW9dbm(}geZwA0L3x+;+Q;9Or9_%H_SZI5m=HhB5TQJB+>#8QxD}! z4(3bt=S%nHOZVo>_7=#Z3*>tW)w>swdr=}#?+3Dx7s(Pv~5UfU4Nrx{q>fp>n-bUfUWCpv_;))kGjBY|RvGAqPd0xQ*$3RG0~xAt3dnl6krfRDQ#q-VJFz z>u+~2Vk+1LhY8YjsdF97-0ohN*1hgd&${%!s7%57Y~lJG@rGQ<29jh+H|EPW=1Vu^ zNjBt2He`#}XNlIsHtGFQclu}$Mx!ez@Kz`BX2&{WJDtwEmbwPK)w%js*Xq>n)wg?A z-|1VO-oH9ixH?<3Do4C3PqHdsx~f3>ULo<_LK(QSPzt{D=oT?$?-a?2#qyOw-+h)0 z9W}H7k+lX9S|->^p++lsdJNS$bQIwh^OQvzYz_2jFw}=1OWqp+ed>f4k=GLz2p?i0 z7kmhW41HESfe{}&lHUh~d1`PK{d(do0%a?UAB_+GVPRgGzNon>{y&>EUy zt!=WeZFUfY>D9Vt*zf>rpDsr!wnLWz?RcL%IeZ2yAe! zwC7w|&~jphP`B@YJ}1n|$a?wtte-uf`?Kfse)fFPtIwCd_I$-_&sV+reBGD^Z(QL+W)40H++vUpYX;Tye0j=_#W8z%kOvp^81~?c)tA?&o{sJ zeB*1+*S+?9^=r?U!(Lu}zW9~r^XX2rfA)OWg;QLB^~UMcmlH3&dj7&MuAF%zC6NYL zZmZS8Mqm{yYsG0E>>mq5;W znq#n%1XxBT4X_l`B*2oFvH)v<1XwFpyjt4nm>y7+{ba=(DXN(P&#boX^okXy%Y1Vz z!&3Xmg@j}fRx4Sa>zwH)0oDw=m3s>rgf-Pj0<6h87GRO92&byZ^@Ee;hRHHL$*M|p zK?mmNxqGo2r_1PltSZc85LUHiuEt8Nwce|<+^aRuahixVMk1Y`g=w96wvMf}%+`gaEFhhiIs$PAgc#?)D3NQ`AUTw^|5Wj<78K1gq)&fG`;WZu3C zV>Gz~)Zm^n-JVkIo)QvW?J1J)DIn?6-U8{q0?B~_$-zR&Vd{}WNo=7wwm=+LAdW8( z#pQ#-xI9q6P4ht^6;_eWK-eCPDG(n9gE1BqyPuRVg}p?R2uZR#U$QG#yfas{Jx91L zTd*ywe`{tRF{5{DM$guCX7`pmVAqzk&ds+wHmA04N^RS8vvp%iOVHL0;LWxTx7s(P zc5J-ewK1)GQ+n^_jJ_>dg00!YZ8@Utx#AsplAU>yU3p}u(fN|SBvzwGS|B-GKn^pe zP!d-pjW3oSEtVye$d8pOj+H6F<7F!F7+9)IC{Y|Omd6*#V9QvV>mA950~8<17az zSs)zX?XC^P&h@FpD45>vTA$Xv{!aJ$^qviweH*g-H|7X8=886fdE!m^RG7&Xk>%Nf zjamI0Gx|29_inh;Lrm*t1#Tb(cC5bzwuecUkZ|x;$GTLobKUK(wP0HJ+VtMF8GUOr z``2a**5nA+gb*qI$PX^InB+Rh52qjcHAtb!~%fZR7B|rjd2c_NZnDu?2LZ zJRdRMqB_<#+aqj>wDCUjHe^w}~X2d^De+a!VBD{ZG#a!R& z+_1n!a;q>mgJJ0v39!HpHUf(USgxH!_pVOQe1O$8A7JgH85Rw&JO_I{hvqXZUrfI* zwx0x8T!tm^B?x`TX@+$|#06MMG{a)o5}uU=&Pn_ir2Y#M|3!(923VdeLK+kH!pSm_QkH>zS#5I z7yEwmBWA*{e-$bm=6Oqw{rcDazk3Pn``t_3)b`)L)cV_(ntuCI{jXoD{nbyP{PMS6 zhJ6*k_0z()ewzQ*PrI)qa{<=RPA9*1@!T)3oqqGy$zNw2Wh1acmk_EQYLEq3!cc(a zCL^#|fc0|0h>?uIA{P$^1FZM!POMmQTw?K)0L!GVBqOj?vxcw$OD7`%R*H0LKuShn zrO2iR9MhfT2JPXzaYH?;^^y#0(Ey8GMcB?=ML5-Hp#c`Vgpdxusv_49lJp7;B~~Q^ z6D0$a#X8Os{S?Ulj9^(Xz@k?Xk|?UqdasU-z^WsIu;%KhWQHbL^dU*FU@fPaq+K=U zxhnHqrD?9*I9sBhDIBDOu+$Ujim_Bl;JUzjrI+0X%YLSHB&m5gvDtRA*>5W^-zuVP_5-)wV4E1k(Xm%W(wHJ?Y_T-1m}NTBW5tpL zum}_<6p0cFMPy1n1{R8s6-lU4FrkP%CBBGAvL0I6ks>HocBn{put;{GNV>lO6hZ60 zkcC;2=zQ^>e9`Va;jUZ(xHG4pnB6yTR_~6?o*kLp+cUbhr-Pl_(mJ-?Zr{q;u_X=c z+LYkK$AjGk?oz1y<-wr2}={X_aD%$zjHq zNRO7t5=vypO6AAP_6%M`FpLWw+~SjLW#9-t(qh@@bL3nhmN z#0Lt*`}4*7@^4!GPy)m8Hvmv8rLuT)WEE1Nj&k?N86|T<{uFn^(FAzl) ziotb3*9Kj^z%}=?h$$f!6W10?);)W|Q8QU15LugWLKBJB6h5VfztCY8KiIIQK%Wvr z-T1-sIzRgK%6nxWZV@P6+^}zu2N?Rg2~)JTfGJ#?4+_@ID};sX3Pi+0Fzi{y;wYko zDh1a^DB&yu#l%7?n~yXKq+f+mh47s?@BAK%7L%+BZbO%la(K>v!_qC;fe?l3$dN_} zOUUxj@q+ZZ!Ma5lERAfxwm`s|4q9wAm?v13CwPx2dapq8UZL#0V#Rx<>eUsxHC2YS zwdQs8)~E(sRO86{X8ZbP$A%WriSk?@DKFc)k2DG-v7kMw=}Cp>wty^ETvXmp(WhPB z>r4AUs0*=qu2(GV8@!_ac=FyLM4D2C8=h5#+_XRvR4s5z(5=*M?XK+|oI5()M0yn= zO|RU$se3wUfYt4Z?)L2M_U!AXBd}P8)#EwXLjx?DVa4=u0Tvh^46u#~e8*{qbwcDn zDe@=M80!?xu+B)h0PDPj23TSeU|kY<$OtT<`>N2T_fEg?>vgpP-RV+cVsU>`Q6G4! zsP|N1@9CnRGlgLHS+J-FJXh3vuDJJHN#FUB{tKmo3uVF!<S1LtUs>Bgi6Kln$Ltpt@ zNoi5xs<(?)y+vv1r;di(bA-(<$WlXqAy*Zacmfi*ib4K}v4SJJ;iD7Mc^owEwpoXQit zgs@;l?^D}tR^CDGfiZZ5#ean1_nZ-X`6HZ;|2B>`50ncf4- zG*x4!!>`E2gOS6p1}2LKCW>i*RYWZwoGR8&l^D1HtK2+O!Cgg20<2o=TwO?#PeoX7 zzDK4ODw!w4wZIyBKddU#T!nGAR6kRspDxf%Do!yglpt&aTQcEU@N_8WSOqEYXoV`i zLKRo8iY-^hlqrvtDGrw^V7~`TUYB38X;69?5vp}@BK)5$wus2r_o!cLs1NQC7 z?%M-XV*l>k{yn*ZJ$b@C`64j7Kpb5t*;^#tS1j9CBHs_?mnsgz?#dKL%9JtXN~l0Q z944*UaX7|G)yYa#VwEbXN_`5f)|{@^oT<@<3roOLRT|hPsZyN?Phr6pJ3weL+HUdC zfMtr9GSZlbOXP=2WC!8UilzIDrTdDcP$gzGUkOxrPoa2E0aLU)pDAQBB;%V`xGRsi zGgkoa0P}=9@&r5bg*ys_I}61-izGXXrMtiq8LSuWjD`cO%Iwl0+Jg;tw==SsIgnP8E4bCHNxDB2X1 zE}@4^_e&2s?5M+}Wpbsls%|QV<`Qiz6m2LJMimI6^7_~2_OHq9U!5mhoiAQhAYEOg zSW~K5TQL|_ZCqbx*-$^Up>cR)vwc&uV^fQhxw+Maf}0j|;{$8~ok1O(&72#WLfRK~ zW0Qjz+@3R34%iyf8FWD%(5F@Qg3{MF{6**W2QYkX$oY=JEB22h?`^`#8%4F4p?oUj z);2eDTl>7*gYIBHS`dL{BFiTtO;{?jzQIx7yGmk=*X{K*pkC9#i;z!K5hV9^m+udLf$ z*QdHsue?wx120xelPe|3Fs+bWs+3%=lw1i}B?Yfm%dXZCuhqz})hdW}itEf;`Hfn6 zy~Og{tw*E=S4xd6rAC@k4N6j~KygZ?m`q{5T5=Ptk%71BXo+|h^gT= zDx2ljL;v)7Wp!2M_Nc1uQPn$$^*h%!?p)Wrb6xB1wVlyxyQA0kMX&DPyGpcgl^EQ= zN_KyxRM`P=H7Gr>S`6-A-M^36OG|??p=2l@b_CY!hyv>m?CQxc-~y~SZ=U>BdcyCr zW8W<}xVmJoT(0+ef&rG-J27#0G!STPX|E6(`)$+05i$r%?wVD)=QJK$%FkE4oIkAh z-!u5%H~QZ<4UhmUZQ!1O+yLv%RLwo3S9FMurMjh@9drr~tXT1Kwt2vAN_iC)zJ5bG zrInWcc*X12rBfRFlty0m;}t7@oNdv#W;E^@jc1mV-o#z$o|U_2Wi4z378hW34^Ma4 zrrU<5TdedpSeD>T+_~XbVFA`)aMaZRjjmuyW~Pc*fTgDa7IzilEE$AlCU>){2}M^V zrMfpSjjLdWTh7h1>kWz3CKh1Ll^JG>2WJX((|Ov-EY-vv`S>l#=nWysurBp_E_A!k zb-B)TI!|{xPjxtxI-H4}&XXNX*NG0-@pjj-4$yhL!%1e^T?uWjgjVNKkmgx&&Gy)) zk=RC(WYKY0rUR9R{pExE%Cvh+ROF6VMY8?H@`I&{Bjw7Na#dWVI-y#7ymsJZoi4FX zcdCByRK4zWz3xoC?rgp8T!Zc$OzU;$i38{BK-~rEMX(+m1TO?VPd!&Zc$Rvme(*FY za4@NUFtKhBc5$Lkcf3}2tac!wX5eUzHoh9v#8q*|f|cr^s@MuuOa%#^Vn_l7l6Yud znoJSPm50k!hbvS^D%D3SH8EA1m}+fowKlG1ARhKot4knz)E%dLhiX7&ph{4;vkimi z8uaJEM*W3G!$q(uq%pb42vf4K(Ew{NG}0{_^zamRfKUQEz$Dsq8NaDiyI(xwBHSvqG`6Tu!V|?5YHn zunNAjNC`EXJ&{J&G6y*82KIurTFx2`7+s@|u2x4^sW_`aSVHFaR4VsWD)v+;c9+X{ zm&yOG8(4k(UwT04kCCc^X0~@Lg8*9y*>aANEhqpG{x3)O9fvqm|!EU{eTlhNXZ2=uy znjcx%n8= zLSiBfuuh4{@T=2e5?!68(baj$=tUA>1ulvGm&Lv-V&7G<_nOE9ibf`PolDz&?0kb_ zB)xqwrFq~+gNB&`HWF_!o3tTQo3*!FzyUBV%sbRJ)yR80k18y_^cF2=GpHdpsWX~2 zoGsc+;y`AbF6dwu*dAea`(UTW9{bI&s2dyV5ACTxyr=Q-uI3}VT952%kKNT3yQ@2H zSAYC2Vf;>U!cOV2o$_Nl5*A=hsz;{O_Nn%4ayNI5*UH=6uotRlR;em~ zky}A|wY=^?gEif1oo=>FH<+i{ecb6KgwyO#5SAOJN(ZOr11y?h(V3|t-BdBG z(oYrZr%Meqz#-3{ z5@4~b2=m!hgvyEAvhkae(d(kXRe}FfpZ8*~_d>7te2@2RkLL{0dkXCKfQi(TU>BKk z^WB~kou1=hhx>S&`&gSRp~V^B?1*a|Ar}?anh#YO4p!(6lxz2ws`eMl50uCcmn&l` z)JLne$Le$^8}z4|jAvR*XWPu@+AQbWEEn5}$?eul?bgfGD`1=TYM9sBiC2k3*CK@_ z;Fb2F%hXHlL&@z!7u&2C+N|f>tmoRSXIm|2S}mtrEvH({Nz7(*BGJUzL_FDKBsPME z6AhrASg$`GvO#~W!2lj_1dYTd(+RK{G@ooSCxWe(B-jz`5%x>>4t2QDZiOmA#h`ju zI)<(iZP&m~+w}#)Lb8eqo599#X#AsVzwgmO9iS$(O2p$~9s`>|BbWd-f`)}24cTCb zC+g$siLu1N*aoIPwh=TCn~a>zk%pGD&AX>s@7U*48~O!qUn?m=JW z2OB*6#pHJk^dsPc_XzqJ9{dye0V-fz+@_$-#6yoD+mcGYj}A8Ki4B7X>U9U|1`gC| zsRIY=b+8at9cnTV>2nV^8;^u+F&$}Tn!}B0F;R^%&BmA}!;vQakw$Qk%FQ3H*B!1K zI8>`WRHHsvtvXnxJW#0s_lJZf)v5!qwpM!(wyYmG)Sx>IPvi-O!!DYGwm_}IY6vzN z4mZLV@!%mioI35n8VwXn%CC@v`@nKKtyJu*Qtl^v)WG4xu^)nG!E-@+)bloh2C|lx zc?dSH)f}i*AE;45341E!yGo_oi^batg_{e68}r#s1H>DO6`RU5o2&F&Yfangt=k)i zcQ!kAwK{jTx^}g>cZ2Por(ZaV564}RlGEu&5l+0@T=TXvoy3;=%QoOP4jL+?{eCXk zJNk4>U)Ip;4)VGLGkk;j&cNgq_(zrZmf;MJmYN?kwU~Q?Mss?Ydpo@$_eHwDi+G^R zdoavHAWf{8G1S;zA2Y7kceD@mCxHF_V<63~P6+%bX?m3?3?vByr-XsiqF{6-9z7=+ zJuex(K+~&aY2cD%^olfaMdH6I@m~kUz8hk1sV2}fVEf_QtGC6SZW5{_)={B3K=q3v z6*cL zM16Icp}NdiOSIOPfVTRQVd}^N?GF>SfhP`8t#u`)+AQtCTFInCMNEVjg18Yez38ny|mZRWu7D% zmTgKjJT0})$ept)*R0w-r}fMYc;6lhJ!5O6soK?7HOu@i(j%F%THE~CAHiU3 zSA~Jgg1{v~;G)2Pq2GVL-v^%S_noDl=_8)z^n<6E-M*x5Un1D$J=x(o(e6G@Vk~=n zqb;`He5A&3xJq}pQggUmeW;XNOcz(BIaa4jY&4v1F`aF>>jz)YrovbUm-JqR$K4jMj^IRu5%-Io~=^Q@WIYR6TX+PU-KSw>^;{c&#C_kC* z5%vpvze;NY^?_QY^t*173cJD7ptmCpEeF|_AUum5TEx-y%^zKI@BE=bHO}>rDnZ?t zXF_(3oDTC8*g3q=q@aml$MDIHA@D?)$2)8%I&CM|v~!r)bsyPUV(=-ELQ&wc1tw6B z28{}+9X$yBQ;*p2R+kWYs z?++onz{pqmeg+T!!;{~ao^5%J!;`o1pT-4moM+njW#iEWOPtk9B}U$2y0Obq$eyf!)JIZtug#p^{MZb}KybXp0HTiE9{yVxjOORZ3!|;&7$n zNR{GnwdzQ%CIwWpn`>XYdw++A z>P7G8zQ@zOm)Rb)?GX%Z92Ck4)3cbo{i08`@Pg9Un!fZA{U=Pec7e;NOYq)1#Lfs0 zJc0*9vSg~;7xHko??})Xu!l1?Xk3pkzL$73XhLr=vFZ<;UcwZj9rq9U6vBBN=L8BMz2dpZ%9W|q=B0f|1GKimc(DA^op(iL)VMm z*nIE@Z@l}1*E#>~4bB(BeUtb@&iB9{h5Huq#kbyj`R#XKe(PN_4G9n5diSSqFYeDC zA(N{^PIomUC9?f>=n zZ~x;Le)UgZ_{~3k@i$-l67|c!{o0pd%K6XS%&)^2e(lS@qQ3pLFTM3oUwZQ&zxc-g z`oin~@b|y`hrj>DSN`YEzx@Bc`lbKz$`}6*T=TDAKKt%(1{`B6G7HKZTiO@e+}7FJ z(cRqI5n7UwS6tYoZ#UfSG~MksPxMLTWz)9Kg6wwY&%N^j1+&Lq2lG|@d zoU>xbtS~IV>axvr49&C+&9qpjn=I1}mg#!)bggl^#yC}Nn5r_6468y&s>d($jD z3#>HFRv2e14725Q_*F3-fmNWJ&ecw3kwI8@(-h;Wvay@eu^W=nYvRCFQQ(Rwa7h?Q zrd|-tdrshIp6w@|qti2e{xiMA(>=b^-QJ{5PhyAbM4RJSv+ZcTIj&Y8TRjk4rH!rB z#8#-{tJKHqbf=n)=i03ox`&f{9as8Y*F@gyA|H4|=mk@#H-+9?)Krl#P2{@+Q?dV! z*q;tc0vVj68PcFIFA2aZ@D4RC=xs?Lm3m78Z_z-C81&x|`>zMR#uPDqS3?S!-YZN& zgqNAZaDA6WzAIE#0+a^j!@gjTuxqFQR0HY*wYno2y(1k>57l2fnmO+nmCT3MGGTir zJQqxpjIyJHl7mOb9U2@FRDe|mY6V^bgHOr#%p0XU}y@@_-y&pA2#Kb342zo*; zXe(m)1`pG{hyu=}4`RP7u@7`6_Bu}XjGXKqKG|s_b`K}^jKD%zl?3*?$afjpo;-zl zDx`pTTHrY?q{58A4bpE+*O@-&>0Za_UOTaec&d9isblD5oB2eu;dtZV@%n*dwVI>V zs-sm(Vl}8bTBA;Y<*>Hdc%s#OvfY~4X-n!JIR#JeWjesqP4d zU$~=KwyR9FyK*49#;~v6a-hj}sMT?}-F3LbeWcTKq|-8U}o&fuZC&7MyA~i|iKP3o&r$J%h4E3xqa84LFFCtzLgQLk3 z;w9>3>DUz#U5#Cnja?^>rbtI`%0_R=MpLDusj@(t)So8vR}GFUozo`&j5$opyt9@7 z(YlyJAx9&$JEyXPPWCjpmsK^Guy-y4E;VZ6tTX zs?w7Hi)C0W#-dJ^>8LQnR>4$1U11c*y5eq{eEha-{FZbqMKVfaEXn9q z@#qy1@v><25-|WKivkygd@q3gf%Ey8BHI-yNqiHPYk&R`_ z#*Fn@P=3Fekut>K!;(>TPOjn75d6p5r$`S;#Rk1sX~^ zc7x{DH^>ZC#+ee7ZafYpq(bw`$xdPK(ArR?OllTXTS=rxF$w0XBFy1Qx5=hvQ8Sej z86Y_{QaCv-`CZr@?3C3!1q@bZM;}4%i5Ec0;fM=@cll9p_laoN_xeU$?Hqcvb>gAC~y1a<5)=c=Hh)6 zpdZk4_jMFJ`vGJnoRb9>QM$P27n8RQ$Ss%n&xw8KM82~^&shP>n;gV`7d$*C^qdoU zVJ+E43|j^_7J1JKiRYLi?|CukV}B(oLb30n$V(J@E`S0zc)rhhwtM(YyY*CyF{yDd zv3}rWjrv5D@_42Ec%|Za6{tK>qdHlqO>ERBwU|z|ThDaa&i2^P^}Ei)(}f<8lqT|$ z@rF+Yi`zy5vYW0U3%rVWjxHd<8hwEskJE6;y z(Ctm=_MwY<^s)6)J;W|*=i|tp!eoUIS(%H<+dKNSNmH1F9)ALvQX_hxH=)aWlyhOn z2)P{lL*#)34ISnJk1gi$Fi(KJ#FM>#A`7Sb{D~p^{YgPj1wAeBpP`pD~^_FZbRX%o`IGQFOy(1q@r)E;Ke^iS*9H?53^!m-pZg=Ox<|3?k;g~acjb?T~z(Nb&qU) zm~_bmHGG4KdPA7T$p+9g#avM$@i2?U?jn&3EEKwmgw8^0k;qXZa+Hc4WfEtF%vB|K z*D1aADsQvK->MC?4~}-~N4pKV4f~lJ**THnMd~mX2 zked?qdDZpYU6aZVY&vU#+e$!Obtv!8fIV>SOw~*E0}}REF+sA;YDtqn^}9)QB?-{? z&v>f*?oHWv3cR%>fg5CmR4~SpjNYb0jYxVWAInmV=P2&xDkpMPlX;+eic>Y2OTwKA zSR0mPO=Kx2vQ(2F*D2zYWn@X6H*m&GEE6iu<(n8L}5n6VIbQqO)+stIgzfM z%ur2clE{h6p0c@EYARO+hcFH1Yi1s5UeH`>j%GSr4Nk!^W~wGLl#}U7vOCx*+dHcX z%jQTD7io%ooMl^_@Q|svdqXjCLpksDpx20Z!K*>9fQl#d@&mmTX>!nuit&&aB0WFv z-6!@!NF{S(p%>sbV~;Sbm1rZ&`JVe=@=ANK7araD9uoHAKCug$<#FV9q-RxL zvn(p_DNlh5-fK^#$;-)0k@D6)sdqzO0vCMOJdxv<$r1IUkSg*fi(q44veZxhyGS-l{`ZJ;^s+R-?pku0{OKsr zo80fd*fVmz!+N&Gc)CG%s!o$stxT+toh+B0ESH^xnF@Jgl`^STbGmVm+;6nqdcJ%3 zVxKcv=($AxhPv-Elm*fz#&|LLZCF|1eD4B z43LkL<07{c_Q7UQD<~g?8lLMOKGSJUYBir|)W_Foj+Dy}6p8j13J;V>50xtpS88Hv z2ICq`3C%;t+wCViT_?NTiQS&09&b{Q551p>kF7Vc$3qOi4ekRB-X51HdpePoMud`i z@^+2>F+ADhT~yv?54V>|!k46l_JXVj(${+NE)ni>>=NN`rFr4F?(eDldzu-#Gf%(& zOi*^66L+P(B9d z{&(bK>55=(r5MekW-CT>l%u&!8eQcpM+;QMu*7P-SUp~%;VcbW77VQ_LJo{q>X>)I zDwa|O4UeUm{8)+^mMF1|DI!!_%!Ws{k$AU(sb@|^IKSCMqj9p)IMrn0Tu~@+6fpbk z`Th31zLC7%;oP3#ydGO_?+{E2dToV$wxa&wV!?2k$X+gXR7;&TGFP3#)2Q+`t9`9n zf7^h+Ll@|zc~+Nxw0m&03)F#uPMyDFz}KN=dfPP~W}C*{rsCTgQtfHe`r1gzfp*2)omu;@YHrsBUZL`j{T4tKf({PXt#>sjk zY3o}31eYVy*Q`o64zD6iLm6ZRytD&%VOpV^pf7VM>LSTk_26U`o1ybeSW=}UR_Z26 z1O^Te%LXP(2PR5DEqJ$xTBx~OpdQaxkLRhzb5vv5%CRiP81z@@xOd3V!O+EM{+l4Z z8106L7`(iW7`(8KDqwoS%YB|pz3${5=fy6^g^uB~Etb=b#-v(ZVvRPjR+Ch(IaRMc z+cbEw!+N#Xks|WZ@roq9VuOa@eRTugZ^4qu#djid<=rhYx!^8c8pxE5X3NKN6ytfy zyLqaKeAQ&WdWuN{tO;0^EeFT4Ksr_{OL3PBaZ*jP04rp8l0}`))Np2LWhC4yEIaB5AC>9DI4dZmw6&WW*(<_>(k?~?|;1wHbMFOmR%}jxI_EF5| zoXG<Qip;Kqh$x zkNUw*5LFRg3YVR8@)j%fDehjCk6)FIg~d$X%VPf(Nq~%Nma);z zfy)vQPC0zZLeE8k`(nR~nM}PTa9Qse1sZ@NjSah-k6epI7lgeeMs#Ry|2hKGc$e)qv z9=X)#ydv_F(;Fy9Itm3s$u|_^MCIKS)dVs4EuW$ylK;n2jKfo|2)*$1i(SL#TTN#g zbWn0qg)FgLnph@*eZe%TQgNzQbGkuyw#9Uz)0PbT68p&&D~h}1|HD-5C&U!@Yk?I@ zMui8iO8i&FpbzSH1&*uNaiMGYT&MMPi}6JLKzya*NU`Wpk?=@~B(_{0SE)K$GjOcI zaI)EYs(s{ir}Ipg>uk6CY>($$uNPg^vrnk!Y!5Un6=NP5caH_TSRRJIt?p~z zyyx%l1x_EapLj9MsAbf0?YtG*u}W}Ytcu7Du&M?_W2|&{ zYpAu<-@C2B{jwSg*afK9$=+GywYvI+%=NiK6IhQbhbeczhjbW)Te9JXX-R(8?+Z%^p`uWH~Ji@ zurJvdNHSnL@(bQ<*94x+eXitQCrq#OyRX77gx;GX?`^R!UE<4>`m<$F?Xf(?c)s#( zekj9IP39`@X3NI1q=8I{KU3__5c`NQFNOCcx!#ansmGJXNt0Qs$!uv&@`awO zJ@!lOmJ3b#bG4c?Rf^MPlB6Qx$-;gxu}F|uBupw5pRQD#t<#=wG9M-!?(N|r2m_xoJf(4UKjb`>6g2PFSeS`)$2}I zDNmJ4PnAlNO2kRULYSVake{hhpKZ{cZ!slz*{;C8B!LvDJSm?Po2r>%KOUfDSOUeu z-pRcV$mK0?P~^C-!?D9&dZBS_=i5xD8g$326mcb@m?A-3iTG%lETKYiyjqi3KX|&? ze6G!QzSDl8%W<(A+S8TX<4*2HBfR(l?QwB-Go6oSX!|fjMS;DGx?u0!h8 zPAZ+}UL(2wS+M7FKk-VWSD6A2oGD)qlbnnTJt;(To_ex{g^Wy~LN-6D;~}B6=CG0*2gjR21{cyT z@3t5xh^9$!MP@t6s)%i-j5cF>t0BEb58i1Rywj}909$mKErVGtgE?*b+;&5LhpC{; zT-0qT>9v;i+sXvP6(r0WA$gX>!6^pqRj^P*)>a5?<^4nDf}skc6|58tRSAjJL17*i zlC}NT@_tfsIXqDW#X71au3Ck+UhQwxjb8)YGM_c2~f$y3Kg-OsT?g+21=o0Dg7l1f3d<}r0^F~3*`QMxsRDA^W{==q`qva zH(Tn-6caPVo^+Atj>w%xy)AO53W&Gnb=?d}|9oBwv(FjwMz7;~&&ajz;j5iPm)a~B zn+@k12H1x&4TJ^bl4LnS4(O>Hty4mkcllbYdFBSvA`^`gstn}C~cG@m<3?+9B z!~E4g=XKbZz;#>bhPpvLvn1XesXtc+@2=521xd2p_?kh`_=x{CWrc@--3X=|-V)0XkY&2cshYy0=LQkr|1+vy)LMw62 zMIJhD_7R~O)1YqT-t+!+_yiF`Jw0H$(3>IhXNm(^(y<)*-CQLJ;|kQ%`9zY+G0ByZ ziwWD)L1%Zf<>YqnaEy1v-ZYUXRY+eft};aWl5sE44S1zUlX`B6SU~AX5x8#jJHZrz z8$JPVihblx^YXDYhXF`m|?H)lewS`A6edu^32L> zmPO?~TZbiRJzOr`vEspM3N=v1-rRG|Q-XUe5#t5xUf2QIc4FL&DD zr`=8XQ9;U|OjAS2@Z({IOrco#&7huw<@BJ&pgwR=)ByQ^HG%tDpYuxhNOFheY~x^J zwKAbZbhM}+rpL-8$1CJX)vD8V1LvBI7u&3tI)*QIj$G-oU+s2Y?FrZQEPLh2buQ3B z?Ea8srE!Mug;x!9i6pIkxf^tVm%8Ay$bPAFgh=Pvac86zzN#>Ag|5qiqs8W?~Cw8q$&OL z-V6#Sp5(M$=!TP1CY%p~cbIUFPlc2H42d_B3MbSw2Y}ORZ!Rb!=E+D_P$2geQi~MC zVy4nh5(cHeROv5M`OB#lpqj|ii7HLV(Q2la4B4p-T1Tzd@f>RiNusN<#z>nM*sQ;= zEstQUVcr(vcxY8K6h1gg)DfG)BufTI$!4&Z8>LnVDS zIvpzRwHEbSU~OTysi4bP&}o2aVVAL}+gRLfEa^3s_LafnVlK^Y7 zMSmCCqH)0Ap!L;hJarm(t=dUcI%<@5uv$4%4O4}qN(nlvl&&hJyGrS;Qh6&?-YTW9 zQbmOsqQ7EZUxmU~PA!uYOXa>2xvv;HoYV^zN<9TqPrihhC-LMm#h#p?*9b$!8oJbOzR;ovliN&}JBP0J zjNE`-^f_+#JD_4v&n&S!M*{COU!IJ_Sk%#MC`#x~>$9hJ*=}}NQ#vdu?UozumXr?b z%`RJNkDVl0{VryDzw1uOJ~|b+?+88VB5yhwx8=`}1Tsmg6()^`U@dF|Ti)(>rNZ%c z52tk5z#CmdaL7!UzY$u}VZGLFfhlZrv&Wv==Y(pc!r^p}-0ZZ0Fq7KjNP{{EyqRKu zwsb64aW_vn0n=Rhc#do=M>d)xC1%qp5tfkUW3YruMx3R?hZL>St)5|Mf7tuAPV2P} z3rw#Qp)&B$dbPuHwcUIbs?=$_(KB+h&vCQQnbK>&(LH>v%LZPD*6wqVcuV9Z1IOg! z8LBDn3QFy4mUb4VAu~8%T$-0;68BEhM`ewdyulb)+mUZ@+m)NH)kX(RiR1fWf5`K(y@6+wPlWPr3-r~o-Y zQXg{LQ!rKHC;!3L=e*uyze2{B=}uQGPm~Cc74;u45uPj+CzeZ3Rgqz37aH}KTg_LY zxjJpvyGCww!>=00jUJSE{X?`Hv_oejc0I9nA}PlXuk8I@uy^!Bx7&UV>>9b+ISlX9 zD;>5g?L)*48$5)Cu!_iDEb{7y`ap1=S0K@Oz1Ml8&vm2U4IgwVbTklr=#i^=1Rj#V z^tx`qHn1g>!|NNYYeo2!^#|U&kF)o_raVYELF0x&guE3doJWJ~JUw*Uo+fbK5x_|$ zF&(65_aK};XNrhfA~^AP!|6YmL(P>C^CWH(7tq`QER+$8sKs(GSVApTc*_*ta!~25 z;Pio&Dt{GI?XLzk{+cjrwah@BHc%h5VPM|IkUGw$NLg}pKU*GXtNsy$&8Xxlx&YWr z^fwO>o2X=7=Vxnav14t9apsEDdM$XXP6OVoRo$#r-mFpHs#V;qQQWFgq}D2K*Q(O$ zRCnss8TIOnMongumc&?K%V16`8IzUQZp`g4=5-qLJ570=rrZwDnA2{|ZZl-J>9bo0 zvs(s;t-74H!MqNAL8qax%UIlFD(y9w(dde#SG|^!9&=H*si4!C*I|HSb4ju0oDNG~ z*HBUaNU7LeDfic?#_9(qn)H*crkM`wY^Qau%XY6D9J<#956#oT3j*yrw zBpDVLV+mXt{Z25w-+8Cs5i+fhNX9gUnbvD(-tM)h5=T;dMs9W6Zgvf&bXcypnyxkt zUaHqzs8L?1R$Q!6CD&;#Hw;{DHl%b8rS&^9=_P?Ad=WTOdu=y6&DY!Xmz%T~>y;Pl zRhOCvuC^O*bPe6?9l70SzteBe5IC}g&TOc**pn;q=1P1y)NHXYQ|P|aYroZLz0qpC z);tLNz1pa|+Bg8y>&^Nbt)`ppmRlXxpq5+ku-yU+IbmVv(5)_8YWK)(l6E;lX;)Au zETjq1$jvTW3hb!ed>!`HVz>%6gZe8G4qk53U24=NHw?h^O0(fwn>nQenq}xloB3Lc z@k%4qP=Br2bfe9h(lMOcZBOfij~H*ZB#?yvY)3B(wvL_c%_*a`|DVpes5A4j<~9LSXxBOJml*q3w^+5~=4WT~gg&k1U_mj1d>lVZsoJn0cp$zPqmBO!-I z2DA6tuXk84H4UDtQ6`m&P8RhimIzOkiBDHZ&s8a)#V$9&L6M(WH#>*v{|nkvdmNn5 zdLI=d|L6EmVGjsDgM)T2?#%^D?kf}${4emuTu=e@L$t>MpBp#3N8pW|(m8yiW9WLj z6+Rq5n1P2kI&CRk!>|^%f!CC593krud|^3!WZfjmiwoZPw}f8!#3Kqlw*+o_VG7*< zN`PXy!r{!3lRYHD=_DuXZwu=GP$Mh$*z!ty9C`2D#SI%55|Ugz6d@V+Kt^CJ@D7ul zsyovKoEZXVCNp?m55hSgzz>qdN*f_t-l_uwWT)^f!x*?iVfH9YA>9fi=ps{-TWNBuK(j~9 z=~Y|2nvhl>Q)~5Whr+b^HQ;KSuP7n>`a|&!ovSY4%K+IH!Y78R-(365Z1w z4elwX9&~||gRV)PbKZgAG<=4qHmJsNKPSRfhqN>Asz>gsM#fbmW6I%C#gJca@kz}d zP-gbZEIzr_uNVp_hsR)JjdM!tn$kGoS>x*AQRR?dVfDz(ZmG!$$}Jvvx^iSp1#9hh zVP9G&7_6#mipZ+!oP^R~k5IDQ>VqAzJxWbfx@)LLq+U7HCtSAN>X$<`h5`!PsKPcz zg&8UoPV~#Hpbxf}k{yMldkj-za*K_i3#JlSV)4Nfp?vm4iO~bXjLZTH$-b1sO49W1OEBIwP%o855|Nrjj7pM7T> z5V|HU5K2(N1QmGxnM(6IE4TUr2-Zl9>Iu9;Ru^CU_)hBd^4vvl>HG8gf!O409?b_& z-RLdoc6PmK>h92R^?ls%AfwY|_*g<=E6Er?uC6uA5=T3whIbN5LK%IvO5&W*t*=X$ zYIU8~)UF}s?IRFm{X_Mx#mE+Bt}z*<2`&_|UfPZ7N|6Nm5*v#gjJgW!38B|S;)*xk z?ag6MJeVVt`tqpuSui%_o+^>r6-$@fP0W`j8ukLREZ(Z-8?;_mQ(|~eboE-WhtKmp z1s?)Grj(92+e@5r=DL~Y&*GV>?a#gRyL)m2JEnQ+ruRv&1W=bIw&V@=>g7)w+a2_% z4@W(l)%Q-;1$5yZ0uXpdsV;oI)b*so95rV<=?ptW9nae$yA;)2HjUY#hpiRC)iO@| zRh!WAmE+vUuGNu8BN>~QTG&=9rVb&Fhp^aOcrBM2bPFCyUtM<4P&!bxXVa(XQZ+pf zF?WIuQtM%#Z0GXV)X`TJZ}^yJIZy8wqoffS3X|{P)1%Z7`2Ird$*a*W)eSrA{v1fw z@UC>(44w#|Ih379h8xnrq-RBe1g;dQ(WR{?2s-uBVX!eE@n#5mkfWi);qSQG+S6yju@GdFu|kIJMpAQu_) z5j=Lzr-hmN`%BptsHaY@BTT?3Q1rq_WjBsFHi?KVFS)u)RdO-aFqNy7Vo}W!L#&lX zz#y2q_nr@>EtT@GIXcd|%v|59d2%!`vyr+(1}+=h;OCmr!k>G&1+rIk3c}AQdS@j+ zaWkd{_Ql(Otl^|yv}(<(I<_(Z;3Zl&%pI%aH=0ZZuSlVuBUdEe^j7X}uKG|Svxpz> zNVQb+2y8f-Vx8Rb$DT}5dIe^K2Uu53ukHhfH0|@9Yl3NVf6bU=akC}VsR3GX-sN8H z=8d5p!XxMNP!@@Kv6kApNnc;@NwcIPmCk}L8)x)~WEswK?VfaVc1s3?@OeeVU(1M|AmnN4?Gk3zN z#bN5L*?_gH>UUTPBiR$whxSkIolh1TIp1;q<#|F((XHlO4!9Db&Ed+XKu}dB0Nbrv zbC#p+7MFKBE&~ZS%G1mXEN>j~x?L`v8pg2~$p3iBZm~yYubt>&@li;r)>2V0nUow> ziwOfMc*zc1E!aT9OS1JLvps&ilkPk{M>_HCf{QQm>MDyFm-#C(QExj3`71lEVoK)` z0Zy;BmW$4v)XW)iVvTR^^KAuSO}-MUiS=m-2Li6GgI3#(j!9AO47eV@e%mMr@-Cjc z_wzUCDIvD{?+uy@u(3FPYjDv>!xMw-w-Im)faE&-Un5*Rr!k=C=Jjg|Tn`RY?i%r* zQve^r`6%=lf1jm|>i-Ah*N*-FyYYVxH|Ca~Nd+mo!h6+nb?3vuU_L&+N4N@QO^SF| z>N+?nD{MCx7U(cW_}Rh8?ZAl8(AR!sv-z!(r`Qc+`av3s0`WCzxw)HVi!p|~iZxv> z2ZbF`0??gS_OV%(Ys#_7v-vi){5M%yVc%H5+rV4f10TISC9)tEY}fQtOxUryET>yu zQGr@@MdX@Q=jU(l#-dIvyF_fK>(1L9r7JqGY>Zc6x`X(0a&w8#VdlMk*~0xrz}=dgvlQGBN^|SzcW=lo#LE__{)h*Dkh?TrdZI zQ3vK)nwmpwb_2moGT`m^ieg@qj+<4`BR?pv*Mmw6J^98u6*EpQPeU!tM^jCr$T$35 zru3S0`qOM@kk5k-J+V*uz#OZWpRQ__-A37BK|#S#U0K=P%>Ilg>EPYZT{ZQtun5=S zw)xe;TvT_U%U;DK;^EcclT|1ZD2aWEmezTtkM)!L@o8m;3-YV*0dxf+RxwtWb)&9$Yu*>1N(U^u*HZ*LDc6&$TwdUQa6SkzuD zvUhEbW7IqUbqnOA0g`8oSVWz~4wHN`zKySjaIaInclY+~+m9Hu&PU~|aPMxSkeg=S zIrf!0HNxyH=Q#9lPsdZ_I=g*uuTwcA16PYJ+Y6^07eK4%Yn+@f`!iI`kV>&|WnEoe zeSJo)3gfOAbLUm9DE^louu0@WDdc!$Fd;E<+54Q`jL>Ffy~t4@$_*xDyHV4w28H(n z3p+SCfTE6}#+hU{VXbP_J;TE-3zYG24sB9QRTU+1rZVv^%{zrlH&0wd+lBQu8HYkb znjQ7FM{sb%%3hP6Lem^ebE0$hsrSJRW7wf9>TuI(QAj-g;(}U^HmpU_#bPi=$85bn zQ%zs`YH*E{jt*@*q{1dZ*k>oe+$j+Xjdk3jM`7$vo-7FHrvS(bZ1tG2=<#smRP1%_ zuSxOo(`dZZha4Yn8lPe;o20WdV)CS8@}wVvP;qn=(jsvfsQc_S?}R#@L;=K3&oUyGE-9*V^OeJ)C?DLh8{Uh9~l*; zfB(UQ4)o$tizt|@-hC;l^P>d61FUgf7^oUZ4n1n{_4WPy`SZ!i2^6^s^}dEWL?I`E z!&OjFU}j-~Zq?zN-Tvds{=BuOE52k=hD2_n=$?TQ%ZiE$3N`IRLqo>kUCMHjKW4cp zoQN?%kKFRHov=^M$iQ0=J;)ENl_=TjLY;Ii!*NxAT~xr;&hoW==JT`$L0(Eq%0RZ3 znyP9e9daLn;-hxAKHL~bb5b+?cgA^&46a6bfsFEaHrz({Yl*x$_=cK-uALX6C`i)7 zkq8ep&hr$p#2FhKJE_`qR?Jql3`EU}y6k+6om*Jw?CgB@^eJKrM|3J2yOx;ND7_Z! z&A~cUdp1Cy9=$~Pl{LNQ5D!`cjVCd+L#M2po zGtcvEH~v^m-E93j$^X_Nhh#$1($Ypt&FkCuR|f@Nj(j7#MMX_5ih^~C9*$X(-_&;V z!7nw^Nk~eXGo(KrN)<&c0}bozSr#bQ^o~9_;2y<${&wWtLPE!$^e0m@4SrmeTXkb& zG^L@K#M!Eua>?*^V=xvm`Ky*0FD~b0`P^#w%FqynJ<<7aQNb}wKn5h+Avn138)lM8 zF_UDg=ZjzeSS$QK)Fb{LKmqKzl{;l!&Nqvgo#fp(>1k+AW&o6bujrIeSoo3C^_IA! zy-khP0;8~}Gv+V64f1;12)y;#M|3Wr2Huwn4vUCTQ&(>`cXJe`@}`}&q!uadRbgxX%t3}aVAqv2SwDY@e^u(ojXv9H@) zs2wiRGXbFHKWtQU0VWp5TjD>YX%6iFl9KDLfU9BQFcO}Nf&)?#`wcUd-%(4F znWVN-;kqI5@J?-QEtku-U+mF07C|AQ;T;yHq6lLg1!KCp+e0itK%(#OTM&f$ZXWc68-b9M*w*$X==8L9QC?mkk#Q}ar}>r^e>L}n>ha8Q25`P z{TD)G6b6so+$ON$c9Ib}ck=xgF#|g0UjY8bE8Ix+Pk;;aZfR)G&=By32v;N^TvxoF z#uWAk$kq9nzg-*Z;@q3^fE!EE-Q@oLmL~8)KKl9r1Wg|wMFRHq&zQZReYXDOKpQ?! z(oa^@pqffb^&%40ko3EVkf?Y3v|xhg@KdKdi2tM`(*s^BY` zhK7c7cL~&yOV|MUO#@>8f4L+M9w(=#FK0p!8Om&4_I6$jc>f@Tf~=aeGyAt@ z@`MLGX95aZzW9?{hV1+kS?zsmEd}QiasS43V^pW!5_K&H1zrUx)af_#hrK3%FtB$X z|CIo{&TX-w-s?U`%QXKsrzWiTygDu*IsM80=SE z%b%p$W#e&j9~Hm_ex|1bIP$H~+p$HuNf& zfW|v0^UYVDTxBcYsxyO(u)p=nKKG%ed@oh6$IN_%In@SBt2yCqEm@cxTYfgV*h@Bl zyc107!E%MQJFV2It@iGZVD}#CGppUe3g*1@nU;Ia&8D^oFWuKCOqQXABq4$A+rf;6 zNpWPbcT3sf-n#2#@Ax8Y(7C+pP)R4T+PO<97Wrjz9mTrFm+yYwzm+el|KgMmZazFph01N**e;#^JJ^P`Wx(r~3%hc-V z?|Iw^=cecHP!=w=y2{th>f_EBkx}p(vGbCIz_?X!rtW@5DHO3ji9#OkH<0}R(@al)eW)fw z_Bb!Md?f>|qoW1EkBVUX*#LnRKTZ`h1tkN~S9b=_exBV`WAPj$?d0n${<^yXrCOv~ z)P&m~LINxUEIGF;5zn>FJMTK^f)DiRMO{wvo9G+?h6g>Y+N@d>+3Y6QGSkBV zn%0EmxqIQAwG)LeB@RMd5!WKLEmpHj!HB(HxPc!b2YN_#68^kL82ov9zzOxd<9T!d#CP>sj?e-46fLROC? z|E-BEQzLrN8<+%VGYqsK)mfaD&QVCJQ0QgdzzHEjcjA!dp;mXhaR$oiD4v8IeeS=| zuR#wB-x~N2KqQ6$3iNOZxZG!BYq2aEepxBItanjG-z`6ZMph6#Kpp|uwR)R{PW87z zo&p2(pACX;qDMJYBhGiWlD~tg+PwJr;r`eK?spm7HR_Lvm}${H)V)IhEP8CFSNjc{ z4E=xui&{Mm`xn*VPoYYwUFY>-|32zKBg*~Z&eGpUb*uZ^s32g}3%`w8gH870KadDN zlGrLlM)6OA7F+f}zMjn$=Ai#INHRX6K0tIY@AWU}Lq8C5D0`o7vd8JEbE8q$!q~ea0_V zFKyqLj|F33KPJVdU~hF#!a|QK<#(JJ0Nu|s`UTk)fb;bE{5t-Ge0MK+-YMTWV+{Z= zqc|HqTV^cr3K8gUh}ueuV4-$h)o=L?R&oGVl3%cT$-x|doA&Rpng$(Ryk_VI@=U|S z@+X}a>p@eNn>cCZ9~>=Ca@jR&dy$R|AgLd$k^}(O_l(K?9av7S@Fo^YtiNIZmDD3b z4zVl0Kx@zku-)({+l=F&L@CU2fjI!SiRRCLXTBa!ooo#B#r}o^_jZs0jSwewfMn1F zj^1fJ0Eqxxf}iqq(;9X{H#9k?~Zb1nJ{66QF{psm(J~>FePKNyl$m*2` z&fetIAo&Q9z+j4efOVe{ggXE1Q*T>pP}{Z8T3LT}h95I?XrZ2Z4^o5huZ31O`~G z>;3!l-3Q)kv>-o*$gJkKKc4ptP#SVX8w7m=_!0Y;MJ%?XyCi7zy+d&CI>&w%t#vB=le~x$A%~jlmxp;4Oyvx*3KAWK2+()Fjs(4BeUrZ!h1Pw4 z!ik2Jh`{pN4UtX@XnF5;&V2&_I(y2fYt}kem`qe$o9;Qc8>0n^TPtpo+&9Cx?kJ5( z3*7BLxL#T?-tocff-Ae})spaVoXuBotpSmTlUyLh&Uw}%m&B-Rv9i0-`gG^w6v{5D zTd7l>oz7~i$Jm{6Y_5{VoYLs?;SIM)NA?a!555+pV-M6?>dR$KF7e;L-g9F7$=JR1 zLFGC1H$QtOVOEF;?`IzM?XwnMi8;JA&uM$?yQDq!d>oa% zq|wmllx5rOcNHGUkG0Q5cJ0~t+7~?GNr_yi@5NnzUf}+oZU3gMfmh^e+1y6N=^1AA zknW?cH9KuwgNrPRF~Sye&GHa!?J`E!NVOG1zHaQQ{ zS+0-4hNxK$-ybY496B9w;F`*4cCzbUqwETr2FF0RCS(X5m*o6cX^>zR=Qn zI>tRlpskOTFMpmOCHn3KQh^w1)>=JB9v2smKNR7O(0M^nAyS+^GI0e}9Zn?xg-twp6S3@7}Jmoe3rot8S^q&M!(V zE0ch#`3Pc`ZeSQma{Oi%tj5x~Ki-sQtV+K#!M{Tr6_}$M-j&BUctBe6mkIOu-H&o6EIIcE|PE3k&Z~I`45p zZ@;ca2o!9nq9s1g9c@Hr=SiD6ZFJ_xxE;gA6^`;8@T9YUdWB)kCKw(%d1atU{quO~ zh}h?KXub7em-YRZU%zbds6T77m~i3E5is^#9Ch_+OS|mM8%xwmk+A zKC1kNt~?16^<=RkkjL6qPIOR4dz`kj_4cJK? zVm9x8p}$YvG(49ixim{FPoO6pcnLJ+(>@*>9op<#KkVbum;&B}C7S}?dEN(HZ?02l z3H3K#V$2DzEe!tpMzd8YYG;$(N?A@aOf@Gs(}1;}TV2zSF0gt=qpB@6!MH7^p^;fN zFwU`PZ`&S<^Q;|7;^x8OZ85!+#itvSe(hZhWkF7MsRJ7=b+lH@$J>AdMEdRW%=<*wyI zVJu>;LtrwCt7MEP{<1rmBYOP?`03h6aFLAkIREJGf$x{cy7c$1zVNc?4trv&;D~P# zK>l!}alLesvzLzSz})jr)Cw8yioiUXhoJAp!D?epl`O~;h*@B*AELe`Rowu?n7mxf z@u)DA_+_iOKv-sRbqV6#&2no_nFNl2w*|IrJTc3gJh^MLrJ|UAl}zvHq}9S1mxIp* zG->oeS?SleoeKNlo^YHGw5~eSCFq^DY5@X;&RyfW3oxmck1YEQ zs_F_$ec$QE{bD@i4gyUS1|FBcGx_}Nx;2*uytSv9*CIe^(qbmSmbzQUQH06Sw6PSa zBP6ehcXSwXH6bF7E#vj!J45qYsD?a#Ou!OQ6YgrF7spGY9!}f9D;iYWeFvo7`kRlW#v@?CFTyT;RX zP>8!?+UidD1dIE_qj9!3oVX@9Ot+J|A@|449glF?IO1vDx+tE}q{a*Bl|8n0eAD9< zz}6^Zo^Ebnag{29I`D-CJ#r3v*8DZWM?!_JPl)dgs&S4o0Gc)nGAgZc6?Nsi>aC~X z=G9#sAlm&V303;yxq|;adgLyR5T3sOi!Jq>rCP4T#^d^uF~3C-_!Vl7*`Ihg%%W9G{->P0o@b0F)&zLBV>2fXjTk{18 z0|T>yJc5^NE_8jcv1R$P1od7xeZgme5}sJiL>p) zjG&aaji&3dF1|Q8FW=}!f3`U_X5}y+?Q?O@*l<=1zgJTBq#oMK;4(D(Gbk5jfL^xzdIp^gQ#Qu_M0qJ$9X!;U03m_Q-1`B=~!n2YD9viDVo9Zk;JfqM)W>GfgsM=J9X6L|p=6Ita=F zrYrbsx>tw@X|NXU8)^ecJsMB7`#Nm)^`Z zekeV`=q~k9tBx7R=uCe`L!oxO(k#TBXGN0vsol-#F9H0QnIasJO5HSQ<;6%mA6VEC zoTFg$abj!N%c93|=?7+;%5=7#qa{%ne6OPLObmQ>cEEF|;@l6F5}5K4&ZHm7f=GXC zu^VV*J(yfp?|cE5(JickGh5hiCJZej|8$;0UNR46?5MddZY+O0302Z(+~Gl3&=o9V^t{ahBP??xNF=ZVw>%Ckp5b;Q3^`q#34LDy?= zZ#Sm_SRRhXasWCvxnz_`GbA+VFQx!I5=$mQ(am+;e+Q_xe^~?Lo&Yl`|NF382{TC| z;%1l}d3aN~0A^WOoFOtOFa9uTk0(t_FN@#@rU0XZxQi>4$FV*EV)zdOCdl{SEhcEo z!5_9K(2alTg;w@KZVCTxazGn2{;**DnCp*T=n+71e-ZcJw+(F;`P~HjbFM#noqqWN z-ruzTQ@idD-S0p5I{nN4v=wQ)XwPoHr#YXREnMxi3+S2h^t1C7w-+}73#!n@*F@NN zKy~{G5Fh-z57?^rfk4%YO0L84=p+)c=?X0?|Dz3HD$T6k3CjgcrTB_q*j#|X#E|y* zV;-Iq)_i&aw8<0w0|@pXYgh5mHqx;lHc~|8ac*N-V_CS}nG77g`8wwf@bkb4oCYhW z>L1T*06dX5%jQBB>K}UXobEeFt`S=`-~+uVa>y{S>S)Gq@_6EKVmIcHSIzd!hz*#U z^szFf1Htg6eZVH#axG%aVKrM(6k%m)4H%nF7x(DOUzg~g_R!NC2(Uu`G=+i09{=QD zAkdFqr$b!v`a666X|epnn)t81PHnwtIR7wp=CStQ9sTyhl>ZBH+(^=FNp$4_R8^hU z!pOZxRLP17avNSIKYNH~1!qrAt@`C?hy|noTjx|L3DfDl^|4z?XZr2sA7;A8eAT49 zs0Q2+A~*YGW=S^87X#G+Tbck+yuh~1Jh)U-Il?T-kD1Z$Og-Ik4g@+yZ_}%8_SPRS zUbv8UYS*tpGyKZy;(*7&&&BF(BR)Va=Z4Pt-_Lp3`TmEM`KMKlJF%8PQWG=7pwf5i z888ug|7Z9v)%Z8wy7>7*nhZ+iZNz1OYoo_x!u;eXf(VLsqavvG*|GpyqgP}r39N{_ zk&+6WFM&2TUVr)8J2TS80Bs^h8#I3&TYCcwA}GPln%aqYdL95CP2HRCK+mRQ9h;xj zXa-ch{cTK8;Z~Q35vyJ{2Nz>yEO5kk(SV)51l;=sc)s}Z`llx7$KlJ_#tZ+ls;ckb zBoZ(OnvmFa#}`1LFtpgCdl5r{i+4LH&21kzU%;G<27v1wD1|)Ou34p~75EAmwa`l< zM=we5o!`5B&C_ENce-8@(!%n?l>XBuU-NCIfT#>l{c`LevF>9~oYUNkW;E*DB654* z@RZhqG>2Qklsq~AT&#s_{ zGGrZ>}>4a*FhVcb=O$p2} z5k~MWgWFe~pU8+TD-dsG!#yEM_)^UEJj{Dsbd|~NQXRq{iEBDPU$eSy!l#B|PU=m# z`psS0qyJHU7IFQMwE`D{b&JM58Q)=hit{PideLnZh(lcIEgOA&x<8u=1xT_I>pq5j zs<=A+!r%cDG~Jg;cFnEO-!l;yq9@MO>$Y>c zm>^*~0aB{!5(3F)Zox>t6J^{?VE}4U6PH`jJ>TLn$bq1am;X8V)J(Ilu?B#PHHlmS?N6-Fdt>%eOQ7A>! zbzzNjJ9e~ALHL~xR(s@dCV1HnbH+~BMIXg+sR&LiQCM)A_aO8R$@gmIj|kWiRG z&GH`LGT~Qe*Rqf9U9m6)*XM;&p1f#4F9WYRhg#Vli^I@R5-F&BL~}tKXMkVswwi3g z73O!HY=HzfG&Z0w)VB(RjqS3ArmSPA^5n$jqu#n#y-zT&l@IQi_tmhi~M1UmL)pAnbUL5dZX z=|Ei5I(KsXD+$rEK-E{CVcwlew}j>@HRh767o|7^h_d3Yu$!B^l5;Z{ZUZ-O#rLN~ z_BS1j8TSi#ty}TLhNNkDiC)dRfTPRt$RnXHh%dMyv^Nbtla6uiqI0^e$yi#(M{h9q zo&5FUTGk#F;n;W2l|f56d25*+&&SH53yDEtnOo#<`Q~c0&L?qhq<#PfFzOw`{siah zA{yRir<8OkPZ%xjQ-UlT-YjfVcLgc?auO zDVND~ZIIEl|MoeIQK_`C{?~{)XG_?J18ujdvSL_a>jmOx1_zgl||K-@YgQ{jq{q5OX>66I~=a`A3L5% z%CJgU4yep_OWXopQnkNIq^m5vinn}tvv#RLoU~6SD4*@6splkosYH+FeF1OJAW`ni zG1r~2SJpso*oOplI=S%0esd%4a1TrZ+%q|w#I;|uQ4OBwG;gnX{;MB7j(*+k~(Tp8ET^tx2F=p>4SnM)bi(1C zU%wp48uKo>8j*+k_TuQ3;Ttl;6O${Saa}xA@tx4&WwC#-i%|vqLEQJq*$rL8)Fx9nK3l=> zmdJeerTxUu?`Sy4cU(IEyou8J2%l}TBz8W?&}z=Ly}^$&aTC_wWH%Ux%Y{w<+P34EKmi{JXHsAL@9oG%yf(y)8z(t3MkF#E-Y zL>f|TI`$5CqjN>@HvQMm?FBECV-c_R8}54F&Pb~rDlSYVR=nqhQ!E0fw?STWw$d^s zuAgdX4d_s@c`3s>P8qOA>>3Z_&N~93=z5Q-lCa~N;*iU9k*KZEk_6-Appq(z#EuCU zweRg&U2L1WCy}Q<70~)%A6XRX0LyMN5E@)OsC)cff*4S+WCh*$k@aKI6e$`) z8JAHmeL*Gj)E)gM9ewM`fCopYlPzBdxkxvqlxOQ_pi@a3m=Dl5=3b|{7jST z|I)UJ_3oVaQc>K+6~;hX3v3~(%ArM#tS+c(Y0{g$03GvTDBn5KfyRtH7al)6tiUiE z3 zkQvZj?m5EDv^~|dQ#Z&HlhWo-B=y!7#UAU&BT*oUiT`sj9KC<%)`p~ ziGynXEjC?v(@c_&vm93E#O_0ry^ay~40ElHYvvlS@8*p4+0aOSe^4a$3CW%e!ncCYhTLC z@+BMy&l!32+0!yxE7MiSPiT-_yp{eW)B0h@&brL3gJrnGMDz{m&j*Qbs_x3)IgRRx z-#suqOcGJMGdS>O0--hwsH$XdCR_?aO**kx_~`>yJBAl3?>=s9v-?tt{`PqlXpz#% z=ltp<6ZS=bMb2(KptB6TpFJA=rdsL9{@#aAp?X2(3%N;%M z<};IfO9%R$9@BN@2ZXh{n8vRM5Z3g37@MUqQ@3RqT>jR`;&e>_S3T`c7sX09=WtWd zQ@65>qS1G+luW?31iDsolzOF2p*G?T zz#D7%T+_dYx4YXZ*!r!;5wS^@-bB=nxtY+HlAds`-47b80w(^C5_;bco7bYS1$KM7 zwL9WX-oTW``^Q3JQ-~}+ewtW1SYx_R|7=2NymL%?*Zv)1l&8CX%_d@BcYJ2!id*mX zwmsg-mulr;4vtBiD9jXP{k8m|PSK+&PhjI*TI6*Bk4rE>p!{mKB!&hbsf_#m4aFZc ziF6EBV0Pe`m#b!$2_~@ibvxywR4iLESOt?&sH6k&JCw0D<8<{ z6$uQv96V%Mpn)p7yHGmk_iGalW=9Pv$G-Y5qr~X*4%?bE877>=TH32k*r(j-FqnL) zs`jfl=j?r&^reoGhW$)7uYucwkw-R*krSk&Z?j@kJYrKiA6k+o@3=~5OzCOJW1RyG zGWtjP6Ew2-%hEpgMRu7)mPqq@X-D>a+38sPuz-Kxuxbh8M#o}{l$D4o)1ZzW|Lo+K zD!qx8P5x&lcg<7f4zQc-Ydm6$Zi`C!_%wBw7slg8T3e%tPG=mw8e?<2}co|k+P1$Zx2Ne5+2voIDv zNmO8aD4)fEJtX9Z3Tt&N*0tX%S)#*PeM$*6rjB01t)0+XW$)0Oy7CIF(C{0Ldi+a}k(d`%sm_~pJ z`rW{d6gted6oxays^cadi_RUkLLL3DA2_>fnU1VKua^DJTl7@Bo4$$HtI-cAp=DaV zOQx2oSlZj~#1ob>m<{X)N-p8+z#g}5n<6+sV)mq zWk!PSVzFl&^3~+%%MwPn%-G}u!OAiZA3SF7GSDf1lMIVaG07a%M72^Fx4hg9Sa@>% zL862wFkMt&7lm-!^NvNM2bL0%B#e=fvym1`@0VV`4(i5=MTX-%rSX2zviPaNs4!a) zZ=F5Cw`W|U09T6|Kak@6LO9X?Ktk^ZY~x~zjoUpiz7COT7PR2siK zF`BnlKZ<(=GLzu46kg&FTd*w1A85>pxNhY?9_3pB#Y~lYB`Y;<2G>)@*XdBf@C-P% z9pM^=KA|?mW{V97=i!X`B$B1;b+0qShGAPjjNcpsppdafst>E(PgplOjba1$u$x}J z-rWM~1J}?*-q2R2vB4P=;ess53YDg#sI%Hzf+gLN!u3r1VULtz8{fNA|_on+V(x}O&~lcY~i-s z4SXG$dlIkAxi_T!zR-+13wGRpVoe`95vo~Pr>g^F-Y;;P^iasEz!uYi%NZl>%`YLw^{@B z`NZ28)+g)U4{MQiEvj@HUi)RhbGs9soEWa6W@#;X?5yOFS;ov@II0mvQu!2wKNCw} zHStcCZk{E&l1W?6LuHoNdjyKvSHrTVL6s)y72i2x!+^l(?osRFSmlyWH6j9u3-|gt zxWAW|^t0P-;cJ!}GaFn;-{6gKgAdKd_PaYMQ>=5Cj*UhVdLwA60<*|NIVI^&|TTsacg?w2VCCl~v)dV`$Q=?Pa9Tr_u zTxY?j;Ew#q$${ZZUg8uSgHwg<>+U4K;_K#_$#4 zZuU)B;WpV4)x!cgZ)V&kw@LML-tVZmj#34;>p&w9n$rg;?ts&J(K#*xW75c^rjj z7$dbIM)$U;ze)WYg7nt4Hd=e~Q}9Ww=smW@gy|o(bajJEz6M_|eSV36J&xYsb707C zQFA0xS@GiG;}$YRactx5hDMCBgP)|JE8hrXN`>^Es`sTSc?EYpv1OpfT=ocm{Mhsr z8g|kzu5gX!MZRatxq|Vti~U5PJR(wL!uI8j8ZDxro6jjpixC(mEP z$700z-R%?P)g{MfSOY7xn zL3$6^PIP8{#@uabWiweCIRrG3G!#tA^btE_vgp9Ru&y0{vhAZ2922hlSq2x~{{*mY z$UyVk)m5U9ERf#4#t9=;n73gW>%1}^ zC>76j>PX6VDjBCaQ|Cz*C+L&37q#HH=+1#arYh6sG@>g+m4{-Q0royBe2k~2PQUNY3VwiYg*8BW;qlNV#y@>!Zpo&T z#u*Oz)11Hr259eLCNW@27es*TwE$OlCfem#xq<<5O9o8tAh$5IIb3)Dr^huf`Mcta z_g#KJV#t5<$mChAID4y6fk1$j5MrbIl*VopaAvXtVX^?IXlG*O`X3IyzX$gM+xLH$ zTkuD8{{L|gsn}`q%4wX%nKS!$V*YQg)&JP>PmiZt<$v<_eSre`Bb#4mKP*TP-^ckG zv3!;!@yomP1@-UlP>CM*zXjHxI;Bo?3Kst*l>|^mloihWuUC?XOVXsPsMQgR&KqN8 z@;A$pU}t}EyR`+a5p+E{+6MAJ)*8qmCli1!7IRpcT84Mp!tGX`yEU>~hQ103U*!Uv zq*~@x`^%}ZuX4`3i*W>Jc_M&&`uYF#DL~MEXAUTjp$qSc&~;odCKlOyWJxN!+sqU= z_PUk}l6hx#?wxVk|tl(jIYrAZD(rdfG=HZp}YLZkv)`tGJE=Gfdd8#kDPR#TI z90n^UtS6lhMSy5lpnBIKXX#jv_W2$fQ5WrNp^LGuNPM7PMt7o2Kj~FMlD@!U7E#!J zgrl@SW8!6&hiR_`9S_zJhm)>rLp;`AAPH$T?KcgEfg&lG3W#;v`7pH%_Hz^kKLU7H zVx^MNK#)-KGzy9C+`?4I-12hWM0Q&rZRzhH^|vhdrgBy7J#oI&Jddtk(60u`e)x{p zDAl#S?>$n4sWB+n0UtF4WMhsDRv%;oOSG-tr9GV&*oor=-K z%4T_?aaW1!@&2r@ti)BOM$O7yCO;RqepsFPP41$b_jR-&})Gdd4>WQtR*}zp4 z%Uif>p_m&Z(|%N%BK(b15~Ck~bqrKJ*{9vK^C=g1 zV@wpN-VP8wnI=}bBZ54dUC}vRWiV1h`Nzz5i#~7pYsxbmrs==BJ|_krO-=$|xD-OyGAph$4G-nC~Y6b43Gt%`1Jo5kdd{T$v z-{hXOhpY8`5w?HAmx+7{Zt|rbojjs;m57xc18&lqN;@cUXRZo##B@SV{9Lzlk^NAI z(U+xsv4#x+;m+)U6W*W_kZRoaSIswy)cRT=aCz6|5c!+-Q|>r>VLtROM;Y0Z$5oTP zYSjnDxwJwyYXxmLD^_zV_DEIQhSK1kqDNRN3jkf%^+rwX&C;XPA;JLe07&R4uQR@A5`m!LgZrfWVQ&h7WAW3gZU>;vQmjbr zeUY2?(RCjH7mHZ^R@gHJ zfaG``=NtsOywD`-*cI|6%@wsUc@hPm(VEx^#{nXKwI<;M0Hi7T?1+t#d_tGxV_KS! zHx}!~gUA7MM0j}x0Jb#bF@#b8h!DubU1*~Lwh>7v#P?UXvwtB_^e z)Xx1DU^6Cb87WyZ%2!rli?M27R@hhAXP*I!Cv&$Y2j+D_AR>`AijF(srIqthlP4+Q zLEYWRK_}#HEEI)2KK3dG3MCz4(I1KJPM_FYy8s+H{UdtA0ZM}I3PCOR`_)!+;cD=4 z4e1^izB@^xKsCHR7PxN)QcG(cHIk{N4#ZS|I50PF0*QEtn?tF&MG#6B2x3JIeI!sI zYUo7Eb=7>C9mwRs>2CrOK4%eiBM$_|_kidgKKjmBwMEy1E~JLF#Y$g#W={D^b1>67 z%A^h%=3*NjTm;$o*#qh;t#Y}-+WPN1&O=bEuFeglYLy$-xyN57VYJT4hzt>6z3S&C zbj~R95fI|?zvok@>u-15IB-h>M_wA4c{cbBAii-i7eGJsbmU|CFA72~DSgY%3?!lShr{3OL4{(e@|XO@VYG zBiiGP%l}z`>Ohg!0c5!GJzio3Vm0ouUo-v+Wcv}w^dD#W4;^cR1ekxMrT#~m z49HphDfR!ADhl|z&B7i=-`NI=9Y}u}1L~vDBbH?LrPhHumLvIwO*bpn3Mw|r<(=0e z`WUxsu!yyRBo)A1Ts`|isITey?@5cG(A&nHV@|sru|VyWS7r0zzzxo?R@&DD)Usef z2fLwN9pD4`m31!xD6C`C6?Lo_3$98pOwKtrT>Xp5v50KZe;W zMpa~>YjZTBFjx66$3G8?i3NdHeleZ})e^s?V0C3JM*v0=Co|dN~_-5uCPz}cf zaGdZVMf2f6!u1hQDr*Pet6yFA5Fv2540tD4t#XEx9Kb+;HO7IZGk;5v{a*-a`*kFL zrWk|%3ZFX@RsRZvJ4J4>gvwF;e-9V^Q$<9#o==H-{-!^1gKR&nJfW0)0x0%&)=K~umr=Fz?XqIp zE*eh&R~9l6K;EP6Su~3SFwA^q_05RxO6`Wfgcpzd`@d!00vnXwk7k01!T*P`w+^dn z>)MAmB3&Zg-JmoGg3=u#vFYyaZV*s5-QAs1(jn3z-Hk{$C?&tO(Q}^jocDdd>w~}c zzSf>=j4{XT`@W~o!3@v@#=Mr@hb?u^psFIjZjNRm+wOGrT5pz)4u3tbs)a5XfN|DR zP_+1;wVMUi*=Sh}K*?}h58FB$0kWeL$c}ij`=7lR++ATKHyg!uIz3&6E zCi+?lr~`+cu8Z~|*Z6V`syHsD#Ejtp_zxImkS-8Nd?zRxR_^as z+P6|HfpL4zYZj@9Z zX(O-{wrx4-Da`a~x>`I*nQ7TN1N0ezWmRPZ=KMX}G@xsEczFLvrukx8^EuF!Zi)N> z(?W|$kiHY@U2*FB9^gGZRgM8H_ngnoCM{H42X9g(v;OE>` z7EVAX7wNrkSm}LW37sJMeCG#FgAN}+u)tjWw@qb)+Q1MD^wu-LVEy9)5C8)Db&HC_ zq9pu@xYU#C7Y)xYW-4As{-{0lqo13jJB+R&1DY5R(BCY58vHNm6p#w_Cj zOOE672T5+XvZwQ-X`)b}G!_`bN%@>4b*)tJ0mLyd3wB$2_3d|Us6uRjy$nx4-V>Oz zL1(EeClRiH1Izus0lSQ)Q204icCQVfC^m1#$ShyhHwauzz8#(-`8~7La}Ni~`@iK* z9D2^uZ|(mrWbx9`_P;b2z@*$&RTls0NST3d63q2G>Hakts*2~xINFR%{l_jn;FjOF zWKUR>CqTCUrsV+oFTi|6dG=Zs-PQDc7Y@ zq4zq_gr|P0e!az`g36g>J>E?Znt2L3W=~-0&jCjxuONdveq;TgZo58RmIZZKGpoc1 zS5rdM!jcle<--8dHLI5Y{POP!I5&;JLf!C-2R$GQh``*xqa>ZRBIU*b1LBb>q5fd- zAoVgM3Q%mC4^fbw(}7m?`eXAH%iw^@Jc&RAflPqtfgV?FN-5D#2LQdNn?%sxd!Dot z>ANKb>Cnw~t2$-{m#z@`fAU`Z=A3mU-Cn?eh&*GcgMYuu75Xavjo_dkSRj1k(Wp&@ z->(Yz>s3ELn)V@|7B-3b&{#aM0?46E1L%%0rd}*tK~qNZ15RF(?#3|vI9q{OuY||j z>6O73fcGR?`@pKwbLl}rI-&!y4rEZwB)ysv0PfoQ#>5Ow&y$DO%=l8Q;lP33%}s2) zk11@z@#b~M{rnM%*0&7-nukuHEfs*N?_l-x(2_X~|AgVgqY9N#apV7w=LKxMqw%tW z4?*UeBijqY(0Xum)nbpx>4NrxfmJ0Kww@Bhcsl9s8?(jyv?9FzN_E zhOZwy0fB}r_pO5(utE5GqmaSTv`wFf`BNzc2$TeL-=HTQ8ANy)FQjhGpu<7syZS`N00xhG!V2gdD_O1o!61%`VL2X_i*V#Gfu1MjbCbvET`k$YQ z`ZW`%8TvKV&x3=9z4v#~}f1xT2UYV2JbT17UOS?1?%unCGSx@i`-? zs+W%G8LMN={us1Lw%|QVO6S0cF7m^1Y|P^yDXou>)0&e8LTAp2!k`+*EsCc& z&~qS|*PzU}PqnpDDZNmJ=6XKVnAxkxq4}u4`6p?yEr*4#A2ddU1xKAqzT051UgQhz z7Z5Th6ao}83tqeL>8_VlegLWP>{Lpano;jdS|w#mDX7E$Tg!{OTt&L;Z6?D!dSJ?M z(R4P#5A6IXeDsIQ;uMq$6@@EH8ZAYvWCDE!kEFi!#om2yUmYHuqX>}JrH^!qv4HL| zu7?f@>I?K->JjtzVRI|&-KJk9;rcmRR(exKORY-qJXJlMG?$i8suT48OZpzl$mwo7 z)eO&hV;7VU^?OVk{6mXcHcqL@Pj|hag33-k9bJg*x!4LnOQ%Uc5-doViw4kaJ%gNZ z_1_JRc~^=yy%f)!xk{SX+P3;#Id!cF$YAsgGNeMa;L76vn10+JV!SEK&hu2|=iX?} z+(aa384+e^kOL{Y)KBHq7h??q2f{s{7abAj0|s!Qiu}giXej`eiS$GK?`3&iN2pDy z9vTuKA~56Ge+g?;h7XN@66ZaE&Rz{Ul)|D(bdSK-pWE;lKRd(;08mdupv}@`Gt(bn z!7yI6haC4j0-<;~QvO|(p7@|U8Z0^Gwm?uKE~rj(BozyZXa|}Du0kLVp5WJsThl z)q;xBeF@XJ^kd4SA9~7X&~PvZyGxfjemxN425+aU0oRSCBW69h zhmZ)pu=}T-z&L=9g-LkF_|RkK2p77>M+QFh&?*5LThx(0tQ{{sRh`2WW>xShn2``Z z!uvIf=8>`ER?+_POv4O4jlnd+xzxce(f*C^<0eK_RMi03{zn~Jl;ao#DB#%8#3##| zph+f9n2|Wv=B1LnC5vYeGvw&au{ZiJt3bqkn195Vo{WjoK?%6c1Sx|Fw|e{u}|etTh4ONAx*kI84B@ ze+x+Onf*>k9$cBoA`#*d3uqT71!O9nWZe)(kQx+;Z0MKeO8y*_B%^grVGgtR9w@dE8UHrQbBJf7&QONt%B-1eqkx;@0REXa zz!j#v7>;If&YZ*IN^Y0O5p;dDj=rWHO|TAm8kVxD zn~hAy_vY|5rC%+9q3ngMUn0Xvqf==tRHX?khP|4}lm21!*u(rm9}L@p$O_y;zl*qq ztn!DgHC=*c?L1COFS=f{`UYTMpI&#CqWBSh$!{~qDmavTCKG#a`F0J9uA8Lq5jem4 zlj_U@EQfTaZw7gl8ABymOB1N*jn-}|xBl+(=10z}c5WO&d*MZYX1|LQR0{)N@txSw z4Om>3Zx?}Tcp$F#GTsxkvP-F23AFb!1zmLVq5M&B>&7m{XA%u7&g4J&!LRWjz~{vhA`eZc1T)aV7#l)&4N#ICt=6tTJ#|TeTc37XBFStvYkA z_1}h1?!=vlTg_wv>HgaqN(KVk6073tWI>KI%_3ddPu2~BPEcrZU*;J{viGT6;$vDwi`mZSC zKEFef?(susy%-IT7LTd~2V*3fx#)Eoss}wvaAr+zc{>~ki%a((8#b{DcJ+H|hn{!6 zSNUldW`cnGGC_=9PaPq)UvLUYR&@t}&-n;83wfteUQlx+Bl1cN%mj?$26cu)qPg+; ztdRY)p+MLKU=0O2j;9&xHyxZiV{1pWgf3*uTqFm7G)OyA2K{+1klu%;X7ERDRgA=2 z{qX9N0@0_M^~{k9?C?&0!=%RDR~l14vF2_Y44~&PXgrH{+h4Px3SpDQ(Dk}1e}XWd zvO4lapWrA!bo^}^m9&kA%IBAS9cl?vlwe& zbr_wG%s6Wos(lXfQtI@oPTiZN9fiv$X%dj%qd}axeB9k$nyt~_+bq&A9|W$Ta#&EEs~5Jf)CV|CyT0!l9XE9~ zs{Xvn+S;>FcKsX(Y`ZsN`2PH?3kcq)j*f(5vN#SRfoRX?*urvWA;LWInr-ldit>D2Le8uz@OA)Jl zoKHblXD)J#UMWG9uuQ~XQkb~au^dFdCmX) zE>c*oqo^N8*6PaWNBE$)HbL!00$z*4B{6jTLTf1;`n9_rrYA7)u@8-7bW(r8u+QKJ z4-2>+u&d?QjI84QBkmLD+}! zlgf}Nuw(diSqZ^S3I^Z@%G_k7;Sz#TT$m_k259Y}&NF>Whn^TbxkPEj3h;HAg}_k&jkqalZY?^2g46g5NAIxQJj z2*IVtFP?rvFSC{excqauF~$@^W~$AA?;hq7)=F{Ws zJLChapDmtid|$X7xo`Bud%PRvErnRdHkEfzh_J4VZ^+DuaEgx1>8bpYnOc^k6sY;v z!q16PO;}iB(Q{A*%Pw=A+lG&BGn-w7ve4%eMGxVfJ%3peheCVLBH})NdN~S;{((N5 z6b8V1xThX-vz(UZ$xcs7Lwyjk=CwuB|-rW-~ zt@4`ct$D;9q$*rsvS1RR%JZbKi`7v3MU)5m@T(qa6meV$afjF!_eTmb{9$iqFB4yz!e2Y_<#$P-}VBwZwgb z^rFepeb;?7KD5rm$Jao*JPxQNSV(A{rz3Hz87jOsIoAA6g$VKQSnp`+WAWQeXhsXF zuq2lcj_w(EAisH?Vj3P#5C*({-Bf9YxbhV)5Co&nN+Zfnq{aIEDW5rv>LUCa)5%WT z^bL&G&W?3Edd7}b+8-_B8r&8Q_W#hw$$DZePPs>w_%nHu>+{~(zTaGbo1qoakAr~l zRZ}a$g~7W=BN9&t;ejwXM{9!2S%~UHX1IW=kTf)Z5#_BI5cAp2&5AkgiBwHKQwUEd z)gu$SpAprTa}6l$0h!fTR?msxytZCZqIOw=O34YYksv=x#mg+oh5xvc^_V7Ptz&kQ z23I~bZ_a`#q@nBWqb-`>MSQp#_uqAI8wrFAn|jXCuX5bm>pxLJ0`rc2QZQ@L<+9O+ z&1MYeOh|y8Lm0nZwn>eBlx#SWsm@CgV^UiFa{N6_hnuuyZ>14(=iEZw{=yfp(KkP= zcG}bM&!h^)2{Jn+R`jd{_8I7a*j!hgmUr7I{zLOMN&AY;jkW6#tj@n2Q&3V)yo?-) zn3TB6-&66;@7Y!#qIIUD6RDLIJ7jRlAmfaT1gZMM&-f|ir`I5>hZtZPDxfL=i-cIi z^a>tBe3pdCvRCs~nMQ$E0V(OjDvEgFH$NR(1qAVs*dJs-DV{vzUYD7-ae9(P$jlJ4 zPZC^$U5c*Cg_S zL9B)x=2|u%u3oKo>q(ZPF?T=qCtd!c2kFK^`&r653)V)bCYP+~ouzza$I&%QU&I^0R6tW|C` zZ|{jNTprsQkTHd4?HZZNfZw<>e7?__$QMJ~Uqn2mIt~K;++(hnDUF_>^{V zA*Am9;I+Qzg*}jMALX#-{993RUCX@5OOZDqa9dT2Ns6#D5<&G93eKYj??M@CCR_$Mc28-f);v6f8{s*;RI#NQf+4Z`rnTH2Pg3g#P=@!94+p-) zW}ge^g4vI}f3O`VsEDahv5%rozqe#;BL!i!!kJJ*s^Rc!SXsQ?-|tMRDK3bwRX4?K z2(WTP*jh2B2+Urs^*k+k^eve=ON5V*iRelR0f1IO>jdRJ5|`3W=k7Chm$>B!Z`SLD zOGF&CL0x{qFJKO8!M9vl|)x<(uQQpI^BQl!o=PM!sCHaK;(c$c8*u7$Aul+UTfL8QJ(Hm#j{CoZx(tq|5=P zsU=bIQKK}$dVNH_yZ^K z=PvBtidc)ee3dM1rQVf?SG7zq_kn=jsWvPE8 zXF_%)Ou!-vx)TDtw}D3;Y#VAr*3h9=P272fpduyQMg$#j`ob{EgJ-3d1{r_ z;9BKfDxo>k$4GIF1A&s_OM2;Uw$0p-LFXKLGWEc=0O`jCK;)O)>a4k+sYDRk# zOWNp71dN5YjgvY`9ksRwpBIoDtQW2?ErC0ey!i1beQ*-69g?4XLMJd3t`p6vVx^T( zQ1c8;DM+M5T-mfcD@~ruCL)l;r1-Ir0FmM{RJl#vO;}7vKo!M7qlYBZ$^JNe;pZOG zL`oG~G}C;Q-y2>^d5u4HRUrV8f1coxEhmmjA!&DWhg?AmU&waaCSC#&Ebg;G&*NNu zs}?UsYRDQ!dI70L*y1@cJl-2oVx(Oe3HYh=;Y*N~V0VQ`MH0EpPsN%^(mvZ5bCPW% zu1Lpi@po^7002Lnq0%rIXS5*PAU#qCZCg0QJDWpgSClL^?9gW2zT)fG^STe-tApJ; zs#8BS&7K46I5~T@_7mpciKqobE(IJ*>qU9~AdeK%ksgR1voPhF_d$&Nt4% z>hgN=yk>tUH(z;ZZ?St4agdCL^R*#0i~I<(~i0Y#wO2Qt;f09^Kp#AZ4lO*Nxdi$br^1>fZ0w0 ztXLk1x{NR?A#8C6xO4ve9o8pHWfqVO!s(sWG6zta@gw}y(# zIvR6jj?|Q+wIm8j~uBuXNtC?VugtLmGQ9#4?^{`vz5ae}Ms)W)Z7Fyh&BS&(aQ7`4!Bs;- z_1?a#K98~PAgdtNVIy+7T;wTZYmw5(XHL6fEttRyh9+GT)>jhpqi$Tim9LF_X{W-! z^?k9D_LV;*-#`>Aw%>(4*-8;qYri}qDRp~hp=^wf+K-I(LMrGZfPRC~y_=E*QFxvS=BfA*Cm*7&xepKi zRe@*WOF2pBZ8a*gRaDO1_v@go%16__&f$!>}?@VgIBDqgPSG zgbhsE^ij`Sww*cI-6R~2KN;srg6r*Z>#-4wOXV-v0D**;r`D*s#X5t#!k&3&=5!U6 z%%9)hdPWj`XI)ZV$Z>66hMTeEhx6DvAHz9QVgu7urTQm=B2h5w3e zI%TJw`2?Ow4G)W-tHiUm;AT=nB=bOobHn&{%uW(IpZLY*;-sV%kO#8%Exji=th zR%BB@<}~_8Ha4}6o$zVW(Q7v$y@il&@O+cs%{`5?Hb?CEpJA#fr^~TKrm#T@ z74K+Vb|wN`@xly~{YDSq%?WF{Q?A9cZ$d4o+xEKI6b9L5XFcbJbSiCbyTO)CnaWaM`=kk59f) z1FbI$G1AVP$P7A__z5QDlT>}}qe{7`h55;e?&7Bwa|#Ex0k+;IBWmRgFJq zSY*oGvwl{ZdftvCGgi>3Op&{TUuJC0*sI4x&MLP=yEGh`Xg5s~p5F(md221r`2p@J zQq@PyYjh>4Ld%q@x2=zzu{C_2_3+a45HD>pWAVxq3c%*l8|uN7!CnrdMu?}x4$obR zB$!~Fe{ff|Dn1obnM4c6o?%fZv}{{?Uae+)U&_|>{w`EsdBJmZkPC z^u$fA-?Nf-s!3276&J(SL}Z4qXxl<~)45Ai>8K{+WvF!?lB+$dXLD>GL$&IqhmzD% zB%<|%`m#<(JAY=xt>)mD@my!t;Y5$2rCidHn_&SWanHjo329y?`NU1SJwzGSqlGWb zU=aG1p+S|Z84g*$MAY!AM{q9+>~lyQyq$yjNr{IC_mizprEa;qM^vc^@P@8`lNdwcoKAmWRs z)j`f%Iu>u^q-#|&?K>u+GG~&F9m41C#}L7VUwaD(|D_#oKwGMDZ9=qv;)X-Vl+R z&;J}Qew&%Qa8|Ul;4v?EAZ1>nJ5$KD{`|l| zX6BI8rb2k9ChnOzYE8r|v(3-O6Fsk3{kGu+7~vOf=e@bciQcf(LN-afu4gqi%c%JbiR298L-Br@m={uouJ9kq{Vf_X}VGNkkC4 z@5tzS0OTgY^RFVn!HTPF(IeoJlnHsA4A?WC*(}rNP2eAhPt|7HH?z8Ty@diXXl5MB z{4uZ4*cWp401-dS#`nQ@%Hi0{THI|)2OjnNul(xseB+(QyswmN6W^>vkl3f;cx%+h zoscCl?&yN6@z5;>DBto&m`u)KlI&Wh zv~+*f!ON67tx4FlA1% zVcVf(3`G|}T3*>A;8AK^7CpVqqXZlT3k0`XX8Y%JraDV5^#Cgmc=fhj_7Bd2+m-XV zz9+B0e_p;&uLGK6OzZJ>L+kUG{5V5r4lIUO(r%qe_Q}p@`&%0|9 z#qwIUHx*wohD@^M$xhZbw9jZd%-p&2e|j?ZNg_Up4(E;7hl-@&eAhAm;vTB`Q2}ZJ zj>%+gMEO*H%}AC!F}EYio~g)C4@SWlsUea2_0!S^r;k!sNp4KD_{> zzOKy#8wd6r?@ybm1ic2-JlpQns%}*`|6Df1KI%$lxO>=_#zQyI>FjJ$zHq0;&#Pv7 zGxLDL8v3r4zMXp&=PNiBvXuv1J#&DwqeI3>reV^4yEThcO5_dP5mQ#dclI2h81~A) zUSe_O-?civ2JVy5J-a^4&8?WuD8-6AZ3C`$L716J&cBVgcmJ`1=A09`6|1g8^lIf! zLi>X8m0iWJg~t77?PJ9oZ`*(iZ}ylg<>4!t2Km+KetmOZyIfTFDTSWeImW-@ogus3 zv$%Bh)^}{X8ECJlFnB(3r*`&2jVvWLt7*X(cEI)vIx=bXlJ z;ZVdjAWruEbh)>>X$iTWy*cuZ{d%yviT!)3p=+C($-akUJpeYN9OPUf_2N)8DHT|W zbB=!_JPJ5Z-SX`F{J_Yc8)^QhfEh=3kV52zn8nlkofKmOl|qKQ1VYr$8x9Z`r!NpK z4DIat%Zs(Au~^qCJ%n${`4=!q{D3ghXm^u;Hy%>D{z-M%hcEJMiJNAgEZ3GUr?*y! zb_$)a%C$c!kAnO=>$#{p;o^P$&b*RfX`qk8`D|uG-lafE_p9Qs@5e}tIeFhPAZ$&j zAz{@iKqSf9_Ve!uk@wirY*q^KGWCDPy?OVcSPb8-=45bMzDT_+RCymKT*dwuaAEt= zcflWx0MEzkvL>_jYAY3B*a5DzN?fosG6#(24f9uD_g_a+)ZP-qi<^=hZ##S_ty936 zpjn7TjK+azB>dvhZEQj$5m`){fV<$IAxE>ozYf)#WZaD46i8}(mv?=!@1e$SllSY6 z*NuB~DcSRlg0K;OkJe6PYeapRwP*E@_@F>}2d5dRLw6M-XP#1eZGoYnte$nkDxl)@OSv604eC!k`m(7Oi59+J>3YAkkdYuG!Z zUE&7J^B~&_zKc|#?v$<#o5Boh{aDRPycHJaQ@D$)&K#Zb`S8uVF?>seVuhafI97Un z)6Mu9$n8XAsp2ii$sGFxKFkf(M~r@X(1R?2AipbYjyAhK;6IJ?y8jD{j4;V&O+@H9nBWg zkC4E(Ad_eFqF4KdC${*rfFYW=)1<1od{=6f=o=%yFH^$aP>>;7$ecmW!gGc)6B(cD z&xT~}x&Gg99d5*(FYL2ADKcmTG>HoK4mGOkjE-oGQEQF~j@NAl4CH=L$_>X0_SA{N zV`yjDNx4&%Hi{dZH($}eijl)e_Sk{6znDWj=xX-L2r;&$mceVR4P>xTKF%ebpLLwj z?H8EpOrUC-P(f#e=cb6!rkU?13=7ho0~4V;_5|%}kae)5Ask6cVwBY#ug*Y9k? zCzl3+8AnlSRF}I=R=$QM(a?g!vn5P#3~Xd_EWX_~X-+s+nZT z4lx>0IchDzq@3j1OCCK%>s?qd9?7JA_LAn7z9sdU((nQyBl)S}8*bb%XylAITl~UH zcMU!Jwz-+7!=C>DG1Hikc~ctR%CwW{Y55;vOkniSZ4`9)5IE;oUX4uDdzs}6iO;}V z!#iUs@&2svZz{&Ysy2Ivm!d0@x)|r3ZeshyGVvAShh9p1V9&xY{2g9Y)4V_so<_TM z|MFs5tF4J)+1D14(Hu_{rcWe#qQEP#F#2ow(@!*pry@E(a4(!@$HNn7V?do)O$x9j zex0?ZQc%&Pn%Q@1)K8TrNuL05UI+MFdIozDY@?~MsX^86Ow*iAXHw_znX$RHpTf#w z6nFSj5Vyw|4x}YBNZ?G*xUH?S9Ssz&l#X4z4ixf!j9xVKM1yRrQ6o1}$6FurJ}U`{ zUY4FxOOdkzcCQ=CS7SfbdM%7HJiZ&wv@myJ!VQly%)7ncb7(Ii7oeyN!lLK)C?p2k z=~8|BJimi2-!kLV{u%As6^l2^AQurFGDcJ1DtK8w*=5v9B^}(3&5VPvOzMZ7fg)*; z{USBZ*#5?;DH+n~P!sNkZvC<-_L3MJWw7D$(O=AkQ;8|7PQJg}lZ%hUdblRFXbhW3 zvSa)O?#$(a4?!nQzkx&?vM()|5xs>E#NdS+)y;Ue*YF})sUzt8!wCC&|HTG{ZBWtl zDL3MIJh9M~_&CO6 zuCg@c)OxsVHm#ctu$aZdD#Oc`7%6EJxslAH(C-;B2_RZ#NQ40Gwr~NKv4OZnJs`fy zoO!0d<-M2}WE*D{O>8iXkM@WKo}O_Y6H-2=R71rawqkb{;HiO@M!c7?uT)Edw2ucl2RMRC-=)KS(yf>eR@-* zDxbmx{cZ?r?X=$2rwW;ZLrF`)AKqxtJ9sN?W30}%uyD#;D|3j-z&H3DZ8O(B5 z=P~xw<--RDoQW>iYEQ*@w$<5g{M5|tYp8kjI*Y4nU;a`7Legx$l*ou=Z#xHg_(V`anS4e)b`C04ekUm8g_y)AFt zEH6$dGq319jW@Wjrw}Mz$rDPF z9RkM!Kpo5L4Sslud*Ew0GRRf9q%|4h?s9&b^ZIP(#Nyaq6!JBOfxxndf|K@kPz~Q& z8p*Z1CyOgnf-`sk-_B9BzSDm9gQ08G-n7H8Vuef3iqMnP_Axu7S0lV!4xXvLcJ_h_e*l?IPs3%ClU4^z*T@v5x$#u@S z*E13Gjh&kCuk7jShfEubk_wKBHwdx0@_7;o3JIo!c=|ArFZw`n{H&?*+^8#iy#;;1~)g=h;Ac#BoLYG8M@={GJTKTO|)0t znSjs_n@S0j%%u)58`=fN4jqWL>P>xoo^V=iMNDbXrIX)9&Xnds3FO*o+)M5+f-Tk0 zYZjH4!!XmgvU)IRCDKFDnKGZ|C`VElP>%&FH14VML2!9Wq57b52%5wBQYPjB&o(7d zbv%RtZK?010`JfVKA}|ZUJ7SZZL2%w;m8bI0P>h=zSUb+nfceV7eYe8j{Q?RCdhzD zDA4)1BimS{NM#h@m1*=Cf5c`c3i*_TU#g-X)Y;F$D2-0~eHOlb)Inm-RLmwtL{l({ z%sGa&jDe~!ieBY&D3O$C`KO2`lO4_xz4nC8^L8b*rj*j^6xI3^8G(e#@i1;dNJ|4b zC&iM<@UuyYNO_T7aAnrajwq6w8?{jnsj=WX9O^m6geIQy5;9eaaJs>gqi+*t{?)#InVlKG@On=a@6Wg<4I>mR*`L66 z-N86s-+Gl5@ki=KWLOkoCV<4nU)|!$Hk{Ud@l?5ZA=p;Tv$2ScXd2VO z@l6dLn}1WnxL1Z~dvh3qUPF2$WUD6LSE{*NoU&Ab^#IGszi#kjcS5l7M$}WRCY#_l zaBsxK;_mg7g>vn#A(BHuqNy69gD3-}D1;@kO^IyQFy1lghhK6SczC``=7co04nhDh z@T!ABi$kOvx}vM9hz0p_KkpYXjJ3A-_ znIq@2)de2{=&!*`pXA6bDE0Ne9synf_NY1a$0#p4&7CBI~ot7cocAG%8Y4930lK zPs@xr4;SKFwI==0#yR$_baA3cMTiAh%Nv8@-@A36yrCeG4`OmCVm+#MApXfBnrsp| z^c7}%-MakzWKhmeaS(I(8O=Sjaav#L{USD#Rjz znp^(V6{RF$+Dp7#*pQsTByR)aCXS9nE3O&=`zis7Kz96MD%x(1ro!VroAZNZ%uOqG z2P@ymyj!@*JI<;msR5=ci}jdb_p+WlWz;g!r!dEH%JyXif2Oqfp#EKWd<5YEdA56m z8F!Jit?K6{tfsvLr<*<|n#(RD!c=|2$0x38!z^!9hIDIY827C6Ijgd#pzRrzIZY}eAjvuJ8+l9-GH>b5 z)KKqYVn3BSp(63@<_0Q4>LXAQYoco=NMoPm9U)Eu{3FX^PJzLN$GaDG#h)gk$watD#RD_SJDI3|9hW0Y=y z$39NnHPJX}V$t$aCx?jn1za>~wHBjC-In7;PN6}?i}1Y}pfc-@Qc_l8y!dVxcVPo%k9t) z;?rqH6Yxu$mlR>=!M~k!0~ujgH+`2wv~Sg9bS4UKsp+(cwuTI_AGl{O{hEYpC@V1= zHtqOAz(UX^#YrCKVx*+MWpu)OZ23MviB|QkhZNar+#s8wE`wZrY=Gpuj$JsGvpGlM zMG$j*6Poz4R=b9g2)DY4;LXMafDORK-wdxs&88zY^iAuG zY(yx=zIN`UmJ#CbB!vHQYbbN5(cOu;6GM8k@P#j9s~)`jnAiRL(P?xe-*8a|pCl_MjjO*zza27E7p3BEJ?Vz0)rnAV zlCd@FVHSP#m~pe_7)1)*{xg1Qo~BGwjnB8dt*)XIPYXtnj7iw0mC&;WF!)_xURT`6 zy8Wst=^!Ox^$w(vll4wxXxz|)io=BBDY+uu&HQsZj&6uimC}Op`0xc29T!4}2{WwG z;2Vd%#34V~fh(~L)DOMDvbUrAV{ek;R}*vYe8|p>fk&izPa5yp*i`T%BqouxvY5MS z`P;87OJb3Ex(Yn;Ya`*b?6rvMSiKxT&*(CjVIJWE4=>V3kqKO?x(B^fl{w&Fb)L_*%vYzuLa?LJ(Dqf zuplW(G5nh~x0>bH@KD{8x7Wj5TiyMUMbEHf!8AF>OX1)72RG_n2?eNgb?W(JE%1~i z4L(f!dc7bsiztBa`LA#&FMl1L)zFf0Wa*Cc;fQb_5EUJV{W`T3#2zbhUet8qu$-*i z40`7r`+AF$rZ%V_wXbj})8tJV8C0FCG@8ldtRmo358wyGoeA+-Tv%uxLPyqwa5dnE zo;8hg%-M94oUs*dN9f`8a9Tl70&6nN752>pbI8R8bjL*Q<72yJl_z7f;iatkd*Pom zm@%VIKau_YgL+iJ`{bV7eGZMC7FdAo4-6l zq#{gp#p$`oa2;ZZ>}anrqcHpMN}$*E#3;oadb9yp9>4_nT7hntdsD?ilpbxa6zjj(YQkK$Lb@DVYne8q7sL`W_gHfOuB<=*Ng?&C=o-=F5*;On!CG*S zJT54%u9z#?2M_Dg-Z}_r>1n?i4S9p`Z!gnZY#7EE@wCk937?v$786=qWS&qai;vlC z#$$|Pqc43tXn7Urs+W2pUy7Dd-5%QA_VKLKpV?B4M&tZ~W=OY3^)C7Y&2fDPJo>=y z;@v2I8`YNX45{AKw;=~jni>L?j3R0=od=8QrXunOJXF00vYG8oK%Chf`lrcsRoM5l zwt-J1wUIN|;Ts-YV31*lmg(yD&?8re&pdm7sT)POUICt|P8d63o_GL=Ui;${yzg)% zPdM+QK5$c|62{J?RGXs~n zN3Oh&U3&bVt2cdJ_eeSXoh-!1*MC8eH_qO2MsU|X`b4A!3l zDy%<+WRiV?NR7{@uZ4IdnR?Z&FOJfODYSCePic(EcYCB=B6vYg*H@r?KWBZbmVa-t zNg>(MzCd@Sb+x19Uv=*6Vr2tK|J=u2TB7;K8;WYh7)PkNOBk;78>VoZnz0hI^oOpV zyJaWMc&U&1T)TC~%qmBpM?Ml5THlIaT@+oKuMvLqE#m^(w_b~`jkpivE=R71sn1{& z4u#&1N>&Z1*L&o0ogYWM6uZuTl3e=CDOHT{exn0%t^LuG9oVGj7`0ByVPIbDX8`lU zHBYH?IJC&HEa-51-=s2mDs$2-ul%+N##=7qT`n#AWV*0;p?P=Au0!T$WUAjjj#uUg zNuIh#44GM4Hs#sXH>r>`m8oZ@b4@9HTO8H*kuOCV%D;};wI@7WtY^T@9?QLYMMhh_ z>W!`QU!`@SblS4rr*bVYScS*J%R~jWxNC`PjadFdzV)5G!mA9mTh{K@W4e>>NC#6R z%_FxW@=a-~&N6iv{Ra9uDT1}4Fv=!?#`6VM4i-PwJ#bqw%}fNXvLlWmLO5pm4@F<8 z@WVyc7IhKfVk9aQt@?~Xi`GHWZg*nKwN&cQm=Bs89w&~4H2_S z1jW~T57#&Di~5!r@GH(|$4+m3%*e{rkM>cRDn_FWLwV^#Rv9^lQM(`k$?U)VvOayA z#>wC3Gk49e_O({=Uz?6*+|UBlw5-)@*KV@J3X<)k!eKr^akg+U6FG=e-Ai`6cc`-0vcU-%KZ!pew~2haztZDai0|g4jCvmB9U6 zIpwC7%{ZOp517I5BM@>S}Rqh?|U9=|b7&ZFzAwMF?MRx+QL1y2d=6Y|#}#79+JC zbU=*=inz;5`Ci0S^=^us^b+4YIOayjcXtzl!>tZQ|13zBkIIBFnij)27Ej%yz7hZijc?sHU&>r6BVGVqKx-C6LXxtbRFO!;0J&w`B zrH{e0I;wsjt1DUW!l^{X;73HwOCwjT`ncR&<26miSIV4R-)_N-$P^=W9NdGg8bKe% z39}bDO;X3DEKgW~%2UF1tt&3JHvI5TiWGt3;w1tAHdcX1_Cfx#co&gu)hLA|=&Q$h z!L^g-dt>mY3pa>*1c3xX&n~$U<8m)+3SzkSPcNXmHbg5oJ;3& z+dbpPKQh0dF*BohQ;}?a+isX>R7Z_;{j&3|5qU10k=MEbAZ{?H-}L=afO3~6t{|e9 z$LhHHidm~98D5vS^;m<8Iu0Wbqxm z!%~7$m{1z$q4VUS_~;GaVx>UF@k7B3Og#JNuh{EAK~W$^>gPBI^*#qmHX$xJ0a^hd z_!jmsNEb@1t6m9UT*)X@Y5G4S^s(wH5X9f>w^6#+qVW4)MB0Bx9R->Lq8 zPmukAEB%iZRh|JJXhGWi|Dpe1MOpd44E4qf+8h4`Zjy&L27P*e=BAvq0(MYJnDF1C zY`+K6{$ebRmV^oXjt|b>(EQY9+whm#lUZeEL$vR|#5f7+pPDHN`F`c3I0F|zjX@9e zV(|p?-|@$`K>3~k%re*v9UxP_3liQR0;(OhhIX(uyliy^oA=B(a5%NXGS`B7E2ujU zk=!Q*$aWM&J6hJm9|jdbXDLw<&n;O*w)=(lD}jcc*W@vyJAHT#IQc+c2U5gbqR@F9Q~+a@p^+$vRR-4I0LB58KgHD#pJ8&9t9l%jH1f{ z06c~LN#OFv_MSk9?=&(qg3{!zZOKo92kc~dn1ace9(TeCl!Z9Za%-RFaF4i7m6NCN zBPWaL2+7c12haIy#+o$Bfd%6I!5+P%%N6p@RsdTSO|S=M;)ubQ^C{JU$b5-CC{iM8I_vdMRkt0YZgoS*BjAX#kiHE=k)z z;IkG00n2@*6Xr}(r%^KICG^lC4lEA&0#bzc4Idx-NU9j;?peCUd+M@56`lQNbqC_O zbQ(Dx0oH|K1Lv$MbWmkalYauoL8X4Jelcf3YuOh465Hpq&&PS62h4()Z?B`z(x4|a z08A4B|D4u;-9Acvns}eD@tV>GQz{I$$tZ-q0Emnx-E8b4iyxgQ=&^uI} zH$Cj9HIdv@GI+GMrbKskR|g=X-T6($$i18c`TbNGKc_b%{HbE@#7NJ>#GC^vm3U!FX^hX{H5_WFh6VJ^bn#t|t;xGvO8Zvt3yK3cKphYG+zL5eX9ullZBnVMFl+ zIC<+I&bY~oI=n#?z>+DnG<7*`V+VLls380L)g*-@m~)!SJ? zNLvlJ5@C6A%Mcd7W>Rtt`4mK=*UYsK;MonNqC|vGx;PlAN&02;*Wh8qWcDQ~Xbj=b z4)A*=4c<8NU+T2qX?<@qou)-_*>fwiw##0bZ55Mg?{sNslS!9*wn>5g(s!Xcd zetZ9$>&#&0TOGc=N-NSgHO7$~=A=yGdsIlA&rHtjjefadPS7x?znSfaaO4~j`t^`; z{9IlL^3@R;l*999bxb+an*6y2JAN^|;s|@Zg?9rPMYd0WK?WMKc$O-p(ec6LED6pw%+Ew${XkQ zATRM8pGN`JH&~-Lk)tWRx zY{cJmN%9)K+_xq&pQzKfC^8N3A=R9a zo&{$lc&ZZ5HRze^Amo}+ Gw0ssI2b}wr600001b5ch_0Itp) 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