ROS探索总结(十二)——坐标系统

        在机器人的控制中,坐标系统是非常重要的,在ROS使用tf软件库进行坐标转换。

        相关链接:http://www.ros.org/wiki/tf/Tutorials#Learning_tf

一、tf简介

        我们通过一个小小的实例来介绍tf的作用。

1、安装turtle包

$ rosdep install turtle_tf rviz
$ rosmake turtle_tf rviz


2、运行demo

        运行简单的demo:
$ roslaunch turtle_tf turtle_tf_demo.launch


        然后就会看到两只小乌龟了。

        该例程中带有turtlesim仿真,可以在终端激活的情况下进行键盘控制。

        可以发现,第二只乌龟会跟随你移动的乌龟进行移动。

3、demo分析

        接下来我们就来看一看到底ROS做了什么事情。
        这个例程使用tf建立了三个参考系:a world frame, a turtle1 frame, and a turtle2 frame。然后使用tf broadcaster发布乌龟的参考系,并且使用tf listener计算乌龟参考系之间的差异,使得第二只乌龟跟随第一只乌龟。
        我们可以使用tf工具来具体研究。
$ rosrun tf view_frames


        然后会看到一些提示,并且生成了一个frames.pdf文件。

        该文件描述了参考系之间的联系。三个节点分别是三个参考系,而/world是其他两个乌龟参考系的父参考系。还包含一些调试需要的发送频率、最近时间等信息。
        tf还提供了一个tf_echo工具来查看两个广播参考系之间的关系。我们可以看一下第二只得乌龟坐标是怎么根据第一只乌龟得出来的。
$ rosrun tf tf_echo turtle1 turtle2


        控制一只乌龟,在终端中会看到第二只乌龟的坐标转换关系。

        我们也可以通过rviz的图形界面更加形象的看到这三者之间的关系。
$ rosrun rviz rviz -d `rospack find turtle_tf`/rviz/turtle_rviz.vcg

        移动乌龟,可以看到在rviz中的坐标会跟随变化。其中左下角的是/world,其他两个是乌龟的参考系。
       下面我们就来详细分析这个实例。

二、Writing a tf broadcaster

1、创建包

$ roscd tutorials
$ roscreate-pkg learning_tf tf roscpp rospy turtlesim
$ rosmake learning_tf


2、broadcast transforms

        我们首先看一下如何把参考系发布到tf。
        代码文件:/nodes/turtle_tf_broadcaster.py
#!/usr/bin/env python  
import roslib
roslib.load_manifest('learning_tf')
import rospy


import tf
import turtlesim.msg


def handle_turtle_pose(msg, turtlename):
    br = tf.TransformBroadcaster()
    br.sendTransform((msg.x, msg.y, 0),
                     tf.transformations.quaternion_from_euler(0, 0, msg.theta),
                     rospy.Time.now(),
                     turtlename,
                     "world")  #发布乌龟的平移和翻转


if __name__ == '__main__':
    rospy.init_node('turtle_tf_broadcaster')
    turtlename = rospy.get_param('~turtle')   #获取海龟的名字(turtle1,turtle2)
    rospy.Subscriber('/%s/pose' % turtlename,
                     turtlesim.msg.Pose,
                     handle_turtle_pose,
                     turtlename)   #订阅 topic "turtleX/pose"
    rospy.spin()


        创建launch文件start_demo.launch:
<launch>
    <!-- Turtlesim Node-->
    <node pkg="turtlesim" type="turtlesim_node" name="sim"/>
    <node pkg="turtlesim" type="turtle_teleop_key" name="teleop" output="screen"/>


    <node name="turtle1_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
      <param name="turtle" type="string" value="turtle1" />
    </node>
    <node name="turtle2_tf_broadcaster" pkg="learning_tf" type="turtle_tf_broadcaster.py" respawn="false" output="screen" >
      <param name="turtle" type="string" value="turtle2" /> 
    </node>


  </launch>


        运行:
$ roslaunch learning_tf start_demo.launch


        可以看到界面中只有移植乌龟了,打开tf_echo的信息窗口:
