Sailboat Support

@skyscraper I’ve merged the catamaran model to SITL_Models. The docs suggest how to adjust the wave settings to reduce the computational load (a FFT of a 4x4 grid should add a negligible load and the grid refinement is immaterial if simulating a flat sea). There are also some notes on setting the wind using the Gazebo services and other plugins available in the asv_sim package.

To reduce the render load you could try running Gazebo with the flag --render-engine-gui ogre. This will use the less demanding rendering of ogre vs the more complex ogre2. Unfortunately I haven’t been able to test on macOS as the ogre render engine does not support the macOS Metal render system.

Hi again @rhys.

I had a good long play with it today. It works well with the calm sea settings. It still goes slowly, but the system is workable. I couldnt get the --render-engine-gui ogre option working, but maybe I need to look again at it. I have also played around with some of the Ardupilot parameters and tried moving the fin positions back. There is a lot to be played with and it is really useful.

There is a practical problem with the boat getting into irons, and then it will stick there. The only way out seems to be to change the wind direction.

Multihulls do have a problem with tacking becuase they are light so dont have much inertia, but a real model has a lot of drag from the wind when the sail is slack so it starts to go backwards and you can reverse out of the situation. The sail in the sim is modelled presumably as an aerofoil which has very low drag at low lift, unlike a sail.

Ideally a soft sail could be modelled differently to an aerofoil. In the situation where the sail isnt filling, then there should be some drag which maybe progressively increases as the sail gets near zero angle of attack and is flogging. I don’t know if one can put different visuals in gazeboo, dependent on which tack the boat is on and whether sail is luffing or flogging?

I would also like to get the wind vane pointing in the right direction and add a cup anemometer. These are things I will attempt to learn more about gazebo. Would be nice to have some racing buoys or something as reference points in the sim.

Anyway the Gazebo Catamaran sim is a great piece of work. Thanks very much for doing it! I hope to spend a lot more time getting to know gazebo and getting productive with it.

This is a general sail boat in AP problem. It does the thing everyone does there first time and puts the rudder hard over and then can’t decide which side it should be on if it blows backwards a little it will swap rudder sides for reversing. There is a branch floating about some where that turns this off and assumes it is always traveling forwards so will never invert the rudder. Its a little better, but not great.

This stuff is very hard to program and parametrise in such a way that is is applicable to a wide range of vehicles designs and sizes.

Stuff that seems very sensible like, a minimum speed requirement before trying to tack can lead to odd edge cases. What if I need to tack due to a geofence should I try and speed up and breach further in the hope that I can then tack or would it be better to tack right now and hope it goes OK.

From a get to the destination point of view a option to always gybe the long way round would solve the problem most of the time, but its not very exciting from efficiency / speed / time point of view.

The automatic motoring function will detect being stuck in a tack and put the motor on for a bit to get going again, which is a nice get out a jail free option.

There are a couple of options to increase the drag of the boat in irons.

  • The first is to enable the wind element and wind system. There is a simple model in Gazebo that allows objects to respond to a global wind environment.
  • The other option is to increase the drag coefficients in the sail lift - drag model. That would affect the boat while sailing as well, rather than just when the boat is near stationary.

The asv_sim package has a tether model which I’ve used for buoys before. I can add a small course to the example world to give you something to aim at. I can fit them with navsat sensors which helps with the mission planning.

@iampete What is great about this sim versus the simple sitl::sailboat, is that you can start to simulate this type of thing. Sitl::Sailboat takes a very simplistic approach to turning in particular, but you need to model inertia, as gazebo does.

start point of video link (2:18) leads up to a failed tack and subsequently getting out of irons manually

Possible algorithm ( Yes I hope to try it out…)

