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 <core/threading/thread.h>
29 #include <core/threading/wait_condition.h>
30 #include <core/exceptions/system.h>
31 #include <netcomm/fawkes/client.h>
32 #include <blackboard/remote.h>
33 #include <blackboard/interface_listener.h>
34 #include <utils/system/argparser.h>
35 #include <utils/system/signal.h>
36 #include <logging/console.h>
37 #include <netcomm/fawkes/client_handler.h>
38 #include <netcomm/socket/socket.h>
39 
40 #include <cstring>
41 #include <cstdlib>
42 #include <cstdio>
43 #include <unistd.h>
44 #include <string>
45 
46 #include <interfaces/JoystickInterface.h>
47 
48 using namespace fawkes;
49 
50 bool quit = false;
51 
52 void
53 print_usage(const char *program_name)
54 {
55  printf("Usage: %s [-h] [-r host[:port]] [-d device] [-l]\n"
56  " -h This help message\n"
57  " -r host[:port] Remote host (and optionally port) to connect to\n"
58  " -d device Joystick device to use\n"
59  " -l Start in logging mode - print data read from bb\n",
60  program_name);
61 }
62 
63 /** Simple signal handler for ffjoystick.
64  * @author Tim Niemueller
65  */
67 {
68  public:
69  /** Constructor.
70  * @param aqt Joystick acquisition thread
71  */
73  : __aqt(aqt)
74  {
75  }
76 
77  virtual void handle_signal(int signal)
78  {
79  __aqt.cancel();
80  }
81 
82  private:
84 };
85 
86 /** Log joystick data gathered via RemoteBlackBoard to console.
87  * @author Tim Niemueller
88  */
91  public SignalHandler
92 {
93  public:
94  /** Constructor.
95  * @param argp argument parser
96  * @param logger logger
97  */
99  : BlackBoardInterfaceListener("JoystickBlackBoardLogger"),
100  __logger(logger)
101  {
102  char *host = (char *)"localhost";
103  unsigned short int port = 1910;
104  bool free_host = argp.parse_hostport("r", &host, &port);
105 
106  __bb = new RemoteBlackBoard(host, port);
107  if ( free_host ) free(host);
108 
109  __joystick_if = __bb->open_for_reading<JoystickInterface>("Joystick");
110  __warning_printed = false;
111 
112  __joystick_if->read();
113  logger->log_debug("Joystick", "Number of Axes: %i",
114  __joystick_if->num_axes());
115  logger->log_debug("Joystick", "Number of Buttons: %i",
116  __joystick_if->num_buttons());
117 
118  /** Just a quick hack for rumble testing
119  __joystick_if->msgq_enqueue(
120  new JoystickInterface::StartRumbleMessage(1000, 0,
121  JoystickInterface::DIRECTION_UP,
122  0xFFFF, 0x8000));
123  */
124 
125  bbil_add_data_interface(__joystick_if);
126  __bb->register_listener(this);
127  }
128 
129  /** Destructor. */
131  {
132  __bb->close(__joystick_if);
133  delete __bb;
134  }
135 
136  virtual void bb_interface_data_changed(Interface *interface) throw()
137  {
138  if ( ! __bb->is_alive() ) {
139  if ( __bb->try_aliveness_restore() ) {
140  __logger->log_info("Joystick", "Connection re-established, writing data");
141  __warning_printed = false;
142  }
143  }
144 
145  try {
146  __joystick_if->read();
147  float *axis_value = __joystick_if->axis();
148  __logger->log_info("Joystick", "Axes: 0: %f 1: %f 2: %f 3: %f 4: %f "
149  "5: %f 6: %f 7: %f 8: %f",
150  axis_value[0], axis_value[1],
151  axis_value[2], axis_value[3],
152  axis_value[4], axis_value[5],
153  axis_value[6], axis_value[7]);
154  char button_string[33];
155  button_string[32] = 0;
156  unsigned int pressed_buttons = __joystick_if->pressed_buttons();
157  for (unsigned int i = 0; i < 32; ++i) {
158  button_string[i] = (pressed_buttons & (1 << i)) ? '1' : '0';
159  }
160  __logger->log_info("Joystick", "Buttons: %s", button_string);
161  } catch (Exception &e) {
162  if ( ! __warning_printed ) {
163  e.print_trace();
164  __logger->log_warn("Joystick", "Lost connection to BlackBoard, "
165  "will try to re-establish");
166  __warning_printed = true;
167  }
168  }
169  }
170 
171  void handle_signal(int signum)
172  {
173  __waitcond.wake_all();
174  }
175 
176  /** Wait for quit signal from signal handler. */
177  void run()
178  {
179  __waitcond.wait();
180  }
181 
182  private:
183  bool __warning_printed;
184  BlackBoard *__bb;
185  Logger *__logger;
186  JoystickInterface *__joystick_if;
187  WaitCondition __waitcond;
188 };
189 
190 
191 /** Wake actuator thread on incomin messages.
192  * @author Tim Niemueller
193  */
196 {
197  public:
198  /** Constructor.
199  * @param aqt acquisition thread to pass to message processor
200  * @param blackboard blackboard to register for message event handling
201  * @param joystick_if joystick interface to listen on for messages
202  * @param logger logger
203  */
205  BlackBoard *blackboard,
206  JoystickInterface *joystick_if,
207  Logger *logger)
208  : BlackBoardInterfaceListener("JoystickBlackBoardActMsgProcThread"),
209  __bb(blackboard), __joystick_if(joystick_if)
210  {
211  __msgproc = new JoystickActThread::MessageProcessor(aqt, __joystick_if);
212  __msgproc->process();
213  bbil_add_message_interface(__joystick_if);
214  __bb->register_listener(this);
215  }
216 
217  /** Destructor. */
219  {
220  __bb->unregister_listener(this);
221  bbil_remove_message_interface(__joystick_if);
222  delete __msgproc;
223  }
224 
225  virtual bool bb_interface_message_received(Interface *interface,
226  Message *message) throw()
227  {
228  try {
229  __msgproc->process();
230  __msgproc->process_message(message);
231  } catch (Exception &e) {
232  e.print_trace();
233  }
234  return false;
235  }
236 
237  private:
239  BlackBoard *__bb;
240  JoystickInterface *__joystick_if;
241 };
242 
243 /** Config tool main.
244  * @param argc argument count
245  * @param argv arguments
246  */
247 int
248 main(int argc, char **argv)
249 {
250  try
251  {
252  ArgumentParser argp(argc, argv, "hr:d:l");
253 
254  if ( argp.has_arg("h") ) {
255  print_usage(argv[0]);
256  exit(0);
257  }
258 
259  const char *joystick_device = "/dev/input/js0";
260  if ( argp.has_arg("d") ) {
261  joystick_device = argp.arg("d");
262  }
263 
264  ConsoleLogger logger;
265 
266  if ( argp.has_arg("l") ) {
267  JoystickBlackBoardLogger jbl(argp, &logger);
268  SignalManager::register_handler(SIGINT, &jbl);
269  jbl.run();
270  } else {
271  char *host = (char *)"localhost";
272  unsigned short int port = 1910;
273  bool free_host = argp.parse_hostport("r", &host, &port);
274 
275  JoystickRemoteBlackBoardPoster jbp(host, port, &logger);
276  JoystickAcquisitionThread aqt(joystick_device, &jbp, &logger);
278  jbp.joystick_if(), &logger);
279 
280  JoystickQuitHandler jqh(aqt);
281  SignalManager::register_handler(SIGINT, &jqh);
282 
283  if (free_host) free(host);
284 
285  aqt.start();
286  aqt.join();
287  }
288  }
289  catch (UnknownArgumentException e)
290  {
291  printf("Error: Unknown Argument\n\n");
292  print_usage(argv[0]);
293  exit(0);
294  }
295  catch (SocketException e)
296  {
297  printf("\nError: could not connect:\n%s\n", e.what());
298  }
299  catch (CouldNotOpenFileException e)
300  {
301  printf("\nError: could not open joystick device:\n%s\n", e.what());
302  }
303 
304  return 0;
305 }
File could not be opened.
Definition: system.h:53
Wait until a given condition holds.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:44
const char * arg(const char *argn)
Get argument value.
Definition: argparser.cpp:182
bool parse_hostport(const char *argn, char **host, unsigned short int *port)
Parse host:port string.
Definition: argparser.cpp:231
Wake actuator thread on incomin messages.
Definition: ffjoystick.cpp:194
JoystickQuitHandler(JoystickAcquisitionThread &aqt)
Constructor.
Definition: ffjoystick.cpp:72
JoystickInterface Fawkes BlackBoard Interface.
Interface for logging to stderr.
Definition: console.h:36
Process incoming messages.
Definition: act_thread.h:47
Fawkes library namespace.
void handle_signal(int signum)
Signal hanlding method.
Definition: ffjoystick.cpp:171
Interface for signal handling.
Definition: signal.h:35
~JoystickBlackBoardActListener()
Destructor.
Definition: ffjoystick.cpp:218
Parse command line arguments.
Definition: argparser.h:66
virtual const char * what() const
Get primary string.
Definition: exception.cpp:661
virtual void handle_signal(int signal)
Signal hanlding method.
Definition: ffjoystick.cpp:77
Joystick acqusition thread for Linux joystick API.
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
virtual bool bb_interface_message_received(Interface *interface, Message *message)
BlackBoard message received notification.
Definition: ffjoystick.cpp:225
~JoystickBlackBoardLogger()
Destructor.
Definition: ffjoystick.cpp:130
Base class for exceptions in Fawkes.
Definition: exception.h:36
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:477
void run()
Wait for quit signal from signal handler.
Definition: ffjoystick.cpp:177
Simple signal handler for ffjoystick.
Definition: ffjoystick.cpp:66
Glue to post new data to a RemoteBlackBoard.
static SignalHandler * register_handler(int signum, SignalHandler *handler)
Register a SignalHandler for a signal.
Definition: signal.cpp:116
Log joystick data gathered via RemoteBlackBoard to console.
Definition: ffjoystick.cpp:89
fawkes::BlackBoard * blackboard()
Get blackboard.
JoystickBlackBoardActListener(JoystickAcquisitionThread *aqt, BlackBoard *blackboard, JoystickInterface *joystick_if, Logger *logger)
Constructor.
Definition: ffjoystick.cpp:204
void print_trace()
Prints trace to stderr.
Definition: exception.cpp:619
JoystickBlackBoardLogger(ArgumentParser &argp, Logger *logger)
Constructor.
Definition: ffjoystick.cpp:98
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
Remote BlackBoard.
Definition: remote.h:48
void join()
Join the thread.
Definition: thread.cpp:610
bool has_arg(const char *argn)
Check if argument has been supplied.
Definition: argparser.cpp:169
The BlackBoard abstract class.
Definition: blackboard.h:48
Thrown if unknown argument was supplied.
Definition: argparser.h:40
virtual void bb_interface_data_changed(Interface *interface)
BlackBoard data changed notification.
Definition: ffjoystick.cpp:136
BlackBoard interface listener.
fawkes::JoystickInterface * joystick_if()
Get joystick interface.
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:511
Socket exception.
Definition: socket.h:58
Interface for logging.
Definition: logger.h:34