GamepadUnit.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * ArmarX is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * ArmarX is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  *
16  * @package RobotAPI::ArmarXObjects::GamepadUnit
17  * @author Simon Ottenhaus ( simon dot ottenhaus at kit dot edu )
18  * @date 2017
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "GamepadUnit.h"
24 
28 
29 #include <linux/joystick.h>
30 
31 using namespace armarx;
32 
33 void
35 {
37  offeringTopic(getProperty<std::string>("GamepadTopicName").getValue());
38  deviceName = getProperty<std::string>("GamepadDeviceName").getValue();
39  deviceEventName = getProperty<std::string>("GamepadForceFeedbackName").getValue();
40  readTask = new RunningTask<GamepadUnit>(this, &GamepadUnit::run, "GamepadUnit");
41 }
42 
43 void
45 {
47  topicPrx =
48  getTopic<GamepadUnitListenerPrx>(getProperty<std::string>("GamepadTopicName").getValue());
50  sendTask = new SimplePeriodicTask<>(
51  [&]
52  {
54  std::unique_lock lock(mutex);
55  if (!js.opened())
56  {
57  return;
58  }
60  if (!dataTimestamp)
61  {
62  ARMARX_INFO << deactivateSpam(1) << "dataTimestamp is null, waiting for value";
63  return;
64  }
65  ARMARX_CHECK_NOT_NULL(dataTimestamp);
66  const IceUtil::Time age = IceUtil::Time::now() - dataTimestamp->toTime();
67  if (age.toMilliSeconds() < getProperty<int>("PublishTimeout").getValue())
68  {
70  ARMARX_CHECK_NOT_NULL(topicPrx) << "Topic proxy must not be null.";
71  topicPrx->reportGamepadState(deviceName, js.name, data, dataTimestamp);
72  }
73  else
74  {
76  ARMARX_INFO << deactivateSpam(100000, std::to_string(dataTimestamp->getTimestamp()))
77  << "No new signal from gamepad for " << age.toMilliSecondsDouble()
78  << " milliseconds. Not sending data. Timeout: "
79  << getProperty<int>("PublishTimeout").getValue() << " ms";
80  }
81  },
82  30);
83 
84  sendTask->start();
87 }
88 
89 void
90 GamepadUnit::vibrate(const ::Ice::Current&)
91 {
92  ARMARX_INFO << "vibration!";
93  js.executeEffect();
94 }
95 
96 bool
98 {
99  if (js.open(deviceName, deviceEventName))
100  {
101 
102  ARMARX_TRACE;
103  ARMARX_INFO << "opened a gamepad named " << js.name << " with " << js.numberOfAxis
104  << " axis and " << js.numberOfButtons << " buttons.";
105  if (js.numberOfAxis == 8 && js.numberOfButtons == 11)
106  {
107  ARMARX_TRACE;
108  readTask->start();
109  }
110  else
111  {
112  ARMARX_TRACE;
113  ARMARX_WARNING << "this is not our trusty logitech gamepad.";
114  js.close();
115  return false;
116  }
117  }
118  else
119  {
120  ARMARX_TRACE;
121  ARMARX_WARNING << "Could not open gamepad device " << deviceName;
122  js.close();
123  return false;
124  }
125  return true;
126 }
127 
128 void
129 GamepadUnit::run()
130 {
131  ARMARX_TRACE;
132  while (readTask->isRunning())
133  {
134  ARMARX_TRACE;
135  if (!js.pollEvent())
136  {
137  ARMARX_TRACE;
138  ARMARX_WARNING << "failed to read gamepad data - trying to reconnect";
139  js.close();
140  sleep(1);
141  while (readTask->isRunning() && !openGamepadConnection())
142  {
143  sleep(1);
144  }
145  }
146  ARMARX_TRACE;
147  std::unique_lock lock(mutex);
148  IceUtil::Time now = IceUtil::Time::now();
149  dataTimestamp = new TimestampVariant(now);
150 
151  //mapping found with command line tool jstest <device file>
152 
153  float axisFactor = 1.0f / 32768.f;
154 
155  data.leftStickY = js.axis[0] * axisFactor;
156  data.leftStickX = js.axis[1] * axisFactor;
157  data.rightStickX = js.axis[3] * axisFactor;
158  data.rightStickY = js.axis[4] * axisFactor;
159  data.dPadX = js.axis[7] * axisFactor;
160  data.dPadY = js.axis[6] * axisFactor;
161  data.leftTrigger = js.axis[2] * axisFactor;
162  data.rightTrigger = js.axis[5] * axisFactor;
163  ARMARX_TRACE;
164 
165  data.leftButton = js.buttonsPressed[4];
166  data.rightButton = js.buttonsPressed[5];
167  data.backButton = js.buttonsPressed[6];
168  data.startButton = js.buttonsPressed[7];
169  data.xButton = js.buttonsPressed[2];
170  data.yButton = js.buttonsPressed[3];
171  data.aButton = js.buttonsPressed[0];
172  data.bButton = js.buttonsPressed[1];
173  data.theMiddleButton = js.buttonsPressed[8];
174  data.leftStickButton = js.buttonsPressed[9];
175  data.rightStickButton = js.buttonsPressed[10];
176  ARMARX_TRACE;
177 
178  ARMARX_VERBOSE << "left x (integer): " << js.axis[0]
179  << " left x (float): " << data.leftStickX
180  << " right trigger: " << data.rightTrigger;
181 
182  //usleep(1000); // 10ms
183  }
184 }
185 
186 void
188 {
189  ARMARX_TRACE;
190  if (sendTask)
191  {
192  ARMARX_TRACE;
193  sendTask->stop();
194  }
195  if (readTask)
196  {
197  ARMARX_TRACE;
198  readTask->stop();
199  }
200 }
201 
202 void
204 {
205 }
206 
209 {
212 }
armarx::Joystick::open
bool open(std::string const &deviceName, std::string const &deviceEventName)
Definition: Joystick.h:55
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::GamepadUnit::onDisconnectComponent
void onDisconnectComponent() override
Definition: GamepadUnit.cpp:187
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
trace.h
armarx::TimestampVariant
Definition: TimestampVariant.h:54
armarx::Joystick::numberOfButtons
int numberOfButtons
Definition: Joystick.h:51
armarx::Joystick::name
std::string name
Definition: Joystick.h:52
armarx::RunningTask
Definition: ArmarXMultipleObjectsScheduler.h:36
armarx::GamepadUnit::onExitComponent
void onExitComponent() override
Definition: GamepadUnit.cpp:203
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::GamepadUnit::vibrate
void vibrate(const ::Ice::Current &=::Ice::emptyCurrent) override
Definition: GamepadUnit.cpp:90
armarx::Joystick::executeEffect
void executeEffect(int gain=100, const int nTimes=1)
Definition: Joystick.h:124
TimestampVariant.h
armarx::Joystick::buttonsPressed
std::vector< bool > buttonsPressed
Definition: Joystick.h:49
armarx::Joystick::axis
std::vector< int16_t > axis
Definition: Joystick.h:48
armarx::Joystick::close
void close()
Definition: Joystick.h:280
armarx::GamepadUnit::onConnectComponent
void onConnectComponent() override
Definition: GamepadUnit.cpp:44
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
armarx::GamepadUnit::onInitComponent
void onInitComponent() override
Definition: GamepadUnit.cpp:34
GamepadUnit.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::ManagedIceObject::offeringTopic
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
Definition: ManagedIceObject.cpp:300
armarx::Joystick::opened
bool opened() const
Definition: Joystick.h:95
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::Joystick::pollEvent
bool pollEvent()
Definition: Joystick.h:101
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:99
armarx::GamepadUnit::openGamepadConnection
bool openGamepadConnection()
Definition: GamepadUnit.cpp:97
Logging.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
armarx::GamepadUnit::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: GamepadUnit.cpp:208
armarx::GamepadUnitPropertyDefinitions
Definition: GamepadUnit.h:44
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::SimplePeriodicTask
Usage:
Definition: ApplicationNetworkStats.h:32
armarx::Joystick::numberOfAxis
int numberOfAxis
Definition: Joystick.h:50