Assume you are on starboard tack and are tacking. (starboard tack: wind from right, sail on left side
tacking && tacking_timed_out && (boat frame velocity.x <= 0) && ( abs(apparent_wind_angle) < (SAIL_ANGLE_MIN + margin) )
1 Set state in_irons_tacking_onto_port_tack. Sheet right out and keep rudder over as if wanting to turn hard left. There needs to be a state for each tack. We want to get a successful tack to required new tack else will get here again once the mission logic takes over again .
2 Wait until the apparent wind angle is at -1 * (SAIL_ANGLE_MAX - margin). Errors here would be if there is no change in position or attitude over time, then if there is wind ( either anemeometer or change in direction of apparent wind say) assume boat is stuck for some reason.
3 Center the rudder and simultaneously sheet in so that sail is at ideal angle of attack. Once useful forward motion is detected, clear in_irons_tacking_onto_port_tack , and you are off on the new tack…

etc for other tack …
Assume you are on port tack and are tacking. (port tack: wind from left, sail on right side)
start tacking
tacking && tacking_timed_out && (boat frame velocity.x <= 0) && ( abs(apparent_wind_angle) < (SAIL_ANGLE_MIN + margin) )
1 Set state in_irons_tacking_onto_stbd_tack. Sheet right out and put rudder over as if wanting to turn hard to starboard
2 Wait until the apparent wind angle is at +1 * (SAIL_ANGLE_MAX - margin)
3 Center the rudder and simultaneously sheet in so that sail is at ideal angle of attack. Once useful forward motion is detected, clear in_irons_tacking_onto_stbd_tack , and you are off on the new tack…

1 Like

@rhys @iampete . I have added a skin friction parameter to the liftDragModel plugin, which solves the reversing issue, as shown in the video (0:42 secs) and again at (3:02)

Note that I am sailing the boat manually here, TODO , get the algorithm coded and tested.

Hi @skyscraper - looks good. Another way to introduce bluff body type drag on any model or link is to add the <enable_wind> to the model or link element and add the wind effect system in the world using:

    <plugin filename="gz-sim-wind-effects-system"
      name="gz::sim::systems::WindEffects">
      <force_approximation_scaling_factor>0.1</force_approximation_scaling_factor>
    </plugin>

This is a fairly blunt instrument though.

For some reason the changing the wind via the wind service plugin is not affecting the wind used in the wind-effect plugin. I’ll look into that. It can be set initially using the world element:

    <wind>
      <linear_velocity>5 5 0</linear_velocity>
    </wind>

but not updated at run-time.

@iampete - I’m sure this has come up before, but I’m wondering whether the main sheeting behaviour can be changed so that throttle low (rc 3 1000) corresponds to fully sheeted out and full throttle (rc 3 2000) is fully sheeted in? The reason is that on initialisation the vehicle starts with the sail fully sheeted in, where I think it may be better to initialise sheeted out. Perhaps the sheeting with throttle direction could be flipped using a param if it’s not practical or desirable to change the current behaviour for everyone?

I’m not keen to change the throttle direction unilaterally. We might be able to fix it in another way.

  • Set INITIAL_MODE to one that does not take pilot input. Hold for example. However, as soon as your RC comes online it will change mode to the one set by your mode switch.

  • The safety button functionality to disable the sail servo output. However, the only way to get out of the safe state is to press a physical button or via GCS.

  • Switch the stick to the dedicated RCx_OPTION “MainSail” for sail control, you can then reverse the stick how ever you like and use another channel for throttle. You could probably even use a transmitter switch, on a pure sailing vehicle throttle is really just stop/go. You could even map the one throttle stick to two RC channels and use one as throttle and the other for sail.

  • As you suggest we could add a “SAIL_OPTIONS” to give the option to invert sail control.

I should probably add that in the video state were changed a lot of parameters in the SITL_Models catamaran and the ASVWaves wave xml as follows.

catamaran model

  • move fins back by 90 mm
  • sail position controller plugin
    • p_gain from 0.3 to 0.75
    • i_gain from 0.1 to 0.0
  • sail lift drag plugin
    • change alpha_stall from 0.1592 to 0.4

ASVWaves waves model

  • cell_count changed to 4
  • windspeed changed to 0

TODO: I will try to document why I changed things and get back…

Still playing with the ardupilot gazebo cat sim.

Before the critique I should say that I love the Gazebo catamaran sim, but feel it needs work to get it working nicely for me anyway

For my old low end system I found that I could get a sim rate of around 95 % of real time eventually. (In the video below I think that the screen recorder takes off another 15% of realtime)

I had to make several changes.
First set the asv_wave_sim/gz-waves-models/world_models/waves/model.sdf file was modified to

    <cell_count>4</cell_count>
    <wind_speed>0.0</wind_speed>

Second the SITL_Models/Gazebo/worlds/catamaran_waves.sdf file was modified to

<max_step_size>0.005</max_step_size>
<real_time_factor>1</real_time_factor>

This reduces the update rate from 1 ms to 5 ms. I would have liked to try even lower rate
but something went boink in the gazebo startup output, so I left it there.

Next I modified the SITL_Models/Gazebo/config/catamaran.params file to set the default SCHED_LOOP_RATE of 50. The Ardupilot loop rate needs to be less than the sim loop rate AFAIK. Lower loop rate means potentially less power used anyway ( maybe can run it on a stm32L4 etc eventually)

I connected my Taranis RC Transmitter as a joystick and used the mavproxy joystick module.

I found that the sail controller is unusable in MANUAL mode with the default settings in the Gazebo/models/catamaran/model.sdf. The integral term means that Integral windup - Wikipedia is a real problem and makes it unusable. It takes around 30 secs to unwind at startup. I set the values to P:1 I:0 D:0 and that makes it work ok for me. Is there any need for a PID in the Gazebo sim? My feeling is that Ardupilot should control the sail position, not the sim.

For the sim itself. The boat currently travels too fast. I think ideally it would be good to model hull skin friction and wave drag, but in some ways the high speed works well since it highlights problems in control, since Gazebo models the effect of rudder throws well, so that if the model is travelling fast slight movements of the rudder have a large effect. This then throws up issues about how the Ardupilot::Sailboat handles turns for example. The direction controller probably need to take account of boatspeed? for a particular rudder angle, the torque is approx proportional to speed^2 after all.

There is a similar situation with the Heel controller. The apparent wind speed has a dramatic effect so the heel controller probably needs to have apparent wind speed as a parameter?

What is clear so far is that a catamaran is a lot more complicated than a keelboat! Anyway I plan to continue to play around with it and see if I can affect some of the issues. With the sim performance acceptable on my system, I now plan to see what I can do to the ardupilot Sailboat code
to make it work better with the sim catamaran

Here is a video of the current status, bearing in mind it is sensitive to windspeed. https://www.youtube.com/watch?v=lkCzBQWEEaU

1 Like

Thanks for the analysis @skyscraper.

<cell_count>4</cell_count> effectively disables the wave model which makes a big difference as wave generation involves a FFT each update step for both physics and visuals.

Is there any need for a PID in the Gazebo sim?

Yes - think of the joint controllers (which have the PIDs) as digital servos, which require a MCU onboard to ensure the servo holds at the commanded setpoint. ArduPilots various control loop controllers issue the setpoints to the servos (and these have their own PIDs that also require tuning). An autotune for the Gazebo joint position and velocity controllers would be very handy and it’s tedious to adjust them at present.

I think ideally it would be good to model hull skin friction and wave drag

There are some drag coefficients you can adjust in the hydrodynamics plugin. Try increasing these to see if you can better match expected speeds.

HydrodynamicsPlugin · srmainwaring/asv_wave_sim Wiki · GitHub (the services may not be working for Gazebo Garden - I’ll have to review if they were ported from Gazebo 11)

The apparent wind speed has a dramatic effect so the heel controller probably needs to have apparent wind speed as a parameter?

The apparent wind determines the applied sail lift, so it’s incorporated via the Gazebo physics engine and manifests as a heeling force. The apparent wind is also passed to the flight controller from the anemometer sensor and the true wind is calculated for navigation and tack angle purposes. For faster vehicles this angle has to be larger (but is not dynamic with increase wind speed - we’d need polars and dynamic PIDs for that).

@rhys, I finally got hang of the physics coefficients in ASVwave.

In the video I probably adjusted them too high, but this allows to see the effect.
lee bow is getting low as the boat is powered up at 0:25
Bearing away when powered up eventually results in a pitchpole as shown at 2:17.

Eventually there probably needs to be a pitch algorithm to complement the heel algorithm.

1 Like

Hi! What sorts of mechanisms are you all using to secure the control the rudder via a servo? Push rods? Any parts (rods, servo attachments) that help! Thank you! I’m using a Kayak rudder, and have some standard form factor servos of various sizes, but am not sure how to hook them up in a reliable way.

Maybe it will be useful to someone. I made a device to measure the speed of the boat, the data is output to the COM port.
Speed through water (STW) sensor. Boat speed measurement - ArduRover / ArduBoat - ArduPilot Discourse

I got the “Get out of Irons in Auto” algorithm working.

Code is grungy. I found it incredibly hard to actually stop the rudders moving and eventually hacked the AR_MotorsUGV class, so will have to figure out a nicer way to do it. Anyway, the algorithm works ( with the addition of some skin friction drag to the asv-sim Lift drag plugin as outlined above)

Hi, has support for any rotary encoder wind vane been added yet? Or is there any documentation for it? I’m hoping to use the AS5048B or AS5600 but am not set up to build my own code.
Also, it it not possible to just set the AS5600 in analog output mode and connect that directly to an analog input on the flight controller? It seems no one is doing this so I must be missing something.
Thanks!

I made a fork with AS4045 and AS5048B support forever ago – there is a comment in this thread or you can find it here: GitHub - playertr/ardupilot: ArduPlane, ArduCopter, ArduRover source

Hope that helps!

BTW I’m in Seattle and interested to help with testing and whatnot!

We have a PR for AS5048B, Add AP_AngleSensor Driver with AS5048B Support, Integrate with Windvane by DavidIngraham · Pull Request #25749 · ArduPilot/ardupilot · GitHub

I see no reason why the analog output would not work in the mean time.

I am using the standard Ardupilot analog windvane setup on this sailboat with a AS5600 board off ebay.

The only consideration is if you are using a longish wire (say more than 0.5m or so), then it is best to make sure that the impedance of the signal is low and relatively well matched, which sounds more technical than it is.

The AS5600 datasheet states that the minimum output resistive load to get a full range output, is 100,000 (100 k) ohms, which is quite a high value Search through the datasheet for ROUT_FD for the details

To make a matched impedance at each end of the wire you can use a similar circuit to this old rssi to analog circuit.

Ignore the fact it is pwm to analog, it is still basically good for this application.

Starting from the left in the diagram, for this circuit you would change the value of R1 to 100,000 ohms to conform to the AS5600 spec. R2 and R3 perform the impedance matching. You don’t need a coax cable. If you have a 3 core ( Power, ground, signal) cable then you can reckon on the wire impedance being around 100 ohms so values of R1 and R2 should match that → 100 ohms. Alternatively if you have some FPV video cable ( which would be a good choice), then its impedance is 75 ohms so that is the value to use. The capacitors C2 and C3 act to divert dynamic noise ( such as wireless pickup) to ground through the resistors. They can stay at 0.1 uF (microfarads) and you don’t need C1 since this is an analog input circuit so doesnt need that at all. R1 and C1 act as a low pass filter for the AS5600 DAC output and with values of 100,000 ohms and 0.1 microfarads I think R1,C1 gives you a cut off frequency of 16 Hz or so, which should be a lively enough response to get you started

Cool boat Skyscraper! I like the uni-rig, how do you like it?

I tried a couple of vanes using the AS5600 with analog output. I eventually went to a P3022 encoder because I couldn’t reliably/easily make the bearings and shaft part myself in the small size I wanted.

More details here https://www.holdentechnology.com/2021/01/06/electronic-windvane/

Here’s a picture of a vane with AS5600 (hooked to an arduino sending NMEA to my PC, not ardupilot)

2 Likes