Fawkes API Fawkes Development Version
ffjoystick.cpp
1
2/***************************************************************************
3 * ffjoystick.cpp - Joystick app to provide a local joystick via a
4 * RemoteBlackBoard connection.
5 *
6 * Created: Sun Nov 23 01:19:54 2008
7 * Copyright 2006-2011 Tim Niemueller [www.niemueller.de]
8 *
9 ****************************************************************************/
10
11/* This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * Read the full text in the LICENSE.GPL file in the doc directory.
22 */
23
24#include "acquisition_thread.h"
25#include "act_thread.h"
26#include "remote_bb_poster.h"
27
28#include <blackboard/interface_listener.h>
29#include <blackboard/remote.h>
30#include <core/exceptions/system.h>
31#include <core/threading/thread.h>
32#include <core/threading/wait_condition.h>
33#include <interfaces/JoystickInterface.h>
34#include <logging/console.h>
35#include <netcomm/fawkes/client.h>
36#include <netcomm/fawkes/client_handler.h>
37#include <netcomm/socket/socket.h>
38#include <utils/system/argparser.h>
39#include <utils/system/signal.h>
40
41#include <cstdio>
42#include <cstdlib>
43#include <cstring>
44#include <string>
45#include <unistd.h>
46
47using namespace fawkes;
48
49bool quit = false;
50
51void
52print_usage(const char *program_name)
53{
54 printf("Usage: %s [-h] [-r host[:port]] [-d device] [-l]\n"
55 " -h This help message\n"
56 " -r host[:port] Remote host (and optionally port) to connect to\n"
57 " -d device Joystick device to use\n"
58 " -l Start in logging mode - print data read from bb\n",
59 program_name);
60}
61
62/** Simple signal handler for ffjoystick.
63 * @author Tim Niemueller
64 */
66{
67public:
68 /** Constructor.
69 * @param aqt Joystick acquisition thread
70 */
72 {
73 }
74
75 virtual void
76 handle_signal(int signal)
77 {
78 aqt_.cancel();
79 }
80
81private:
83};
84
85/** Log joystick data gathered via RemoteBlackBoard to console.
86 * @author Tim Niemueller
87 */
89{
90public:
91 /** Constructor.
92 * @param argp argument parser
93 * @param logger logger
94 */
96 : BlackBoardInterfaceListener("JoystickBlackBoardLogger"), logger_(logger)
97 {
98 char * host = (char *)"localhost";
99 unsigned short int port = 1910;
100 bool free_host = argp.parse_hostport("r", &host, &port);
101
102 bb_ = new RemoteBlackBoard(host, port);
103 if (free_host)
104 free(host);
105
106 joystick_if_ = bb_->open_for_reading<JoystickInterface>("Joystick");
107 warning_printed_ = false;
108
109 joystick_if_->read();
110 logger->log_debug("Joystick", "Number of Axes: %i", joystick_if_->num_axes());
111 logger->log_debug("Joystick", "Number of Buttons: %i", joystick_if_->num_buttons());
112
113 /** Just a quick hack for rumble testing
114 joystick_if_->msgq_enqueue(
115 new JoystickInterface::StartRumbleMessage(1000, 0,
116 JoystickInterface::DIRECTION_UP,
117 0xFFFF, 0x8000));
118 */
119
120 bbil_add_data_interface(joystick_if_);
121 bb_->register_listener(this);
122 }
123
124 /** Destructor. */
126 {
127 bb_->close(joystick_if_);
128 delete bb_;
129 }
130
131 virtual void
133 {
134 if (!bb_->is_alive()) {
135 if (bb_->try_aliveness_restore()) {
136 logger_->log_info("Joystick", "Connection re-established, writing data");
137 warning_printed_ = false;
138 }
139 }
140
141 try {
142 joystick_if_->read();
143 float *axis_value = joystick_if_->axis();
144 logger_->log_info("Joystick",
145 "Axes: 0: %f 1: %f 2: %f 3: %f 4: %f "
146 "5: %f 6: %f 7: %f",
147 axis_value[0],
148 axis_value[1],
149 axis_value[2],
150 axis_value[3],
151 axis_value[4],
152 axis_value[5],
153 axis_value[6],
154 axis_value[7]);
155 char button_string[33];
156 button_string[32] = 0;
157 unsigned int pressed_buttons = joystick_if_->pressed_buttons();
158 for (unsigned int i = 0; i < 32; ++i) {
159 button_string[i] = (pressed_buttons & (1 << i)) ? '1' : '0';
160 }
161 logger_->log_info("Joystick", "Buttons: %s", button_string);
162 } catch (Exception &e) {
163 if (!warning_printed_) {
164 e.print_trace();
165 logger_->log_warn("Joystick",
166 "Lost connection to BlackBoard, "
167 "will try to re-establish");
168 warning_printed_ = true;
169 }
170 }
171 }
172
173 void
174 handle_signal(int signum)
175 {
176 waitcond_.wake_all();
177 }
178
179 /** Wait for quit signal from signal handler. */
180 void
182 {
183 waitcond_.wait();
184 }
185
186private:
187 bool warning_printed_;
188 BlackBoard * bb_;
189 Logger * logger_;
190 JoystickInterface *joystick_if_;
191 WaitCondition waitcond_;
192};
193
194/** Wake actuator thread on incomin messages.
195 * @author Tim Niemueller
196 */
198{
199public:
200 /** Constructor.
201 * @param aqt acquisition thread to pass to message processor
202 * @param blackboard blackboard to register for message event handling
203 * @param joystick_if joystick interface to listen on for messages
204 * @param logger logger
205 */
207 BlackBoard * blackboard,
208 JoystickInterface * joystick_if,
209 Logger * logger)
210 : BlackBoardInterfaceListener("JoystickBlackBoardActMsgProcThread"),
211 bb_(blackboard),
212 joystick_if_(joystick_if)
213 {
214 msgproc_ = new JoystickActThread::MessageProcessor(aqt, joystick_if_);
215 msgproc_->process();
216 bbil_add_message_interface(joystick_if_);
217 bb_->register_listener(this);
218 }
219
220 /** Destructor. */
222 {
223 bb_->unregister_listener(this);
224 bbil_remove_message_interface(joystick_if_);
225 delete msgproc_;
226 }
227
228 virtual bool
229 bb_interface_message_received(Interface *interface, Message *message) noexcept
230 {
231 try {
232 msgproc_->process();
233 msgproc_->process_message(message);
234 } catch (Exception &e) {
235 e.print_trace();
236 }
237 return false;
238 }
239
240private:
242 BlackBoard * bb_;
243 JoystickInterface * joystick_if_;
244};
245
246/** Config tool main.
247 * @param argc argument count
248 * @param argv arguments
249 */
250int
251main(int argc, char **argv)
252{
253 try {
254 ArgumentParser argp(argc, argv, "hr:d:l");
255
256 if (argp.has_arg("h")) {
257 print_usage(argv[0]);
258 exit(0);
259 }
260
261 const char *joystick_device = "/dev/input/js0";
262 if (argp.has_arg("d")) {
263 joystick_device = argp.arg("d");
264 }
265
266 ConsoleLogger logger;
267
268 if (argp.has_arg("l")) {
269 JoystickBlackBoardLogger jbl(argp, &logger);
270 SignalManager::register_handler(SIGINT, &jbl);
271 jbl.run();
272 } else {
273 char * host = (char *)"localhost";
274 unsigned short int port = 1910;
275 bool free_host = argp.parse_hostport("r", &host, &port);
276
277 JoystickRemoteBlackBoardPoster jbp(host, port, &logger);
278 JoystickAcquisitionThread aqt(joystick_device, &jbp, &logger);
279 JoystickBlackBoardActListener aml(&aqt, jbp.blackboard(), jbp.joystick_if(), &logger);
280
281 JoystickQuitHandler jqh(aqt);
282 SignalManager::register_handler(SIGINT, &jqh);
283
284 if (free_host)
285 free(host);
286
287 aqt.start();
288 aqt.join();
289 }
290 } catch (UnknownArgumentException &e) {
291 printf("Error: Unknown Argument\n\n");
292 print_usage(argv[0]);
293 exit(0);
294 } catch (SocketException &e) {
295 printf("\nError: could not connect:\n%s\n", e.what());
296 } catch (CouldNotOpenFileException &e) {
297 printf("\nError: could not open joystick device:\n%s\n", e.what());
298 }
299
300 return 0;
301}
Joystick acqusition thread for Linux joystick API.
Process incoming messages.
Definition: act_thread.h:47
void process_message(fawkes::Message *msg)
Process a single message.
Definition: act_thread.cpp:93
void process()
Process message currently in the queue.
Definition: act_thread.cpp:129
Wake actuator thread on incomin messages.
Definition: ffjoystick.cpp:198
virtual bool bb_interface_message_received(Interface *interface, Message *message) noexcept
BlackBoard message received notification.
Definition: ffjoystick.cpp:229
JoystickBlackBoardActListener(JoystickAcquisitionThread *aqt, BlackBoard *blackboard, JoystickInterface *joystick_if, Logger *logger)
Constructor.
Definition: ffjoystick.cpp:206
~JoystickBlackBoardActListener()
Destructor.
Definition: ffjoystick.cpp:221
Log joystick data gathered via RemoteBlackBoard to console.
Definition: ffjoystick.cpp:89
JoystickBlackBoardLogger(ArgumentParser &argp, Logger *logger)
Constructor.
Definition: ffjoystick.cpp:95
~JoystickBlackBoardLogger()
Destructor.
Definition: ffjoystick.cpp:125
void run()
Wait for quit signal from signal handler.
Definition: ffjoystick.cpp:181
virtual void bb_interface_data_refreshed(Interface *interface) noexcept
BlackBoard data refreshed notification.
Definition: ffjoystick.cpp:132
void handle_signal(int signum)
Signal hanlding method.
Definition: ffjoystick.cpp:174
Simple signal handler for ffjoystick.
Definition: ffjoystick.cpp:66
virtual void handle_signal(int signal)
Signal hanlding method.
Definition: ffjoystick.cpp:76
JoystickQuitHandler(JoystickAcquisitionThread &aqt)
Constructor.
Definition: ffjoystick.cpp:71
Glue to post new data to a RemoteBlackBoard.
Parse command line arguments.
Definition: argparser.h:64
bool parse_hostport(const char *argn, char **host, unsigned short int *port)
Parse host:port string.
Definition: argparser.cpp:224
BlackBoard interface listener.
void bbil_add_message_interface(Interface *interface)
Add an interface to the message received watch list.
void bbil_remove_message_interface(Interface *interface)
Remove an interface to the message received watch list.
void bbil_add_data_interface(Interface *interface)
Add an interface to the data modification watch list.
The BlackBoard abstract class.
Definition: blackboard.h:46
virtual bool is_alive() const noexcept=0
Check if the BlackBoard is still alive.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual bool try_aliveness_restore() noexcept=0
Try to restore the aliveness of the BlackBoard instance.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Definition: blackboard.cpp:212
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
Definition: blackboard.cpp:185
virtual void close(Interface *interface)=0
Close interface.
Interface for logging to stderr.
Definition: console.h:37
File could not be opened.
Definition: system.h:53
Base class for exceptions in Fawkes.
Definition: exception.h:36
void print_trace() noexcept
Prints trace to stderr.
Definition: exception.cpp:601
virtual const char * what() const noexcept
Get primary string.
Definition: exception.cpp:639
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:80
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:479
JoystickInterface Fawkes BlackBoard Interface.
uint32_t pressed_buttons() const
Get pressed_buttons value.
uint8_t num_buttons() const
Get num_buttons value.
uint8_t num_axes() const
Get num_axes value.
float * axis() const
Get axis value.
Interface for logging.
Definition: logger.h:42
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_info(const char *component, const char *format,...)=0
Log informational message.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: multi.cpp:174
Remote BlackBoard.
Definition: remote.h:50
Interface for signal handling.
Definition: signal.h:36
Socket exception.
Definition: socket.h:57
void cancel()
Cancel a thread.
Definition: thread.cpp:646
Thrown if unknown argument was supplied.
Definition: argparser.h:39
Wait until a given condition holds.
void wait()
Wait for the condition forever.
void wake_all()
Wake up all waiting threads.
Fawkes library namespace.