$ rosrun tf tf_echo /world /turtle1 

        world参考系的原点在最下角,对于turtle1的转换关系,其实就是turtle1在world参考系中所在的坐标位置以及旋转角度。

三、Writing a tf listener

             这一步,我们将看到如何使用tf进行参考系转换。首先写一个tf listener(nodes/turtle_tf_listener.py):
#!/usr/bin/env python  
import roslib
roslib.load_manifest('learning_tf')
import rospy
import math
import tf
import turtlesim.msg
import turtlesim.srv

if __name__ == '__main__':
    rospy.init_node('tf_turtle')

    listener = tf.TransformListener() #TransformListener创建后就开始接受tf广播信息,最多可以缓存10s

    rospy.wait_for_service('spawn')
    spawner = rospy.ServiceProxy('spawn', turtlesim.srv.Spawn)
    spawner(4, 2, 0, 'turtle2')

    turtle_vel = rospy.Publisher('turtle2/command_velocity', turtlesim.msg.Velocity)

    rate = rospy.Rate(10.0)
    while not rospy.is_shutdown():
        try:
            (trans,rot) = listener.lookupTransform('/turtle2', '/turtle1', rospy.Time(0))
        except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException):
            continue

        angular = 4 * math.atan2(trans[1], trans[0])
        linear = 0.5 * math.sqrt(trans[0] ** 2 + trans[1] ** 2)
        turtle_vel.publish(turtlesim.msg.Velocity(linear, angular))

        rate.sleep()

        在launch文件中添加下面的节点:
<launch>
    ...
    <node pkg="learning_tf" type="turtle_tf_listener.py" 
          name="listener" />
</launch>

        然后在运行,就可以看到两只turtle了,也就是我们在最开始见到的那种跟随效果。

四、Adding a frame

        在很多应用中,添加一个参考系是很有必要的,比如在一个world参考系下,有很一个激光扫描节点,tf可以帮助我们将激光扫描的信息坐标装换成全局坐标。

1、tf消息结构

        tf中的信息是一个树状的结构,world参考系是最顶端的父参考系,其他的参考系都需要向下延伸。如果我们在上文的基础上添加一个参考系,就需要让这个新的参考系成为已有三个参考系中的一个的子参考系。


2、建立固定参考系(fixed frame)

        我们以turtle1作为父参考系,建立一个新的参考系“carrot1”。代码如下(nodes/fixed_tf_broadcaster.py):
#!/usr/bin/env python  
import roslib
roslib.load_manifest('learning_tf')

import rospy
import tf

if __name__ == '__main__':
    rospy.init_node('my_tf_broadcaster')
    br = tf.TransformBroadcaster()
    rate = rospy.Rate(10.0)
    while not rospy.is_shutdown():
        br.sendTransform((0.0, 2.0, 0.0),
                         (0.0, 0.0, 0.0, 1.0),
                         rospy.Time.now(),
                         "carrot1",
                         "turtle1") #建立一个新的参考系,父参考系为turtle1,并且距离父参考系2米
        rate.sleep()

       在launch文件中添加节点:
  <launch>
    ...
    <node pkg="learning_tf" type="fixed_tf_broadcaster.py"
          name="broadcaster_fixed" />
  </launch>

        运行,还是看到两只乌龟和之前的效果一样。新添加的参考系并没有对其他参考系产生什么影响。打开nodes/turtle_tf_listener.py文件,将turtle1改成carrot1:
(trans,rot) = self.tf.lookupTransform("/turtle2", "/carrot1", rospy.Time(0))

        重新运行,现在乌龟之间的跟随关系就改变了:

3、建立移动参考系(moving frame)

        我们建立的新参考系是一个固定的参考系,在仿真过程中不会改变,如果我们要把carrot1参考系和turtle1参考系之间的关系设置可变的,可以修改代码如下:
#!/usr/bin/env python  
import roslib
roslib.load_manifest('learning_tf')

import rospy
import tf
import math

