Open ghost opened 1 year ago
If you can share your rules.d
file, maybe I can help.
Moreover, our computer doesn't even see anything connected to the port where we connect our VESC.
Does lsusb
not show the VESC connected?
If you can share your
rules.d
file, maybe I can help.Moreover, our computer doesn't even see anything connected to the port where we connect our VESC.
Does
lsusb
not show the VESC connected?
No we can't seem to find it with lsusb
The udev
rules seem fine. But if the device doesn't show up on lsusb
, then there's a good chance there is something wrong with the connections or the VESC is not powered.
The
udev
rules seem fine. But if the device doesn't show up onlsusb
, then there's a good chance there is something wrong with the connections or the VESC is not powered.
I saw in your motor_examples.py
file that you use stop_heartbeat()
saying that not using it before we get out of scope may cause issues.
I'm not making use of a heartbeat function anywhere in my code, either to stop or start the heartbeat. is there a chance my connection issues have anything to do with that?
could you maybe expand a bit on what you meant here?
this is how we get data from the VESC.
I'm not making use of a heartbeat function anywhere in my code, either to stop or start the heartbeat. is there a chance my connection issues have anything to do with that?
I am not familiar with the exact details of stop_heartbeat
, as I did not write the code for it, but, it seems that VESC sends the last command periodically. It is done automatically, but since it spawns a separate thread, you need to shutdown that thread before you stop using the motor. You should add a call to stop_heartbeat
in your code too.
https://github.com/kknives/pyvesc/blob/cc0043383b7f86d28a479ceab2d4c8cca8b7daee/pyvesc/VESC/VESC.py#L77-L81
Also, could you post your code as text, so its easier for me to make corrections.
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from lar_interfaces.msg import Joystick, JetMotorData, TigerMode, MotorGuidance
import pyvesc
from pyvesc import VESC
import time
from autopilot_pkg.lar_common import Error_code, Tiger_mode
import os
import subprocess
serialport = '/dev/jet'
class JetNode(Node): # MODIFY NAME !!
def __init__(self):
super().__init__('jet_node') # MODIFY NAME !!
self.vesc_is_connected = False
while not self.vesc_is_connected:
try:
self.motor = VESC(serialport)
self.get_logger().info('vesc has been connected')
self.vesc_is_connected = True
except Exception as e:
# self.get_logger().info(e)
self.get_logger().info('VESC has serial connection issue')
pass
finally:
pass
# self.motor = VESC(serialport)
self.get_logger().info('Jet node has been started')
# self.motor_data_valid = False
self.wdt_jet = 0
self.epoch_jet = int(time.time() * 1e6)
self.motor_data_list = [None] * 19
self.tiger_mode = 1
self.tiger_mode_subscriber = self.create_subscription(TigerMode, 'tiger_mode', self.tiger_mode_callback, 10)
self.jet_subscriber = self.create_subscription(Joystick, "joystick_data", self.callback_jet, 10)
self.servo_guided_subscriber = self.create_subscription(MotorGuidance, "motor_guidance_data", self.callback_jet_guided, 0)
self.jet_data_publisher = self.create_publisher(JetMotorData, "jet_motor_data",10)
self.jet_pub_timer = self.create_timer(1, self.motor_data)
# self.jet_data_timer = self.create_timer(1, self.get_motor_data)
# self.motor.set_rpm(2000)
# self.motor_test()
# self.motor_data_list[0] = int(time.time()*1e6)
def callback_jet_guided(self, msg):
if self.tiger_mode == Tiger_mode.Tiger_GUIDED_MISSION.value:
self.motor.set_rpm(int(msg.jet_rpm))
def tiger_mode_callback(self, msg):
self.tiger_mode = msg.tiger_mode
if self.tiger_mode == Tiger_mode.Tiger_HOLD_POSITION.value:
self.motor.set_rpm(0)
def motor_test(self):
initial_speed = 2000
with VESC(serialport, timeout=1) as motor:
motor.set_rpm(initial_speed)
def callback_jet(self, msg):
if self.tiger_mode == Tiger_mode.Tiger_IDLE.value:
desired_rpm = self.remote_value_scaling(msg.chan3)
self.motor.set_rpm(int(desired_rpm))
def remote_value_scaling(self, x):
old_min = 1000
old_max = 2000
new_min = -20000
new_max = 20000
desired_speed = (((x - old_min) * (new_max - new_min)) / (old_max - old_min)) + new_min
if desired_speed < 900 and desired_speed > -900:
desired_speed = 0
return desired_speed
else:
return desired_speed
def motor_data(self):
msg = JetMotorData()
msg.timestamp = int(time.time() * 1e6)
try:
# msg = JetMotorData()
# msg.avg_motor_current = self.motor.get_measurements().avg_motor_current
# self.get_logger().info(str(msg.avg_motor_current))
msg.rpm = self.motor.get_measurements().rpm
msg.temp_fet = self.motor.get_measurements().temp_fet
msg.temp_motor = self.motor.get_measurements().temp_motor
msg.v_in = self.motor.get_measurements().v_in
self.jet_data_publisher.publish(msg)
except Exception as e:
self.wdt_jet = (int(time.time()*1e6) - msg.timestamp)/1e6
# if self.wdt_vn
if self.wdt_jet > 5:
message = 'Problem with JET, Time: ' + str(self.wdt_jet)
self.get_logger().info(message)
finally:
pass
# rosbag_process = subprocess.Popen('ros2 bag record /ADC_measurements /BME_Back_measurements /BA30_measurements /BME_Front_measurements /Vn200Data /joystick_data /qgc_mode /status /tiger_mode /pid_data_log /GnssVn200 /InsStatus /jet_motor_data /motor_guidance_data /parameter /status /servo_motor_data /waypoint /guidance_data_log', stdin=subprocess.PIPE, shell=True, cwd=self.dir_save_bagfile)
def main(args=None):
rclpy.init(args=args) # Starts ros2 comm
node = JetNode() # MODIFY NAME !! # Node constructor ("node name")
rclpy.spin(node)
rclpy.shutdown() # Ends comm
if __name__ == '__main__':
main()
thank you for the help!
For adding a call to stop_heartbeat
, make a new method in JetNode
:
def close(self):
self.motor.stop_heartbeat()
Modify main
:
def main(args=None):
rclpy.init(args=args) # Starts ros2 comm
node = JetNode() # MODIFY NAME !! # Node constructor ("node name")
rclpy.spin(node)
node.close()
rclpy.shutdown() # Ends comm
also now the problem is that it seems to connect, send out a couple of messages and then stops sending. we're using ROS2 to manage the communication.
Are you getting Exception messages? As you defined them in motor_data
:
def motor_data(self):
msg = JetMotorData()
msg.timestamp = int(time.time() * 1e6)
try:
# msg = JetMotorData()
# msg.avg_motor_current = self.motor.get_measurements().avg_motor_current
# self.get_logger().info(str(msg.avg_motor_current))
msg.rpm = self.motor.get_measurements().rpm
msg.temp_fet = self.motor.get_measurements().temp_fet
msg.temp_motor = self.motor.get_measurements().temp_motor
msg.v_in = self.motor.get_measurements().v_in
self.jet_data_publisher.publish(msg)
except Exception as e:
self.wdt_jet = (int(time.time()*1e6) - msg.timestamp)/1e6
# if self.wdt_vn
if self.wdt_jet > 5:
message = 'Problem with JET, Time: ' + str(self.wdt_jet)
self.get_logger().info(message)
finally:
pass
Are you getting Exception messages? As you defined them in
motor_data
:
No. I get a connection, a few messages (it changes between 2 and a max of 25) are sent by the VESC and received on my end, and after that it just seems to be getting out of the scope of the node. it just doesn't go into the publisher function at some point.
Can you try running the example? Make sure to change the serial port. Let me know if you get errors here too.
the example works and doesn't seem to make problems.
also when I run my code from the IDE and not a ROS2 terminal command, it seems to work. only when I try and use the ROS2 terminal command ros2 run motor_pkg jet_node
am I getting problems.
def motor_data(self):
msg = JetMotorData()
msg.timestamp = int(time.time() * 1e6)
try:
# msg = JetMotorData()
# msg.avg_motor_current = self.motor.get_measurements().avg_motor_current
# self.get_logger().info(str(msg.avg_motor_current))
msg.rpm = self.motor.get_measurements().rpm
msg.temp_fet = self.motor.get_measurements().temp_fet
msg.temp_motor = self.motor.get_measurements().temp_motor
msg.v_in = self.motor.get_measurements().v_in
self.jet_data_publisher.publish(msg)
self.get_logger().info('done with msg')
except Exception as e:
self.wdt_jet = (int(time.time()*1e6) - msg.timestamp)/1e6
# if self.wdt_vn
if self.wdt_jet > 5:
message = 'Problem with JET, Time: ' + str(self.wdt_jet)
self.get_logger().info(message)
finally:
pass
I added a get_logger()
function to see when the motor is still sending messages and you can see in the image that it just stops sending at a seemingly random time.
Try running ros2 topic echo /jet_motor_data
in another terminal when you run the jet_node
, does it also stop updating after sometime?
the example works and doesn't seem to make problems.
Then the problem isn't in PyVESC
Try running
ros2 topic echo /jet_motor_data
in another terminal when you run thejet_node
, does it also stop updating after sometime?
It does. It stops echoing at the same time as it stops printing.
Then the problem isn't in PyVESC
I thought as much, I think it's either a ROS2 problem or a hardware problem but I just hoped someone else faced a similar problem.
also when I run my code from the IDE and not a ROS2 terminal command, it seems to work
Does your IDE start the node from a launch file?
Also, can you try printing a message every time the motor_data
function is called, something like this:
def motor_data(self):
msg = JetMotorData()
msg.timestamp = int(time.time() * 1e6)
try:
# msg = JetMotorData()
# msg.avg_motor_current = self.motor.get_measurements().avg_motor_current
# self.get_logger().info(str(msg.avg_motor_current))
msg.rpm = self.motor.get_measurements().rpm
msg.temp_fet = self.motor.get_measurements().temp_fet
msg.temp_motor = self.motor.get_measurements().temp_motor
msg.v_in = self.motor.get_measurements().v_in
self.get_logger().info('Read all values')
...
This would narrow the problem down to the self.jet_data_publisher.publish(msg)
call
I'm using Visual studio code IDE and I think it does make use of a launch file.
also printing the outputs never stops in the middle of the publisher function. at some point (5 - 15 seconds in) the communication with the VESC just seems to stop.
def motor_data(self):
msg = JetMotorData()
msg.timestamp = int(time.time() * 1e6)
try:
meas = self.motor.get_measurements()
# msg = JetMotorData()
# msg.avg_motor_current = self.motor.get_measurements().avg_motor_current
# self.get_logger().info(str(msg.avg_motor_current))
# msg.rpm = self.motor.get_measurements().rpm
msg.rpm = meas.rpm
self.get_logger().info(str(msg.rpm))
# msg.temp_fet = self.motor.get_measurements().temp_fet
msg.temp_fet = meas.temp_fet
self.get_logger().info(str(msg.temp_fet))
# msg.temp_motor = self.motor.get_measurements().temp_motor
msg.temp_motor = meas.temp_motor
self.get_logger().info(str(msg.temp_motor))
# msg.v_in = self.motor.get_measurements().v_in
msg.v_in = meas.v_in
self.get_logger().info(str(msg.v_in))
self.jet_data_publisher.publish(msg)
self.get_logger().info('done with msg')
except Exception as e:
self.wdt_jet = (int(time.time()*1e6) - msg.timestamp)/1e6
# if self.wdt_vn
if self.wdt_jet > 5:
message = 'Problem with JET, Time: ' + str(self.wdt_jet)
self.get_logger().info(message)
finally:
pass
It's strange that a connection or a hardware issue only occurs when not using VSCode.
I'm using Visual studio code IDE and I think it does make use of a launch file.
That's the only thing left to check now. When you run the node from VSCode, what command does it use?
when I hit play in the IDE that's the command that he uses.
what's most strange to me is that it just seems to happen at random. I've tried using different system loads (other nodes working in parallel) and it dosen't seem to matter. it always claims to make a connection, just after some times stops interacting.
The VSCode command does the same thing as ros2 run
.
As for the connection issues, you can try increasing the range in the example to see what error occurs: https://github.com/kknives/pyvesc/blob/cc0043383b7f86d28a479ceab2d4c8cca8b7daee/pyvesc/examples/motor_example.py#L15
Without a good idea of what is stopping the connection, it's hard to come up with a fix 😕
hello everyone.
My name is Yonatan. My team and I are making an AUV and we're using the VESC 75/300 in order to control our main motor. We do most of our coding in oython and we make use of ROS2 in order to manage the communication between different modules.
While workshopping in the lab, we had little to no connection problems with the VESC. For some reason, after transportting the AUV and locking it up, we cant seem to reach serial connection. Moreover, our computer doesn't even see anything connected to the port where we connect our VESC.
Our connection method:
We have a rules.d file that sends '/dev/jet' to '/dev/ttyACM0'
We're using a USB cable to connect the VESC to an UP board (https://up-board.org/wp-content/uploads/datasheets/UPDatasheetV8.5.pdf). While in transit, the VESC is powered and physically connected to the UP board, but the UP board itself is turned off. We started thinking this might be one of the reasons for our trouble but we're unable to confirm this yet.
Has anyone used the python PyVESC module and had a similar problem?
Thanks in advance,
Yonatan.