Help me get my "rover" running

Edit 1: Corrected PX4 to Pixhawk 4.

Hi everyone, I’m new here and so far very impressed with the community support I see.

I’ve recently joined on a project that involves giving a golf cart-type vehicle autonomous navigation capabilities (using Pixhawk 4) and unfortunately am at a lack for someone to help guide me through this. I’ll try to be as thorough as possible without being long-winded…

My end goal:

  • To control a rover-type vehicle (motor control and steering) programmatically through Python + mavlink scripting, and / or with QGroudControl.

Vehicle details:

  • Vehicle (back wheel drive) speed is controlled via a 3.3v PWM signal. I’ve managed to control this using QGC’s motor test sliders. Duty cycle corresponds to speed, as one would expect.
  • Steering is via a servo motor controlling the front wheels. Still working on the mechanics behind this but let’s assume this will work out.
  • Forward / reverse are controlled by GPIO output + relay. To simplify things let’s assume only forward.

Hardware I have:

  • Pixhawk 4
  • Pixhawk 4 GPS module
  • Sufficient options for power supply
  • Raspberry Pi 4 acting as “Companion Computer” (I also have a Jetson Nano / laptop)
  • All necessary wires / cables

First thing I’d like to achieve:

  • Set vehicle off traveling in a straight line (no steering) for X seconds at Y speed, before coming to a stop. This should be achieved by setting the desired speed via Python script + mavlink command, which will should result in a PWM signal on one of the Pixhawk 4’s PWM pins, whose duty cycle corresponds to the desired speed.

What I’ve tried:
Somewhat blindly (I don’t really know what I’m doing) I have tried passing a command to the Pixhawk 4 with the following script that I finagled together. I’m sure there are plenty of issues:

from dronekit import * 
import time

# Initialize connection
vehicle = connect('/dev/ttyUSB0', wait_ready=True, baud=57600)
print("Vehicle connected.") # The connection succeeds

# Set mode
while vehicle.mode.name != "ACRO":
    vehicle.mode = VehicleMode("ACRO")
    time.sleep(1)
print(vehicle.mode.name)
print(f"Mode set: {vehicle.mode.name}")

while not vehicle.armed :
    vehicle.armed = True
print(vehicle.armed)

# Set speed 
def send_global_velocity(velocity_x, velocity_y, velocity_z, duration):

    msg = vehicle.message_factory.set_position_target_global_int_encode(
        0,       # time_boot_ms (not used)
        0, 0,    # target system, target component
        mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT_INT, # frame
        0b0000111111000111, # type_mask (only speeds enabled)
        0, # lat_int - X Position in WGS84 frame in 1e7 * meters
        0, # lon_int - Y Position in WGS84 frame in 1e7 * meters
        0, # alt - Altitude in meters in AMSL altitude(not WGS84 if absolute or relative)
        # altitude above terrain if GLOBAL_TERRAIN_ALT_INT
        velocity_x, # X velocity in NED frame in m/s
        velocity_y, # Y velocity in NED frame in m/s
        velocity_z, # Z velocity in NED frame in m/s
        0, 0, 0, # afx, afy, afz acceleration (not supported yet, ignored in GCS_Mavlink)
        0, 0)    # yaw, yaw_rate (not supported yet, ignored in GCS_Mavlink) 
	
    # send command to vehicle on 1 Hz cycle
    for x in range(0, duration):
        vehicle.send_mavlink(msg)
        time.sleep(1)  
 
send_global_velocity(2, 0, 0, 30)
vehicle.armed = False

—> I chose the ACRO mode because it doesn’t require GPS - though I have the GPS module. I am testing this inside so the GPS doesn’t lock, but if a different mode is required I will happily connect the GPS and take things outside.

Results of the above script:
I tested the Pixhawk’s I/O PWM pins with an oscilloscope and found that when I ran the script I received a constant 3.3v signal on pin 3 – which is the same pin that gives a PWM signal when I do the motor test on QGC. This signal no longer appears when I remove vehicle.arm, and appears to have nothing to do with the rest of the code. The script seems to have no effect.

WHEW.
I hope this makes sense and someone can help me take my first steps at getting this vehicle running. Thanks in advance for any and all help!

1 Like

Your project sounds quite interesting, but first we need to clarify a few things. It’s entirely possible you’ve arrived at the wrong website…

PX4 is open source autopilot software. There is a community/forum dedicated to it.

Likewise, ArduPilot is open source autopilot software, and you’ve arrived at the forum for discussing it.

On the contrary, Pixhawk is an open source autopilot hardware standard. Quite a few manufacturers provide compatible hardware.