if __name__ == '__main__':
    rospy.init_node('my_tf_broadcaster')
    br = tf.TransformBroadcaster()
    rate = rospy.Rate(10.0)
    while not rospy.is_shutdown():
        t = rospy.Time.now().to_sec() * math.pi
        br.sendTransform((2.0 * math.sin(t), 2.0 * math.cos(t), 0.0),
                         (0.0, 0.0, 0.0, 1.0),
                         rospy.Time.now(),
                         "carrot1",
                         "turtle1")
        rate.sleep()

        这次carrot1的位置现对于turtle1来说是一个三角函数关系了。


----------------------------------------------------------------

欢迎大家转载我的文章。

转载请注明:转自古-月

http://blog.csdn.net/hcx25909

欢迎继续关注我的博客



 
<think>好的,我现在需要回答用户关于如何从Django的User模型中解密密码哈希值并展示明文密码的问题。首先,用户的问题涉及到密码哈希的解密,但根据我之前学到的知识,哈希函数通常是单向的,不可逆的。这意味着哈希后的密码无法被解密回原始明文。不过,用户可能误解了存储机制,或者有特殊需求需要获取明文密码,所以需要详细解释。 首先,我应该确认Django的User模型如何处理密码存储。根据引用[1]和[2],Django在用户注册时会自动对密码进行哈希处理,并存储哈希值,而不是明文。例如,使用authenticate函数进行验证时,系统会比较哈希值而不是明文。这说明Django的设计是出于安全考虑,不会存储原始密码,因此无法直接获取明文。 接下来,用户提到“解密哈希值”,这里可能存在概念错误。哈希不是加密,加密是可逆的,而哈希是不可逆的。因此,我需要明确指出哈希和加密的区别,避免混淆。引用[3]中的例子也展示了哈希的使用,比如用SHA-256生成哈希,但无法逆向得到原始密码。 然后,用户可能想知道是否有其他方法获取明文密码,比如在用户注册时记录明文,或者在登录时捕获。但这样做会有严重的安全风险,如引用[1]提到的密钥安全和哈希算法选择的重要性。因此,需要强调不应该存储或记录明文密码,否则会违反安全最佳实践。 另外,如果用户的需求是临时显示明文密码,比如在用户忘记密码时,正确的做法是提供密码重置功能,而不是显示原密码。Django内置的密码重置机制可以满足这一需求,而不需要存储明文。 最后,需要总结安全注意事项,强调不存储明文、使用强哈希算法、定期更新密钥等。同时,提醒用户遵循Django的安全机制,避免自行实现可能引入漏洞的方法。</think>### Django User模型密码哈希处理与安全性说明 #### 一、Django密码存储机制 Django的User模型默认使用**不可逆的密码哈希算法**存储用户密码[^1][^2],其安全机制设计如下: $$ \text{存储值} = \text{哈希算法}( \text{盐值} + \text{原始密码} ) $$ 整个过程为单向加密,**无法通过哈希值逆向计算原始密码**。验证密码时,系统会将输入密码重新哈希后与存储值比对[^2]。 #### 二、获取明文密码的不可行性 1. **技术限制** 哈希算法(如PBKDF2、bcrypt等)被设计为抗碰撞和不可逆的数学函数。即使通过数据库注入获取哈希值,也无法通过常规计算还原明文密码[^3]。 2. **Django架构限制** Django框架在密码处理流程中: ```python # 密码设置过程 user.set_password(raw_password) # 立即哈希化处理 user.save() # 仅存储哈希值 ``` 系统**从未存储过明文密码**,因此无法从数据库中提取明文密码。 #### 三、替代解决方案 若需实现密码相关功能,应采用安全方案: 1. **密码重置功能** ```python from django.contrib.auth.views import PasswordResetView ``` 2. **临时密码显示** 仅在用户注册时短暂显示(需前端配合): ```python def register(request): if request.method == 'POST': raw_password = User.objects.make_random_password() user = User.objects.create_user(username, password=raw_password) # 立即在前端显示后销毁变量 ``` #### 四、安全注意事项 1. **绝对禁止行为** - 在数据库、日志或文件中存储明文密码 - 覆盖`set_password`方法保留明文副本 2. **安全增强建议** - 使用`django.contrib.auth.hashers`模块的`make_password`和`check_password`方法 - 定期升级哈希算法(通过`PASSWORD_HASHERS`配置) - 启用PBKDF2迭代次数自动增长机制
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值