├── BuggyRemote
├── ic_launcher-web.png
├── libs
│ └── android-support-v4.jar
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── values
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── menu
│ │ └── activity_main.xml
│ ├── values-v11
│ │ └── styles.xml
│ ├── values-v14
│ │ └── styles.xml
│ └── layout
│ │ └── activity_main.xml
├── gen
│ └── com
│ │ └── poconoco
│ │ └── buggyremote
│ │ ├── BuildConfig.java
│ │ └── R.java
├── .classpath
├── project.properties
├── proguard-project.txt
├── .project
├── AndroidManifest.xml
├── src
│ └── com
│ │ └── poconoco
│ │ └── buggyremote
│ │ ├── BuggyBodyShift.java
│ │ ├── BuggyProtocol.java
│ │ ├── BuggyMandibles.java
│ │ ├── BuggyBodyMovement.java
│ │ ├── BuggySensors.java
│ │ ├── MainActivity.java
│ │ └── BuggyBluetooth.java
└── .settings
│ ├── org.eclipse.jdt.ui.prefs
│ └── org.eclipse.jdt.core.prefs
├── .gitignore
├── README.md
├── serial_interface.txt
└── Buggy
├── SmoothFloat.h
├── Mark1Config.h
├── Geometry.h
├── Mark2Config.h
├── Buggy.ino
├── SimpleMovements.h
├── Gait2.h
└── Leg.h
/BuggyRemote/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poconoco/buggybug/HEAD/BuggyRemote/ic_launcher-web.png
--------------------------------------------------------------------------------
/BuggyRemote/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poconoco/buggybug/HEAD/BuggyRemote/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/BuggyRemote/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poconoco/buggybug/HEAD/BuggyRemote/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/BuggyRemote/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poconoco/buggybug/HEAD/BuggyRemote/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/BuggyRemote/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poconoco/buggybug/HEAD/BuggyRemote/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/BuggyRemote/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/poconoco/buggybug/HEAD/BuggyRemote/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 |
6 | # Compiled Dynamic libraries
7 | *.so
8 |
9 | # Compiled Static libraries
10 | *.lai
11 | *.la
12 | *.a
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | buggybug
2 | ========
3 |
4 | Hexapod firmware sources
5 |
6 | - master branch contains bluetooth controlled version,
7 | - flysky branch - PWM RC controlled version, tuned for FlySky-iA6 receiver
8 |
--------------------------------------------------------------------------------
/BuggyRemote/gen/com/poconoco/buggyremote/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /** Automatically generated file. DO NOT MODIFY */
2 | package com.poconoco.buggyremote;
3 |
4 | public final class BuildConfig {
5 | public final static boolean DEBUG = true;
6 | }
--------------------------------------------------------------------------------
/BuggyRemote/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | BuggyRC
5 | Hello world!
6 | Settings
7 |
8 |
--------------------------------------------------------------------------------
/BuggyRemote/res/menu/activity_main.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/BuggyRemote/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/BuggyRemote/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/BuggyRemote/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/serial_interface.txt:
--------------------------------------------------------------------------------
1 | Serial commands with one character:
2 |
3 | " " - (single space, no quotes) attach/detach all leg servos
4 | "_" - (single underline, no quotes) attach/detach mandible servos
5 |
6 | Multibyte commands:
7 |
8 | bB - body shift, x, y and z are signed bytes, 0 are centers
9 | mM - movement, x, y are signed bytes, Turn is signed byte (o - no turn), Speed - unsigned byte
10 | gG
11 | pP - mandible movement, right and left independently
12 |
--------------------------------------------------------------------------------
/BuggyRemote/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 |
--------------------------------------------------------------------------------
/BuggyRemote/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/BuggyRemote/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/BuggyRemote/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | BuggyRemote
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Buggy/SmoothFloat.h:
--------------------------------------------------------------------------------
1 | #ifndef SMOOTH_FLOAT_H__
2 | #define SMOOTH_FLOAT_H__
3 |
4 | #include "Geometry.h"
5 |
6 | class SmoothFloat
7 | {
8 | public:
9 |
10 | SmoothFloat(float target, float current)
11 | : _target(target)
12 | , _current(current)
13 | {}
14 |
15 | void setTarget(float target)
16 | {
17 | _target = target;
18 | }
19 |
20 | float getCurrent()
21 | {
22 | return _current;
23 | }
24 |
25 | float getCurrent(float stepDeltaOrig)
26 | {
27 | float stepDelta;
28 | const float dist = abs(_current - _target);
29 | if (dist < stepDeltaOrig * 5)
30 | stepDelta = stepDeltaOrig * 0.2;
31 | else if (dist < stepDeltaOrig * 2)
32 | stepDelta = stepDeltaOrig * 0.1;
33 | else stepDelta = stepDeltaOrig;
34 |
35 | if (_current >= _target)
36 | _current = max(_target, _current - stepDelta);
37 | else
38 | _current = min(_target, _current + stepDelta);
39 |
40 | return _current;
41 | }
42 |
43 | private:
44 |
45 | float _target;
46 | float _current;
47 | };
48 |
49 | #endif
50 |
--------------------------------------------------------------------------------
/BuggyRemote/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/BuggyRemote/src/com/poconoco/buggyremote/BuggyBodyShift.java:
--------------------------------------------------------------------------------
1 | package com.poconoco.buggyremote;
2 |
3 | public class BuggyBodyShift
4 | {
5 | public byte x = 0;
6 | public byte y = 0;
7 | public byte z = 0;
8 | public byte pitch = 0;
9 | public byte roll = 0;
10 | public byte yaw = 0;
11 |
12 | public void copyFrom(final BuggyBodyShift src)
13 | {
14 | x = src.x;
15 | y = src.y;
16 | z = src.z;
17 | pitch = src.pitch;
18 | roll = src.roll;
19 | yaw = src.yaw;
20 | }
21 |
22 | public boolean differ(final BuggyBodyShift arg)
23 | {
24 | if (arg == null)
25 | return true;
26 |
27 | final byte angleMargin = 0;
28 | final byte linearMargin = 0;
29 |
30 | return !(withinMargin(x, arg.x, linearMargin)
31 | && withinMargin(y, arg.y, linearMargin)
32 | && withinMargin(z, arg.z, linearMargin)
33 | && withinMargin(pitch, arg.pitch, angleMargin)
34 | && withinMargin(roll, arg.roll, angleMargin)
35 | && withinMargin(yaw, arg.yaw, angleMargin));
36 | }
37 |
38 | private boolean withinMargin(final byte a1, final byte a2, final byte margin)
39 | {
40 | return Math.abs(a1 - a2) <= margin;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/BuggyRemote/src/com/poconoco/buggyremote/BuggyProtocol.java:
--------------------------------------------------------------------------------
1 | package com.poconoco.buggyremote;
2 |
3 | public class BuggyProtocol
4 | {
5 | public static byte[] getToggleServoCmd()
6 | {
7 | return new byte[] {' '};
8 | }
9 |
10 | public static byte[] getToggleMandibleCmd()
11 | {
12 | return new byte[] {'_'};
13 | }
14 |
15 | public static byte[] getGaitCmd(final int gait)
16 | {
17 | return new byte[] { 'g', (byte) gait, 'G'};
18 | }
19 |
20 | public static byte[] getBodyShiftCmd(final BuggyBodyShift bodyShift)
21 | {
22 | final byte[] cmd = new byte[8];
23 |
24 | cmd[0] = 'b';
25 |
26 | cmd[1] = bodyShift.x;
27 | cmd[2] = bodyShift.y;
28 | cmd[3] = bodyShift.z;
29 |
30 | cmd[4] = bodyShift.pitch;
31 | cmd[5] = bodyShift.roll;
32 | cmd[6] = bodyShift.yaw;
33 |
34 | cmd[7] = 'B';
35 |
36 | return cmd;
37 | }
38 |
39 | public static byte[] getBodyMovementCmd(final BuggyBodyMovement bodyMovement)
40 | {
41 | final byte[] cmd = new byte[6];
42 |
43 | cmd[0] = 'm';
44 |
45 | cmd[1] = bodyMovement.x;
46 | cmd[2] = bodyMovement.y;
47 | cmd[3] = bodyMovement.turn;
48 | cmd[4] = bodyMovement.speed;
49 |
50 | cmd[5] = 'M';
51 |
52 | return cmd;
53 | }
54 |
55 | public static byte[] getMandiblesCmd(final BuggyMandibles mandibles)
56 | {
57 | final byte[] cmd = new byte[8];
58 |
59 | cmd[0] = 'p';
60 |
61 | cmd[1] = mandibles.rx;
62 | cmd[2] = mandibles.ry;
63 | cmd[3] = mandibles.rz;
64 |
65 | cmd[4] = mandibles.lx;
66 | cmd[5] = mandibles.ly;
67 | cmd[6] = mandibles.lz;
68 |
69 | cmd[7] = 'P';
70 |
71 | return cmd;
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/BuggyRemote/src/com/poconoco/buggyremote/BuggyMandibles.java:
--------------------------------------------------------------------------------
1 | package com.poconoco.buggyremote;
2 |
3 | public class BuggyMandibles
4 | {
5 | public byte rx = 0;
6 | public byte ry = 0;
7 | public byte rz = 0;
8 |
9 | public byte lx = 0;
10 | public byte ly = 0;
11 | public byte lz = 0;
12 |
13 | public void copyFrom(final BuggyMandibles src)
14 | {
15 | rx = src.rx;
16 | ry = src.ry;
17 | rz = src.rz;
18 | lx = src.lx;
19 | ly = src.ly;
20 | lz = src.lz;
21 | }
22 |
23 | // all args are -1..1
24 | public void encodeRight(final double joystickRX,
25 | final double joystickRY)
26 | {
27 | rx = (byte) (joystickRX * 127.0);
28 | rz = (byte) (joystickRY * 127.0);
29 | }
30 |
31 | // all args are -1..1
32 | public void encodeLeft(final double joystickLX,
33 | final double joystickLY)
34 | {
35 | lx = (byte) (joystickLX * 127.0);
36 | lz = (byte) (joystickLY * 127.0);
37 | }
38 |
39 | // all args are -1..1
40 | public void encodeHeight(final double height)
41 | {
42 | ry = (byte) (height * 127.0);
43 | ly = (byte) (height * 127.0);
44 | }
45 |
46 | public boolean differ(final BuggyMandibles arg)
47 | {
48 | if (arg == null)
49 | return true;
50 |
51 | final byte linearMargin = 0;
52 |
53 | return !(withinMargin(rx, arg.rx, linearMargin)
54 | && withinMargin(ry, arg.ry, linearMargin)
55 | && withinMargin(rz, arg.rz, linearMargin)
56 | && withinMargin(lx, arg.lx, linearMargin)
57 | && withinMargin(ly, arg.ly, linearMargin)
58 | && withinMargin(lz, arg.lz, linearMargin));
59 | }
60 |
61 | private boolean withinMargin(final byte a1, final byte a2, final byte margin)
62 | {
63 | return Math.abs(a1 - a2) <= margin;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/BuggyRemote/src/com/poconoco/buggyremote/BuggyBodyMovement.java:
--------------------------------------------------------------------------------
1 | package com.poconoco.buggyremote;
2 |
3 | public class BuggyBodyMovement
4 | {
5 | public byte x;
6 | public byte y;
7 | public byte turn;
8 | public byte speed;
9 |
10 | // joystick* are -1..1
11 | public void encodeLinear(final double joystickX, final double joystickY_)
12 | {
13 | final double joystickY = - joystickY_;
14 | final double length = Math.sqrt(joystickX * joystickX + joystickY
15 | * joystickY);
16 |
17 | if (length < 0.0001)
18 | {
19 | speed = 0;
20 | x = 0;
21 | y = 0;
22 | turn = 0;
23 | return;
24 | }
25 |
26 | speed = (byte) (length * 127);
27 |
28 | x = (byte) (joystickX * (1.0 / length) * 127.0);
29 | y = (byte) (joystickY * (1.0 / length) * 127.0);
30 |
31 | final double slowTreshold = 0.1;
32 | if (length < slowTreshold)
33 | {
34 | final double breaking = 1 - (slowTreshold - length)
35 | / slowTreshold;
36 |
37 | x = (byte) (x * breaking);
38 | y = (byte) (y * breaking);
39 | }
40 |
41 | turn = 0;
42 | }
43 |
44 | // joystick* are -1..1
45 | public void encodeWithTurn(final double joystickX_, final double joystickY_)
46 | {
47 | final double joystickX = 0;
48 | final double joystickY = - joystickY_;
49 |
50 | final double length = Math.sqrt(joystickX * joystickX + joystickY
51 | * joystickY);
52 |
53 | if (length < 0.0001)
54 | {
55 | speed = 0;
56 | x = 0;
57 | y = 0;
58 | turn = 0;
59 | return;
60 | }
61 |
62 | speed = (byte) (length * 127);
63 |
64 | x = (byte) (joystickX * (1.0 / length) * 127.0);
65 | y = (byte) (joystickY * (1.0 / length) * 127.0);
66 |
67 | final double slowTreshold = 0.1;
68 | if (length < slowTreshold)
69 | {
70 | final double breaking = 1 - (slowTreshold - length)
71 | / slowTreshold;
72 |
73 | x = (byte) (x * breaking);
74 | y = (byte) (y * breaking);
75 | return;
76 | }
77 |
78 | turn = (byte) (joystickX_ * 127);
79 | }
80 |
81 | public void copyFrom(final BuggyBodyMovement src)
82 | {
83 | x = src.x;
84 | y = src.y;
85 | turn = src.turn;
86 | speed = src.speed;
87 | }
88 |
89 | public boolean differ(final BuggyBodyMovement arg)
90 | {
91 | if (arg == null)
92 | return true;
93 |
94 | return x != arg.x || y != arg.y || turn != arg.turn
95 | || speed != arg.speed;
96 |
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/BuggyRemote/.settings/org.eclipse.jdt.ui.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
3 | formatter_profile=_Nocco
4 | formatter_settings_version=12
5 | sp_cleanup.add_default_serial_version_id=true
6 | sp_cleanup.add_generated_serial_version_id=false
7 | sp_cleanup.add_missing_annotations=true
8 | sp_cleanup.add_missing_deprecated_annotations=true
9 | sp_cleanup.add_missing_methods=false
10 | sp_cleanup.add_missing_nls_tags=false
11 | sp_cleanup.add_missing_override_annotations=true
12 | sp_cleanup.add_missing_override_annotations_interface_methods=true
13 | sp_cleanup.add_serial_version_id=false
14 | sp_cleanup.always_use_blocks=true
15 | sp_cleanup.always_use_parentheses_in_expressions=false
16 | sp_cleanup.always_use_this_for_non_static_field_access=false
17 | sp_cleanup.always_use_this_for_non_static_method_access=false
18 | sp_cleanup.convert_to_enhanced_for_loop=true
19 | sp_cleanup.correct_indentation=false
20 | sp_cleanup.format_source_code=false
21 | sp_cleanup.format_source_code_changes_only=false
22 | sp_cleanup.make_local_variable_final=true
23 | sp_cleanup.make_parameters_final=true
24 | sp_cleanup.make_private_fields_final=true
25 | sp_cleanup.make_type_abstract_if_missing_method=false
26 | sp_cleanup.make_variable_declarations_final=true
27 | sp_cleanup.never_use_blocks=false
28 | sp_cleanup.never_use_parentheses_in_expressions=true
29 | sp_cleanup.on_save_use_additional_actions=true
30 | sp_cleanup.organize_imports=true
31 | sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
32 | sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
33 | sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
34 | sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
35 | sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
36 | sp_cleanup.remove_private_constructors=true
37 | sp_cleanup.remove_trailing_whitespaces=true
38 | sp_cleanup.remove_trailing_whitespaces_all=true
39 | sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
40 | sp_cleanup.remove_unnecessary_casts=true
41 | sp_cleanup.remove_unnecessary_nls_tags=false
42 | sp_cleanup.remove_unused_imports=false
43 | sp_cleanup.remove_unused_local_variables=false
44 | sp_cleanup.remove_unused_private_fields=true
45 | sp_cleanup.remove_unused_private_members=false
46 | sp_cleanup.remove_unused_private_methods=true
47 | sp_cleanup.remove_unused_private_types=true
48 | sp_cleanup.sort_members=false
49 | sp_cleanup.sort_members_all=false
50 | sp_cleanup.use_blocks=false
51 | sp_cleanup.use_blocks_only_for_return_and_throw=false
52 | sp_cleanup.use_parentheses_in_expressions=true
53 | sp_cleanup.use_this_for_non_static_field_access=false
54 | sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
55 | sp_cleanup.use_this_for_non_static_method_access=false
56 | sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
57 |
--------------------------------------------------------------------------------
/BuggyRemote/gen/com/poconoco/buggyremote/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package com.poconoco.buggyremote;
9 |
10 | public final class R {
11 | public static final class attr {
12 | }
13 | public static final class drawable {
14 | public static final int ic_launcher=0x7f020000;
15 | }
16 | public static final class id {
17 | public static final int bodyShiftArea=0x7f07000c;
18 | public static final int buttonBT=0x7f070000;
19 | public static final int buttonEngine=0x7f070001;
20 | public static final int buttonGait1=0x7f070009;
21 | public static final int buttonGait2=0x7f07000a;
22 | public static final int buttonGait3=0x7f07000b;
23 | public static final int buttonMandiblesEngine=0x7f070002;
24 | public static final int checkBoxHorizShift=0x7f070007;
25 | public static final int checkBoxMandibleControl=0x7f070008;
26 | public static final int checkBoxSensors=0x7f070005;
27 | public static final int checkLinear=0x7f070006;
28 | public static final int menu_settings=0x7f07000e;
29 | public static final int movementAreaImage=0x7f070004;
30 | public static final int movementHint=0x7f07000d;
31 | public static final int seekMandibleHeight=0x7f070003;
32 | }
33 | public static final class layout {
34 | public static final int activity_main=0x7f030000;
35 | }
36 | public static final class menu {
37 | public static final int activity_main=0x7f060000;
38 | }
39 | public static final class string {
40 | public static final int app_name=0x7f040000;
41 | public static final int hello_world=0x7f040001;
42 | public static final int menu_settings=0x7f040002;
43 | }
44 | public static final class style {
45 | /**
46 | Base application theme, dependent on API level. This theme is replaced
47 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
48 |
49 |
50 | Theme customizations available in newer API levels can go in
51 | res/values-vXX/styles.xml, while customizations related to
52 | backward-compatibility can go here.
53 |
54 |
55 | Base application theme for API 11+. This theme completely replaces
56 | AppBaseTheme from res/values/styles.xml on API 11+ devices.
57 |
58 | API 11 theme customizations can go here.
59 |
60 | Base application theme for API 14+. This theme completely replaces
61 | AppBaseTheme from BOTH res/values/styles.xml and
62 | res/values-v11/styles.xml on API 14+ devices.
63 |
64 | API 14 theme customizations can go here.
65 | */
66 | public static final int AppBaseTheme=0x7f050000;
67 | /** Application theme.
68 | All customizations that are NOT specific to a particular API-level can go here.
69 | */
70 | public static final int AppTheme=0x7f050001;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Buggy/Mark1Config.h:
--------------------------------------------------------------------------------
1 | #ifndef MARK1_CONFIG_H__
2 | #define MARK1_CONFIG_H__
3 |
4 | class LegConfiguration
5 | {
6 | public:
7 |
8 | // NOTE: legs are attached after calling this method but are not moved
9 | static void apply(Leg* legs, int N)
10 | {
11 | Leg* rightLegs = legs;
12 | Leg* leftLegs = legs + N / 2;
13 |
14 | rightLegs[0].setPins(46, 47, 39);
15 | rightLegs[1].setPins(40, 41, 42);
16 | rightLegs[2].setPins(43, 44, 45);
17 |
18 | leftLegs[0].setPins(29, 28, 36);
19 | leftLegs[1].setPins(35, 34, 33);
20 | leftLegs[2].setPins(32, 31, 30);
21 |
22 | rightLegs[0].configureServoDirections(-1, -1, 1, false);
23 | leftLegs [0].configureServoDirections(-1, 1, -1, true);
24 |
25 | rightLegs[1].configureServoDirections(-1, -1, 1, false);
26 | leftLegs [1].configureServoDirections(-1, 1, -1, true);
27 |
28 | rightLegs[2].configureServoDirections(-1, -1, 1, false);
29 | leftLegs [2].configureServoDirections(-1, 1, -1, true);
30 |
31 | for (int i = 0; i < 3; i++)
32 | {
33 | rightLegs[i].configureFemur(-26, 12, 46.5, deg2rad(10));
34 | leftLegs [i].configureFemur(-26, 12, 46.5, deg2rad(10));
35 |
36 | rightLegs[i].configureTibia(58, deg2rad(-70));
37 | leftLegs [i].configureTibia(58, deg2rad(-70));
38 | }
39 |
40 | rightLegs[0].configureCoxa( 34, 65, deg2rad( 20), 10);
41 | leftLegs [0].configureCoxa(-34, 65, deg2rad(- (180 + 20)), -10);
42 |
43 | rightLegs[1].configureCoxa( 52, 0, deg2rad(- 20), 10);
44 | leftLegs [1].configureCoxa(-52, 0, deg2rad(- (180 - 20)), -10);
45 |
46 | rightLegs[2].configureCoxa( 34, -65, deg2rad(- 63), 10);
47 | leftLegs [2].configureCoxa(-34, -65, deg2rad(- (180 - 63)), -10);
48 |
49 | rightLegs[0].configureDefault(Point( 60, 130, -70), true);
50 | leftLegs [0].configureDefault(Point(-60, 130, -70), true);
51 |
52 | rightLegs[1].configureDefault(Point( 110, -10, -65), true);
53 | leftLegs [1].configureDefault(Point(-110, -10, -70), true);
54 |
55 | rightLegs[2].configureDefault(Point( 70, -120, -70), true);
56 | leftLegs [2].configureDefault(Point(-70, -120, -70), true);
57 |
58 | // Fine tuning
59 | rightLegs[0].tuneRestAngles(PI / 2,
60 | PI / 2 + deg2rad(10),
61 | PI / 2);
62 |
63 | leftLegs[0].tuneRestAngles(PI / 2,
64 | PI / 2 - deg2rad(5),
65 | PI / 2);
66 |
67 | leftLegs[1].tuneRestAngles(PI / 2,
68 | PI / 2,
69 | PI / 2 - deg2rad(10));
70 |
71 | rightLegs[1].tuneRestAngles(PI / 2,
72 | PI / 2,
73 | PI / 2 + deg2rad(20));
74 |
75 |
76 | leftLegs[2].tuneRestAngles(PI / 2,
77 | PI / 2 - deg2rad(10),
78 | PI / 2);
79 |
80 | }
81 |
82 | };
83 |
84 | #endif
85 |
--------------------------------------------------------------------------------
/Buggy/Geometry.h:
--------------------------------------------------------------------------------
1 | #ifndef GEOMETRY_H__
2 | #define GEOMETRY_H__
3 |
4 | #include
5 |
6 | #define sqr(x) ((x)*(x))
7 | #define PI 3.141592653589793238
8 | #define rad2deg(x) ( (180.0 / PI) * (x) )
9 | #define deg2rad(x) ( (PI / 180.0) * (x) )
10 | #define fabs(x) ((x) >= 0 ? (x) : - (x))
11 | #define max(x, y) ((x) > (y) ? (x) : (y))
12 | #define distanceSqr2D(x1, y1, x2, y2) (sqr((x1) - (x2)) + sqr((y1) - (y2)))
13 | #define distance2D(x1, y1, x2, y2) (sqrt(distanceSqr2D(x1, y1, x2, y2)))
14 |
15 | // TODO: Rename third quarter fix to something more meaningful
16 | float polarAngle(float x, float y, bool thirdQuarterFix)
17 | {
18 | if (x > 0)
19 | {
20 | if (thirdQuarterFix && y > 0)
21 | return atan(y / x) - 2 * PI;
22 | return atan(y / x);
23 | }
24 |
25 | if (x < 0 && y >= 0)
26 | {
27 | if (thirdQuarterFix)
28 | return atan(y / x) - PI;
29 | return atan(y / x) + PI;
30 | }
31 |
32 | if (x < 0 && y < 0)
33 | return atan(y / x) - PI;
34 |
35 | // x = 0
36 | if (y > 0)
37 | return PI * 0.5;
38 |
39 | if (y < 0)
40 | return PI * -0.5;
41 |
42 | // y = 0
43 | return 0;
44 | }
45 |
46 | struct Point
47 | {
48 | Point()
49 | {}
50 |
51 | Point(float _x, float _y, float _z)
52 | {
53 | x = _x;
54 | y = _y;
55 | z = _z;
56 | }
57 |
58 | float x, y, z;
59 |
60 | Point operator+(Point& that)
61 | {
62 | return Point(x + that.x,
63 | y + that.y,
64 | z + that.z);
65 | }
66 |
67 | Point operator-(Point& that)
68 | {
69 | return Point(x - that.x,
70 | y - that.y,
71 | z - that.z);
72 | }
73 |
74 | Point operator*(float m)
75 | {
76 | return Point(x * m,
77 | y * m,
78 | z * m);
79 | }
80 |
81 | Point operator/(float d)
82 | {
83 | return Point(x / d,
84 | y / d,
85 | z / d);
86 | }
87 |
88 | void operator=(Point& that)
89 | {
90 | x = that.x;
91 | y = that.y;
92 | z = that.z;
93 | }
94 |
95 | // Workaround for an gccavr issue with reference args
96 | void assign(Point that)
97 | {
98 | x = that.x;
99 | y = that.y;
100 | z = that.z;
101 | }
102 |
103 | void assign(float _x, float _y, float _z)
104 | {
105 | x = _x;
106 | y = _y;
107 | z = _z;
108 | }
109 |
110 | void assignZero()
111 | {
112 | x = y = z = 0;
113 | }
114 |
115 | float maxDistance(Point& that)
116 | {
117 | float dx = fabs(x - that.x);
118 | float dy = fabs(y - that.y);
119 | float dz = fabs(z - that.z);
120 |
121 | return max(dz, max(dx, dy));
122 | }
123 |
124 | float distance(Point& that)
125 | {
126 | return sqrt(sqr(x - that.x) + sqr(y - that.y) + sqr(z - that.z));
127 | }
128 |
129 | };
130 |
131 | void normalize2D(Point& vector, float normalizer)
132 | {
133 | vector.x = vector.x * normalizer;
134 | vector.y = vector.y * normalizer;
135 | // vector.z = vector.z * normalizer;
136 | }
137 |
138 | bool floatEqual(float a, float b)
139 | {
140 | return fabs(a - b) < 0.00001;
141 | }
142 |
143 | float normalizeByte(char b, float normal)
144 | {
145 | return ((float) b) * normal * 0.0078125; // * (1 / 128.0);
146 | }
147 |
148 | float distanceToHorde(float hordeLength,
149 | float hordeAngle)
150 | {
151 | return (hordeLength * 0.5) / tan(hordeAngle * 0.5);
152 | }
153 |
154 | void rotate2d(float cx, float cy, float angle, Point& p)
155 | {
156 | float s = sin(angle);
157 | float c = cos(angle);
158 |
159 | // translate point back to origin:
160 | p.x -= cx;
161 | p.y -= cy;
162 |
163 | // rotate point
164 | float xnew = p.x * c - p.y * s;
165 | float ynew = p.x * s + p.y * c;
166 |
167 | // translate point back:
168 | p.x = xnew + cx;
169 | p.y = ynew + cy;
170 | }
171 |
172 | #endif
173 |
--------------------------------------------------------------------------------
/BuggyRemote/src/com/poconoco/buggyremote/BuggySensors.java:
--------------------------------------------------------------------------------
1 | package com.poconoco.buggyremote;
2 |
3 | import android.content.Context;
4 | import android.hardware.Sensor;
5 | import android.hardware.SensorEvent;
6 | import android.hardware.SensorEventListener;
7 | import android.hardware.SensorManager;
8 |
9 | public class BuggySensors
10 | implements SensorEventListener
11 | {
12 | public interface Listener
13 | {
14 | void onPitchRollChanged(float pitch, float roll);
15 | }
16 |
17 | BuggySensors(final Context context, final Listener listener)
18 | {
19 | _listener = listener;
20 | _context = context;
21 |
22 | register();
23 | }
24 |
25 | public void unregister()
26 | {
27 | _sensorManager.unregisterListener(this);
28 | }
29 |
30 | public void register()
31 | {
32 | _sensorManager = (SensorManager) _context.getSystemService(Context.SENSOR_SERVICE);
33 |
34 | _sensorManager.registerListener(this, _sensorManager
35 | .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
36 | SensorManager.SENSOR_DELAY_GAME);
37 | _sensorManager
38 | .registerListener(this, _sensorManager
39 | .getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
40 | SensorManager.SENSOR_DELAY_GAME);
41 | }
42 |
43 | @Override
44 | public void onAccuracyChanged(final Sensor sensor, final int accuracy)
45 | {
46 | }
47 |
48 | @Override
49 | public void onSensorChanged(final SensorEvent event)
50 | {
51 | if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
52 | {
53 | accel(event);
54 | }
55 | if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
56 | {
57 | mag(event);
58 | }
59 | }
60 |
61 | private void accel(final SensorEvent event)
62 | {
63 | if (_lastAccels == null)
64 | {
65 | _lastAccels = new float[3];
66 | }
67 |
68 | System.arraycopy(event.values, 0, _lastAccels, 0, 3);
69 |
70 | /*
71 | * if (m_lastMagFields != null) { computeOrientation(); }
72 | */
73 | }
74 |
75 | private void mag(final SensorEvent event)
76 | {
77 | if (_lastMagFields == null)
78 | {
79 | _lastMagFields = new float[3];
80 | }
81 |
82 | System.arraycopy(event.values, 0, _lastMagFields, 0, 3);
83 |
84 | if (_lastAccels != null)
85 | {
86 | computeOrientation();
87 | }
88 | }
89 |
90 | private void computeOrientation()
91 | {
92 | if (SensorManager.getRotationMatrix(_rotationMatrix, null,
93 | _lastAccels, _lastMagFields))
94 | {
95 | SensorManager.getOrientation(_rotationMatrix, _orientation);
96 |
97 | /* 1 radian = 57.2957795 degrees */
98 | /*
99 | * [0] : yaw, rotation around z axis [1] : pitch, rotation
100 | * around x axis [2] : roll, rotation around y axis
101 | */
102 | final float yaw = _orientation[0] * 57.2957795f;
103 | final float pitch = _orientation[1] * 57.2957795f;
104 | final float roll = _orientation[2] * 57.2957795f;
105 |
106 | /* append returns an average of the last 10 values */
107 | /*
108 | * m_lastYaw = m_filters[0].append(yaw); m_lastPitch =
109 | * m_filters[1].append(pitch); m_lastRoll =
110 | * m_filters[2].append(roll);
111 | */
112 | _lastYaw = yaw;
113 | _lastPitch = pitch;
114 | _lastRoll = roll;
115 |
116 | _listener.onPitchRollChanged(limitTo90(_lastRoll), limitTo90(-_lastPitch));
117 | }
118 | }
119 |
120 | private float limitTo90(final float angle)
121 | {
122 | if (angle < -90)
123 | return -90;
124 | if (angle > 90)
125 | return 90;
126 |
127 | return angle;
128 | }
129 |
130 | private final Listener _listener;
131 | private final Context _context;
132 |
133 | SensorManager _sensorManager;
134 |
135 | private float[] _lastMagFields;
136 | private float[] _lastAccels;
137 | private final float[] _rotationMatrix = new float[16];
138 | private final float[] _orientation = new float[4];
139 |
140 | float _lastPitch = 0.f;
141 | float _lastYaw = 0.f;
142 | float _lastRoll = 0.f;
143 | }
144 |
--------------------------------------------------------------------------------
/Buggy/Mark2Config.h:
--------------------------------------------------------------------------------
1 | #ifndef MARK1_CONFIG_H__
2 | #define MARK1_CONFIG_H__
3 |
4 | class MandibleConfiguration
5 | {
6 | public:
7 |
8 | static void apply(Leg* mandibles, int N)
9 | {
10 | if (N != 2) // Only 2 mandibles supported for now
11 | return;
12 |
13 | Leg* rightMandible = mandibles;
14 | Leg* leftMandible = mandibles + 1;
15 |
16 | rightMandible->setPins(50, 49, 48);
17 | leftMandible ->setPins(25, 26, 27);
18 |
19 | rightMandible->configureServoDirections(-1, -1, 1, false);
20 | leftMandible ->configureServoDirections(-1, 1, -1, true);
21 |
22 | /* configureFemur(float fStartZOffset,
23 | * float fStartFarOffset,
24 | * float fLength,
25 | * float fStartAngle)
26 | */
27 | rightMandible->configureFemur(-26, 12, 46.5, deg2rad(10));
28 | leftMandible ->configureFemur(-26, 12, 46.5, deg2rad(10));
29 |
30 | /* configureTibia(float tLenght,
31 | * float tStartAngle)
32 | */
33 | rightMandible->configureTibia(58, deg2rad(-70));
34 | leftMandible ->configureTibia(58, deg2rad(-70));
35 |
36 | /*
37 | * configureCoxa(float cStartX,
38 | * float cStartY,
39 | * float cStartAngle,
40 | * float cFemurOffset)
41 | */
42 | rightMandible->configureCoxa( 30, -20, deg2rad( 70), 10);
43 | leftMandible ->configureCoxa(-30, -20, deg2rad(- (180 + 70)), -10);
44 |
45 | rightMandible->configureDefault(Point( 30, 0, -70), true);
46 | leftMandible ->configureDefault(Point(-30, 0, -70), true);
47 | }
48 | };
49 |
50 | class LegConfiguration
51 | {
52 | public:
53 |
54 | // NOTE: legs are attached after calling this method but are not moved
55 | static void apply(Leg* legs, int N)
56 | {
57 | Leg* rightLegs = legs;
58 | Leg* leftLegs = legs + N / 2;
59 |
60 | rightLegs[0].setPins(46, 47, 39);
61 | rightLegs[1].setPins(40, 41, 42);
62 | rightLegs[2].setPins(43, 44, 45);
63 |
64 | leftLegs[0].setPins(29, 28, 36);
65 | leftLegs[1].setPins(35, 34, 33);
66 | leftLegs[2].setPins(32, 31, 30);
67 |
68 | /*
69 | * configureServoDirections(float cServoDirection,
70 | * float fServoDirection,
71 | * float tServoDirection,
72 | * bool thirdQuarterFix)
73 | */
74 |
75 | rightLegs[0].configureServoDirections(1, -1, 1, false);
76 | leftLegs [0].configureServoDirections(1, 1, -1, true);
77 |
78 | rightLegs[1].configureServoDirections(1, -1, 1, false);
79 | leftLegs [1].configureServoDirections(1, 1, -1, true);
80 |
81 | rightLegs[2].configureServoDirections(1, -1, 1, false);
82 | leftLegs [2].configureServoDirections(1, 1, -1, true);
83 |
84 | for (int i = 0; i < 3; i++)
85 | {
86 | /* configureFemur(float fStartZOffset,
87 | * float fStartFarOffset,
88 | * float fLength,
89 | * float fStartAngle)
90 | */
91 | rightLegs[i].configureFemur(-26, 3, 32, deg2rad(0));
92 | leftLegs [i].configureFemur(-26, 3, 32, deg2rad(0));
93 |
94 | /* configureTibia(float tLenght,
95 | * float tStartAngle)
96 | */
97 | rightLegs[i].configureTibia(61, deg2rad(-90));
98 | leftLegs [i].configureTibia(61, deg2rad(-90));
99 | }
100 |
101 | /*
102 | * configureCoxa(float cStartX,
103 | * float cStartY,
104 | * float cStartAngle,
105 | * float cFemurOffset)
106 | */
107 | rightLegs[0].configureCoxa( 23, 55, deg2rad( 54), 5);
108 | leftLegs [0].configureCoxa(-23, 55, deg2rad(- (180 + 54)), -5);
109 |
110 | rightLegs[1].configureCoxa( 28, 2, deg2rad(- 0), 5);
111 | leftLegs [1].configureCoxa(-28, 3, deg2rad(- (180 - 0)), -5);
112 |
113 | rightLegs[2].configureCoxa( 24, -38, deg2rad(- 34), 5);
114 | leftLegs [2].configureCoxa(-24, -38, deg2rad(- (180 - 34)), -5);
115 |
116 | /*
117 | * configureDefault(Point def, bool move)
118 | */
119 | rightLegs[0].configureDefault(Point( 45, 90, -90), true);
120 | leftLegs [0].configureDefault(Point(-45, 90, -90), true);
121 |
122 | rightLegs[1].configureDefault(Point( 70, 10, -90), true);
123 | leftLegs [1].configureDefault(Point(-70, 10, -90), true);
124 |
125 | rightLegs[2].configureDefault(Point( 60, -60, -90), true);
126 | leftLegs [2].configureDefault(Point(-60, -60, -90), true);
127 |
128 | /*
129 | * tuneRestAngles(float cServoRestAngle,
130 | * float fServoRestAngle,
131 | * float tServoRestAngle)
132 | * +/- deg2rad(10)
133 | */
134 | rightLegs[0].tuneRestAngles(PI / 2,
135 | PI / 2 - deg2rad(5),
136 | PI / 2);
137 |
138 | leftLegs[0].tuneRestAngles(PI / 2,
139 | PI / 2 + deg2rad(10),
140 | PI / 2);
141 |
142 | rightLegs[1].tuneRestAngles(PI / 2,
143 | PI / 2,
144 | PI / 2);
145 |
146 | leftLegs[1].tuneRestAngles(PI / 2,
147 | PI / 2 - deg2rad(5),
148 | PI / 2 - deg2rad(5));
149 |
150 | rightLegs[2].tuneRestAngles(PI / 2,
151 | PI / 2 + deg2rad(10),
152 | PI / 2);
153 |
154 | leftLegs[2].tuneRestAngles(PI / 2,
155 | PI / 2 + deg2rad(5),
156 | PI / 2);
157 |
158 | }
159 |
160 | };
161 |
162 | #endif
163 |
--------------------------------------------------------------------------------
/BuggyRemote/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
15 |
16 |
19 |
20 |
25 |
26 |
31 |
32 |
37 |
38 |
43 |
44 |
45 |
46 |
50 |
51 |
55 |
56 |
61 |
62 |
63 |
64 |
68 |
69 |
74 |
75 |
80 |
81 |
86 |
87 |
92 |
93 |
94 |
95 |
99 |
100 |
104 |
105 |
106 |
111 |
112 |
117 |
118 |
123 |
124 |
125 |
126 |
130 |
131 |
136 |
137 |
138 |
139 |
140 |
144 |
145 |
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/Buggy/Buggy.ino:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "Leg.h"
4 | #include "Gait2.h"
5 | #include "Mark2Config.h"
6 | #include "SimpleMovements.h"
7 |
8 | static Point zero(0,0,0);
9 |
10 | static const int N = 6;
11 | static Leg legs[N];
12 | static Leg mandibles[2];
13 |
14 | static SimpleMovements moveSimple(legs, N, mandibles, 2);
15 | static Gait2 gait(legs);
16 |
17 | static bool attached = false;
18 | static bool mandiblesAttached = false;
19 |
20 | char command = 0;
21 | unsigned long lastCommandTime = 0;
22 | static float progress = 0;
23 |
24 | SmoothFloat fpitch(0,0);
25 | SmoothFloat froll(0,0);
26 | SmoothFloat fyaw(0,0);
27 | SmoothFloat fbodyX(0,0);
28 | SmoothFloat fbodyY(0,0);
29 | SmoothFloat fbodyZ(0,0);
30 |
31 | SmoothFloat fRMandibleX(0,0);
32 | SmoothFloat fRMandibleY(0,0);
33 | SmoothFloat fRMandibleZ(0,0);
34 | SmoothFloat fLMandibleX(0,0);
35 | SmoothFloat fLMandibleY(0,0);
36 | SmoothFloat fLMandibleZ(0,0);
37 |
38 | void attachAllLegs()
39 | {
40 | if (attached)
41 | return;
42 |
43 | attached = true;
44 |
45 | for (int i = 0; i < N; i++)
46 | legs[i].attach();
47 | }
48 |
49 | void detachAllLegs()
50 | {
51 | if (! attached)
52 | return;
53 |
54 | attached = false;
55 |
56 | for (int i = 0; i < N; i++)
57 | legs[i].detach();
58 | }
59 |
60 | void attachMandibles()
61 | {
62 | if (mandiblesAttached)
63 | return;
64 |
65 | mandiblesAttached = true;
66 | mandibles[0].attach();
67 | mandibles[1].attach();
68 | }
69 |
70 | void detachMandibles()
71 | {
72 | if (! mandiblesAttached)
73 | return;
74 |
75 | mandiblesAttached = false;
76 | mandibles[0].detach();
77 | mandibles[1].detach();
78 | }
79 |
80 | bool toggleMandibles()
81 | {
82 | mandiblesAttached ? detachMandibles()
83 | : attachMandibles();
84 |
85 | return mandiblesAttached;
86 | }
87 |
88 | bool toggleLegs()
89 | {
90 | attached ? detachAllLegs()
91 | : attachAllLegs();
92 |
93 | return attached;
94 | }
95 |
96 | bool tryMultibyte(char cmd)
97 | {
98 | static unsigned long lastMoveCommandTime = 0;
99 | const unsigned long now = millis();
100 |
101 | if (cmd == 'b')
102 | {
103 | while (Serial1.available() < 7)
104 | tickMovements();
105 |
106 | char x, y, z, pitch, roll, yaw;
107 | x = Serial1.read();
108 | y = Serial1.read();
109 | z = Serial1.read();
110 | pitch = Serial1.read();
111 | roll = Serial1.read();
112 | yaw = Serial1.read();
113 |
114 | // Confirm footer byte
115 | if (Serial1.read() != 'B')
116 | return false;
117 |
118 | fbodyX.setTarget(normalizeByte(x, 40));
119 | fbodyY.setTarget(normalizeByte(y, 40));
120 | fbodyZ.setTarget(normalizeByte(z, 40));
121 | fpitch.setTarget(normalizeByte(pitch, PI / 6));
122 | froll.setTarget(normalizeByte(roll, PI / 6));
123 | fyaw.setTarget(normalizeByte(yaw, PI / 6));
124 |
125 | return true;
126 | }
127 |
128 | if (cmd == 'm')
129 | {
130 | while (Serial1.available() < 5)
131 | tickMovements();
132 |
133 | char x,y,turn, speed;
134 |
135 | x = Serial1.read();
136 | y = Serial1.read();
137 | turn = Serial1.read();
138 | speed = Serial1.read();
139 |
140 | // Confirm footer byte
141 | if (Serial1.read() != 'M')
142 | return false;
143 |
144 | gait.setStep(Point(normalizeByte(x, 40),
145 | normalizeByte(y, 40),
146 | 0),
147 | turn != 0,
148 | normalizeByte(turn, 1.0));
149 |
150 | if (speed < 0)
151 | speed = 0;
152 |
153 | gait.setSpeed(normalizeByte(speed, 2.0));
154 |
155 | return true;
156 | }
157 |
158 | if (cmd == 'g')
159 | {
160 | while (Serial1.available() < 2)
161 | tickMovements();
162 |
163 | char gaitId = Serial1.read();
164 |
165 | // Confirm footer byte
166 | if (Serial1.read() != 'G')
167 | return false;
168 |
169 | switch (gaitId)
170 | {
171 | case 1:
172 | gait.setGait2x3();
173 | break;
174 | case 2:
175 | gait.setGait6x1();
176 | break;
177 | case 3:
178 | gait.setGait3x2();
179 | break;
180 | }
181 |
182 | lastMoveCommandTime = now;
183 | return true;
184 | }
185 |
186 | if (cmd == 'p')
187 | {
188 | while (Serial1.available() < 7)
189 | tickMovements();
190 |
191 | char buffer[6];
192 | for (int i = 0; i < sizeof(buffer); ++i)
193 | buffer[i] = Serial1.read();
194 |
195 | // Confirm footer byte
196 | if (Serial1.read() != 'P')
197 | return false;
198 |
199 | fRMandibleX.setTarget(normalizeByte(buffer[0], 50));
200 | fRMandibleY.setTarget(normalizeByte(buffer[1], 50));
201 | fRMandibleZ.setTarget(normalizeByte(buffer[2], 50));
202 |
203 | fLMandibleX.setTarget(normalizeByte(buffer[3], 50));
204 | fLMandibleY.setTarget(normalizeByte(buffer[4], 50));
205 | fLMandibleZ.setTarget(normalizeByte(buffer[5], 50));
206 |
207 | return true;
208 | }
209 |
210 | if (now - lastMoveCommandTime > 1000)
211 | {
212 | gait.setSpeed(0);
213 | gait.setStep(zero, false, 0);
214 |
215 | lastMoveCommandTime = now + 1000000;
216 | }
217 |
218 | return false;
219 | }
220 |
221 | void tickMovements()
222 | {
223 | gait.tick();
224 |
225 | #ifdef SMOOTH_ANGLES
226 | for (int i = 0; i < N; i++)
227 | legs[i].tick();
228 | #endif
229 |
230 | static unsigned long _lastTickTime = 0;
231 | const unsigned long now = millis();
232 | const unsigned long deltaT = now - _lastTickTime;
233 | const float angleStepDelta = ((PI * 0.25) * 0.001) * (float) deltaT;
234 | const float shiftStepDelta = (100.0 * 0.001) * (float) deltaT;
235 | const float shiftMandibleDelta = (200.0 * 0.001) * (float) deltaT;
236 |
237 | Point bodyShift(fbodyX.getCurrent(shiftStepDelta),
238 | fbodyY.getCurrent(shiftStepDelta),
239 | fbodyZ.getCurrent(shiftStepDelta));
240 |
241 | moveSimple.shiftAbsolute(
242 | bodyShift,
243 | fpitch.getCurrent(angleStepDelta),
244 | froll.getCurrent(angleStepDelta),
245 | fyaw.getCurrent(angleStepDelta));
246 |
247 | moveSimple.mandiblesReach(Point(fRMandibleX.getCurrent(shiftMandibleDelta),
248 | fRMandibleY.getCurrent(shiftMandibleDelta),
249 | fRMandibleZ.getCurrent(shiftMandibleDelta)),
250 | Point(fLMandibleX.getCurrent(shiftMandibleDelta),
251 | fLMandibleY.getCurrent(shiftMandibleDelta),
252 | fLMandibleZ.getCurrent(shiftMandibleDelta)));
253 |
254 | _lastTickTime = now;
255 | }
256 |
257 | void setup()
258 | {
259 | Serial1.begin(9600);
260 | // Serial1.println("AT+BAUD8");
261 | // delay(500);
262 | // Serial1.begin(115200);
263 |
264 | LegConfiguration::apply(legs, N);
265 | MandibleConfiguration::apply(mandibles, 2);
266 |
267 | moveSimple.rememberDefault();
268 |
269 | for (Leg* leg = legs; leg < legs + N; leg++)
270 | leg->reachRelativeToDefault(zero);
271 |
272 | for (Leg* mandible = mandibles; mandible < mandibles + 2; mandible++)
273 | mandible->reachRelativeToDefault(zero);
274 |
275 | gait.setGait3x2();
276 | }
277 |
278 | void loop()
279 | {
280 | tickMovements();
281 | char incoming;
282 |
283 | if (Serial1.available() > 0)
284 | incoming = Serial1.read();
285 | else
286 | return;
287 |
288 | if (tryMultibyte(incoming))
289 | return;
290 |
291 | // One shot actions
292 | if (incoming == ' ')
293 | toggleLegs();
294 | else if (incoming == '_')
295 | toggleMandibles();
296 | }
297 |
--------------------------------------------------------------------------------
/Buggy/SimpleMovements.h:
--------------------------------------------------------------------------------
1 | #ifndef SIMPLE_MOVEMENTS_H__
2 | #define SIMPLE_MOVEMENTS_H__
3 |
4 | class SimpleMovements
5 | {
6 | public:
7 | SimpleMovements(Leg* legs, int legCount, Leg* mandibles, int mandibleCount)
8 | : _legs(legs)
9 | , _legCount(legCount)
10 | , _mandibles(mandibles)
11 | , _mandibleCount(mandibleCount)
12 | {
13 | //_defaultPositions = new Point[_legCount];
14 | //_defaultMandiblePositions = new Point[_mandibleCount];
15 |
16 | _speedFactor = 0.025;
17 | }
18 |
19 | ~SimpleMovements()
20 | {
21 | ..delete _defaultPositions;
22 | //delete _defaultMandiblePositions;
23 | }
24 |
25 | void rememberDefault()
26 | {
27 | for (byte i = 0; i < _legCount; ++i)
28 | _defaultPositions[i] = _legs[i].getDefaultPos();
29 |
30 | for (byte i = 0; i < _mandibleCount; ++i)
31 | _defaultMandiblePositions[i] = _mandibles[i].getDefaultPos();
32 |
33 | _linearShift.assignZero();
34 | }
35 |
36 | void shiftAbsolute(Point& absolute, float pitch, float roll, float yaw)
37 | {
38 | for (byte i = 0; i < _legCount; ++i)
39 | _legs[i].delayReach();
40 |
41 | for (byte i = 0; i < _legCount; ++i)
42 | _legs[i].shiftDefault(_defaultPositions[i] + absolute);
43 |
44 | shiftPitch(pitch);
45 | shiftRoll(roll);
46 | shiftYaw(yaw);
47 |
48 | for (byte i = 0; i < _legCount; ++i)
49 | _legs[i].commitDelayedReach();
50 | }
51 |
52 | void mandiblesReach(Point right, Point left)
53 | {
54 | _mandibles[0].shiftDefault(_defaultMandiblePositions[0] + right);
55 | _mandibles[1].shiftDefault(_defaultMandiblePositions[1] + left);
56 | }
57 |
58 | void shift(Point& delta)
59 | {
60 | for (byte i = 0; i < _legCount; ++i)
61 | _legs[i].shiftDefaultRelative(delta);
62 |
63 | // TODO: Do we need to store shift in _linearShift?
64 | }
65 |
66 | void shiftPitch(float angleDelta)
67 | {
68 | float sinval = sin(angleDelta);
69 | float cosval = cos(angleDelta);
70 |
71 | for (byte i = 0; i < _legCount; ++i)
72 | {
73 | Point currDef = _legs[i].getDefaultPos();
74 | Point newDef;
75 | newDef.x = currDef.x;
76 | newDef.y = currDef.y * cosval - currDef.z * sinval;
77 | newDef.z = currDef.y * sinval + currDef.z * cosval;
78 |
79 | _legs[i].shiftDefault(newDef);
80 | }
81 | }
82 |
83 | void shiftRoll(float angleDelta)
84 | {
85 | float sinval = sin(angleDelta);
86 | float cosval = cos(angleDelta);
87 |
88 | for (byte i = 0; i < _legCount; ++i)
89 | {
90 | Point currDef = _legs[i].getDefaultPos();
91 | Point newDef;
92 | newDef.x = currDef.x * cosval - currDef.z * sinval;
93 | newDef.y = currDef.y;
94 | newDef.z = currDef.x * sinval + currDef.z * cosval;
95 |
96 | _legs[i].shiftDefault(newDef);
97 | }
98 | }
99 |
100 | void shiftYaw(float angleDelta)
101 | {
102 | float sinval = sin(angleDelta);
103 | float cosval = cos(angleDelta);
104 |
105 | for (byte i = 0; i < _legCount; ++i)
106 | {
107 | Point currDef = _legs[i].getDefaultPos();
108 | Point newDef;
109 | newDef.x = currDef.x * cosval - currDef.y * sinval;
110 | newDef.y = currDef.x * sinval + currDef.y * cosval;
111 | newDef.z = currDef.z;
112 |
113 | _legs[i].shiftDefault(newDef);
114 | }
115 | }
116 |
117 | void shiftReset()
118 | {
119 | const int steps = 20;
120 | Point currDefs[_legCount];
121 |
122 | for (byte i = 0; i < _legCount; ++i)
123 | currDefs[i] = _legs[i].getDefaultPos();
124 |
125 | for (byte si = 0; si < steps; ++si)
126 | {
127 | for (byte i = 0; i < _legCount; ++i)
128 | {
129 | Point step = (_defaultPositions[i] - currDefs[i]) / steps;
130 | _legs[i].shiftDefaultRelative(step);
131 | }
132 |
133 | delay(2);
134 | }
135 |
136 | // Prevent default migration
137 | for (byte i = 0; i < _legCount; ++i)
138 | _legs[i].shiftDefault(_defaultPositions[i]);
139 | }
140 |
141 | float rotate(int steps, float clockwise, float startProgress = 0, bool (*pContinue)() = NULL)
142 | {
143 | float p = startProgress;
144 | for (int i = 0; i < steps; i++)
145 | {
146 | for(; p <= 2; /*p += 0.025*/)
147 | {
148 | float progress;
149 | float h[2]; // height
150 | float s[2]; // sine
151 | float c[2]; // cosine
152 | const float angle = clockwise * (PI / 500);
153 |
154 | if (p < 1)
155 | {
156 | progress = p;
157 | h[0] = 0;
158 | h[1] = 50 * (0.5 - fabs(0.5 - p));
159 | s[0] = sin(angle);
160 | c[0] = cos(angle);
161 | s[1] = sin(- angle);
162 | c[1] = cos(- angle);
163 | }
164 | else
165 | {
166 | progress = 1 - (p - 1);
167 | h[0] = 50 * (0.5 - fabs(1.5 - p));
168 | h[1] = 0;
169 | s[0] = sin(- angle);
170 | c[0] = cos(- angle);
171 | s[1] = sin(angle);
172 | c[1] = cos(angle);
173 | }
174 |
175 | for (int li = 0; li < _legCount; ++li)
176 | {
177 | // li - leg index, gi - group index
178 | int gi = li % 2;
179 | Point pNew;
180 | Point pCurr = _legs[li].getCurrentPos();
181 |
182 | pNew.x = pCurr.x * c[gi] - pCurr.y * s[gi];
183 | pNew.y = pCurr.x * s[gi] + pCurr.y * c[gi];
184 |
185 | // Calc default pos
186 | pNew.x -= _legs[li].getDefaultPos().x;
187 | pNew.y -= _legs[li].getDefaultPos().y;
188 | pNew.z = h[gi];
189 |
190 | _legs[li].reachRelativeToDefault(pNew);
191 | }
192 |
193 | delay(1);
194 | if (pContinue != NULL && ! pContinue())
195 | return p;
196 |
197 | p += _speedFactor /*+ 0.00 * (0.5 - fabs(0.5 - progress))*/;
198 | }
199 |
200 | if (p > 2)
201 | p = 0;
202 | }
203 |
204 | return p;
205 | }
206 |
207 | void smoothTo(Point& to)
208 | {
209 | smoothTo(to, 0);
210 | smoothTo(to, 1);
211 | }
212 |
213 | // Relative to default!
214 | void smoothTo(Point& to, int legGroup)
215 | {
216 | Point relative[_legCount];
217 | Point currentPositions[_legCount];
218 | for (int i = legGroup; i < _legCount; i += 2)
219 | {
220 | currentPositions[i] = _legs[i].getCurrentPos();
221 | relative[i].assign((_legs[i].getDefaultPos() + to) - _legs[i].getCurrentPos());
222 | }
223 |
224 | for(float p = 0; p <= 1; p += 0.03)
225 | {
226 | for (int li = legGroup; li < _legCount; li += 2)
227 | {
228 | Point currSubStep = relative[li] * p;
229 | Point currStep = currentPositions[li] + currSubStep;
230 | currStep.z = _legs[li].getDefaultPos().z + to.z + 50 * (0.5 - fabs(0.5 - p));
231 | _legs[li].reachAbsolute(currStep);
232 | }
233 |
234 | delay(5);
235 | }
236 | }
237 |
238 | private:
239 |
240 | Leg* _legs;
241 | const int _legCount;
242 | Leg* _mandibles;
243 | const int _mandibleCount;
244 |
245 | // FIXME
246 | Point _defaultPositions[6];
247 | Point _defaultMandiblePositions[2];
248 |
249 | Point _linearShift;
250 |
251 | float _speedFactor;
252 | };
253 |
254 | #endif
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/Buggy/Gait2.h:
--------------------------------------------------------------------------------
1 | #ifndef GAIT_2_H__
2 | #define GAIT_2_H__
3 |
4 | #include
5 | #include
6 |
7 | #include "Leg.h"
8 | #include "Geometry.h"
9 | #include "SmoothFloat.h"
10 |
11 | class LegCycle
12 | {
13 | public:
14 |
15 | LegCycle()
16 | : _leg(NULL)
17 | , _cycleShift(0)
18 | , _stepHeight(0)
19 | , _turn(false)
20 | , _turnAngle(0)
21 | , _turnCX(0)
22 | , _turnCY(0)
23 | {
24 | setCycleMiddle(127);
25 | }
26 |
27 | void setLeg(Leg *leg, bool rightLeg)
28 | {
29 | _leg = leg;
30 | _rightLeg = rightLeg;
31 | }
32 |
33 | void setCycleShift(byte shift)
34 | {
35 | _cycleShift = shift;
36 | }
37 |
38 | void setCycleMiddle(byte middle)
39 | {
40 | _cycleMiddle = middle;
41 | _invCycleMiddle = 1.0 / static_cast(_cycleMiddle);
42 |
43 | _cycleAfterMiddle = 255 - _cycleMiddle;
44 | _invCycleAfterMiddle = 1.0 / static_cast(_cycleAfterMiddle);
45 | }
46 |
47 | void setStep(Point start,
48 | Point stop,
49 | float height,
50 | bool turn,
51 | float turnAngle,
52 | float turnCX,
53 | float turnCY)
54 | {
55 | _start = start;
56 | _stop = stop;
57 | _stepHeight = height;
58 | _turn = turn;
59 | _turnAngle = turnAngle;
60 | _turnCX = turnCX;
61 | _turnCY = turnCY;
62 | }
63 |
64 | void setCyclePos(byte pos)
65 | {
66 | float norm1pos;
67 | float height;
68 | cycle(shiftCyclePos(pos), norm1pos, height);
69 |
70 | Point point;
71 |
72 | if (! _turn)
73 | {
74 | point.x = _start.x + (_stop.x - _start.x) * norm1pos;
75 | point.y = _start.y + (_stop.y - _start.y) * norm1pos;
76 | point.z = _start.z + (_stop.z - _start.z) * norm1pos + height;
77 |
78 | _leg->reachRelativeToDefault(point);
79 | }
80 | else
81 | {
82 | point = _start;
83 | point.z += height;
84 | _leg->reachRelativeToDefaultAndRotate(point, _turnAngle * norm1pos, _turnCX, _turnCY);
85 | }
86 | }
87 |
88 | private:
89 |
90 | inline byte shiftCyclePos(byte pos)
91 | {
92 | // Hope overflow will work as expected here :)
93 | return pos + _cycleShift;
94 | }
95 |
96 | void cycle(byte cyclePos, float& norm1pos, float& height)
97 | {
98 | if (cyclePos <= _cycleMiddle)
99 | {
100 | norm1pos = static_cast(cyclePos) * _invCycleMiddle;
101 | height = 0.0;
102 | }
103 | else
104 | {
105 | norm1pos = static_cast(_cycleAfterMiddle - (cyclePos - _cycleMiddle)) * _invCycleAfterMiddle;
106 | height = _stepHeight * (1 - fabs(0.5 - norm1pos) * 2);
107 | }
108 | }
109 |
110 | private:
111 |
112 | Leg* _leg;
113 | byte _cycleShift;
114 | byte _cycleMiddle;
115 | float _invCycleMiddle;
116 | byte _cycleAfterMiddle;
117 | float _invCycleAfterMiddle;
118 |
119 | Point _start;
120 | Point _stop;
121 | float _stepHeight;
122 | bool _turn;
123 | float _turnAngle;
124 | float _turnCX;
125 | float _turnCY;
126 | bool _rightLeg;
127 | };
128 |
129 | class Gait2
130 | {
131 | public:
132 |
133 | Gait2(Leg* legs)
134 | : _legs(legs)
135 | , _stepHeight(50)
136 | , _stepPerSecond(0, 0)
137 | , _lastTickTime(0)
138 | , _currentCyclePos(0)
139 | , _turn(0, 0)
140 | , _directionX(0, 0)
141 | , _directionY(0, 0)
142 | , _directionZ(0, 0)
143 | , _doTurn(false)
144 | {
145 | for (byte i = 0; i < 6; ++i)
146 | _legCycles[i].setLeg(&_legs[i], i < 3);
147 |
148 | _rightLegCycles = _legCycles;
149 | _leftLegCycles = _legCycles + 3;
150 | }
151 |
152 | void setGait2x3()
153 | {
154 | _legCycles[0].setCycleShift(0);
155 | _legCycles[1].setCycleShift(127);
156 | _legCycles[2].setCycleShift(0);
157 | _legCycles[3].setCycleShift(127);
158 | _legCycles[4].setCycleShift(0);
159 | _legCycles[5].setCycleShift(127);
160 |
161 | for (byte i = 0; i < 6; ++i)
162 | _legCycles[i].setCycleMiddle(127);
163 | }
164 |
165 | void setGait3x2()
166 | {
167 | _legCycles[0].setCycleShift(0);
168 | _legCycles[5].setCycleShift(0);
169 |
170 | _legCycles[1].setCycleShift((255 / 3) * 1);
171 | _legCycles[4].setCycleShift((255 / 3) * 1);
172 |
173 | _legCycles[2].setCycleShift((255 / 3) * 2);
174 | _legCycles[3].setCycleShift((255 / 3) * 2);
175 |
176 | for (byte i = 0; i < 6; ++i)
177 | _legCycles[i].setCycleMiddle(255 - (255 / 3));
178 | }
179 |
180 | void setGait6x1()
181 | {
182 | _legCycles[0].setCycleShift(0);
183 | _legCycles[1].setCycleShift((255 / 6) * 1);
184 | _legCycles[2].setCycleShift((255 / 6) * 2);
185 | _legCycles[3].setCycleShift((255 / 6) * 3);
186 | _legCycles[4].setCycleShift((255 / 6) * 4);
187 | _legCycles[5].setCycleShift((255 / 6) * 5);
188 |
189 | for (byte i = 0; i < 6; ++i)
190 | _legCycles[i].setCycleMiddle(255 - (255 / 6));
191 | }
192 |
193 | void setStep(Point dir, bool turn, float turnValue)
194 | {
195 | _directionX.setTarget(dir.x);
196 | _directionY.setTarget(dir.y);
197 | _directionZ.setTarget(dir.z);
198 | _turn.setTarget(turnValue);
199 | _doTurn = turn;
200 | }
201 |
202 | void tickStep()
203 | {
204 | Point direction(_directionX.getCurrent(),
205 | _directionY.getCurrent(),
206 | _directionZ.getCurrent());
207 |
208 | float cx, cy; // rotate around these points
209 | float angle;
210 | if (_doTurn)
211 | {
212 | angle = _turn.getCurrent() * 0.7;
213 |
214 | cx = distanceToHorde(fabs(direction.y), angle);
215 | cy = 0;
216 |
217 | if (direction.y < 0)
218 | angle *= -1;
219 | }
220 |
221 | Point stepStart = direction * 0.5;
222 | Point stepStop = stepStart * (-1);
223 |
224 | for (byte i = 0; i < 6; ++i)
225 | _legCycles[i].setStep(stepStart,
226 | stepStop,
227 | _stepHeight,
228 | _doTurn,
229 | angle,
230 | cx,
231 | cy);
232 | }
233 |
234 | void setSpeed(float stepsPerSecond)
235 | {
236 | _stepPerSecond.setTarget(stepsPerSecond);
237 | }
238 |
239 | void tick()
240 | {
241 | const unsigned long now = millis();
242 | const unsigned long deltaT = now - _lastTickTime;
243 | _lastTickTime = now;
244 |
245 | const float speedStepDelta = 0.01 * (float) deltaT;
246 | const float directionStepDelta = 0.1 * (float) deltaT;
247 | const float turnStepDelta = 0.01 * (float) deltaT;
248 | _directionX.getCurrent(directionStepDelta);
249 | _directionY.getCurrent(directionStepDelta);
250 | _directionZ.getCurrent(directionStepDelta);
251 | _turn.getCurrent(turnStepDelta);
252 |
253 | tickStep();
254 |
255 | const float cycleDelta = deltaT * (255.0 * 0.001) * _stepPerSecond.getCurrent(speedStepDelta);
256 | _currentCyclePos += cycleDelta;
257 |
258 | while (_currentCyclePos >= 255)
259 | _currentCyclePos -= 255;
260 |
261 | byte currCyclePosByte = (byte) _currentCyclePos;
262 |
263 | for (byte i = 0; i < 6; ++i)
264 | _legCycles[i].setCyclePos(currCyclePosByte);
265 | }
266 |
267 | private:
268 |
269 | LegCycle _legCycles[6];
270 | LegCycle* _rightLegCycles;
271 | LegCycle* _leftLegCycles;
272 | Leg* _legs;
273 | float _stepHeight;
274 | float _currentCyclePos; // 0 .. 255 number to be rounded to byte
275 |
276 | bool _doTurn;
277 | SmoothFloat _stepPerSecond;
278 | SmoothFloat _turn;
279 | SmoothFloat _directionX;
280 | SmoothFloat _directionY;
281 | SmoothFloat _directionZ;
282 |
283 | unsigned long _lastTickTime;
284 | };
285 |
286 | #endif
287 |
--------------------------------------------------------------------------------
/Buggy/Leg.h:
--------------------------------------------------------------------------------
1 | #ifndef LEG_H__
2 | #define LEG_H__
3 |
4 | #include
5 | #include
6 |
7 | #include "Geometry.h"
8 | #include "SmoothFloat.h"
9 |
10 | #define DONT_MOVE 123456.123456
11 |
12 | class Leg
13 | {
14 | public:
15 |
16 | Leg()
17 | : _debug(false)
18 | , _attached(false)
19 | , _cServoRestAngle(PI / 2)
20 | , _fServoRestAngle(PI / 2)
21 | , _tServoRestAngle(PI / 2)
22 | , _cServoDirection(0.0)
23 | , _fServoDirection(0.0)
24 | , _tServoDirection(0.0)
25 | , _delayReach(false)
26 | , _cAngle(_cServoRestAngle, _cServoRestAngle)
27 | , _fAngle(_fServoRestAngle, _fServoRestAngle)
28 | , _tAngle(_tServoRestAngle, _tServoRestAngle)
29 | , _lastTickTime(0)
30 | , _speedRadMsec((PI * 2) / 1000)
31 | {}
32 |
33 | void debug(bool on)
34 | {
35 | _debug = on;
36 | }
37 |
38 | void setPins(int coxaPin, int femurPin, int tibiaPin)
39 | {
40 | if (_debug)
41 | return;
42 |
43 | _coxaPin = coxaPin;
44 | _femurPin = femurPin;
45 | _tibiaPin = tibiaPin;
46 | }
47 |
48 | void attach()
49 | {
50 | if (_attached)
51 | return;
52 |
53 | _attached = true;
54 | _cServo.attach(_coxaPin);
55 | _fServo.attach(_femurPin);
56 | _tServo.attach(_tibiaPin);
57 | }
58 |
59 | void detach()
60 | {
61 | if (! _attached)
62 | return;
63 |
64 | _attached = false;
65 | _cServo.detach();
66 | _fServo.detach();
67 | _tServo.detach();
68 | }
69 |
70 | void configureCoxa(float cStartX,
71 | float cStartY,
72 | float cStartAngle,
73 | float cFemurOffset)
74 | {
75 | _cStart.x = cStartX;
76 | _cStart.y = cStartY;
77 | _cStartAngle = cStartAngle;
78 | _cFemurOffset = cFemurOffset;
79 | }
80 |
81 | void configureFemur(float fStartZOffset,
82 | float fStartFarOffset,
83 | float fLength,
84 | float fStartAngle)
85 | {
86 | _fStartZOffset = fStartZOffset;
87 | _fStartFarOffset = fStartFarOffset;
88 | _fLength = fLength;
89 | _fStartAngle = fStartAngle;
90 | }
91 |
92 | void configureTibia(float tLenght,
93 | float tStartAngle)
94 | {
95 | _tLenght = tLenght;
96 | _tStartAngle = tStartAngle;
97 | }
98 |
99 | void configureServoDirections(float cServoDirection,
100 | float fServoDirection,
101 | float tServoDirection,
102 | bool thirdQuarterFix)
103 | {
104 | _cServoDirection = cServoDirection;
105 | _fServoDirection = fServoDirection;
106 | _tServoDirection = tServoDirection;
107 | _thirdQuarterFix = thirdQuarterFix;
108 | }
109 |
110 | void tuneRestAngles(float cServoRestAngle,
111 | float fServoRestAngle,
112 | float tServoRestAngle)
113 | {
114 | _cServoRestAngle = cServoRestAngle;
115 | _fServoRestAngle = fServoRestAngle;
116 | _tServoRestAngle = tServoRestAngle;
117 | }
118 |
119 | bool reset()
120 | {
121 | move(0, 0, 0);
122 | }
123 |
124 | // Can't use reference argument here due to limitations in gcc avr
125 | void configureDefault(Point def, bool move)
126 | {
127 | _defaultPos = def;
128 | _currentPos = def;
129 |
130 | if (move)
131 | reach(def);
132 | }
133 |
134 | void shiftDefault(Point def)
135 | {
136 | Point delta = def - _defaultPos;
137 | _currentPos.assign(_currentPos + delta);
138 | _defaultPos = def;
139 |
140 | reach(_currentPos);
141 | }
142 |
143 | void shiftDefaultRelative(Point& delta)
144 | {
145 | _currentPos.assign(_currentPos + delta);
146 | _defaultPos.assign(_defaultPos + delta);
147 |
148 | reach(_currentPos);
149 | }
150 |
151 | void reachRelativeToDefault(Point& dest)
152 | {
153 | _currentPos.assign(_defaultPos + dest);
154 | reach(_currentPos);
155 | }
156 |
157 | void reachRelativeToDefaultAndRotate(Point& dest, float angle, float cx, float cy)
158 | {
159 | _currentPos.assign(_defaultPos + dest);
160 | rotate2d(cx, cy, angle, _currentPos);
161 | reach(_currentPos);
162 | }
163 |
164 | void reachRelativeToCurrent(Point& dest)
165 | {
166 | _currentPos.assign(_currentPos + dest);
167 | reach(_currentPos);
168 | }
169 |
170 | void reachAbsolute(Point& dest)
171 | {
172 | _currentPos = dest;
173 | reach(_currentPos);
174 | }
175 |
176 | Point getCurrentRelative()
177 | {
178 | return _currentPos - _defaultPos;
179 | }
180 |
181 | Point& getCurrentPos()
182 | {
183 | return _currentPos;
184 | }
185 |
186 | Point& getDefaultPos()
187 | {
188 | return _defaultPos;
189 | }
190 |
191 | void rememberRaisePoint()
192 | {
193 | _raisePoint.assign(getCurrentRelative());
194 | }
195 |
196 | Point& getRaisePoint()
197 | {
198 | return _raisePoint;
199 | }
200 |
201 | void delayReach()
202 | {
203 | _delayReach = true;
204 | }
205 |
206 | void commitDelayedReach()
207 | {
208 | _delayReach = false;
209 | reach(_delayedReach);
210 | }
211 |
212 | void tick()
213 | {
214 | #ifdef SMOOTH_ANGLES
215 | const unsigned long now = millis();
216 | const unsigned long deltaT = now - _lastTickTime;
217 |
218 | _lastTickTime = now;
219 |
220 | const float stepDelta = _speedRadMsec * deltaT;
221 |
222 | moveInternal(_cAngle.getCurrent(stepDelta),
223 | _fAngle.getCurrent(stepDelta),
224 | _tAngle.getCurrent(stepDelta));
225 | #endif
226 | }
227 |
228 | private:
229 |
230 | void reach(Point& dest)
231 | {
232 | if (_delayReach)
233 | {
234 | _delayedReach = dest;
235 | return;
236 | }
237 |
238 | float hDist = sqrt( sqr(dest.x - _cStart.x) + sqr(dest.y - _cStart.y) );
239 | float additionalCoxaAngle = hDist == 0.0 ? DONT_MOVE
240 | : asin( _cFemurOffset / hDist );
241 |
242 | float primaryCoxaAngle = polarAngle(dest.x - _cStart.x, dest.y - _cStart.y, _thirdQuarterFix);
243 |
244 | float cAngle = hDist == 0.0 ? DONT_MOVE
245 | : primaryCoxaAngle - additionalCoxaAngle - _cStartAngle;
246 |
247 | // Moving to local Coxa-Femur-target coordinate system
248 | // Note the case when hDist <= _cFemurOffset. This is for the blind zone.
249 | // We never can't reach the point that is nearer to the _cStart then
250 | // femur offset (_fStartFarOffset)
251 | float localDestX = hDist <= _cFemurOffset
252 | ? - _fStartFarOffset
253 | : sqrt(sqr(hDist) - sqr(_cFemurOffset)) - _fStartFarOffset;
254 |
255 | float localDestY = dest.z - _fStartZOffset;
256 |
257 | // Check reachability
258 | float localDistSqr = sqr(localDestX) + sqr(localDestY);
259 | if (localDistSqr > sqr(_fLength + _tLenght))
260 | {
261 | // log("Can't reach!");
262 | return;
263 | }
264 |
265 | // Find joint as circle intersect ( equations from http://e-maxx.ru/algo/circles_intersection & http://e-maxx.ru/algo/circle_line_intersection )
266 | float A = -2 * localDestX;
267 | float B = -2 * localDestY;
268 | float C = sqr(localDestX) + sqr(localDestY) + sqr(_fLength) - sqr(_tLenght);
269 | float X0 = -A * C / (sqr(A) + sqr(B));
270 | float Y0 = -B * C / (sqr(A) + sqr(B));
271 | float D = sqrt( sqr(_fLength) - (sqr(C) / (sqr(A) + sqr(B))) );
272 | float mult = sqrt ( sqr(D) / (sqr(A) + sqr(B)));
273 | float ax, ay, bx, by;
274 | ax = X0 + B * mult;
275 | bx = X0 - B * mult;
276 | ay = Y0 - A * mult;
277 | by = Y0 + A * mult;
278 |
279 | // Select solution on top as joint
280 | float jointLocalX = ax;
281 | float jointLocalY = ay;
282 |
283 | float primaryFemurAngle = polarAngle(jointLocalX, jointLocalY, false);
284 | float fAngle = primaryFemurAngle - _fStartAngle;
285 |
286 | float primaryTibiaAngle = polarAngle(localDestX - jointLocalX, localDestY - jointLocalY, false);
287 | float tAngle = (primaryTibiaAngle - fAngle) - _tStartAngle;
288 |
289 | move(cAngle, fAngle, tAngle);
290 | }
291 |
292 | void move(float cAngle, float fAngle, float tAngle)
293 | {
294 | #ifdef SMOOTH_ANGLES
295 | _cAngle.setTarget(cAngle);
296 | _fAngle.setTarget(fAngle);
297 | _tAngle.setTarget(tAngle);
298 |
299 | tick();
300 | #else
301 | moveInternal(cAngle, fAngle, tAngle);
302 | #endif
303 | }
304 |
305 | void moveInternal(float cAngle, float fAngle, float tAngle)
306 | {
307 | if (! _attached)
308 | return;
309 |
310 | int mc = rad2deg(_cServoDirection * cAngle + _cServoRestAngle);
311 | int mf = rad2deg(_fServoDirection * fAngle + _fServoRestAngle);
312 | int mt = rad2deg(_tServoDirection * tAngle + _tServoRestAngle);
313 |
314 | if (! _debug)
315 | {
316 | if (cAngle != DONT_MOVE)
317 | _cServo.write(coxaLimit(mc));
318 | if (fAngle != DONT_MOVE)
319 | _fServo.write(femurLimit(mf));
320 | if (tAngle != DONT_MOVE)
321 | _tServo.write(tibiaLimit(mt));
322 | }
323 | else
324 | {
325 | // log("Angles:");
326 | // log(mc);
327 | // log(mf);
328 | // log(mt);
329 | }
330 | }
331 |
332 | int coxaLimit(int x)
333 | {
334 | const int cMin = 90 - 70;
335 | const int cMax = 90 + 70;
336 |
337 | if (x < cMin) return cMin;
338 | if (x > cMax) return cMax;
339 |
340 | return x;
341 | }
342 |
343 | int femurLimit(int x)
344 | {
345 | const int fMin = 90 - 70;
346 | const int fMax = 90 + 70;
347 |
348 | if (x < fMin) return fMin;
349 | if (x > fMax) return fMax;
350 |
351 | return x;
352 | }
353 |
354 | int tibiaLimit(int x)
355 | {
356 | const int tMin = 90 - 70;
357 | const int tMax = 90 + 70;
358 |
359 | if (x < tMin) return tMin;
360 | if (x > tMax) return tMax;
361 |
362 | return x;
363 | }
364 |
365 | private:
366 | bool _debug;
367 |
368 | // 3dof leg has Coxa, Femur and Tibia segments and joints.
369 | // Coxa is nearest to the body, Tibia is farthest.
370 |
371 | // Config
372 | Point _cStart; // Coordinates of the Coxa start point
373 | float _cStartAngle; // Angle where Coxa is pointed to when relaxed
374 | float _cFemurOffset; // Offset of Femur and Tibia axis from the Coxa axis
375 | float _fStartZOffset; // Botton offset of Femur start from the z0 plane
376 | float _fStartFarOffset;
377 | float _fLength; // Femur length
378 | float _fStartAngle;
379 | float _tLenght; // Tibia length
380 | float _tStartAngle;
381 |
382 | // Servo rest angles are for fine tune of angles. By default it is pi/2
383 | float _cServoRestAngle;
384 | float _fServoRestAngle;
385 | float _tServoRestAngle;
386 |
387 | // Servo direction should be 1.0 or -1.0 - determines servo orientation
388 | float _cServoDirection;
389 | float _fServoDirection;
390 | float _tServoDirection;
391 |
392 | Point _raisePoint;
393 | Point _defaultPos;
394 | Point _currentPos;
395 | bool _attached;
396 | bool _thirdQuarterFix;
397 |
398 | int _coxaPin;
399 | int _femurPin;
400 | int _tibiaPin;
401 |
402 | // Delayed move
403 | bool _delayReach;
404 | Point _delayedReach;
405 |
406 | // Arduino servos
407 | Servo _cServo;
408 | Servo _fServo;
409 | Servo _tServo;
410 |
411 | // Smooth angle movement
412 | unsigned long _lastTickTime;
413 | SmoothFloat _cAngle;
414 | SmoothFloat _fAngle;
415 | SmoothFloat _tAngle;
416 | float _speedRadMsec;
417 |
418 | };
419 |
420 | typedef Leg* PLeg;
421 |
422 | #endif
423 |
--------------------------------------------------------------------------------
/BuggyRemote/src/com/poconoco/buggyremote/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.poconoco.buggyremote;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Rect;
5 | import android.os.Bundle;
6 | import android.view.Menu;
7 | import android.view.MotionEvent;
8 | import android.view.TouchDelegate;
9 | import android.view.View;
10 | import android.view.View.OnClickListener;
11 | import android.widget.Button;
12 | import android.widget.CheckBox;
13 | import android.widget.ImageView;
14 | import android.widget.SeekBar;
15 | import android.widget.SeekBar.OnSeekBarChangeListener;
16 | import android.widget.TextView;
17 |
18 | public class MainActivity extends Activity
19 | implements BuggySensors.Listener, BuggyBluetooth.Listener
20 | {
21 | @Override
22 | protected void onCreate(final Bundle savedInstanceState)
23 | {
24 | super.onCreate(savedInstanceState);
25 | _bt = new BuggyBluetooth(this, this);
26 | _sensors = new BuggySensors(this, this);
27 |
28 | _sensorsThread = new StateUpdateThread();
29 | _sensorsThread.start();
30 |
31 | // FIXME: hardcoded UUID
32 | _bt.setUUID("00001101-0000-1000-8000-00805F9B34FB");
33 |
34 | setContentView(R.layout.activity_main);
35 | this.findViewById(android.R.id.content).setKeepScreenOn(true);
36 |
37 | _bodyMovementJoystick = (ImageView)findViewById(R.id.movementAreaImage);
38 | _bodyShiftPitchRollJoystick = (ImageView)findViewById(R.id.bodyShiftArea);
39 | _movementHint = (TextView)findViewById(R.id.movementHint);
40 | _buttonBluetoothToggle = (Button)findViewById(R.id.buttonBT);
41 | _buttonSendEngineToggle = (Button)findViewById(R.id.buttonEngine);
42 | _buttonSendMandibleToggle = (Button)findViewById(R.id.buttonMandiblesEngine);
43 |
44 | _buttonSendGait1 = (Button)findViewById(R.id.buttonGait1);
45 | _buttonSendGait2 = (Button)findViewById(R.id.buttonGait2);
46 | _buttonSendGait3 = (Button)findViewById(R.id.buttonGait3);
47 | _checkBoxUseSensors = (CheckBox)findViewById(R.id.checkBoxSensors);
48 | _checkBoxSwitchLinearMovement = (CheckBox)findViewById(R.id.checkLinear);
49 | _checkBoxSwitchHorizShift = (CheckBox)findViewById(R.id.checkBoxHorizShift);
50 | _checkBoxSwitchMandibleControl = (CheckBox)findViewById(R.id.checkBoxMandibleControl);
51 |
52 | _seekMandibleHeight = (SeekBar)findViewById(R.id.seekMandibleHeight);
53 | _seekMandibleHeight.setProgress(50);
54 |
55 | _bodyMovementJoystick.setTouchDelegate(
56 | new MovementJoystickTouchDelegate(null, _bodyMovementJoystick));
57 |
58 | _bodyShiftPitchRollJoystick.setTouchDelegate(
59 | new ShiftPithRollTouchDelegate(null, _bodyShiftPitchRollJoystick));
60 |
61 | _buttonSendEngineToggle.setOnClickListener(new OnClickListener()
62 | {
63 | @Override
64 | public void onClick(final View v)
65 | {
66 | _bt.write(BuggyProtocol.getToggleServoCmd());
67 | }
68 | });
69 |
70 | _buttonSendMandibleToggle.setOnClickListener(new OnClickListener()
71 | {
72 | @Override
73 | public void onClick(final View v)
74 | {
75 | _bt.write(BuggyProtocol.getToggleMandibleCmd());
76 | }
77 | });
78 |
79 | _buttonSendGait1.setOnClickListener(new OnClickListener()
80 | {
81 | @Override
82 | public void onClick(final View v)
83 | {
84 | _bt.write(BuggyProtocol.getGaitCmd(1));
85 | }
86 | });
87 |
88 | _buttonSendGait2.setOnClickListener(new OnClickListener()
89 | {
90 | @Override
91 | public void onClick(final View v)
92 | {
93 | _bt.write(BuggyProtocol.getGaitCmd(2));
94 | }
95 | });
96 |
97 | _buttonSendGait3.setOnClickListener(new OnClickListener()
98 | {
99 | @Override
100 | public void onClick(final View v)
101 | {
102 | _bt.write(BuggyProtocol.getGaitCmd(3));
103 | }
104 | });
105 |
106 | _buttonBluetoothToggle.setOnClickListener(new OnClickListener()
107 | {
108 | @Override
109 | public void onClick(final View v)
110 | {
111 | _bt.toggle();
112 | }
113 | });
114 |
115 | _seekMandibleHeight.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
116 | {
117 | @Override
118 | public void onStopTrackingTouch(final SeekBar seekBar)
119 | {}
120 |
121 | @Override
122 | public void onStartTrackingTouch(final SeekBar seekBar)
123 | {}
124 |
125 | @Override
126 | public void onProgressChanged(final SeekBar seekBar,
127 | final int progress,
128 | final boolean fromUser)
129 | {
130 | _mandibles.encodeHeight((progress - 50.0) / 50.0);
131 | }
132 | });
133 | }
134 |
135 | class MovementJoystickTouchDelegate extends TouchDelegate
136 | {
137 | public MovementJoystickTouchDelegate(final Rect bounds, final View delegateView)
138 | {
139 | super(bounds, delegateView);
140 | }
141 |
142 | @Override
143 | public boolean onTouchEvent(final MotionEvent event)
144 | {
145 | float x = event.getX();
146 | float y = event.getY();
147 |
148 | if (event.getActionMasked() == MotionEvent.ACTION_MOVE
149 | || event.getActionMasked() == MotionEvent.ACTION_DOWN)
150 | {
151 | if (x < 0)
152 | x = 0;
153 | if (y < 0)
154 | y = 0;
155 |
156 | if (x > _bodyMovementJoystick.getWidth())
157 | x = _bodyMovementJoystick.getWidth();
158 | if (y > _bodyMovementJoystick.getHeight())
159 | y = _bodyMovementJoystick.getHeight();
160 |
161 | x = x * 2 / _bodyMovementJoystick.getWidth() - 1;
162 | y = y * 2 / _bodyMovementJoystick.getHeight() - 1;
163 |
164 | if (_checkBoxSwitchMandibleControl.isChecked())
165 | _mandibles.encodeLeft(x, y);
166 | }
167 | else if (event.getAction() == MotionEvent.ACTION_UP)
168 | {
169 | x = 0;
170 | y = 0;
171 | }
172 |
173 | if (! _checkBoxSwitchMandibleControl.isChecked())
174 | {
175 | if (_checkBoxSwitchLinearMovement.isChecked())
176 | _bodyMovement.encodeLinear(x, y);
177 | else
178 | _bodyMovement.encodeWithTurn(x, y);
179 | }
180 |
181 | _movementHint.setText((int)(x * 100) + ":" + (int)(y * 100));
182 | return true;
183 | }
184 | }
185 |
186 | class ShiftPithRollTouchDelegate extends TouchDelegate
187 | {
188 | public ShiftPithRollTouchDelegate(final Rect bounds, final View delegateView)
189 | {
190 | super(bounds, delegateView);
191 | }
192 |
193 | @Override
194 | public boolean onTouchEvent(final MotionEvent event)
195 | {
196 | float x = event.getX();
197 | float y = event.getY();
198 |
199 | if (event.getActionMasked() == MotionEvent.ACTION_MOVE
200 | || event.getActionMasked() == MotionEvent.ACTION_DOWN)
201 | {
202 | if (x < 0)
203 | x = 0;
204 | if (y < 0)
205 | y = 0;
206 |
207 | if (x > _bodyShiftPitchRollJoystick.getWidth())
208 | x = _bodyShiftPitchRollJoystick.getWidth();
209 | if (y > _bodyShiftPitchRollJoystick.getHeight())
210 | y = _bodyShiftPitchRollJoystick.getHeight();
211 |
212 | x = x * 2 / _bodyShiftPitchRollJoystick.getWidth() - 1;
213 | y = y * 2 / _bodyShiftPitchRollJoystick.getHeight() - 1;
214 |
215 | if (_checkBoxSwitchMandibleControl.isChecked())
216 | {
217 | _mandibles.encodeRight(x, y);
218 | }
219 | else
220 | {
221 | _bodyShift.x = (byte) (- x * 127);
222 | if (_checkBoxSwitchHorizShift.isChecked())
223 | _bodyShift.y = (byte) (y * 127);
224 | else
225 | _bodyShift.z = (byte) (y * 127);
226 | }
227 |
228 | _movementHint.setText((int)(x * 100) + ":" + (int)(y * 100));
229 | }
230 |
231 | return true;
232 | }
233 |
234 | }
235 |
236 | @Override
237 | public void onDestroy()
238 | {
239 | super.onDestroy();
240 | _sensors.unregister();
241 | }
242 |
243 | @Override
244 | public void onPause()
245 | {
246 | super.onPause();
247 | _bt.stop();
248 | _sensors.unregister();
249 | }
250 |
251 | @Override
252 | public void onResume()
253 | {
254 | super.onResume();
255 | _sensors.register();
256 | }
257 |
258 | @Override
259 | public boolean onCreateOptionsMenu(final Menu menu)
260 | {
261 | // Inflate the menu; this adds items to the action bar if it is present.
262 | getMenuInflater().inflate(R.menu.activity_main, menu);
263 | return true;
264 | }
265 |
266 |
267 | private class StateUpdateThread extends Thread
268 | {
269 | @Override
270 | public void run()
271 | {
272 | while (true)
273 | {
274 | if (_connected)
275 | {
276 | runOnUiThread(new Runnable()
277 | {
278 | @Override
279 | public void run()
280 | {
281 | if (_checkBoxUseSensors.isChecked()
282 | && _bodyShift
283 | .differ(_prevBodyShift))
284 | {
285 | _prevBodyShift.copyFrom(_bodyShift);
286 | _bt.write(BuggyProtocol.getBodyShiftCmd(_bodyShift));
287 | }
288 |
289 | _prevBodyMovement.copyFrom(_bodyMovement);
290 |
291 | _bt.write(BuggyProtocol.getBodyMovementCmd(_bodyMovement));
292 |
293 | if (_mandibles.differ(_prevMandibles))
294 | {
295 | _prevMandibles.copyFrom(_mandibles);
296 | _bt.write(BuggyProtocol.getMandiblesCmd(_mandibles));
297 | }
298 | }
299 | });
300 | }
301 |
302 | try
303 | {
304 | sleep(100);
305 | } catch (final InterruptedException e)
306 | {
307 | e.printStackTrace();
308 | }
309 |
310 | }
311 | }
312 | };
313 |
314 | @Override
315 | public void onStateChanged(final BuggyBluetooth.State state, final String stateStr)
316 | {
317 | runOnUiThread(new Runnable()
318 | {
319 | @Override
320 | public void run()
321 | {
322 | _movementHint.setText(stateStr);
323 | }
324 | });
325 |
326 | _connected = state == BuggyBluetooth.State.STATE_CONNECTED;
327 | }
328 |
329 | @Override
330 | public void onPitchRollChanged(final float pitch, final float roll)
331 | {
332 | _bodyShift.pitch = (byte)(pitch / 90 * 127);
333 | _bodyShift.roll = (byte)(roll / 90 * 127);
334 | }
335 |
336 | private BuggyBluetooth _bt;
337 | private BuggySensors _sensors;
338 | private boolean _connected = false;
339 |
340 | private StateUpdateThread _sensorsThread;
341 |
342 | private ImageView _bodyMovementJoystick;
343 | private ImageView _bodyShiftPitchRollJoystick;
344 | private TextView _movementHint;
345 |
346 | private Button _buttonBluetoothToggle;
347 | private Button _buttonSendEngineToggle;
348 | private Button _buttonSendMandibleToggle;
349 |
350 | private Button _buttonSendGait1;
351 | private Button _buttonSendGait2;
352 | private Button _buttonSendGait3;
353 |
354 | private CheckBox _checkBoxUseSensors;
355 | private CheckBox _checkBoxSwitchLinearMovement;
356 | private CheckBox _checkBoxSwitchHorizShift;
357 | private CheckBox _checkBoxSwitchMandibleControl;
358 |
359 | private SeekBar _seekMandibleHeight;
360 |
361 | private final BuggyBodyShift _bodyShift = new BuggyBodyShift();
362 | private final BuggyBodyMovement _bodyMovement = new BuggyBodyMovement();
363 | private final BuggyMandibles _mandibles = new BuggyMandibles();
364 |
365 | private final BuggyBodyShift _prevBodyShift = new BuggyBodyShift();
366 | private final BuggyBodyMovement _prevBodyMovement = new BuggyBodyMovement();
367 | private final BuggyMandibles _prevMandibles = new BuggyMandibles();
368 | }
369 |
370 |
--------------------------------------------------------------------------------
/BuggyRemote/src/com/poconoco/buggyremote/BuggyBluetooth.java:
--------------------------------------------------------------------------------
1 | package com.poconoco.buggyremote;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.OutputStream;
6 | import java.util.UUID;
7 |
8 | import android.app.Activity;
9 | import android.bluetooth.BluetoothAdapter;
10 | import android.bluetooth.BluetoothDevice;
11 | import android.bluetooth.BluetoothSocket;
12 | import android.content.Intent;
13 | import android.util.Log;
14 |
15 | public class BuggyBluetooth
16 | {
17 | enum State
18 | {
19 | STATE_NONE,
20 | STATE_LISTEN,
21 | STATE_CONNECTING,
22 | STATE_CONNECTED
23 | }
24 |
25 | public interface Listener
26 | {
27 | void onStateChanged(State state, String stateStr);
28 | }
29 |
30 | BuggyBluetooth(final Listener listener, final Activity activity)
31 | {
32 | _listener = listener;
33 | _context = activity;
34 | }
35 |
36 | void setUUID(final String uuid)
37 | {
38 | _uuid = uuid;
39 | }
40 |
41 | public void toggle()
42 | {
43 | _adapter = BluetoothAdapter.getDefaultAdapter();
44 | if (_adapter == null)
45 | {
46 | _listener.onStateChanged(_state, "No bluetooth on device");
47 | return;
48 | }
49 |
50 | if (! _adapter.isEnabled())
51 | {
52 | final Intent enableBtIntent = new Intent(
53 | BluetoothAdapter.ACTION_REQUEST_ENABLE);
54 | _context.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
55 | return;
56 | }
57 |
58 | // FIXME: hardcoded MAC
59 | if (_state == State.STATE_NONE)
60 | connect(_adapter.getRemoteDevice("00:12:10:12:10:04"));
61 |
62 | if (_state == State.STATE_CONNECTED)
63 | stop();
64 | }
65 |
66 | public synchronized void connect(final BluetoothDevice device)
67 | {
68 | Log.d(LOG_TAG, "connect to: " + device);
69 |
70 | // Cancel any thread attempting to make a connection
71 | if (_state == State.STATE_CONNECTING)
72 | {
73 | if (_connectThread != null)
74 | {
75 | _connectThread.cancel();
76 | _connectThread = null;
77 | }
78 | }
79 |
80 | // Cancel any thread currently running a connection
81 | if (_connectedThread != null)
82 | {
83 | _connectedThread.cancel();
84 | _connectedThread = null;
85 | }
86 |
87 | // Start the thread to connect with the given device
88 | _connectThread = new ConnectThread(device);
89 | _connectThread.start();
90 | setState(State.STATE_CONNECTING);
91 | }
92 |
93 | public synchronized void connected(final BluetoothSocket socket,
94 | final BluetoothDevice device)
95 | {
96 | // Cancel the thread that completed the connection
97 | if (_connectThread != null)
98 | {
99 | _connectThread.cancel();
100 | _connectThread = null;
101 | }
102 |
103 | // Cancel any thread currently running a connection
104 | if (_connectedThread != null)
105 | {
106 | _connectedThread.cancel();
107 | _connectedThread = null;
108 | }
109 |
110 | // Start the thread to manage the connection and perform transmissions
111 | _connectedThread = new ConnectedThread(socket);
112 | _connectedThread.start();
113 |
114 | /*
115 | * // Send the name of the connected device back to the UI Activity
116 | * Message msg = mHandler.obtainMessage(BlueTerm.MESSAGE_DEVICE_NAME);
117 | * Bundle bundle = new Bundle(); bundle.putString(BlueTerm.DEVICE_NAME,
118 | * device.getName()); msg.setData(bundle); mHandler.sendMessage(msg);
119 | */
120 |
121 | setState(State.STATE_CONNECTED);
122 | }
123 |
124 | public synchronized void start()
125 | {
126 | // Cancel any thread attempting to make a connection
127 | if (_connectThread != null)
128 | {
129 | _connectThread.cancel();
130 | _connectThread = null;
131 | }
132 |
133 | // Cancel any thread currently running a connection
134 | if (_connectedThread != null)
135 | {
136 | _connectedThread.cancel();
137 | _connectedThread = null;
138 | }
139 |
140 | setState(State.STATE_NONE);
141 | }
142 |
143 | /**
144 | * Stop all threads
145 | */
146 | public synchronized void stop()
147 | {
148 | Log.d(LOG_TAG, "stop");
149 |
150 | if (_connectThread != null)
151 | {
152 | _connectThread.cancel();
153 | _connectThread = null;
154 | }
155 |
156 | if (_connectedThread != null)
157 | {
158 | _connectedThread.cancel();
159 | _connectedThread = null;
160 | }
161 |
162 | setState(State.STATE_NONE);
163 | }
164 |
165 | public synchronized State getState()
166 | {
167 | return _state;
168 | }
169 |
170 | public String stateToString(final State state)
171 | {
172 | switch (state)
173 | {
174 | case STATE_NONE:
175 | return "Sate: none";
176 | case STATE_LISTEN:
177 | return "State: listening";
178 | case STATE_CONNECTING:
179 | return "State: connecting";
180 | case STATE_CONNECTED:
181 | return "State: connected";
182 | }
183 |
184 | return "Unknown";
185 | }
186 |
187 | private synchronized void setState(final State state)
188 | {
189 | _state = state;
190 |
191 | _listener.onStateChanged(state, stateToString(state));
192 | }
193 |
194 | public void write(final byte[] out)
195 | {
196 | // Create temporary object
197 | ConnectedThread r;
198 | // Synchronize a copy of the ConnectedThread
199 | synchronized (this)
200 | {
201 | if (_state != State.STATE_CONNECTED)
202 | return;
203 | r = _connectedThread;
204 | r.write(out);
205 | }
206 | }
207 |
208 | public void write(final String str)
209 | {
210 | write(str.getBytes());
211 | }
212 |
213 | /**
214 | * This thread runs during a connection with a remote device. It handles all
215 | * incoming and outgoing transmissions.
216 | */
217 | private class ConnectedThread extends Thread
218 | {
219 | private final BluetoothSocket mmSocket;
220 | private final InputStream mmInStream;
221 | private final OutputStream mmOutStream;
222 |
223 | public ConnectedThread(final BluetoothSocket socket)
224 | {
225 | Log.d(LOG_TAG, "create ConnectedThread");
226 | mmSocket = socket;
227 | InputStream tmpIn = null;
228 | OutputStream tmpOut = null;
229 |
230 | // Get the BluetoothSocket input and output streams
231 | try
232 | {
233 | tmpIn = socket.getInputStream();
234 | tmpOut = socket.getOutputStream();
235 | } catch (final IOException e)
236 | {
237 | Log.e(LOG_TAG, "temp sockets not created", e);
238 | }
239 |
240 | mmInStream = tmpIn;
241 | mmOutStream = tmpOut;
242 | }
243 |
244 | @Override
245 | public void run()
246 | {
247 | Log.i(LOG_TAG, "BEGIN mConnectedThread");
248 | final byte[] buffer = new byte[1024];
249 |
250 | // Keep listening to the InputStream while connected
251 | while (true)
252 | {
253 | try
254 | {
255 | // Read from the InputStream
256 | @SuppressWarnings("unused")
257 | final int bytes = mmInStream.read(buffer);
258 |
259 | /*
260 | * runOnUiThread(new Runnable(){
261 | *
262 | * @Override public void run() {
263 | * //textBTReceived.setText(new String(buffer, 0, bytes)); }
264 | * });
265 | */
266 | // Send the obtained bytes to the UI Activity
267 | // mHandler.obtainMessage(BlueTerm.MESSAGE_READ, bytes, -1,
268 | // buffer).sendToTarget();
269 | try
270 | {
271 | Thread.sleep(500);
272 | } catch (final InterruptedException e)
273 | {
274 | e.printStackTrace();
275 | }
276 | } catch (final IOException e)
277 | {
278 | Log.e(LOG_TAG, "disconnected", e);
279 | connectionLost();
280 | break;
281 | }
282 | }
283 | }
284 |
285 | /**
286 | * Write to the connected OutStream.
287 | *
288 | * @param buffer
289 | * The bytes to write
290 | */
291 | public void write(final byte[] buffer)
292 | {
293 | try
294 | {
295 | mmOutStream.write(buffer);
296 |
297 | /*
298 | * // Share the sent message back to the UI Activity
299 | * mHandler.obtainMessage(BlueTerm.MESSAGE_WRITE, buffer.length,
300 | * -1, buffer) .sendToTarget();
301 | */
302 | } catch (final IOException e)
303 | {
304 | Log.e(LOG_TAG, "Exception during write", e);
305 | }
306 | }
307 |
308 | public void cancel()
309 | {
310 | try
311 | {
312 | mmSocket.close();
313 | } catch (final IOException e)
314 | {
315 | Log.e(LOG_TAG, "close() of connect socket failed", e);
316 | }
317 | }
318 | }
319 |
320 | /**
321 | * This thread runs while attempting to make an outgoing connection with a
322 | * device. It runs straight through; the connection either succeeds or
323 | * fails.
324 | */
325 | private class ConnectThread extends Thread
326 | {
327 | private final BluetoothSocket mmSocket;
328 | private final BluetoothDevice mmDevice;
329 |
330 | public ConnectThread(final BluetoothDevice device)
331 | {
332 | mmDevice = device;
333 | BluetoothSocket tmp = null;
334 |
335 | // Get a BluetoothSocket for a connection with the
336 | // given BluetoothDevice
337 | try
338 | {
339 | tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(_uuid));
340 | } catch (final IOException e)
341 | {
342 | Log.e(LOG_TAG, "create() failed", e);
343 | }
344 | mmSocket = tmp;
345 | }
346 |
347 | @Override
348 | public void run()
349 | {
350 | Log.i(LOG_TAG, "BEGIN mConnectThread");
351 | setName("ConnectThread");
352 |
353 | // Always cancel discovery because it will slow down a connection
354 | _adapter.cancelDiscovery();
355 |
356 | // Make a connection to the BluetoothSocket
357 | try
358 | {
359 | // This is a blocking call and will only return on a
360 | // successful connection or an exception
361 | mmSocket.connect();
362 | } catch (final IOException e)
363 | {
364 | connectionFailed();
365 | // Close the socket
366 | try
367 | {
368 | mmSocket.close();
369 | } catch (final IOException e2)
370 | {
371 | Log.e(LOG_TAG,
372 | "unable to close() socket during connection failure",
373 | e2);
374 | }
375 | // Start the service over to restart listening mode
376 | // BluetoothSerialService.this.start();
377 | return;
378 | }
379 |
380 | // Reset the ConnectThread because we're done
381 | synchronized (_context)
382 | {
383 | _connectThread = null;
384 | }
385 |
386 | // Start the connected thread
387 | connected(mmSocket, mmDevice);
388 | }
389 |
390 | public void cancel()
391 | {
392 | try
393 | {
394 | mmSocket.close();
395 | } catch (final IOException e)
396 | {
397 | Log.e(LOG_TAG, "close() of connect socket failed", e);
398 | }
399 | }
400 | }
401 |
402 | private void connectionLost()
403 | {
404 | setState(State.STATE_NONE);
405 | }
406 |
407 | private void connectionFailed()
408 | {
409 | setState(State.STATE_NONE);
410 | }
411 |
412 | private final Listener _listener;
413 | private final Activity _context;
414 |
415 | private String _uuid;
416 | private State _state = State.STATE_NONE;
417 |
418 | private ConnectThread _connectThread;
419 | private ConnectedThread _connectedThread;
420 | private BluetoothAdapter _adapter;
421 |
422 | protected static final int REQUEST_ENABLE_BT = 12; // Magic number :)
423 | private static final String LOG_TAG = "BluetoothReadService";
424 | }
425 |
--------------------------------------------------------------------------------
/BuggyRemote/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 | org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
6 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
7 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
8 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
9 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
10 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
11 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
12 | org.eclipse.jdt.core.formatter.alignment_for_assignment=0
13 | org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
14 | org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
15 | org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
16 | org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
17 | org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
18 | org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
19 | org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
20 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
21 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
22 | org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
23 | org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
24 | org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
25 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
26 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
27 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
28 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
29 | org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
30 | org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
31 | org.eclipse.jdt.core.formatter.blank_lines_after_package=1
32 | org.eclipse.jdt.core.formatter.blank_lines_before_field=0
33 | org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
34 | org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
35 | org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
36 | org.eclipse.jdt.core.formatter.blank_lines_before_method=1
37 | org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
38 | org.eclipse.jdt.core.formatter.blank_lines_before_package=0
39 | org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
40 | org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
41 | org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=next_line
42 | org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=next_line
43 | org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=next_line
44 | org.eclipse.jdt.core.formatter.brace_position_for_block=next_line
45 | org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=next_line
46 | org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=next_line
47 | org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=next_line
48 | org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=next_line
49 | org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=next_line
50 | org.eclipse.jdt.core.formatter.brace_position_for_switch=next_line
51 | org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=next_line
52 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
53 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
54 | org.eclipse.jdt.core.formatter.comment.format_block_comments=true
55 | org.eclipse.jdt.core.formatter.comment.format_header=false
56 | org.eclipse.jdt.core.formatter.comment.format_html=true
57 | org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
58 | org.eclipse.jdt.core.formatter.comment.format_line_comments=true
59 | org.eclipse.jdt.core.formatter.comment.format_source_code=true
60 | org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
61 | org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
62 | org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
63 | org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
64 | org.eclipse.jdt.core.formatter.comment.line_length=80
65 | org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
66 | org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
67 | org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
68 | org.eclipse.jdt.core.formatter.compact_else_if=true
69 | org.eclipse.jdt.core.formatter.continuation_indentation=2
70 | org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
71 | org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
72 | org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
73 | org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
74 | org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
75 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
76 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
77 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
78 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
79 | org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
80 | org.eclipse.jdt.core.formatter.indent_empty_lines=false
81 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
82 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
83 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
84 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
85 | org.eclipse.jdt.core.formatter.indentation.size=4
86 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
87 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
88 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
89 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
90 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
91 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
92 | org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
93 | org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
94 | org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
95 | org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
96 | org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
97 | org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
98 | org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
99 | org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
100 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=do not insert
101 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=do not insert
102 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=do not insert
103 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=do not insert
104 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=do not insert
105 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=do not insert
106 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=do not insert
107 | org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
108 | org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
109 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
110 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
111 | org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
112 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
113 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
114 | org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
115 | org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
116 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
117 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
118 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
119 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
120 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
121 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
122 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
123 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
124 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
125 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
126 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
127 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
128 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
129 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
130 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
131 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
132 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
133 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
134 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
135 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
136 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
137 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
138 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
139 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
140 | org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
141 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
142 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
143 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
144 | org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
145 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
146 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
147 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
148 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
149 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
150 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
151 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
152 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
153 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
154 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
155 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
156 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
157 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
158 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
159 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
160 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
161 | org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
162 | org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
163 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
164 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
165 | org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
166 | org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
167 | org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
168 | org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
169 | org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
170 | org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
171 | org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
172 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
173 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
174 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
175 | org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
176 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
177 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
178 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
179 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
180 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
181 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
182 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
183 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
184 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
185 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
186 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
187 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
188 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
189 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
190 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
191 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
192 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
193 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
194 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
195 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
196 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
197 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
198 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
199 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
200 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
201 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
202 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
203 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
204 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
205 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
206 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
207 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
208 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
209 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
210 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
211 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
212 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
213 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
214 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
215 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
216 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
217 | org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
218 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
219 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
220 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
221 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
222 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
223 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
224 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
225 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
226 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
227 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
228 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
229 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
230 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
231 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
232 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
233 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
234 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
235 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
236 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
237 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
238 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
239 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
240 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
241 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
242 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
243 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
244 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
245 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
246 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
247 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
248 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
249 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
250 | org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
251 | org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
252 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
253 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
254 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
255 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
256 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
257 | org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
258 | org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
259 | org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
260 | org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
261 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
262 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
263 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
264 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
265 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
266 | org.eclipse.jdt.core.formatter.join_lines_in_comments=true
267 | org.eclipse.jdt.core.formatter.join_wrapped_lines=true
268 | org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
269 | org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
270 | org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
271 | org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
272 | org.eclipse.jdt.core.formatter.lineSplit=80
273 | org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
274 | org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
275 | org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
276 | org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
277 | org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
278 | org.eclipse.jdt.core.formatter.tabulation.char=space
279 | org.eclipse.jdt.core.formatter.tabulation.size=4
280 | org.eclipse.jdt.core.formatter.use_on_off_tags=false
281 | org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
282 | org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
283 | org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
284 | org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
285 |
--------------------------------------------------------------------------------