Skip to content

added ChannelConfig message for configuration of multi-actuator setups#80

Open
alexcekay wants to merge 1 commit into
dronecan:masterfrom
alexcekay:pr-actuator-channel-config
Open

added ChannelConfig message for configuration of multi-actuator setups#80
alexcekay wants to merge 1 commit into
dronecan:masterfrom
alexcekay:pr-actuator-channel-config

Conversation

@alexcekay
Copy link
Copy Markdown

@alexcekay alexcekay commented May 1, 2026

Context

This started off as a specific feature needed by our company but I think others could also benefit from it.

The current ArrayCommand setup works great for simple setups or in case one can assign individual actuator IDs to each servo. It already gets hard to use when one has a general CAN to PWM board with multiple output channels. As long as just one is used it is ok, but with multiple boards, one needs to use workarounds like introducing some offset parameter or similar.

In bigger setups that are produced at scale all of this does not scale well as changing the setup requires connecting to individual servos or individual CAN to PWM boards. To deploy such setups it is easier to set up all nodes once and only change the configuration on the flight controller.

Solution

A new message ChannelConfig is introduced which originates from the flight controller and is received by servos / CAN to PWM boards. In it, the flight controller can specify which actuator (using its ID) should handle a Command on which of its channels. All of it is 0-based. For example when ArrayCommand contains two commands, it could specify that actuator 0 should handle Command 0 on its channel 0 and actuator 1 should handle Command 1 on its channel 3.

This scales well to more complex setups where one has CAN to PWM boards in each wing and tail of a larger fixed-wing. After assigning actuator IDs to each of the nodes, one can dynamically change which node handles what on which channel.

Compatibility

This message is optional. If the flight controller does not send it or an actuator does not react to it, the current behavior stays unchanged. The idea is that the nodes have a parameter that controls whether they react to this message and only process it when enabled. When enabled, they have to wait for one ChannelConfig before processing ArrayCommand. The frequency of ChannelConfig can be very low as it should not change frequently (or at all) after startup.

@dakejahl
Copy link
Copy Markdown
Contributor

dakejahl commented May 9, 2026

This is great, definitely needed. Can you provided a concrete example? We'd want to make sure this lands in AM32 at the same time.

@alexcekay
Copy link
Copy Markdown
Author

@dakejahl for sure.

Setup

A concrete example for a large fixed-wing with a couple of meters wing-span.
In this case there is one PX4 CAN Node in each wing and at the back. All are connected via CAN to the flight controller. The PX4 CAN Nodes are connected to their respective servos (ailerons, elevator, rudder).

Node configuration

The user needs to assign an actuator ID to each PX4 CAN Node. This can be done via a parameter or for example HW switches. As an example:

  • Left aileron node: 0
  • Right aileron node: 1
  • Rear node: 2

In addition the user has to set a parameter that states that this CAN Node should listen to ChannelConfig messages and not execute ArrayCommand before the first ChannelConfig is received.

Flight-controller configuration

On the flight-controller each output function can be assigned a actuator_id and actuator_channel that handles it. I prepared the PX4 relevant change, can upstream soon. It is basically a set of parameters. As an example:

Actuator actuator_id actuator_channel
Left aileron 0 0
Right aileron 1 0
Elevator 2 0
Rudder 2 1

Logic

The flight-controller uses its parameters to build the correct ChannelConfig message. Let's assume that the index in ArrayCommand are:

  • Index 0: Left aileron
  • Index 1: Right aileron
  • Index 2: Elevator
  • Index 3: Rudder

In this case the message is:

actuator_id: [0, 1, 2, 2, 255, 255, ...]
actuator_channel: [0, 0, 0, 1, 255, 255, ...]

The PX4 Nodes can use this information to see which ArrayCommand they should react to and on which of its local output channels they should map this to.

Mapping two different functions to exactly the same actuator_id and actuator_channel is undefined behavior and represents a configuration error.

@alexcekay alexcekay force-pushed the pr-actuator-channel-config branch from 1d2fb24 to a44e063 Compare May 18, 2026 12:11
@alexcekay alexcekay force-pushed the pr-actuator-channel-config branch from a44e063 to 8411852 Compare May 18, 2026 12:13
@alexcekay alexcekay marked this pull request as ready for review May 18, 2026 12:13
@IamPete1
Copy link
Copy Markdown
Contributor

Dosn't this just move the conplexity from the nodes on to the main flight controller? Is that exactly the oposite of what we should be trying to do? Why not just change the param on the node?

Its is posible that the PX4 actuator config makes this more apealing. I dont think it would add anything for AP.

@alexcekay
Copy link
Copy Markdown
Author

alexcekay commented May 18, 2026

@IamPete1,

basically yes, this is mostly a configuration topic. In complex systems with a lot of nodes that are produced in mass it's easier to have the configuration centralized.

With this and HW DIP switches on the nodes to set the actuator ID one can have an assembly line that does not require to ever connect to one of the nodes and change its configuration. If later the config should be changed it's only required to map differently on the flight controller.

Connecting to the nodes individually to change params does not allow producing systems in a quick and easy to repeat manner for non-technical users. The way presented here is repeatable and easy to use, thus avoids an error-prone manual process. Setting params from the flight-controller is also hard as it requires knowing the NodeID and probing for the correct actuator ID to set the correct indexes a node should listen to.

For smaller/hobby users or other projects it's of course possible to simply not use/implement this message.

@IamPete1
Copy link
Copy Markdown
Contributor

In production settings why not just bake the config into the firmware so you flash once and are done? Again, its possible that this is easy in AP but not in PX4.

@alexcekay
Copy link
Copy Markdown
Author

alexcekay commented May 18, 2026

@IamPete1:

Really good point.

The main reason is that the individual nodes would require individual firmware in this case.

Let's take left aileron, right aileron as an example. If both are handled by two different CAN nodes (one in each wing) one would need to create two firmware variants. One firmware variant would react to index 0, the other to index 1 using the baked in settings. Apart from that the firmware would be exactly the same as it's the same hardware product.

This complicates the manufacturing process of the nodes itself as one would need different SKUs for the node variants. The node manufacturer would basically need to flash half of the nodes with variant 1 and half with variant 2. As soon as a rear node is needed the next variant is needed.

The people at the assembly line would in this case have identical looking nodes but have to take care to not mix them. Alternatives like having physical different looking nodes increase manufacturing complexity of the nodes.

The solution presented here allows one to keep using the same firmware on all nodes and configure everything centrally. In addition after the nodes have been produced they can simply be installed into the vehicle without needing to connect to them manually again. Firmware update from the flight-controller is simple as they all have the same one. The solution also does not cause problems for the ones that don't want to use it. Thus, I think it is a good solution as others especially OEMs will also face the same problem as soon as they want to manufacture complex CAN based systems.

It is also very easy to use in the QGC actuator config:
image

  • Servo 1 and Servo 2 are both mapped to actuator 1 on it's channel 1 and 2
  • Servo 3 and Servo 4 are both mapped to actuator 2 on it's channel 1 and 2
  • One can directly change the mapping in this view instantly.

@alexcekay
Copy link
Copy Markdown
Author

Hi @tridge, @peterbarker would also love to hear your opinion regarding this topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants