Firmware
uavcan_main.hpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2014 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
43 #pragma once
44 
45 #include <px4_config.h>
46 
47 #include "uavcan_driver.hpp"
48 #include <uavcan/helpers/heap_based_pool_allocator.hpp>
49 #include <uavcan/protocol/global_time_sync_master.hpp>
50 #include <uavcan/protocol/global_time_sync_slave.hpp>
51 #include <uavcan/protocol/node_status_monitor.hpp>
52 #include <uavcan/protocol/param/GetSet.hpp>
53 #include <uavcan/protocol/param/ExecuteOpcode.hpp>
54 #include <uavcan/protocol/RestartNode.hpp>
55 
56 #include <drivers/device/device.h>
57 #include <perf/perf_counter.h>
58 
59 #include <uORB/topics/actuator_controls.h>
60 #include <uORB/topics/actuator_outputs.h>
61 #include <uORB/topics/actuator_armed.h>
62 #include <uORB/topics/test_motor.h>
63 #include <uORB/topics/actuator_direct.h>
64 
65 #include "actuators/esc.hpp"
66 #include "actuators/hardpoint.hpp"
67 #include "sensors/sensor_bridge.hpp"
68 
69 #include "uavcan_servers.hpp"
70 #include "allocator.hpp"
71 
72 #define NUM_ACTUATOR_CONTROL_GROUPS_UAVCAN 4
73 
74 // we add two to allow for actuator_direct and busevent
75 #define UAVCAN_NUM_POLL_FDS (NUM_ACTUATOR_CONTROL_GROUPS_UAVCAN+2)
76 
80 class UavcanNode : public cdev::CDev
81 {
82  static constexpr unsigned MaxBitRatePerSec = 1000000;
83  static constexpr unsigned bitPerFrame = 148;
84  static constexpr unsigned FramePerSecond = MaxBitRatePerSec / bitPerFrame;
85  static constexpr unsigned FramePerMSecond = ((FramePerSecond / 1000) + 1);
86 
87  static constexpr unsigned PollTimeoutMs = 3;
88 
89 
90  /*
91  * This memory is reserved for uavcan to use for queuing CAN frames.
92  * At 1Mbit there is approximately one CAN frame every 145 uS.
93  * The number of buffers sets how long you can go without calling
94  * node_spin_xxxx. Since our task is the only one running and the
95  * driver will light the fd when there is a CAN frame we can nun with
96  * a minimum number of buffers to conserver memory. Each buffer is
97  * 32 bytes. So 5 buffers costs 160 bytes and gives us a poll rate
98  * of ~1 mS
99  * 1000000/200
100  */
101 
102  static constexpr unsigned RxQueueLenPerIface = FramePerMSecond * PollTimeoutMs; // At
103  static constexpr unsigned StackSize = 2400;
104 
105 public:
106  typedef UAVCAN_DRIVER::CanInitHelper<RxQueueLenPerIface> CanInitHelper;
107  enum eServerAction {None, Start, Stop, CheckFW, Busy};
108 
109  UavcanNode(uavcan::ICanDriver &can_driver, uavcan::ISystemClock &system_clock);
110 
111  virtual ~UavcanNode();
112 
113  virtual int ioctl(file *filp, int cmd, unsigned long arg);
114 
115  static int start(uavcan::NodeID node_id, uint32_t bitrate);
116 
117  uavcan::Node<> &get_node() { return _node; }
118 
119  // TODO: move the actuator mixing stuff into the ESC controller class
120  static int control_callback(uintptr_t handle, uint8_t control_group, uint8_t control_index, float &input);
121 
122  void subscribe();
123 
124  int teardown();
125 
126  int arm_actuators(bool arm);
127 
128  void print_info();
129 
130  void shrink();
131 
132  void hardpoint_controller_set(uint8_t hardpoint_id, uint16_t command);
133 
134  static UavcanNode *instance() { return _instance; }
135  static int getHardwareVersion(uavcan::protocol::HardwareVersion &hwver);
136  int fw_server(eServerAction action);
137  void attachITxQueueInjector(ITxQueueInjector *injector) {_tx_injector = injector;}
138  int list_params(int remote_node_id);
139  int save_params(int remote_node_id);
140  int set_param(int remote_node_id, const char *name, char *value);
141  int get_param(int remote_node_id, const char *name);
142  int reset_node(int remote_node_id);
143 
144 private:
145  void fill_node_info();
146  int init(uavcan::NodeID node_id);
147  void node_spin_once();
148  int run();
149  int add_poll_fd(int fd);
150  int start_fw_server();
151  int stop_fw_server();
152  int request_fw_check();
153  int print_params(uavcan::protocol::param::GetSet::Response &resp);
154  int get_set_param(int nodeid, const char *name, uavcan::protocol::param::GetSet::Request &req);
155  void update_params();
156  void set_setget_response(uavcan::protocol::param::GetSet::Response *resp)
157  {
158  _setget_response = resp;
159  }
160  void free_setget_response(void)
161  {
162  _setget_response = nullptr;
163  }
164 
165  int _task = -1;
166  bool _task_should_exit = false;
167  volatile eServerAction _fw_server_action;
168  int _fw_server_status;
169  int _armed_sub = -1;
170  actuator_armed_s _armed = {};
171  bool _is_armed = false;
172 
173  int _test_motor_sub = -1;
174  test_motor_s _test_motor = {};
175  bool _test_in_progress = false;
176 
177  unsigned _output_count = 0;
178 
179  static UavcanNode *_instance;
180 
181  uavcan_node::Allocator _pool_allocator;
182 
183  uavcan::Node<> _node;
184  pthread_mutex_t _node_mutex;
185  px4_sem_t _server_command_sem;
186  UavcanEscController _esc_controller;
187  UavcanHardpointController _hardpoint_controller;
188  uavcan::GlobalTimeSyncMaster _time_sync_master;
189  uavcan::GlobalTimeSyncSlave _time_sync_slave;
190  uavcan::NodeStatusMonitor _node_status_monitor;
191 
192  List<IUavcanSensorBridge *> _sensor_bridges;
193 
194  MixerGroup *_mixers = nullptr;
195  ITxQueueInjector *_tx_injector;
196  uint32_t _groups_required = 0;
197  uint32_t _groups_subscribed = 0;
198  int _control_subs[NUM_ACTUATOR_CONTROL_GROUPS_UAVCAN];
199  actuator_controls_s _controls[NUM_ACTUATOR_CONTROL_GROUPS_UAVCAN] = {};
200  orb_id_t _control_topics[NUM_ACTUATOR_CONTROL_GROUPS_UAVCAN] = {};
201  pollfd _poll_fds[UAVCAN_NUM_POLL_FDS] = {};
202  unsigned _poll_fds_num = 0;
203  int32_t _idle_throttle_when_armed = 0;
204 
205  int _actuator_direct_sub = -1;
206  uint8_t _actuator_direct_poll_fd_num = 0;
207  actuator_direct_s _actuator_direct = {};
208 
209  actuator_outputs_s _outputs = {};
210 
211  perf_counter_t _perf_control_latency;
212 
213  Mixer::Airmode _airmode = Mixer::Airmode::disabled;
214 
215  // index into _poll_fds for each _control_subs handle
216  uint8_t _poll_ids[NUM_ACTUATOR_CONTROL_GROUPS_UAVCAN];
217 
218  void handle_time_sync(const uavcan::TimerEvent &);
219 
220  typedef uavcan::MethodBinder<UavcanNode *, void (UavcanNode::*)(const uavcan::TimerEvent &)> TimerCallback;
221  uavcan::TimerEventForwarder<TimerCallback> _master_timer;
222 
223  bool _callback_success;
224  uavcan::protocol::param::GetSet::Response *_setget_response;
225  typedef uavcan::MethodBinder<UavcanNode *,
226  void (UavcanNode::*)(const uavcan::ServiceCallResult<uavcan::protocol::param::GetSet> &)> GetSetCallback;
227  typedef uavcan::MethodBinder<UavcanNode *,
228  void (UavcanNode::*)(const uavcan::ServiceCallResult<uavcan::protocol::param::ExecuteOpcode> &)> ExecuteOpcodeCallback;
229  typedef uavcan::MethodBinder<UavcanNode *,
230  void (UavcanNode::*)(const uavcan::ServiceCallResult<uavcan::protocol::RestartNode> &)> RestartNodeCallback;
231  void cb_setget(const uavcan::ServiceCallResult<uavcan::protocol::param::GetSet> &result);
232  void cb_opcode(const uavcan::ServiceCallResult<uavcan::protocol::param::ExecuteOpcode> &result);
233  void cb_restart(const uavcan::ServiceCallResult<uavcan::protocol::RestartNode> &result);
234 
235 };
Definition: esc.hpp:55
Configuration flags used in code.
UAVCAN <–> ORB bridge for ESC messages: uavcan.equipment.esc.RawCommand uavcan.equipment.esc.RPMCommand uavcan.equipment.esc.Status.
A UAVCAN node.
Definition: uavcan_main.hpp:80
Group of mixers, built up from single mixers and processed in order when mixing.
Definition: mixer.h:329
Header common to all counters.
Definition: perf_counter.cpp:65
Definition: List.hpp:59
The UavcanHardpointController class.
Definition: hardpoint.hpp:51
This interface defines one method that will be called by the main node thread periodically in order t...
Definition: uavcan_virtual_can_driver.hpp:323
Object metadata.
Definition: uORB.h:50
Abstract class for any character device.
Definition: CDev.hpp:58
Defines basic functionality of UAVCAN node.
Definition: allocator.hpp:53
Performance measuring tools.