As such, we need to clarify which hardware and software you’re actually using. If you are truly using PX4 software, I’m afraid we won’t be much help here.

One bit of advice I can give immediately, though, is that an RC transmitter and receiver will likely prove invaluable to you during the prototype phase. Even if you don’t plan to use RC control in the long run, you’ll likely have an easier time testing and tuning by RC than by script (whether you use PX4, ArduPilot, or any other similar software suite).

Thanks. I saw PX4 somewhere online and thoughtlessly assumed it was shorthand for Pixhawk 4. Corrected my post to say Pixhawk 4 instead!

I will try to get my hands on an RC tx/rx. I understand it’s possible (but not recommended) to override output channels to simulate RC input, and I made a feeble attempt at this (with vehicle.channels.overrides) but this command didn’t seem to affect the PWM output pins. But I digress…

Here’s a Mission Planner script that I use to tune PWM output for my own motor control on a large Rover like yours. It mimics RC control as you suggest. And as you suggest, it’s a terrible idea to use this script with the vehicle off of jack stands.

This video shows the script in use.

You might consider using Mission Planner instead of QGroundControl if you are using ArduPilot. Mission Planner is developed by ArduPilot’s dev team. QGroundControl is third party.

Wow. Awesome project.

Is this code handwritten or is it “exported” from Mission Control according to your configurations? Or something else entirely :slight_smile:

Why is it such a bad idea to set PWM outputs with overrides?

Assuming I get Mission Control up and running (I’m not currently at the work bench) what should be my first step in achieving a short straight line mission? Feel free to refer me to learning material - don’t expect to be spoon fed the solution.

I wrote every line of that code.

It exploits the fact that IronPython is exposed to Mission Planner’s own scripting engine, so you can add windows, widgets, buttons, etc.

If you begin using a bunch of overrides, you potentially disable a lot of native functionality, including failsafes. Also, you’d possibly be fighting the closed loop controllers on the autopilot itself by attempting a control loop of your own design. It’s a pretty ugly solution to a problem that can almost certainly be solved more elegantly.

If you just want to script PWM output to motor controllers, you could write some ESP32 code to do that on far cheaper hardware in a few hours’ time. I don’t think that’s your intent, but you’re kind of suggesting that you’d relegate a fully featured autopilot to that sort of control with your scripts.

Here’s the path I suggest:

  1. Get your hands on an RC transmitter and receiver. I prefer OpenTX hardware, but there are TONS of alternatives. You are putting the cart way ahead of the horse by trying to script control of a vehicle that hasn’t even moved yet.

  2. Follow the setup and tuning steps in the documentation extremely carefully. They are well written but quite concise, so go line by line and do not miss a step. Keep a notebook/log as you go. Try to only change one or maybe two variables at a time and always keep track of previous settings.

  3. Once you have a running, driving Rover, explore the use of AUTO and GUIDED modes to control it the way you desire. You can script waypoints, mission commands, etc quite easily.

Well, community support doesn’t get any better than this. Thanks, Yuri. I’ll follow your steps and report on my progress.

A fully featured autopilot is certainly preferred over micromanagey scripting - my intent behind “just getting it to go in a straight line” was to start to get my hands dirty and make some progress.

Will update soon hopefully with good news.

1 Like

Yuri, quick clarification:

For the sake of tuning, the RC gear is meant to control the motor via the Pixhawk, rather than interface directly with the motor control, correct?

The Pixhawk 4 has a PPM input, which I imagine Ardupilot can receive and translate into a PWM signal on the I/O PWM pins.

So: RC Tx > RC Rx > Pixhawk PPM in > Ardupilot software > Pixhawk PWM out.

In that case I’ll just need to make sure to buy RC gear that supports PPM output, right?

That is correct. The RC controller is just a hands-on means of giving the Pixhawk some control inputs. The Pixhawk handles all the outputs.

In VERY broad and loose terms, you can consider the Pixhawk like a very feature rich mixer that sits between the receiver and the motors/steering/control surfaces.

I recommend using RC hardware to get started because you can make real time changes without having to change your codebase if you are trying to script the controls. Additionally, all of the documentation will lead you to use RC control for testing and tuning. Later, you can explore “headless” operation without RC hardware (or even without GCS software).

You can use any RC receiver that outputs PPM, SBus, FPort, DSM, Crossfire, or probably a few other protocols I’m forgetting about. The link in my #1 bullet above lists all the compatible RC hardware. I’ve personally used Spektrum and FrSky hardware with PPM, DSM2, SBus, and FPort all with equal success.

1 Like